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:
@@ -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.
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
|
@@ -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 );
|
||||
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user