mesa: fix _mesa_get_fallback_texture() to handle all texture targets
authorBrian Paul <brianp@vmware.com>
Wed, 4 Jan 2012 21:55:32 +0000 (14:55 -0700)
committerBrian Paul <brianp@vmware.com>
Wed, 15 Feb 2012 21:07:43 +0000 (14:07 -0700)
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>
src/mesa/main/mtypes.h
src/mesa/main/shared.c
src/mesa/main/texobj.c
src/mesa/main/texobj.h
src/mesa/main/texstate.c

index 5ef97c86c151c51e80475b18ccdab00b6d1d299c..9200f3fc4c19291748d6811d8e01d14375a95c49 100644 (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
index c07ce8238469a7ebe6c8ddaeffd3aaca32627422..226947638cad4667395c44ac0559863b70f55980 100644 (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
index 1b61d3a63f49574eca75021671f68e9d663ceef4..59059482626397c864cdf6e1cb5faafec3c15db3 100644 (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;
-
-      for (i = 0; i < 8 * 8; i++) {
-         texels[i][0] =
-         texels[i][1] =
-         texels[i][2] = 0x0;
-         texels[i][3] = 0xff;
+      GLuint dims, face, numFaces = 1;
+      GLenum target;
+
+      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);
-
-      /* 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, 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];
 }
 
 
index 9ca7a4c9e11834cdd3fbcff23340d1b145af9e8b..03dfbe3045d3f29694e207469092e8b3f6f0d5fd 100644 (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 );
index cc49916a92cb22709855c1751b888f6ec3afbba2..187ec9c366f453983ffe9dd8b2e16f09512df584 100644 (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 */