mesa: fix potential mem leak in generate_mipmap_compressed()
[mesa.git] / src / mesa / main / texobj.c
index 0e84b8744119d450a63a6d110fd9e029f18113e8..17c78ce3e6382200548bd3c141928da31d1e0fb4 100644 (file)
@@ -107,6 +107,7 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
           target == GL_TEXTURE_RECTANGLE_NV ||
           target == GL_TEXTURE_1D_ARRAY_EXT ||
           target == GL_TEXTURE_2D_ARRAY_EXT ||
+          target == GL_TEXTURE_EXTERNAL_OES ||
           target == GL_TEXTURE_BUFFER);
 
    memset(obj, 0, sizeof(*obj));
@@ -119,8 +120,12 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
    obj->BaseLevel = 0;
    obj->MaxLevel = 1000;
 
+   /* must be one; no support for (YUV) planes in separate buffers */
+   obj->RequiredTextureImageUnits = 1;
+
    /* sampler state */
-   if (target == GL_TEXTURE_RECTANGLE_NV) {
+   if (target == GL_TEXTURE_RECTANGLE_NV ||
+       target == GL_TEXTURE_EXTERNAL_OES) {
       obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
       obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
       obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
@@ -161,7 +166,8 @@ finish_texture_init(struct gl_context *ctx, GLenum target,
 {
    assert(obj->Target == 0);
 
-   if (target == GL_TEXTURE_RECTANGLE_NV) {
+   if (target == GL_TEXTURE_RECTANGLE_NV ||
+       target == GL_TEXTURE_EXTERNAL_OES) {
       /* have to init wrap and filter state here - kind of klunky */
       obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
       obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
@@ -198,13 +204,11 @@ _mesa_delete_texture_object(struct gl_context *ctx,
     */
    texObj->Target = 0x99;
 
-   _mesa_free_colortable_data(&texObj->Palette);
-
    /* free the texture images */
    for (face = 0; face < 6; face++) {
       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
          if (texObj->Image[face][i]) {
-            _mesa_delete_texture_image( ctx, texObj->Image[face][i] );
+            ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]);
          }
       }
    }
@@ -258,10 +262,11 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
    dest->_MaxLevel = src->_MaxLevel;
    dest->_MaxLambda = src->_MaxLambda;
    dest->GenerateMipmap = src->GenerateMipmap;
-   dest->Palette = src->Palette;
    dest->_Complete = src->_Complete;
    COPY_4V(dest->Swizzle, src->Swizzle);
    dest->_Swizzle = src->_Swizzle;
+
+   dest->RequiredTextureImageUnits = src->RequiredTextureImageUnits;
 }
 
 
@@ -309,6 +314,7 @@ valid_texture_object(const struct gl_texture_object *tex)
    case GL_TEXTURE_1D_ARRAY_EXT:
    case GL_TEXTURE_2D_ARRAY_EXT:
    case GL_TEXTURE_BUFFER:
+   case GL_TEXTURE_EXTERNAL_OES:
       return GL_TRUE;
    case 0x99:
       _mesa_problem(NULL, "invalid reference to a deleted texture object");
@@ -325,16 +331,14 @@ valid_texture_object(const struct gl_texture_object *tex)
  * Reference (or unreference) a texture object.
  * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
  * If 'tex' is non-null, increment its refcount.
+ * This is normally only called from the _mesa_reference_texobj() macro
+ * when there's a real pointer change.
  */
 void
-_mesa_reference_texobj(struct gl_texture_object **ptr,
-                       struct gl_texture_object *tex)
+_mesa_reference_texobj_(struct gl_texture_object **ptr,
+                        struct gl_texture_object *tex)
 {
    assert(ptr);
-   if (*ptr == tex) {
-      /* no change */
-      return;
-   }
 
    if (*ptr) {
       /* Unreference the old texture */
@@ -471,7 +475,8 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx,
                      t->Image[0][baseLevel]->HeightLog2);
       maxLevels = ctx->Const.MaxCubeTextureLevels;
    }
-   else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
+   else if (t->Target == GL_TEXTURE_RECTANGLE_NV ||
+            t->Target == GL_TEXTURE_EXTERNAL_OES) {
       maxLog2 = 0;  /* not applicable */
       maxLevels = 1;  /* no mipmapping */
    }
@@ -495,6 +500,15 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx,
    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
    t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
 
+   if (t->Immutable) {
+      /* This texture object was created with glTexStorage1/2/3D() so we
+       * know that all the mipmap levels are the right size and all cube
+       * map faces are the same size.
+       * We don't need to do any of the additional checks below.
+       */
+      return;
+   }
+
    if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
       /* make sure that all six cube map level 0 images are the same size */
       const GLuint w = t->Image[0][baseLevel]->Width2;
@@ -548,12 +562,13 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx,
                width /= 2;
             }
             if (i >= minLevel && i <= maxLevel) {
-               if (!t->Image[0][i]) {
-                  incomplete(t, "1D Image[0][i] == NULL");
+               const struct gl_texture_image *img = t->Image[0][i];
+               if (!img) {
+                  incomplete(t, "1D Image[%d] is missing", i);
                   return;
                }
-               if (t->Image[0][i]->Width2 != width ) {
-                  incomplete(t, "1D Image[0][i] bad width");
+               if (img->Width2 != width ) {
+                  incomplete(t, "1D Image[%d] bad width %u", i, img->Width2);
                   return;
                }
             }
@@ -575,16 +590,17 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx,
                height /= 2;
             }
             if (i >= minLevel && i <= maxLevel) {
-               if (!t->Image[0][i]) {
-                  incomplete(t, "2D Image[0][i] == NULL");
+               const struct gl_texture_image *img = t->Image[0][i];
+               if (!img) {
+                  incomplete(t, "2D Image[%d of %d] is missing", i, maxLevel);
                   return;
                }
-               if (t->Image[0][i]->Width2 != width) {
-                  incomplete(t, "2D Image[0][i] bad width");
+               if (img->Width2 != width) {
+                  incomplete(t, "2D Image[%d] bad width %u", i, img->Width2);
                   return;
                }
-               if (t->Image[0][i]->Height2 != height) {
-                  incomplete(t, "2D Image[0][i] bad height");
+               if (img->Height2 != height) {
+                  incomplete(t, "2D Image[i] bad height %u", i, img->Height2);
                   return;
                }
                if (width==1 && height==1) {
@@ -609,24 +625,25 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx,
                depth /= 2;
             }
             if (i >= minLevel && i <= maxLevel) {
-               if (!t->Image[0][i]) {
-                  incomplete(t, "3D Image[0][i] == NULL");
+               const struct gl_texture_image *img = t->Image[0][i];
+               if (!img) {
+                  incomplete(t, "3D Image[%d] is missing", i);
                   return;
                }
-               if (t->Image[0][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
+               if (img->_BaseFormat == GL_DEPTH_COMPONENT) {
                   incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
                   return;
                }
-               if (t->Image[0][i]->Width2 != width) {
-                  incomplete(t, "3D Image[0][i] bad width");
+               if (img->Width2 != width) {
+                  incomplete(t, "3D Image[%d] bad width %u", i, img->Width2);
                   return;
                }
-               if (t->Image[0][i]->Height2 != height) {
-                  incomplete(t, "3D Image[0][i] bad height");
+               if (img->Height2 != height) {
+                  incomplete(t, "3D Image[%d] bad height %u", i, img->Height2);
                   return;
                }
-               if (t->Image[0][i]->Depth2 != depth) {
-                  incomplete(t, "3D Image[0][i] bad depth");
+               if (img->Depth2 != depth) {
+                  incomplete(t, "3D Image[%d] bad depth %u", i, img->Depth2);
                   return;
                }
             }
@@ -844,7 +861,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures )
       struct gl_texture_object *texObj;
       GLuint name = first + i;
       GLenum target = 0;
-      texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
+      texObj = ctx->Driver.NewTextureObject(ctx, name, target);
       if (!texObj) {
          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
@@ -1003,6 +1020,8 @@ target_enum_to_index(GLenum target)
       return TEXTURE_2D_ARRAY_INDEX;
    case GL_TEXTURE_BUFFER_ARB:
       return TEXTURE_BUFFER_INDEX;
+   case GL_TEXTURE_EXTERNAL_OES:
+      return TEXTURE_EXTERNAL_INDEX;
    default:
       return -1;
    }
@@ -1068,7 +1087,7 @@ _mesa_BindTexture( GLenum target, GLuint texName )
       }
       else {
          /* if this is a new texture id, allocate a texture object now */
-         newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target);
+         newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
          if (!newTexObj) {
             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
             return;
@@ -1110,7 +1129,7 @@ _mesa_BindTexture( GLenum target, GLuint texName )
 
    /* Pass BindTexture call to device driver */
    if (ctx->Driver.BindTexture)
-      (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
+      ctx->Driver.BindTexture(ctx, target, newTexObj);
 }