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). --- src/mesa/main/mtypes.h | 2 +- src/mesa/main/shared.c | 8 ++- src/mesa/main/texobj.c | 115 ++++++++++++++++++++++++++++++++++++---------- src/mesa/main/texobj.h | 4 +- src/mesa/main/texstate.c | 10 +++- 5 files changed, 107 insertions(+), 32 deletions(-)
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 107371e..5158100 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2419,7 +2419,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 diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c index 276fac1..f889abe 100644 --- a/src/mesa/main/shared.c +++ b/src/mesa/main/shared.c @@ -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 diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 7ee2005..112d58a 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -757,59 +757,126 @@ _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 = 4, height = 4, depth = 4; + GLubyte texels[width * height * depth][4]; struct gl_texture_object *texObj; struct gl_texture_image *texImage; gl_format texFormat; - GLuint i; + GLuint i, dims, face, numFaces = 1; + GLenum target; - for (i = 0; i < 8 * 8; i++) { + for (i = 0; i < width * height * depth; i++) { texels[i][0] = texels[i][1] = texels[i][2] = 0x0; texels[i][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); 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); - - /* set image data */ - ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA, - 8, 8, 0, - GL_RGBA, GL_UNSIGNED_BYTE, texels, - &ctx->DefaultPacking); + if (target == GL_TEXTURE_CUBE_MAP) + faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + else + faceTarget = target; + + /* 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, texels, + &ctx->DefaultPacking); + break; + case 2: + ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA, + width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texels, + &ctx->DefaultPacking); + break; + case 3: + ctx->Driver.TexImage3D(ctx, texImage, GL_RGBA, + width, height, depth, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texels, + &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]; } diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index 9ca7a4c..03dfbe3 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -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 ); diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 7cd2858..351a556 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -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) (_mesa_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 */ -- 1.7.3.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev