Fixed image flickering when showing overlaid TIA messages in OpenGL mode.

Fixed misplacement of TIA messages when gl_fsmax is activated.

Cleaned up OpenGL function prototype declarations and instantiations.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1605 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-01-10 18:42:49 +00:00
parent b7f913415c
commit a36c6f08d1
3 changed files with 122 additions and 137 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBufferGL.cxx,v 1.132 2009-01-03 22:57:12 stephena Exp $ // $Id: FrameBufferGL.cxx,v 1.133 2009-01-10 18:42:49 stephena Exp $
//============================================================================ //============================================================================
#ifdef DISPLAY_OPENGL #ifdef DISPLAY_OPENGL
@ -33,40 +33,34 @@
#include "FrameBufferGL.hxx" #include "FrameBufferGL.hxx"
// Maybe this code could be cleaner ... // OpenGL functions we'll be using in Stella
static void (APIENTRY* p_glClear)( GLbitfield ); #define OGL_DECLARE(RET,FUNC,PARAMS) static RET (APIENTRY* p_ ## FUNC) PARAMS
static void (APIENTRY* p_glEnable)( GLenum );
static void (APIENTRY* p_glDisable)( GLenum );
static void (APIENTRY* p_glPushAttrib)( GLbitfield );
static const GLubyte* (APIENTRY* p_glGetString)( GLenum );
static void (APIENTRY* p_glHint)( GLenum, GLenum );
static void (APIENTRY* p_glShadeModel)( GLenum );
// Matrix OGL_DECLARE(void,glClear,(GLbitfield));
static void (APIENTRY* p_glMatrixMode)( GLenum ); OGL_DECLARE(void,glEnable,(GLenum));
static void (APIENTRY* p_glOrtho)( GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble ); OGL_DECLARE(void,glDisable,(GLenum));
static void (APIENTRY* p_glViewport)( GLint, GLint, GLsizei, GLsizei ); OGL_DECLARE(void,glPushAttrib,(GLbitfield));
static void (APIENTRY* p_glPushMatrix)( void ); OGL_DECLARE(const GLubyte*,glGetString,(GLenum));
static void (APIENTRY* p_glLoadIdentity)( void ); OGL_DECLARE(void,glHint,(GLenum, GLenum));
OGL_DECLARE(void,glShadeModel,(GLenum));
// Drawing OGL_DECLARE(void,glMatrixMode,(GLenum));
static void (APIENTRY* p_glBegin)( GLenum ); OGL_DECLARE(void,glOrtho,(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble));
static void (APIENTRY* p_glEnd)( void ); OGL_DECLARE(void,glViewport,(GLint, GLint, GLsizei, GLsizei));
static void (APIENTRY* p_glVertex2i)( GLint, GLint ); OGL_DECLARE(void,glPushMatrix,(void));
static void (APIENTRY* p_glTexCoord2f)( GLfloat, GLfloat ); OGL_DECLARE(void,glLoadIdentity,(void));
OGL_DECLARE(void,glBegin,(GLenum));
// Raster funcs OGL_DECLARE(void,glEnd,(void));
static void (APIENTRY* p_glReadPixels)( GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid* ); OGL_DECLARE(void,glVertex2i,(GLint, GLint));
static void (APIENTRY* p_glPixelStorei)( GLenum, GLint ); OGL_DECLARE(void,glTexCoord2f,(GLfloat, GLfloat));
OGL_DECLARE(void,glReadPixels,(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*));
// Texture mapping OGL_DECLARE(void,glPixelStorei,(GLenum, GLint));
static void (APIENTRY* p_glTexEnvf)( GLenum, GLenum, GLfloat ); OGL_DECLARE(void,glTexEnvf,(GLenum, GLenum, GLfloat));
static void (APIENTRY* p_glGenTextures)( GLsizei, GLuint* ); // 1.1 OGL_DECLARE(void,glGenTextures,(GLsizei, GLuint*));
static void (APIENTRY* p_glDeleteTextures)( GLsizei, const GLuint* ); // 1.1 OGL_DECLARE(void,glDeleteTextures,(GLsizei, const GLuint*));
static void (APIENTRY* p_glBindTexture)( GLenum, GLuint ); // 1.1 OGL_DECLARE(void,glBindTexture,(GLenum, GLuint));
static void (APIENTRY* p_glTexImage2D)( GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid* ); OGL_DECLARE(void,glTexImage2D,(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*));
static void (APIENTRY* p_glTexSubImage2D)( GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid* ); // 1.1 OGL_DECLARE(void,glTexSubImage2D,(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*));
static void (APIENTRY* p_glTexParameteri)( GLenum, GLenum, GLint ); OGL_DECLARE(void,glTexParameteri,(GLenum, GLenum, GLint));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -116,66 +110,42 @@ bool FrameBufferGL::loadLibrary(const string& library)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferGL::loadFuncs() bool FrameBufferGL::loadFuncs()
{ {
#define OGL_INIT(RET,FUNC,PARAMS) \
p_ ## FUNC = (RET(APIENTRY*)PARAMS) SDL_GL_GetProcAddress(#FUNC); if(!p_ ## FUNC) return false
if(myLibraryLoaded) if(myLibraryLoaded)
{ {
// Fill the function pointers for GL functions // Fill the function pointers for GL functions
// If anything fails, we'll know it immediately, and return false // If anything fails, we'll know it immediately, and return false
// Yes, this syntax is ugly, but I can type it out faster than the time OGL_INIT(void,glClear,(GLbitfield));
// it takes to figure our macro magic to do it neatly OGL_INIT(void,glEnable,(GLenum));
p_glClear = (void(APIENTRY*)(GLbitfield)) OGL_INIT(void,glDisable,(GLenum));
SDL_GL_GetProcAddress("glClear"); if(!p_glClear) return false; OGL_INIT(void,glPushAttrib,(GLbitfield));
p_glEnable = (void(APIENTRY*)(GLenum)) OGL_INIT(const GLubyte*,glGetString,(GLenum));
SDL_GL_GetProcAddress("glEnable"); if(!p_glEnable) return false; OGL_INIT(void,glHint,(GLenum, GLenum));
p_glDisable = (void(APIENTRY*)(GLenum)) OGL_INIT(void,glShadeModel,(GLenum));
SDL_GL_GetProcAddress("glDisable"); if(!p_glDisable) return false;
p_glPushAttrib = (void(APIENTRY*)(GLbitfield))
SDL_GL_GetProcAddress("glPushAttrib"); if(!p_glPushAttrib) return false;
p_glGetString = (const GLubyte*(APIENTRY*)(GLenum))
SDL_GL_GetProcAddress("glGetString"); if(!p_glGetString) return false;
p_glHint = (void(APIENTRY*)(GLenum, GLenum))
SDL_GL_GetProcAddress("glHint"); if(!p_glHint) return false;
p_glShadeModel = (void(APIENTRY*)(GLenum))
SDL_GL_GetProcAddress("glShadeModel"); if(!p_glShadeModel) return false;
p_glMatrixMode = (void(APIENTRY*)(GLenum)) OGL_INIT(void,glMatrixMode,(GLenum));
SDL_GL_GetProcAddress("glMatrixMode"); if(!p_glMatrixMode) return false; OGL_INIT(void,glOrtho,(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble));
p_glOrtho = (void(APIENTRY*)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble)) OGL_INIT(void,glViewport,(GLint, GLint, GLsizei, GLsizei));
SDL_GL_GetProcAddress("glOrtho"); if(!p_glOrtho) return false; OGL_INIT(void,glPushMatrix,(void));
p_glViewport = (void(APIENTRY*)(GLint, GLint, GLsizei, GLsizei)) OGL_INIT(void,glLoadIdentity,(void));
SDL_GL_GetProcAddress("glViewport"); if(!p_glViewport) return false;
p_glPushMatrix = (void(APIENTRY*)(void))
SDL_GL_GetProcAddress("glPushMatrix"); if(!p_glPushMatrix) return false;
p_glLoadIdentity = (void(APIENTRY*)(void))
SDL_GL_GetProcAddress("glLoadIdentity"); if(!p_glLoadIdentity) return false;
p_glBegin = (void(APIENTRY*)(GLenum)) OGL_INIT(void,glBegin,(GLenum));
SDL_GL_GetProcAddress("glBegin"); if(!p_glBegin) return false; OGL_INIT(void,glEnd,(void));
p_glEnd = (void(APIENTRY*)(void)) OGL_INIT(void,glVertex2i,(GLint, GLint));
SDL_GL_GetProcAddress("glEnd"); if(!p_glEnd) return false; OGL_INIT(void,glTexCoord2f,(GLfloat, GLfloat));
p_glVertex2i = (void(APIENTRY*)(GLint, GLint))
SDL_GL_GetProcAddress("glVertex2i"); if(!p_glVertex2i) return false;
p_glTexCoord2f = (void(APIENTRY*)(GLfloat, GLfloat))
SDL_GL_GetProcAddress("glTexCoord2f"); if(!p_glTexCoord2f) return false;
p_glReadPixels = (void(APIENTRY*)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*)) OGL_INIT(void,glReadPixels,(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*));
SDL_GL_GetProcAddress("glReadPixels"); if(!p_glReadPixels) return false; OGL_INIT(void,glPixelStorei,(GLenum, GLint));
p_glPixelStorei = (void(APIENTRY*)(GLenum, GLint))
SDL_GL_GetProcAddress("glPixelStorei"); if(!p_glPixelStorei) return false;
p_glTexEnvf = (void(APIENTRY*)(GLenum, GLenum, GLfloat)) OGL_INIT(void,glTexEnvf,(GLenum, GLenum, GLfloat));
SDL_GL_GetProcAddress("glTexEnvf"); if(!p_glTexEnvf) return false; OGL_INIT(void,glGenTextures,(GLsizei, GLuint*));
p_glGenTextures = (void(APIENTRY*)(GLsizei, GLuint*)) OGL_INIT(void,glDeleteTextures,(GLsizei, const GLuint*));
SDL_GL_GetProcAddress("glGenTextures"); if(!p_glGenTextures) return false; OGL_INIT(void,glBindTexture,(GLenum, GLuint));
p_glDeleteTextures = (void(APIENTRY*)(GLsizei, const GLuint*)) OGL_INIT(void,glTexImage2D,(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*));
SDL_GL_GetProcAddress("glDeleteTextures"); if(!p_glDeleteTextures) return false; OGL_INIT(void,glTexSubImage2D,(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*));
p_glBindTexture = (void(APIENTRY*)(GLenum, GLuint)) OGL_INIT(void,glTexParameteri,(GLenum, GLenum, GLint));
SDL_GL_GetProcAddress("glBindTexture"); if(!p_glBindTexture) return false;
p_glTexImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*))
SDL_GL_GetProcAddress("glTexImage2D"); if(!p_glTexImage2D) return false;
p_glTexSubImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*))
SDL_GL_GetProcAddress("glTexSubImage2D"); if(!p_glTexSubImage2D) return false;
p_glTexParameteri = (void(APIENTRY*)(GLenum, GLenum, GLint))
SDL_GL_GetProcAddress("glTexParameteri"); if(!p_glTexParameteri) return false;
} }
else else
return false; return false;

View File

@ -1,4 +1,4 @@
//============================================================================
// //
// SSSS tt lll lll // SSSS tt lll lll
// SS SS tt ll ll // SS SS tt ll ll
@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBuffer.cxx,v 1.155 2009-01-06 23:14:34 stephena Exp $ // $Id: FrameBuffer.cxx,v 1.156 2009-01-10 18:42:49 stephena Exp $
//============================================================================ //============================================================================
#include <algorithm> #include <algorithm>
@ -205,26 +205,34 @@ void FrameBuffer::update()
case EventHandler::S_MENU: case EventHandler::S_MENU:
{ {
myOSystem->menu().draw(); // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->menu().draw(myMsg.enabled && type() == kGLBuffer);
break; // S_MENU break; // S_MENU
} }
case EventHandler::S_CMDMENU: case EventHandler::S_CMDMENU:
{ {
myOSystem->commandMenu().draw(); // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->commandMenu().draw(myMsg.enabled && type() == kGLBuffer);
break; // S_CMDMENU break; // S_CMDMENU
} }
case EventHandler::S_LAUNCHER: case EventHandler::S_LAUNCHER:
{ {
myOSystem->launcher().draw(); // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->launcher().draw(myMsg.enabled && type() == kGLBuffer);
break; // S_LAUNCHER break; // S_LAUNCHER
} }
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
case EventHandler::S_DEBUGGER: case EventHandler::S_DEBUGGER:
{ {
myOSystem->debugger().draw(); // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->debugger().draw(myMsg.enabled && type() == kGLBuffer);
break; // S_DEBUGGER break; // S_DEBUGGER
} }
#endif #endif
@ -235,7 +243,7 @@ void FrameBuffer::update()
} }
// Draw any pending messages // Draw any pending messages
if(myMsg.counter > 0) if(myMsg.enabled)
drawMessage(); drawMessage();
// Do any post-frame stuff // Do any post-frame stuff
@ -265,8 +273,50 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
myMsg.h = myOSystem->font().getFontHeight() + 8; myMsg.h = myOSystem->font().getFontHeight() + 8;
myMsg.surface->setWidth(myMsg.w); myMsg.surface->setWidth(myMsg.w);
myMsg.surface->setHeight(myMsg.h); myMsg.surface->setHeight(myMsg.h);
myMsg.position = position;
myMsg.enabled = true;
}
switch(position) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFrameStats()
{
showFrameStats(!myOSystem->settings().getBool("stats"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showFrameStats(bool enable)
{
myOSystem->settings().setBool("stats", enable);
myStatsMsg.enabled = enable;
refresh();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::enableMessages(bool enable)
{
if(enable)
{
// Only re-anable frame stats if they were already enabled before
myStatsMsg.enabled = myOSystem->settings().getBool("stats");
}
else
{
// Temporarily disable frame stats
myStatsMsg.enabled = false;
// Erase old messages on the screen
myMsg.enabled = false;
myMsg.counter = 0;
refresh();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void FrameBuffer::drawMessage()
{
// Draw the bounded box and text
switch(myMsg.position)
{ {
case kTopLeft: case kTopLeft:
myMsg.x = 5; myMsg.x = 5;
@ -313,46 +363,7 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
myMsg.y = myImageRect.height() - myMsg.h - 5; myMsg.y = myImageRect.height() - myMsg.h - 5;
break; break;
} }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFrameStats()
{
showFrameStats(!myOSystem->settings().getBool("stats"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showFrameStats(bool enable)
{
myOSystem->settings().setBool("stats", enable);
myStatsMsg.enabled = enable;
refresh();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::enableMessages(bool enable)
{
if(enable)
{
// Only re-anable frame stats if they were already enabled before
myStatsMsg.enabled = myOSystem->settings().getBool("stats");
}
else
{
// Temporarily disable frame stats
myStatsMsg.enabled = false;
// Erase old messages on the screen
myMsg.counter = 0;
refresh();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void FrameBuffer::drawMessage()
{
// Draw the bounded box and text
myMsg.surface->setPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y()); myMsg.surface->setPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y());
myMsg.surface->fillRect(0, 0, myMsg.w-2, myMsg.h-4, kBGColor); myMsg.surface->fillRect(0, 0, myMsg.w-2, myMsg.h-4, kBGColor);
myMsg.surface->box(0, 0, myMsg.w, myMsg.h-2, kColor, kShadowColor); myMsg.surface->box(0, 0, myMsg.w, myMsg.h-2, kColor, kShadowColor);
@ -363,10 +374,13 @@ inline void FrameBuffer::drawMessage()
// Either erase the entire message (when time is reached), // Either erase the entire message (when time is reached),
// or show again this frame // or show again this frame
if(myMsg.counter == 0) // Force an immediate update if(myMsg.counter == 0) // Force an immediate update
{
myMsg.enabled = false;
refresh(); refresh();
}
else else
{ {
myMsg.surface->addDirtyRect(0, 0, 0, 0); // force a full draw myMsg.surface->addDirtyRect(0, 0, 0, 0);
myMsg.surface->update(); myMsg.surface->update();
} }
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBuffer.hxx,v 1.113 2009-01-03 22:57:12 stephena Exp $ // $Id: FrameBuffer.hxx,v 1.114 2009-01-10 18:42:49 stephena Exp $
//============================================================================ //============================================================================
#ifndef FRAMEBUFFER_HXX #ifndef FRAMEBUFFER_HXX
@ -91,7 +91,7 @@ enum {
turn drawn here as well. turn drawn here as well.
@author Stephen Anthony @author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.113 2009-01-03 22:57:12 stephena Exp $ @version $Id: FrameBuffer.hxx,v 1.114 2009-01-10 18:42:49 stephena Exp $
*/ */
class FrameBuffer class FrameBuffer
{ {
@ -531,6 +531,7 @@ class FrameBuffer
string text; string text;
int counter; int counter;
int x, y, w, h; int x, y, w, h;
MessagePosition position;
uInt32 color; uInt32 color;
FBSurface* surface; FBSurface* surface;
int surfaceID; int surfaceID;
@ -562,7 +563,7 @@ class FrameBuffer
FrameBuffer type. FrameBuffer type.
@author Stephen Anthony @author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.113 2009-01-03 22:57:12 stephena Exp $ @version $Id: FrameBuffer.hxx,v 1.114 2009-01-10 18:42:49 stephena Exp $
*/ */
// Text alignment modes for drawString() // Text alignment modes for drawString()
enum TextAlignment { enum TextAlignment {