mesa: fix _mesa_get_fallback_texture() to handle all texture targets

Previously, this function only handled 2D textures.

The fallback texture is used when we try to sample from an incomplete
texture object.  GLSL says sampling an incomplete texture should return
(0,0,0,1).

v2: use a 1-texel texture image, per José.

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
Brian Paul
2012-01-04 14:55:32 -07:00
parent 447071cfb0
commit c04db7f7fa
5 changed files with 111 additions and 35 deletions

View File

@@ -2483,7 +2483,7 @@ struct gl_shared_state
struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
/** Fallback texture used when a bound texture is incomplete */
struct gl_texture_object *FallbackTex;
struct gl_texture_object *FallbackTex[NUM_TEXTURE_TARGETS];
/**
* \name Thread safety and statechange notification for texture

View File

@@ -307,9 +307,11 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
{
GLuint i;
/* Free the dummy/fallback texture object */
if (shared->FallbackTex)
ctx->Driver.DeleteTexture(ctx, shared->FallbackTex);
/* Free the dummy/fallback texture objects */
for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
if (shared->FallbackTex[i])
ctx->Driver.DeleteTexture(ctx, shared->FallbackTex[i]);
}
/*
* Free display lists

View File

@@ -759,59 +759,127 @@ _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
/**
* 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
* Return pointer to a default/fallback texture of the given type/target.
* The texture is an RGBA texture with all texels = (0,0,0,1).
* That's the value a GLSL sampler should get when sampling from an
* incomplete texture.
*/
struct gl_texture_object *
_mesa_get_fallback_texture(struct gl_context *ctx)
_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
{
if (!ctx->Shared->FallbackTex) {
if (!ctx->Shared->FallbackTex[tex]) {
/* create fallback texture now */
static GLubyte texels[8 * 8][4];
const GLsizei width = 1, height = 1, depth = 1;
GLubyte texel[4];
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
gl_format texFormat;
GLuint i;
GLuint dims, face, numFaces = 1;
GLenum target;
for (i = 0; i < 8 * 8; i++) {
texels[i][0] =
texels[i][1] =
texels[i][2] = 0x0;
texels[i][3] = 0xff;
texel[0] =
texel[1] =
texel[2] = 0x0;
texel[3] = 0xff;
switch (tex) {
case TEXTURE_2D_ARRAY_INDEX:
dims = 3;
target = GL_TEXTURE_2D_ARRAY;
break;
case TEXTURE_1D_ARRAY_INDEX:
dims = 2;
target = GL_TEXTURE_1D_ARRAY;
break;
case TEXTURE_CUBE_INDEX:
dims = 2;
target = GL_TEXTURE_CUBE_MAP;
numFaces = 6;
break;
case TEXTURE_3D_INDEX:
dims = 3;
target = GL_TEXTURE_3D;
break;
case TEXTURE_RECT_INDEX:
dims = 2;
target = GL_TEXTURE_RECTANGLE;
break;
case TEXTURE_2D_INDEX:
dims = 2;
target = GL_TEXTURE_2D;
break;
case TEXTURE_1D_INDEX:
dims = 1;
target = GL_TEXTURE_1D;
break;
case TEXTURE_BUFFER_INDEX:
case TEXTURE_EXTERNAL_INDEX:
default:
/* no-op */
return NULL;
}
/* create texture object */
texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
if (!texObj)
return NULL;
assert(texObj->RefCount == 1);
texObj->Sampler.MinFilter = GL_NEAREST;
texObj->Sampler.MagFilter = GL_NEAREST;
/* create level[0] texture image */
texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
texFormat = ctx->Driver.ChooseTextureFormat(ctx, GL_RGBA, GL_RGBA,
GL_UNSIGNED_BYTE);
/* init the image fields */
_mesa_init_teximage_fields(ctx, texImage,
8, 8, 1, 0, GL_RGBA, texFormat);
/* need a loop here just for cube maps */
for (face = 0; face < numFaces; face++) {
GLenum faceTarget;
ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
if (target == GL_TEXTURE_CUBE_MAP)
faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
else
faceTarget = target;
/* set image data */
ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA,
8, 8, 0,
GL_RGBA, GL_UNSIGNED_BYTE, texels,
&ctx->DefaultPacking);
/* initialize level[0] texture image */
texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
_mesa_init_teximage_fields(ctx, texImage,
width,
(dims > 1) ? height : 1,
(dims > 2) ? depth : 1,
0, /* border */
GL_RGBA, texFormat);
switch (dims) {
case 1:
ctx->Driver.TexImage1D(ctx, texImage, GL_RGBA,
width, 0,
GL_RGBA, GL_UNSIGNED_BYTE, texel,
&ctx->DefaultPacking);
break;
case 2:
ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA,
width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, texel,
&ctx->DefaultPacking);
break;
case 3:
ctx->Driver.TexImage3D(ctx, texImage, GL_RGBA,
width, height, depth, 0,
GL_RGBA, GL_UNSIGNED_BYTE, texel,
&ctx->DefaultPacking);
break;
default:
_mesa_problem(ctx, "bad dims in _mesa_get_fallback_texture()");
}
}
_mesa_test_texobj_completeness(ctx, texObj);
assert(texObj->_Complete);
ctx->Shared->FallbackTex = texObj;
ctx->Shared->FallbackTex[tex] = texObj;
}
return ctx->Shared->FallbackTex;
return ctx->Shared->FallbackTex[tex];
}

View File

@@ -34,8 +34,8 @@
#include "compiler.h"
#include "glheader.h"
#include "mtypes.h"
struct gl_context;
/**
* \name Internal functions
@@ -89,7 +89,7 @@ _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
GLboolean invalidate_state);
extern struct gl_texture_object *
_mesa_get_fallback_texture(struct gl_context *ctx);
_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex);
extern void
_mesa_unlock_context_textures( struct gl_context *ctx );

View File

@@ -586,9 +586,15 @@ update_texture_state( struct gl_context *ctx )
* 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;
struct gl_texture_object *texObj;
gl_texture_index texTarget;
assert(_mesa_bitcount(enabledTargets) == 1);
texTarget = (gl_texture_index) (ffs(enabledTargets) - 1);
texObj = _mesa_get_fallback_texture(ctx, texTarget);
_mesa_reference_texobj(&texUnit->_Current, texObj);
texUnit->_ReallyEnabled = 1 << texTarget;
}
else {
/* fixed-function: texture unit is really disabled */