[Mesa-dev] [PATCH 2/6] main: Add TEXTURE_CUBE_MAP support for glCompressedTextureSubImage3D.

Laura Ekstrand laura at jlekstrand.net
Fri Feb 27 16:07:13 PST 2015


---
 src/mesa/main/teximage.c | 204 ++++++++++++++++++++++++++++++++++++++++-------
 src/mesa/main/teximage.h |   3 +-
 2 files changed, 179 insertions(+), 28 deletions(-)

diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index dfad9ed..d454dd9 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -4747,30 +4747,19 @@ _mesa_CompressedTexImage3D(GLenum target, GLint level,
 void
 _mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims,
                                    struct gl_texture_object *texObj,
+                                   struct gl_texture_image *texImage,
                                    GLenum target, GLint level,
                                    GLint xoffset, GLint yoffset,
                                    GLint zoffset,
                                    GLsizei width, GLsizei height,
                                    GLsizei depth,
                                    GLenum format, GLsizei imageSize,
-                                   const GLvoid *data, bool dsa)
+                                   const GLvoid *data)
 {
-   struct gl_texture_image *texImage;
-
-   if (compressed_subtexture_error_check(ctx, dims, texObj, target,
-                                         level, xoffset, yoffset, zoffset,
-                                         width, height, depth,
-                                         format, imageSize, dsa)) {
-      return;
-   }
-
    FLUSH_VERTICES(ctx, 0);
 
    _mesa_lock_texture(ctx, texObj);
    {
-      texImage = _mesa_select_tex_image(texObj, target, level);
-      assert(texImage);
-
       if (width > 0 && height > 0 && depth > 0) {
          ctx->Driver.CompressedTexSubImage(ctx, dims, texImage,
                                            xoffset, yoffset, zoffset,
@@ -4794,6 +4783,8 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
                               GLsizei imageSize, const GLvoid *data)
 {
    struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
    GET_CURRENT_CONTEXT(ctx);
 
    if (compressed_subtexture_target_check(ctx, target, 1, format, false,
@@ -4805,9 +4796,20 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
    if (!texObj)
       return;
 
-   _mesa_compressed_texture_sub_image(ctx, 1, texObj, target, level,
+   if (compressed_subtexture_error_check(ctx, 1, texObj, target,
+                                         level, xoffset, 0, 0,
+                                         width, 1, 1,
+                                         format, imageSize, false)) {
+      return;
+   }
+
+   texImage = _mesa_select_tex_image(texObj, target, level);
+   if (!texImage)
+      return;
+
+   _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage, target, level,
                                       xoffset, 0, 0, width, 1, 1,
-                                      format, imageSize, data, false);
+                                      format, imageSize, data);
 }
 
 void GLAPIENTRY
@@ -4816,6 +4818,8 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
                                   GLsizei imageSize, const GLvoid *data)
 {
    struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
    GET_CURRENT_CONTEXT(ctx);
 
    texObj = _mesa_lookup_texture_err(ctx, texture,
@@ -4829,9 +4833,21 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
       return;
    }
 
-   _mesa_compressed_texture_sub_image(ctx, 1, texObj, texObj->Target, level,
+   if (compressed_subtexture_error_check(ctx, 1, texObj, texObj->Target,
+                                         level, xoffset, 0, 0,
+                                         width, 1, 1,
+                                         format, imageSize, true)) {
+      return;
+   }
+
+   texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
+   if (!texImage)
+      return;
+
+   _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage,
+                                      texObj->Target, level,
                                       xoffset, 0, 0, width, 1, 1,
-                                      format, imageSize, data, true);
+                                      format, imageSize, data);
 }
 
 
@@ -4842,6 +4858,8 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
                               const GLvoid *data)
 {
    struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
    GET_CURRENT_CONTEXT(ctx);
 
    if (compressed_subtexture_target_check(ctx, target, 2, format, false,
@@ -4853,9 +4871,21 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
    if (!texObj)
       return;
 
-   _mesa_compressed_texture_sub_image(ctx, 2, texObj, target, level,
+   if (compressed_subtexture_error_check(ctx, 2, texObj, target,
+                                         level, xoffset, yoffset, 0,
+                                         width, height, 1,
+                                         format, imageSize, false)) {
+      return;
+   }
+
+
+   texImage = _mesa_select_tex_image(texObj, target, level);
+   if (!texImage)
+      return;
+
+   _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage, target, level,
                                       xoffset, yoffset, 0, width, height, 1,
-                                      format, imageSize, data, false);
+                                      format, imageSize, data);
 }
 
 void GLAPIENTRY
@@ -4866,6 +4896,8 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
                                   const GLvoid *data)
 {
    struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
    GET_CURRENT_CONTEXT(ctx);
 
    texObj = _mesa_lookup_texture_err(ctx, texture,
@@ -4879,9 +4911,21 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
       return;
    }
 
-   _mesa_compressed_texture_sub_image(ctx, 2, texObj, texObj->Target, level,
+   if (compressed_subtexture_error_check(ctx, 2, texObj, texObj->Target,
+                                         level, xoffset, yoffset, 0,
+                                         width, height, 1,
+                                         format, imageSize, true)) {
+      return;
+   }
+
+   texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
+   if (!texImage)
+      return;
+
+   _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage,
+                                      texObj->Target, level,
                                       xoffset, yoffset, 0, width, height, 1,
-                                      format, imageSize, data, true);
+                                      format, imageSize, data);
 }
 
 void GLAPIENTRY
@@ -4891,6 +4935,8 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
                               GLsizei imageSize, const GLvoid *data)
 {
    struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
    GET_CURRENT_CONTEXT(ctx);
 
    if (compressed_subtexture_target_check(ctx, target, 3, format, false,
@@ -4902,10 +4948,22 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
    if (!texObj)
       return;
 
-   _mesa_compressed_texture_sub_image(ctx, 3, texObj, target, level,
+   if (compressed_subtexture_error_check(ctx, 3, texObj, target,
+                                         level, xoffset, yoffset, zoffset,
+                                         width, height, depth,
+                                         format, imageSize, false)) {
+      return;
+   }
+
+
+   texImage = _mesa_select_tex_image(texObj, target, level);
+   if (!texImage)
+      return;
+
+   _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage, target, level,
                                       xoffset, yoffset, zoffset,
                                       width, height, depth,
-                                      format, imageSize, data, false);
+                                      format, imageSize, data);
 }
 
 void GLAPIENTRY
@@ -4916,6 +4974,8 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
                                   const GLvoid *data)
 {
    struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
    GET_CURRENT_CONTEXT(ctx);
 
    texObj = _mesa_lookup_texture_err(ctx, texture,
@@ -4929,10 +4989,100 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
       return;
    }
 
-   _mesa_compressed_texture_sub_image(ctx, 3, texObj, texObj->Target, level,
-                                      xoffset, yoffset, zoffset,
-                                      width, height, depth,
-                                      format, imageSize, data, true);
+   if (compressed_subtexture_error_check(ctx, 3, texObj, texObj->Target,
+                                         level, xoffset, yoffset, zoffset,
+                                         width, height, depth,
+                                         format, imageSize, true)) {
+      return;
+   }
+
+   /* Must handle special case GL_TEXTURE_CUBE_MAP. */
+   if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+      const char *pixels = data;
+      int i;
+      GLint image_stride;
+
+      /* Error checking */
+      if (texObj->NumLayers < 6) {
+         /* Not enough image planes for a cube map.  The spec does not say
+          * what should happen in this case because the user has always
+          * specified each cube face separately (using
+          * GL_TEXTURE_CUBE_MAP_POSITIVE_X+i) in previous GL versions.
+          * This is addressed in Khronos Bug 13223.
+          */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCompressedTextureSubImage3D"
+                     "(insufficient cube map storage)");
+         return;
+      }
+
+      /*
+       * What do we do if the user created a texture with the following code
+       * and then called this function with its handle?
+       *
+       *    GLuint tex;
+       *    glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex);
+       *    glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
+       *    glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ...);
+       *    glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ...);
+       *    glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ...);
+       *    // Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set, or given the
+       *    // wrong format, or given the wrong size, etc.
+       *    glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ...);
+       *    glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ...);
+       *
+       * A bug has been filed against the spec for this case.  In the
+       * meantime, we will check for cube completeness.
+       *
+       * According to Section 8.17 Texture Completeness in the OpenGL 4.5
+       * Core Profile spec (30.10.2014):
+       *    "[A] cube map texture is cube complete if the
+       *    following conditions all hold true: The [base level] texture
+       *    images of each of the six cube map faces have identical, positive,
+       *    and square dimensions. The [base level] images were each specified
+       *    with the same internal format."
+       *
+       * It seems reasonable to check for cube completeness of an arbitrary
+       * level here so that the image data has a consistent format and size.
+       */
+      if (!_mesa_cube_level_complete(texObj, level)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCompressedTextureSubImage3D(cube map incomplete)");
+         return;
+      }
+
+      /* Copy in each face. */
+      for (i = 0; i < 6; ++i) {
+         texImage = texObj->Image[i][level];
+         if (!texImage)
+            return;
+
+         _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage,
+                                            texObj->Target, level,
+                                            xoffset, yoffset, zoffset,
+                                            width, height, 1,
+                                            format, imageSize, pixels);
+
+         /* Compressed images don't have a client format */
+         image_stride = _mesa_format_image_size(texImage->TexFormat,
+                                                texImage->Width,
+                                                texImage->Height, 1);
+
+         pixels += image_stride;
+         imageSize -= image_stride;
+      }
+   }
+   else {
+      texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
+      if (!texImage)
+         return;
+
+      _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage,
+                                         texObj->Target, level,
+                                         xoffset, yoffset, zoffset,
+                                         width, height, depth,
+                                         format, imageSize, data);
+   }
 }
 
 static mesa_format
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
index b7336bc..9468650 100644
--- a/src/mesa/main/teximage.h
+++ b/src/mesa/main/teximage.h
@@ -181,13 +181,14 @@ _mesa_texture_sub_image(struct gl_context *ctx, GLuint dims,
 extern void
 _mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims, 
                                    struct gl_texture_object *texObj, 
+                                   struct gl_texture_image *texImage,
                                    GLenum target, GLint level,
                                    GLint xoffset, GLint yoffset,
                                    GLint zoffset,
                                    GLsizei width, GLsizei height,
                                    GLsizei depth,
                                    GLenum format, GLsizei imageSize,
-                                   const GLvoid *data, bool dsa);
+                                   const GLvoid *data);
 
 extern void
 _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims,
-- 
2.1.0



More information about the mesa-dev mailing list