# Fix water-related crash on some video drivers

Detect some errors loading fancy-water fragment shader, and disable
fancy water.
Fixes crash with Mesa on 945GM (which doesn't support fragment shaders,
though it advertises the extensions).

This was SVN commit r6773.
This commit is contained in:
Ykkrosh 2009-03-24 21:00:41 +00:00
parent 45b734c08a
commit 228859da99
4 changed files with 32 additions and 5 deletions

View File

@ -299,11 +299,12 @@ void ogl_WarnIfError()
// this is useful for suppressing annoying error messages, e.g.
// "invalid enum" for GL_CLAMP_TO_EDGE even though we've already
// warned the user that their OpenGL implementation is too old.
void ogl_SquelchError(GLenum err_to_ignore)
bool ogl_SquelchError(GLenum err_to_ignore)
{
// glGetError may return multiple errors, so we poll it in a loop.
// the debug_printf should only happen once (if this is set), though.
bool error_enountered = false;
bool error_ignored = false;
GLenum first_error = 0;
for(;;)
@ -313,7 +314,10 @@ void ogl_SquelchError(GLenum err_to_ignore)
break;
if(err == err_to_ignore)
{
error_ignored = true;
continue;
}
if(!error_enountered)
first_error = err;
@ -328,6 +332,8 @@ void ogl_SquelchError(GLenum err_to_ignore)
snprintf(msg, ARRAY_SIZE(msg), "OpenGL error(s) occurred: %04x", (int)first_error);
debug_printf(msg);
}
return error_ignored;
}

View File

@ -153,8 +153,9 @@ extern void ogl_WarnIfError(void);
* different error is pending, those are reported immediately.
*
* @param err_to_ignore: one of the glGetError enums.
* @return true if the requested error was seen and ignored
**/
extern void ogl_SquelchError(GLenum err_to_ignore);
extern bool ogl_SquelchError(GLenum err_to_ignore);
//-----------------------------------------------------------------------------

View File

@ -117,7 +117,14 @@ static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const VfsPath& pathname, Han
const GLchar* strings[] = { (const GLchar*)file.get() };
const GLint tmp = (GLint)file_size;
pglShaderSourceARB(shdr->id, 1, strings, &tmp);
// Some drivers (Mesa i915 on 945GM) give GL_INVALID_ENUM after calling
// CompileShader on a GL_FRAGMENT_PROGRAM, because the hardware doesn't support
// fragment programs. I can't find a better way to detect that situation in advance,
// so detect the error afterwards and return failure.
ogl_WarnIfError();
pglCompileShaderARB(shdr->id);
if(ogl_SquelchError(GL_INVALID_ENUM))
goto fail_shadercreated;
}
GLint log_length;
@ -152,7 +159,7 @@ static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const VfsPath& pathname, Han
pathname.string().c_str(),
shader_type_to_string(shdr->type, typenamebuf, ARRAY_SIZE(typenamebuf)));
err = ERR::SHDR_COMPILE;
err = ERR::SHDR_COMPILE;
goto fail_shadercreated;
}

View File

@ -17,6 +17,7 @@
#include "maths/MathUtil.h"
#include "ps/CLogger.h"
#include "ps/Game.h"
#include "ps/Profile.h"
#include "ps/Pyrogenesis.h" // MICROLOG
@ -32,6 +33,8 @@
#include "lib/res/graphics/ogl_shader.h"
#define LOG_CATEGORY "graphics"
///////////////////////////////////////////////////////////////////////////////////////////////
// TerrainRenderer implementation
@ -327,7 +330,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
pglActiveTextureARB(GL_TEXTURE0);
pglClientActiveTextureARB(GL_TEXTURE0);
for (size_t i = 0; i < m->visiblePatches.size(); ++i)
{
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
@ -398,7 +401,17 @@ void TerrainRenderer::RenderWater()
// If we're using fancy water, make sure its shader is loaded
if(fancy && !m->fancyWaterShader)
{
m->fancyWaterShader = ogl_program_load( "shaders/water_high.xml" );
Handle h = ogl_program_load("shaders/water_high.xml");
if (h < 0)
{
LOG(CLogger::Error, LOG_CATEGORY, "Failed to load water shader. Falling back to non-fancy water.\n");
g_Renderer.m_Options.m_FancyWater = false;
fancy = false;
}
else
{
m->fancyWaterShader = h;
}
}
//(Crappy) fresnel effect