mesa: Fix core GL genned-name handling for glBeginQuery().
[mesa.git] / src / mesa / main / mipmap.c
index fd6e582ec92a2d2ba850b3712b54c753621595cb..a2f3767a327177d3d8ac02d19e6f95661797b0c7 100644 (file)
 
 #include "imports.h"
 #include "formats.h"
+#include "glformats.h"
 #include "mipmap.h"
 #include "mtypes.h"
 #include "teximage.h"
+#include "texobj.h"
 #include "texstore.h"
 #include "image.h"
 #include "macros.h"
@@ -476,7 +478,7 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
       GLuint *dst = (GLuint *) dstRow;
       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
            i++, j += colStride, k += colStride) {
-         dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4);
+         dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
       }
    }
 
@@ -991,7 +993,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
       }
    }
    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) {
-      DECLARE_ROW_POINTERS(GLhalfARB, 4);
+      DECLARE_ROW_POINTERS(GLhalfARB, 3);
 
       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
            i++, j += colStride, k += colStride) {
@@ -1001,7 +1003,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
       }
    }
    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) {
-      DECLARE_ROW_POINTERS(GLhalfARB, 4);
+      DECLARE_ROW_POINTERS(GLhalfARB, 2);
 
       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
            i++, j += colStride, k += colStride) {
@@ -1010,7 +1012,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
       }
    }
    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) {
-      DECLARE_ROW_POINTERS(GLhalfARB, 4);
+      DECLARE_ROW_POINTERS(GLhalfARB, 1);
 
       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
            i++, j += colStride, k += colStride) {
@@ -1803,6 +1805,80 @@ next_mipmap_level_size(GLenum target, GLint border,
    }
 }
 
+
+/**
+ * Helper function for mipmap generation.
+ * Make sure the specified destination mipmap level is the right size/format
+ * for mipmap generation.  If not, (re) allocate it.
+ * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop
+ */
+GLboolean
+_mesa_prepare_mipmap_level(struct gl_context *ctx,
+                           struct gl_texture_object *texObj, GLuint level,
+                           GLsizei width, GLsizei height, GLsizei depth,
+                           GLsizei border, GLenum intFormat, gl_format format)
+{
+   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
+   GLuint face;
+
+   if (texObj->Immutable) {
+      /* The texture was created with glTexStorage() so the number/size of
+       * mipmap levels is fixed and the storage for all images is already
+       * allocated.
+       */
+      if (!texObj->Image[0][level]) {
+         /* No more levels to create - we're done */
+         return GL_FALSE;
+      }
+      else {
+         /* Nothing to do - the texture memory must have already been
+          * allocated to the right size so we're all set.
+          */
+         return GL_TRUE;
+      }
+   }
+
+   for (face = 0; face < numFaces; face++) {
+      struct gl_texture_image *dstImage;
+      GLenum target;
+
+      if (numFaces == 1)
+         target = texObj->Target;
+      else
+         target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+
+      dstImage = _mesa_get_tex_image(ctx, texObj, target, level);
+      if (!dstImage) {
+         /* out of memory */
+         return GL_FALSE;
+      }
+
+      if (dstImage->Width != width ||
+          dstImage->Height != height ||
+          dstImage->Depth != depth ||
+          dstImage->Border != border ||
+          dstImage->InternalFormat != intFormat ||
+          dstImage->TexFormat != format) {
+         /* need to (re)allocate image */
+         ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
+
+         _mesa_init_teximage_fields(ctx, dstImage,
+                                    width, height, depth,
+                                    border, intFormat, format);
+
+         ctx->Driver.AllocTextureImageBuffer(ctx, dstImage);
+
+         /* in case the mipmap level is part of an FBO: */
+         _mesa_update_fbo_texture(ctx, texObj, face, level);
+
+         ctx->NewState |= _NEW_TEXTURE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
 static void
 generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
                             struct gl_texture_object *texObj,
@@ -1841,31 +1917,20 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
       if (!nextLevel)
          return;
 
-      /* get dest gl_texture_image */
-      dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
-      if (!dstImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+      if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1,
+                                      dstWidth, dstHeight, dstDepth,
+                                      border, srcImage->InternalFormat,
+                                      srcImage->TexFormat)) {
          return;
       }
 
-      /* Free old image data */
-      ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
-
-      _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
-                                 dstDepth, border, srcImage->InternalFormat,
-                                 srcImage->TexFormat);
-
-      /* Alloc storage for new texture image */
-      if (!ctx->Driver.AllocTextureImageBuffer(ctx, dstImage,
-                                               dstImage->TexFormat,
-                                               dstWidth, dstHeight,
-                                               dstDepth)) {
+      /* get dest gl_texture_image */
+      dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
+      if (!dstImage) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
          return;
       }
 
-      ASSERT(dstImage->TexFormat);
-
       if (target == GL_TEXTURE_1D_ARRAY) {
         srcDepth = srcHeight;
         dstDepth = dstHeight;
@@ -1874,7 +1939,7 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
       }
 
       /* Map src texture image slices */
-      srcMaps = (GLubyte **) calloc(srcDepth, sizeof(GLubyte *));
+      srcMaps = calloc(srcDepth, sizeof(GLubyte *));
       if (srcMaps) {
          for (slice = 0; slice < srcDepth; slice++) {
             ctx->Driver.MapTextureImage(ctx, srcImage, slice,
@@ -1892,7 +1957,7 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
       }
 
       /* Map dst texture image slices */
-      dstMaps = (GLubyte **) calloc(dstDepth, sizeof(GLubyte *));
+      dstMaps = calloc(dstDepth, sizeof(GLubyte *));
       if (dstMaps) {
          for (slice = 0; slice < dstDepth; slice++) {
             ctx->Driver.MapTextureImage(ctx, dstImage, slice,
@@ -1988,7 +2053,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
    /* allocate storage for the temporary, uncompressed image */
    /* 20 extra bytes, just be safe when calling last FetchTexel */
    temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
-   temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20);
+   temp_src = malloc(temp_src_stride * srcImage->Height + 20);
    if (!temp_src) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
       return;
@@ -2037,7 +2102,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
 
       temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth);
       if (!temp_dst) {
-        temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight);
+        temp_dst = malloc(temp_dst_stride * dstHeight);
         if (!temp_dst) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
            break;
@@ -2052,9 +2117,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
          return;
       }
 
-      /* Free old image data */
-      ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
-
+      /* rescale src image to dest image */
       _mesa_generate_mipmap_level(target, temp_datatype, components, border,
                                   srcWidth, srcHeight, srcDepth,
                                   (const GLubyte **) &temp_src,
@@ -2062,19 +2125,19 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
                                   dstWidth, dstHeight, dstDepth,
                                   &temp_dst, temp_dst_stride);
 
-      /* initialize new image */
-      _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
-                                 dstDepth, border, srcImage->InternalFormat,
-                                 srcImage->TexFormat);
-
-      /* Free old dest texture image buffer */
-      ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
+      if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1,
+                                      dstWidth, dstHeight, dstDepth,
+                                      border, srcImage->InternalFormat,
+                                      srcImage->TexFormat)) {
+         free(temp_dst);
+         return;
+      }
 
-      ctx->Driver.TexImage2D(ctx, target, level + 1,
-                            srcImage->InternalFormat,
-                            dstWidth, dstHeight, border,
-                            temp_base_format, temp_datatype,
-                            temp_dst, &ctx->DefaultPacking, texObj, dstImage);
+      /* The image space was allocated above so use glTexSubImage now */
+      ctx->Driver.TexSubImage(ctx, 2, dstImage,
+                              0, 0, 0, dstWidth, dstHeight, 1,
+                              temp_base_format, temp_datatype,
+                              temp_dst, &ctx->DefaultPacking);
 
       /* swap src and dest pointers */
       {