mesa: clean up validate_texture_wrap_mode
[mesa.git] / src / mesa / main / texgetimage.c
index 2830dda867f207922b4c81d715df07c182a14167..3adf7e3217ec9f13dfa811e85c6cd093baaf70fd 100644 (file)
@@ -49,8 +49,8 @@
 /**
  * Can the given type represent negative values?
  */
-static INLINE GLboolean
-type_with_negative_values(GLenum type)
+static inline GLboolean
+type_needs_clamping(GLenum type)
 {
    switch (type) {
    case GL_BYTE:
@@ -58,9 +58,11 @@ type_with_negative_values(GLenum type)
    case GL_INT:
    case GL_FLOAT:
    case GL_HALF_FLOAT_ARB:
-      return GL_TRUE;
-   default:
+   case GL_UNSIGNED_INT_10F_11F_11F_REV:
+   case GL_UNSIGNED_INT_5_9_9_9_REV:
       return GL_FALSE;
+   default:
+      return GL_TRUE;
    }
 }
 
@@ -71,14 +73,13 @@ type_with_negative_values(GLenum type)
 static void
 get_tex_depth(struct gl_context *ctx, GLuint dimensions,
               GLenum format, GLenum type, GLvoid *pixels,
-              const struct gl_texture_image *texImage)
+              struct gl_texture_image *texImage)
 {
    const GLint width = texImage->Width;
    const GLint height = texImage->Height;
    const GLint depth = texImage->Depth;
    GLint img, row;
    GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
-   const GLint texelSize = _mesa_get_format_bytes(texImage->TexFormat);
 
    if (!depthRow) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
@@ -86,18 +87,24 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions,
    }
 
    for (img = 0; img < depth; img++) {
+      GLubyte *srcMap;
+      GLint srcRowStride;
+
+      /* map src texture buffer */
+      ctx->Driver.MapTextureImage(ctx, texImage, img,
+                                  0, 0, width, height, GL_MAP_READ_BIT,
+                                  &srcMap, &srcRowStride);
+
       for (row = 0; row < height; row++) {
          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                           width, height, format, type,
                                           img, row, 0);
-         const GLubyte *src = (GLubyte *) texImage->Data +
-            (texImage->ImageOffsets[img] +
-             texImage->RowStride * row) * texelSize;
-
+         const GLubyte *src = srcMap + row * srcRowStride;
          _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow);
-
          _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
       }
+
+      ctx->Driver.UnmapTextureImage(ctx, texImage, img);
    }
 
    free(depthRow);
@@ -110,27 +117,35 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions,
 static void
 get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
                       GLenum format, GLenum type, GLvoid *pixels,
-                      const struct gl_texture_image *texImage)
+                      struct gl_texture_image *texImage)
 {
    const GLint width = texImage->Width;
    const GLint height = texImage->Height;
    const GLint depth = texImage->Depth;
-   const GLint rowstride = texImage->RowStride;
-   const GLuint *src = (const GLuint *) texImage->Data;
    GLint img, row;
 
    for (img = 0; img < depth; img++) {
+      GLubyte *srcMap;
+      GLint rowstride;
+
+      /* map src texture buffer */
+      ctx->Driver.MapTextureImage(ctx, texImage, img,
+                                  0, 0, width, height, GL_MAP_READ_BIT,
+                                  &srcMap, &rowstride);
+
       for (row = 0; row < height; row++) {
+        const GLubyte *src = srcMap + row * rowstride;
          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                           width, height, format, type,
                                           img, row, 0);
+         /* XXX Z24_S8 vs. S8_Z24??? */
          memcpy(dest, src, width * sizeof(GLuint));
          if (ctx->Pack.SwapBytes) {
             _mesa_swap4((GLuint *) dest, width);
          }
-
-         src += rowstride;
       }
+
+      ctx->Driver.UnmapTextureImage(ctx, texImage, img);
    }
 }
 
@@ -141,17 +156,24 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
 static void
 get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
               GLenum format, GLenum type, GLvoid *pixels,
-              const struct gl_texture_image *texImage)
+              struct gl_texture_image *texImage)
 {
    const GLint width = texImage->Width;
    const GLint height = texImage->Height;
    const GLint depth = texImage->Depth;
-   const GLint rowstride = texImage->RowStride;
-   const GLushort *src = (const GLushort *) texImage->Data;
    GLint img, row;
 
    for (img = 0; img < depth; img++) {
+      GLubyte *srcMap;
+      GLint rowstride;
+
+      /* map src texture buffer */
+      ctx->Driver.MapTextureImage(ctx, texImage, img,
+                                  0, 0, width, height, GL_MAP_READ_BIT,
+                                  &srcMap, &rowstride);
+
       for (row = 0; row < height; row++) {
+        const GLubyte *src = srcMap + row * rowstride;
          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                           width, height, format, type,
                                           img, row, 0);
@@ -168,9 +190,9 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
          else if (ctx->Pack.SwapBytes) {
             _mesa_swap2((GLushort *) dest, width);
          }
-
-         src += rowstride;
       }
+
+      ctx->Driver.UnmapTextureImage(ctx, texImage, img);
    }
 }
 
@@ -199,7 +221,7 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
    /* In general, clamping does not apply to glGetTexImage, except when
     * the returned type of the image can't hold negative values.
     */
-   if (!type_with_negative_values(type)) {
+   if (type_needs_clamping(type)) {
       /* the returned image type can't have negative values */
       if (dataType == GL_FLOAT ||
           dataType == GL_SIGNED_NORMALIZED ||
@@ -221,8 +243,32 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
          return;
       }
 
-      _mesa_decompress_image(texFormat, texImage->Width, texImage->Height,
-                             texImage->Data, texImage->RowStride, tempImage);
+      /* Decompress the texture image - results in 'tempImage' */
+      {
+         GLubyte *srcMap;
+         GLint srcRowStride;
+         GLuint bytes, bw, bh;
+
+         bytes = _mesa_get_format_bytes(texImage->TexFormat);
+         _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
+
+         ctx->Driver.MapTextureImage(ctx, texImage, 0,
+                                     0, 0, width, height,
+                                     GL_MAP_READ_BIT,
+                                     &srcMap, &srcRowStride);
+
+         /* XXX This line is a bit of a hack to work around the
+          * mismatch of compressed row strides as returned by
+          * MapTextureImage() vs. what the texture decompression code
+          * uses.  This will be fixed in the future.
+          */
+         srcRowStride = srcRowStride * bh / bytes;
+
+         _mesa_decompress_image(texFormat, width, height,
+                                srcMap, srcRowStride, tempImage);
+
+         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+      }
 
       if (baseFormat == GL_LUMINANCE ||
           baseFormat == GL_LUMINANCE_ALPHA) {
@@ -250,7 +296,6 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
    }
    else {
       /* No decompression needed */
-      const GLint texelSize = _mesa_get_format_bytes(texFormat);
       GLuint img, row;
       GLfloat (*rgba)[4];
 
@@ -261,13 +306,19 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
       }
 
       for (img = 0; img < depth; img++) {
+        GLubyte *srcMap;
+        GLint rowstride;
+
+         /* map src texture buffer */
+         ctx->Driver.MapTextureImage(ctx, texImage, img,
+                                     0, 0, width, height, GL_MAP_READ_BIT,
+                                     &srcMap, &rowstride);
+
          for (row = 0; row < height; row++) {
+           const GLubyte *src = srcMap + row * rowstride;
             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                              width, height, format, type,
                                              img, row, 0);
-            const GLubyte *src = (const GLubyte *) texImage->Data +
-               (texImage->ImageOffsets[img] +
-                texImage->RowStride * row) * texelSize;
 
             _mesa_unpack_rgba_row(texFormat, width, src, rgba);
 
@@ -307,6 +358,9 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
                                        format, type, dest,
                                        &ctx->Pack, transferOps);
          }
+
+         /* Unmap the src texture buffer */
+         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
       }
 
       free(rgba);
@@ -319,26 +373,24 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
  * \return GL_TRUE if done, GL_FALSE otherwise
  */
 static GLboolean
-get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels,
-               const struct gl_texture_object *texObj,
-               const struct gl_texture_image *texImage)
+get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type,
+               GLvoid *pixels,
+               struct gl_texture_image *texImage)
 {
+   const GLenum target = texImage->TexObject->Target;
    GLboolean memCopy = GL_FALSE;
 
-   /* Texture image should have been mapped already */
-   assert(texImage->Data);
-
    /*
     * Check if the src/dst formats are compatible.
     * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
     * so we don't have to worry about those.
     * XXX more format combinations could be supported here.
     */
-   if ((texObj->Target == GL_TEXTURE_1D ||
-        texObj->Target == GL_TEXTURE_2D ||
-        texObj->Target == GL_TEXTURE_RECTANGLE ||
-        (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
-         texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
+   if ((target == GL_TEXTURE_1D ||
+        target == GL_TEXTURE_2D ||
+        target == GL_TEXTURE_RECTANGLE ||
+        (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+         target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
       if ((texImage->TexFormat == MESA_FORMAT_ARGB8888 ||
              texImage->TexFormat == MESA_FORMAT_SARGB8) &&
           format == GL_BGRA &&
@@ -386,20 +438,28 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixel
                                texImage->Height, format, type, 0, 0);
       const GLint dstRowStride =
          _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
-      const GLubyte *src = texImage->Data;
-      const GLint srcRowStride = texImage->RowStride * bpp;
-      GLuint row;
+      GLubyte *src;
+      GLint srcRowStride;
+
+      /* map src texture buffer */
+      ctx->Driver.MapTextureImage(ctx, texImage, 0,
+                                  0, 0, texImage->Width, texImage->Height,
+                                  GL_MAP_READ_BIT, &src, &srcRowStride);
 
       if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
          memcpy(dst, src, bytesPerRow * texImage->Height);
       }
       else {
+         GLuint row;
          for (row = 0; row < texImage->Height; row++) {
             memcpy(dst, src, bytesPerRow);
             dst += dstRowStride;
             src += srcRowStride;
          }
       }
+
+      /* unmap src texture buffer */
+      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
    }
 
    return memCopy;
@@ -409,20 +469,17 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixel
 /**
  * This is the software fallback for Driver.GetTexImage().
  * All error checking will have been done before this routine is called.
- * The texture image must be mapped.
+ * We'll call ctx->Driver.MapTextureImage() to access the data, then
+ * unmap with ctx->Driver.UnmapTextureImage().
  */
 void
-_mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_get_teximage(struct gl_context *ctx,
                    GLenum format, GLenum type, GLvoid *pixels,
-                   struct gl_texture_object *texObj,
                    struct gl_texture_image *texImage)
 {
    GLuint dimensions;
 
-   /* If we get here, the texture image should be mapped */
-   assert(texImage->Data);
-
-   switch (target) {
+   switch (texImage->TexObject->Target) {
    case GL_TEXTURE_1D:
       dimensions = 1;
       break;
@@ -433,6 +490,7 @@ _mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
       dimensions = 2;
    }
 
+   /* map dest buffer, if PBO */
    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
       /* Packing texture image into a PBO.
        * Map the (potentially) VRAM-based buffer into our process space so
@@ -454,7 +512,7 @@ _mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
       pixels = ADD_POINTERS(buf, pixels);
    }
 
-   if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) {
+   if (get_tex_memcpy(ctx, format, type, pixels, texImage)) {
       /* all done */
    }
    else if (format == GL_DEPTH_COMPONENT) {
@@ -487,11 +545,11 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level
                               struct gl_texture_object *texObj,
                               struct gl_texture_image *texImage)
 {
-   const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat,
-                                                     texImage->Width);
-   const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat,
-                                                            texImage->RowStride);
+   const GLuint row_stride =
+      _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
    GLuint i;
+   GLubyte *src;
+   GLint srcRowStride;
 
    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
       /* pack texture image into a PBO */
@@ -507,25 +565,32 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level
       img = ADD_POINTERS(buf, img);
    }
 
+   /* map src texture buffer */
+   ctx->Driver.MapTextureImage(ctx, texImage, 0,
+                               0, 0, texImage->Width, texImage->Height,
+                               GL_MAP_READ_BIT, &src, &srcRowStride);
+
    /* no pixelstore or pixel transfer, but respect stride */
 
-   if (row_stride == row_stride_stored) {
+   if (row_stride == srcRowStride) {
       const GLuint size = _mesa_format_image_size(texImage->TexFormat,
                                                   texImage->Width,
                                                   texImage->Height,
                                                   texImage->Depth);
-      memcpy(img, texImage->Data, size);
+      memcpy(img, src, size);
    }
    else {
       GLuint bw, bh;
       _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
       for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
          memcpy((GLubyte *)img + i * row_stride,
-                (GLubyte *)texImage->Data + i * row_stride_stored,
+                (GLubyte *)src + i * srcRowStride,
                 row_stride);
       }
    }
 
+   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+
    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
       ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
    }
@@ -708,8 +773,7 @@ _mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format,
 
    _mesa_lock_texture(ctx, texObj);
    {
-      ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
-                              texObj, texImage);
+      ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage);
    }
    _mesa_unlock_texture(ctx, texObj);
 }
@@ -822,7 +886,7 @@ _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,
       return;
    }
 
-   if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
+   if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
       /* not an error, do nothing */
       return;
    }