Fixed incorrect initialization of certain OpenGL function pointers.

Basically, the OpenGL class can use functions from several different
versions of OpenGL (1.3 and 2.0+), and all sections of code need to
be wrapped in IF statements to make sure we don't use a function
pointer that is NULL.  Basically, this means that all GLSL/2.0+
stuff needs to be wrapped in 'if(myTvFiltersEnabled) ...'.

This actually lays the groundwork for the next feature I'll be
adding (frame buffer objects), since those require yet another
level of OpenGL functions that may not be available everywhere.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1816 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-06-24 11:28:07 +00:00
parent 1275c25681
commit 79fdcb3480
1 changed files with 183 additions and 155 deletions

View File

@ -59,6 +59,7 @@ OGL_DECLARE(void,glPixelStorei,(GLenum, GLint));
OGL_DECLARE(void,glTexEnvf,(GLenum, GLenum, GLfloat));
OGL_DECLARE(void,glGenTextures,(GLsizei, GLuint*));
OGL_DECLARE(void,glDeleteTextures,(GLsizei, const GLuint*));
OGL_DECLARE(void,glActiveTexture,(GLenum));
OGL_DECLARE(void,glBindTexture,(GLenum, GLuint));
OGL_DECLARE(void,glTexImage2D,(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*));
OGL_DECLARE(void,glTexSubImage2D,(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*));
@ -77,7 +78,6 @@ OGL_DECLARE(void,glUniform1i,(GLint, GLint));
OGL_DECLARE(void,glUniform1f,(GLint, GLfloat));
OGL_DECLARE(void,glCopyTexImage2D,(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint));
OGL_DECLARE(void,glCopyTexSubImage2D,(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei));
OGL_DECLARE(void,glActiveTexture,(GLenum));
OGL_DECLARE(void,glGetIntegerv,(GLenum, GLint*));
OGL_DECLARE(void,glTexEnvi,(GLenum, GLenum, GLint));
OGL_DECLARE(void,glMultiTexCoord2f,(GLenum, GLfloat, GLfloat));
@ -163,6 +163,7 @@ bool FrameBufferGL::loadFuncs(GLFunctionality functionality)
OGL_INIT(void,glTexEnvf,(GLenum, GLenum, GLfloat));
OGL_INIT(void,glGenTextures,(GLsizei, GLuint*));
OGL_INIT(void,glDeleteTextures,(GLsizei, const GLuint*));
OGL_INIT(void,glActiveTexture,(GLenum));
OGL_INIT(void,glBindTexture,(GLenum, GLuint));
OGL_INIT(void,glTexImage2D,(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*));
OGL_INIT(void,glTexSubImage2D,(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*));
@ -184,7 +185,6 @@ bool FrameBufferGL::loadFuncs(GLFunctionality functionality)
OGL_INIT(void,glUniform1f,(GLint, GLfloat));
OGL_INIT(void,glCopyTexImage2D,(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint));
OGL_INIT(void,glCopyTexSubImage2D,(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei));
OGL_INIT(void,glActiveTexture,(GLenum));
OGL_INIT(void,glGetIntegerv,(GLenum, GLint*));
OGL_INIT(void,glTexEnvi,(GLenum, GLenum, GLint));
OGL_INIT(void,glMultiTexCoord2f,(GLenum, GLfloat, GLfloat));
@ -359,7 +359,7 @@ bool FrameBufferGL::setVidMode(VideoMode& mode)
myGLVersion = atof(version.substr(0, 3).c_str());
// TV effects depend on the GLSL functions being available
myGLSLAvailable = myGLVersion >= 2.0 && loadFuncs(kGL_SHADER);
myGLSLAvailable = loadFuncs(kGL_SHADER);
}
else
return false;
@ -429,7 +429,12 @@ cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl
// and other UI surfaces are no longer tied together
// Note that this may change in the future, when we add more
// complex filters/scalers, but for now it's fine
//
// Also note that TV filtering is only available with OpenGL 2.0+
// The hint we provide here is only that GLSL is available and
// TV effects *can* be applied to this surface
// The specific TV effect settings still determine whether any
// filtering *will* be applied in such a case
myTiaSurface = new FBSurfaceGL(*this, baseWidth>>1, baseHeight,
mode.image_w, mode.image_h,
myGLSLAvailable);
@ -587,7 +592,7 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
myPhosphorProgram(0),
myTextureNoiseProgram(0),
myNoiseNum(0),
myTvFiltersEnabled(allowFiltering)
myTvFiltersEnabled(false)
{
// Fill buffer struct with valid data
// This changes depending on the texturing used
@ -620,6 +625,19 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
myPitch = myTexture->pitch >> 1;
// The 'allowFiltering' boolean is only a hint that filtering is allowed
// on this surface
// We still need to check if the functionality exists to do it
if(allowFiltering)
{
// It's only enabled if we use one of the filters *AND* GLSL is available
myTvFiltersEnabled = myFB.myGLSLAvailable &&
(myFB.myUseTexture || myFB.myUseNoise ||
myFB.myUseBleed || myFB.myUseGLPhosphor);
}
else
myTvFiltersEnabled = false;
// Only do this if TV filters enabled, otherwise it won't be used anyway
if(myTvFiltersEnabled)
{
@ -643,11 +661,10 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
myFilterTexCoord[2] = (GLfloat) scaleWidth / myFilterTexWidth;
myFilterTexCoord[1] = (GLfloat) scaleHeight / myFilterTexHeight;
}
}
// Only do this if TV and color bleed filters are enabled
// This filer applies a color averaging of surrounding pixels for each pixel
if(myTvFiltersEnabled && myFB.myUseBleed)
if(myFB.myUseBleed)
{
// Load shader programs. If it fails, don't use this filter.
myBleedProgram = genShader(SHADER_BLEED);
@ -662,7 +679,7 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
// Make sure we can use three textures at once first
GLint texUnits;
p_glGetIntegerv(GL_MAX_TEXTURE_UNITS, &texUnits);
if(myTvFiltersEnabled && texUnits >= 3 && myFB.myUseTexture && myFB.myUseNoise)
if(texUnits >= 3 && myFB.myUseTexture && myFB.myUseNoise)
{
// Load shader program. If it fails, don't use this shader.
myTextureNoiseProgram = genShader(SHADER_TEXNOISE);
@ -688,7 +705,7 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
}
}
// Else, detect individual settings
else if(myTvFiltersEnabled)
else
{
if(myFB.myUseTexture)
{
@ -714,8 +731,8 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
}
// Only do this if TV and color texture filters are enabled
// This filer applies an RGB color pixel mask as well as a blackspace mask
if(myTvFiltersEnabled && myFB.myUseTexture)
// This filter applies an RGB color pixel mask as well as a blackspace mask
if(myFB.myUseTexture)
{
// Prepare subpixel texture
mySubpixelTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
@ -751,7 +768,7 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
// Only do this if TV and noise filters are enabled
// This filter applies a texture filled with gray pixel of random intensities
if(myTvFiltersEnabled && myFB.myUseNoise)
if(myFB.myUseNoise)
{
// Get the current number of nose textures to use
myNoiseNum = myFB.myNoiseQuality;
@ -801,7 +818,7 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
// Only do this if TV and phosphor filters are enabled
// This filter merges the past screen with the current one, to give a phosphor burn-off effect
if(myTvFiltersEnabled && myFB.myUseGLPhosphor)
if(myFB.myUseGLPhosphor)
{
// Load shader program. If it fails, don't use this filter.
myPhosphorProgram = genShader(SHADER_PHOS);
@ -811,6 +828,14 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
cout << "ERROR: Failed to make phosphor program" << endl;
}
}
}
// Check to see if filters should still be used
// Filtering must have been previously enabled, and GLSL must still be
// available
myTvFiltersEnabled = myTvFiltersEnabled && myFB.myGLSLAvailable &&
(myFB.myUseTexture || myFB.myUseNoise ||
myFB.myUseBleed || myFB.myUseGLPhosphor);
// Associate the SDL surface with a GL texture object
reload();
@ -1025,11 +1050,8 @@ void FBSurfaceGL::update()
bool firstRender = true;
// Render as usual if no filters are used
if(!myTvFiltersEnabled ||
(!myFB.myUseTexture && !myFB.myUseNoise && !myFB.myUseBleed && !myFB.myUseGLPhosphor))
if(!myTvFiltersEnabled)
{
p_glUseProgram(0);
// Texturemap complete texture to surface so we have free scaling
// and antialiasing
p_glActiveTexture(GL_TEXTURE0);
@ -1054,6 +1076,7 @@ void FBSurfaceGL::update()
}
// If TV filters are enabled
// TODO - check if this IF is necessary, or can it be chained by else to above
if(myTvFiltersEnabled)
{
// If combined texture/noise program exists,
@ -1205,6 +1228,11 @@ void FBSurfaceGL::update()
// We have rendered, set firstRender to false
firstRender = false;
}
// Disable all shader programs for the next rendering pass
// This is placed here since it's a GLSL 2.0-specific function, and
// doesn't exist (and isn't required) for base OpenGL functionality
p_glUseProgram(0);
}
mySurfaceIsDirty = false;