mesa: consolidate texstore functions
authorBrian Paul <brianp@vmware.com>
Sat, 24 Dec 2011 15:54:27 +0000 (08:54 -0700)
committerBrian Paul <brianp@vmware.com>
Sat, 24 Dec 2011 16:25:41 +0000 (09:25 -0700)
The code for storing 1D, 2D and 3D tex images (whole or sub-images) was
all pretty similar.  This consolidates those six paths.

v2: rework switch statement to catch unexpected targets

Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/mesa/main/texstore.c

index fb1ad04e014162b5ce7a19a5bf629a6f7a6d997d..86c35d38f7458e5024d941a47b69ddf0279847d9 100644 (file)
@@ -4565,9 +4565,137 @@ get_read_write_mode(GLenum userFormat, gl_format texFormat)
       return GL_MAP_WRITE_BIT;
 }
 
+
+/**
+ * Helper function for storing 1D, 2D, 3D whole and subimages into texture
+ * memory.
+ * The source of the image data may be user memory or a PBO.  In the later
+ * case, we'll map the PBO, copy from it, then unmap it.
+ */
+static void
+store_texsubimage(struct gl_context *ctx,
+                  struct gl_texture_image *texImage,
+                  GLint xoffset, GLint yoffset, GLint zoffset,
+                  GLint width, GLint height, GLint depth,
+                  GLenum format, GLenum type, const GLvoid *pixels,
+                  const struct gl_pixelstore_attrib *packing,
+                  const char *caller)
+
+{
+   const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat);
+   const GLenum target = texImage->TexObject->Target;
+   GLboolean success = GL_FALSE;
+   GLuint dims, slice, numSlices = 1, sliceOffset = 0;
+   GLint srcImageStride = 0;
+   const GLubyte *src;
+
+   assert(xoffset + width <= texImage->Width);
+   assert(yoffset + height <= texImage->Height);
+   assert(zoffset + depth <= texImage->Depth);
+
+   switch (target) {
+   case GL_TEXTURE_1D:
+      dims = 1;
+      break;
+   case GL_TEXTURE_2D_ARRAY:
+   case GL_TEXTURE_3D:
+      dims = 3;
+      break;
+   default:
+      dims = 2;
+   }
+
+   /* get pointer to src pixels (may be in a pbo which we'll map here) */
+   src = (const GLubyte *)
+      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
+                                  format, type, pixels, packing, caller);
+   if (!src)
+      return;
+
+   /* compute slice info (and do some sanity checks) */
+   switch (target) {
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_RECTANGLE:
+   case GL_TEXTURE_CUBE_MAP:
+      /* one image slice, nothing special needs to be done */
+      break;
+   case GL_TEXTURE_1D:
+      assert(height == 1);
+      assert(depth == 1);
+      assert(yoffset == 0);
+      assert(zoffset == 0);
+      break;
+   case GL_TEXTURE_1D_ARRAY:
+      assert(depth == 1);
+      assert(zoffset == 0);
+      numSlices = height;
+      sliceOffset = yoffset;
+      height = 1;
+      yoffset = 0;
+      srcImageStride = _mesa_image_row_stride(packing, width, format, type);
+      break;
+   case GL_TEXTURE_2D_ARRAY:
+      numSlices = depth;
+      sliceOffset = zoffset;
+      depth = 1;
+      zoffset = 0;
+      srcImageStride = _mesa_image_image_stride(packing, width, height,
+                                                format, type);
+      break;
+   case GL_TEXTURE_3D:
+      /* we'll store 3D images as a series of slices */
+      numSlices = depth;
+      sliceOffset = zoffset;
+      srcImageStride = _mesa_image_image_stride(packing, width, height,
+                                                format, type);
+      break;
+   default:
+      _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target);
+      return;
+   }
+
+   assert(numSlices == 1 || srcImageStride != 0);
+
+   for (slice = 0; slice < numSlices; slice++) {
+      GLubyte *dstMap;
+      GLint dstRowStride;
+
+      ctx->Driver.MapTextureImage(ctx, texImage,
+                                  slice + sliceOffset,
+                                  xoffset, yoffset, width, height,
+                                  mapMode, &dstMap, &dstRowStride);
+      if (dstMap) {
+         /* Note: we're only storing a 2D (or 1D) slice at a time but we need
+          * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
+          * used for 3D images.
+          */
+         success = _mesa_texstore(ctx, dims, texImage->_BaseFormat,
+                                  texImage->TexFormat,
+                                  0, 0, 0,  /* dstX/Y/Zoffset */
+                                  dstRowStride,
+                                  &dstMap,
+                                  width, height, 1,  /* w, h, d */
+                                  format, type, src, packing);
+
+         ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
+      }
+
+      src += srcImageStride;
+
+      if (!success)
+         break;
+   }
+
+   if (!success)
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+
 /**
- * This is the software fallback for Driver.TexImage1D().
- * \sa _mesa_store_teximage2d()
+ * This is the fallback for Driver.TexImage1D().
  */
 void
 _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
@@ -4578,13 +4706,6 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
-
-   (void) border;
-
    if (width == 0)
       return;
 
@@ -4595,47 +4716,14 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
-                                        pixels, packing, "glTexImage1D");
-   if (!pixels) {
-      /* Note: we check for a NULL image pointer here, _after_ we allocated
-       * memory for the texture.  That's what the GL spec calls for.
-       */
-      return;
-   }
-
-   /* Map dest texture buffer (write to whole region) */
-   ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                               0, 0, width, 1,
-                               rwMode,
-                               &dstMap, &dstRowStride);
-   if (dstMap) {
-      success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               0, 0, 0,  /* dstX/Y/Zoffset */
-                               0, /* dstRowStride */
-                               &dstMap,
-                               width, 1, 1,
-                               format, type, pixels, packing);
-
-      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-   }
-   else {
-      success = GL_FALSE;
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     0, 0, 0, width, 1, 1,
+                     format, type, pixels, packing, "glTexImage1D");
 }
 
 
 /**
- * This is the software fallback for Driver.TexImage2D().
- *
- * This function is oriented toward storing images in main memory, rather
- * than VRAM.  Device driver's can easily plug in their own replacement.
+ * This is the fallback for Driver.TexImage2D().
  */
 void
 _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
@@ -4646,13 +4734,6 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
-
-   (void) border;
-
    if (width == 0 || height == 0)
       return;
 
@@ -4663,80 +4744,15 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
-                                        pixels, packing, "glTexImage2D");
-   if (!pixels) {
-      /* Note: we check for a NULL image pointer here, _after_ we allocated
-       * memory for the texture.  That's what the GL spec calls for.
-       */
-      return;
-   }
-
-   if (target == GL_TEXTURE_1D_ARRAY) {
-      const GLint srcStride =
-         _mesa_image_row_stride(packing, width, format, type);
-      int y;
-
-      success = GL_TRUE;
-
-      for (y = 0; y < height; y++) {
-         /* Map dest texture buffer (write to whole region) */
-         ctx->Driver.MapTextureImage(ctx, texImage, y,
-                                     0, 0, width, 1,
-                                     rwMode,
-                                     &dstMap, &dstRowStride);
-         if (dstMap) {
-            success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                                     texImage->TexFormat,
-                                     0, 0, 0,  /* dstX/Y/Zoffset */
-                                     dstRowStride,
-                                     &dstMap,
-                                     width, 1, 1,
-                                     format, type, pixels, packing);
-            ctx->Driver.UnmapTextureImage(ctx, texImage, y);
-         }
-         else {
-            success = GL_FALSE;
-         }
-
-         if (!success)
-            break;
-
-         pixels = (const GLubyte *) pixels + srcStride;
-      }
-   } else {
-      /* Map dest texture buffer (write to whole region) */
-      ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                                  0, 0, width, height,
-                                  rwMode,
-                                  &dstMap, &dstRowStride);
-      if (dstMap) {
-         success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                                  texImage->TexFormat,
-                                  0, 0, 0,  /* dstX/Y/Zoffset */
-                                  dstRowStride,
-                                  &dstMap,
-                                  width, height, 1,
-                                  format, type, pixels, packing);
-
-         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-      }
-      else {
-         success = GL_FALSE;
-      }
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     0, 0, 0, width, height, 1,
+                     format, type, pixels, packing, "glTexImage2D");
 }
 
 
 
 /**
- * This is the software fallback for Driver.TexImage3D().
- * \sa _mesa_store_teximage2d()
+ * This is the fallback for Driver.TexImage3D().
  */
 void
 _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
@@ -4747,14 +4763,6 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLboolean success = GL_TRUE;
-   GLint slice;
-   GLubyte **sliceMaps;
-   GLint dstRowStride;
-
-   (void) border;
-
    if (width == 0 || height == 0 || depth == 0)
       return;
 
@@ -4765,66 +4773,16 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth,
-                                        format, type,
-                                        pixels, packing, "glTexImage3D");
-   if (!pixels) {
-      /* Note: we check for a NULL image pointer here, _after_ we allocated
-       * memory for the texture.  That's what the GL spec calls for.
-       */
-      return;
-   }
-
-   if (target == GL_TEXTURE_1D_ARRAY) {
-      depth = height;
-      height = 1;
-   }
-
-   sliceMaps = (GLubyte **) calloc(depth, sizeof(GLubyte *));
-
-   /* Map dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      ctx->Driver.MapTextureImage(ctx, texImage, slice,
-                                  0, 0, width, height,
-                                  rwMode,
-                                  &sliceMaps[slice], &dstRowStride);
-      if (!sliceMaps[slice]) {
-         success = GL_FALSE;
-         break;
-      }
-   }
-
-   if (success) {
-      success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               0, 0, 0,  /* dstX/Y/Zoffset */
-                               dstRowStride,
-                               sliceMaps,
-                               width, height, depth,
-                               format, type, pixels, packing);
-   }
-
-   /* Unmap dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      if (sliceMaps[slice]) {
-         ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
-      }
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
-
-   free(sliceMaps);
+   store_texsubimage(ctx, texImage,
+                     0, 0, 0, width, height, depth,
+                     format, type, pixels, packing, "glTexImage3D");
 }
 
 
 
 
 /*
- * This is the software fallback for Driver.TexSubImage1D()
- * and Driver.CopyTexSubImage1D().
+ * This is the fallback for Driver.TexSubImage1D().
  */
 void
 _mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level,
@@ -4834,49 +4792,15 @@ _mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
-
-   /* get pointer to src pixels (may be in a pbo which we'll map here) */
-   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
-                                        pixels, packing, "glTexSubImage1D");
-   if (!pixels)
-      return;
-
-   /* Map dest texture buffer */
-   ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                               xoffset, 0, width, 1,
-                               rwMode,
-                               &dstMap, &dstRowStride);
-
-   if (dstMap) {
-      success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               0, 0, 0,  /* dstX/Y/Zoffset */
-                               dstRowStride,
-                               &dstMap,
-                               width, 1, 1,
-                               format, type, pixels, packing);
-
-      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-   }
-   else {
-      success = GL_FALSE;
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     xoffset, 0, 0, width, 1, 1,
+                     format, type, pixels, packing, "glTexSubImage1D");
 }
 
 
 
 /**
- * This is the software fallback for Driver.TexSubImage2D()
- * and Driver.CopyTexSubImage2D().
+ * This is the fallback for Driver.TexSubImage2D().
  */
 void
 _mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level,
@@ -4887,69 +4811,14 @@ _mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLboolean success = GL_FALSE;
-   GLuint slice, numSlices, sliceOffset, srcImageStride;
-   const GLubyte *src;
-
-   /* get pointer to src pixels (may be in a pbo which we'll map here) */
-   src = (const GLubyte *)
-      _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
-                                  pixels, packing, "glTexSubImage2D");
-   if (!src)
-      return;
-
-   if (target == GL_TEXTURE_1D_ARRAY) {
-      /* map each slice of the 1D array separately */
-      numSlices = height;
-      sliceOffset = yoffset;
-      height = 1;
-      yoffset = 0;
-      srcImageStride = _mesa_image_row_stride(packing, width, format, type);
-   }
-   else {
-      /* regular 2D image */
-      numSlices = 1;
-      sliceOffset = 0;
-      srcImageStride = 0;
-   }
-
-   for (slice = 0; slice < numSlices; slice++) {
-      GLubyte *dstMap;
-      GLint dstRowStride;
-
-      ctx->Driver.MapTextureImage(ctx, texImage,
-                                  slice + sliceOffset,
-                                  xoffset, yoffset, width, height,
-                                  rwMode, &dstMap, &dstRowStride);
-      if (dstMap) {
-         success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                                  texImage->TexFormat,
-                                  0, 0, 0,  /* dstX/Y/Zoffset */
-                                  dstRowStride,
-                                  &dstMap,
-                                  width, height, 1,  /* w, h, d */
-                                  format, type, src, packing);
-
-         ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
-      }
-
-      src += srcImageStride;
-
-      if (!success)
-         break;
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     xoffset, yoffset, 0, width, height, 1,
+                     format, type, pixels, packing, "glTexSubImage2D");
 }
 
 
 /*
- * This is the software fallback for Driver.TexSubImage3D().
- * and Driver.CopyTexSubImage3D().
+ * This is the fallback for Driver.TexSubImage3D().
  */
 void
 _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
@@ -4960,56 +4829,9 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLboolean success = GL_TRUE;
-   GLint slice;
-   GLubyte **sliceMaps;
-   GLint dstRowStride;
-
-   /* get pointer to src pixels (may be in a pbo which we'll map here) */
-   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
-                                        type, pixels, packing,
-                                        "glTexSubImage3D");
-   if (!pixels)
-      return;
-
-   sliceMaps = (GLubyte **) calloc(depth, sizeof(GLubyte *));
-
-   /* Map dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice,
-                                  xoffset, yoffset, width, height,
-                                  rwMode,
-                                  &sliceMaps[slice], &dstRowStride);
-      if (!sliceMaps[slice]) {
-         success = GL_FALSE;
-         break;
-      }
-   }
-
-   if (success) {
-      success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               0, 0, 0,
-                               dstRowStride,
-                               sliceMaps,
-                               width, height, depth,
-                               format, type, pixels, packing);
-   }
-
-   /* Unmap dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      if (sliceMaps[slice]) {
-         ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice);
-      }
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
-
-   free(sliceMaps);
+   store_texsubimage(ctx, texImage,
+                     xoffset, yoffset, zoffset, width, height, depth,
+                     format, type, pixels, packing, "glTexSubImage3D");
 }