mesa: create/use a fallback texture when bound texture is incomplete

When a GLSL sampler reads from an incomplete texture it should
return (0,0,0,1).  Instead of jumping through hoops in all the drivers
to make this happen, just create/install a fallback texture with those
texel values.

Fixes piglit/fp-incomplete-tex on i965 and more importantly, fixes some
GPU lockups when trying to sample from missing surfaces.  If a binding
table entry is NULL, it seems that sampling sometimes works, but not
always (lockup).

Todo: create a fallback texture for each type of texture target?
(cherry picked from commit 3f25219c7b)
This commit is contained in:
Brian Paul
2009-05-01 09:30:32 -06:00
committed by Ian Romanick
parent abfd56c24c
commit 00e203fe17
4 changed files with 66 additions and 2 deletions

View File

@@ -2053,6 +2053,9 @@ struct gl_shared_state
/** Default texture objects (shared by all texture units) */
struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
/** Fallback texture used when a bound texture is incomplete */
struct gl_texture_object *FallbackTex;
/**
* \name Thread safety and statechange notification for texture
* objects.

View File

@@ -662,6 +662,59 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
}
}
/**
* Return pointer to a default/fallback texture.
* The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
* That's the value a sampler should get when sampling from an
* incomplete texture.
*/
struct gl_texture_object *
_mesa_get_fallback_texture(GLcontext *ctx)
{
if (!ctx->Shared->FallbackTex) {
/* create fallback texture now */
static GLubyte texels[8 * 8][4];
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLuint i;
for (i = 0; i < 8 * 8; i++) {
texels[i][0] =
texels[i][1] =
texels[i][2] = 0x0;
texels[i][3] = 0xff;
}
/* create texture object */
texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
assert(texObj->RefCount == 1);
texObj->MinFilter = GL_NEAREST;
texObj->MagFilter = GL_NEAREST;
/* create level[0] texture image */
texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
/* init the image fields */
_mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
8, 8, 1, 0, GL_RGBA);
/* set image data */
ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
8, 8, 0,
GL_RGBA, GL_UNSIGNED_BYTE, texels,
&ctx->DefaultPacking, texObj, texImage);
_mesa_test_texobj_completeness(ctx, texObj);
assert(texObj->_Complete);
ctx->Shared->FallbackTex = texObj;
}
return ctx->Shared->FallbackTex;
}
/*@}*/

View File

@@ -65,6 +65,9 @@ extern void
_mesa_test_texobj_completeness( const GLcontext *ctx,
struct gl_texture_object *obj );
extern struct gl_texture_object *
_mesa_get_fallback_texture(GLcontext *ctx);
extern void
_mesa_unlock_context_textures( GLcontext *ctx );

View File

@@ -561,8 +561,13 @@ update_texture_state( GLcontext *ctx )
}
if (!texUnit->_ReallyEnabled) {
_mesa_reference_texobj(&texUnit->_Current, NULL);
continue;
/* If we get here it means the shader (or fixed-function state)
* is expecting a texture object, but there isn't one (or it's
* incomplete). Use the fallback texture.
*/
struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
_mesa_reference_texobj(&texUnit->_Current, texObj);
}
/* if we get here, we know this texture unit is enabled */