[intel] Fix and reenable (software) SGIS_generate_mipmap
authorEric Anholt <eric@anholt.net>
Wed, 19 Dec 2007 22:26:14 +0000 (14:26 -0800)
committerEric Anholt <eric@anholt.net>
Thu, 20 Dec 2007 19:26:34 +0000 (11:26 -0800)
The core problem was that _mesa_generate_mipmap was not respecting RowStride
of the source image.  Additionally, the intel private data associated with the
images (level and face) was not being initialized for the
_mesa_generate_mipmap-generated images.

src/mesa/drivers/dri/i915/intel_context.c
src/mesa/drivers/dri/intel/intel_mipmap_tree.c
src/mesa/drivers/dri/intel/intel_tex.c
src/mesa/drivers/dri/intel/intel_tex.h
src/mesa/drivers/dri/intel/intel_tex_copy.c
src/mesa/drivers/dri/intel/intel_tex_image.c
src/mesa/drivers/dri/intel/intel_tex_subimage.c
src/mesa/drivers/dri/intel/intel_tex_validate.c
src/mesa/main/mipmap.c
src/mesa/main/mtypes.h

index 5d34642a5dcccd0a0c936974b4f287a706e1d994..f407f7ec4750b1b12bfbf4a7ef8b2aba63e71d2a 100644 (file)
@@ -202,7 +202,7 @@ const struct dri_extension card_extensions[] = {
    {"GL_NV_blend_square", NULL},
    {"GL_NV_vertex_program", GL_NV_vertex_program_functions},
    {"GL_NV_vertex_program1_1", NULL},
-/*     { "GL_SGIS_generate_mipmap",           NULL }, */
+   { "GL_SGIS_generate_mipmap", NULL },
    {NULL, NULL}
 };
 
index 6610771b6e29fa6808dbca6b95fcbe42f57078c1..763758503310200924cb79b78b91f8126c18206c 100644 (file)
@@ -351,7 +351,7 @@ intel_miptree_image_data(struct intel_context *intel,
    GLuint i;
    GLuint height = 0;
 
-   DBG("%s\n", __FUNCTION__);
+   DBG("%s: %d/%d\n", __FUNCTION__, face, level);
    for (i = 0; i < depth; i++) {
       height = dst->level[level].height;
       if(dst->compressed)
index e02972ec637bfdfe769e0773b3df497fc40761c6..f016b6b4dc4aa9df74e54817b0b7805baf484ae6 100644 (file)
@@ -1,5 +1,6 @@
 #include "swrast/swrast.h"
 #include "texobj.h"
+#include "mipmap.h"
 #include "intel_context.h"
 #include "intel_mipmap_tree.h"
 #include "intel_tex.h"
@@ -156,6 +157,46 @@ timed_memcpy(void *dest, const void *src, size_t n)
 }
 #endif /* DO_DEBUG */
 
+/**
+ * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap
+ * level).
+ *
+ * The texture object's miptree must be mapped.
+ *
+ * It would be really nice if this was just called by Mesa whenever mipmaps
+ * needed to be regenerated, rather than us having to remember to do so in
+ * each texture image modification path.
+ *
+ * This function should also include an accelerated path.
+ */
+void
+intel_generate_mipmap(GLcontext *ctx, GLenum target,
+                      const struct gl_texture_unit *texUnit,
+                      struct gl_texture_object *texObj)
+{
+   struct intel_texture_object *intelObj = intel_texture_object(texObj);
+   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+   int face, i;
+
+   _mesa_generate_mipmap(ctx, target, texUnit, texObj);
+
+   /* Update the level information in our private data in the new images, since
+    * it didn't get set as part of a normal TexImage path.
+    */
+   for (face = 0; face < nr_faces; face++) {
+      for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
+         struct intel_texture_image *intelImage;
+
+        intelImage = intel_texture_image(texObj->Image[face][i]);
+        if (intelImage == NULL)
+           break;
+
+        intelImage->level = i;
+        intelImage->face = face;
+      }
+   }
+}
+
 
 void
 intelInitTextureFuncs(struct dd_function_table *functions)
index b77d7a1d8af96144ed87cc2e7e62351041e82d4c..2973e0ceb9feb8ce21011005fac93606ab119fc8 100644 (file)
@@ -148,4 +148,8 @@ void intel_tex_unmap_images(struct intel_context *intel,
 
 int intel_compressed_num_bytes(GLuint mesaFormat);
 
+void intel_generate_mipmap(GLcontext *ctx, GLenum target,
+                          const struct gl_texture_unit *texUnit,
+                          struct gl_texture_object *texObj);
+
 #endif
index f1a455a04cd1f090247692eba9759a6d1828ee48..521ce06640f53e21bb9addcf5486be35af434552 100644 (file)
@@ -29,6 +29,7 @@
 #include "enums.h"
 #include "image.h"
 #include "teximage.h"
+#include "mipmap.h"
 #include "swrast/swrast.h"
 
 #include "intel_screen.h"
@@ -85,12 +86,14 @@ get_teximage_source(struct intel_context *intel, GLenum internalFormat)
 
 static GLboolean
 do_copy_texsubimage(struct intel_context *intel,
+                   GLenum target,
                     struct intel_texture_image *intelImage,
                     GLenum internalFormat,
                     GLint dstx, GLint dsty,
                     GLint x, GLint y, GLsizei width, GLsizei height)
 {
    GLcontext *ctx = &intel->ctx;
+   struct gl_texture_object *texObj = intelImage->base.TexObject;
    const struct intel_region *src =
       get_teximage_source(intel, internalFormat);
 
@@ -156,16 +159,12 @@ do_copy_texsubimage(struct intel_context *intel,
 
    UNLOCK_HARDWARE(intel);
 
-#if 0
-   /* GL_SGIS_generate_mipmap -- this can be accelerated now.
-    * XXX Add a ctx->Driver.GenerateMipmaps() function?
-    */
-   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+   /* GL_SGIS_generate_mipmap */
+   if (intelImage->level == texObj->BaseLevel && texObj->GenerateMipmap) {
       intel_generate_mipmap(ctx, target,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
-#endif
 
    return GL_TRUE;
 }
@@ -197,7 +196,7 @@ intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
                           GL_RGBA, CHAN_TYPE, NULL,
                           &ctx->DefaultPacking, texObj, texImage);
 
-   if (!do_copy_texsubimage(intel_context(ctx),
+   if (!do_copy_texsubimage(intel_context(ctx), target,
                             intel_texture_image(texImage),
                             internalFormat, 0, 0, x, y, width, 1))
       goto fail;
@@ -234,7 +233,7 @@ intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
                           &ctx->DefaultPacking, texObj, texImage);
 
 
-   if (!do_copy_texsubimage(intel_context(ctx),
+   if (!do_copy_texsubimage(intel_context(ctx), target,
                             intel_texture_image(texImage),
                             internalFormat, 0, 0, x, y, width, height))
       goto fail;
@@ -264,7 +263,7 @@ intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
    /* Need to check texture is compatible with source format. 
     */
 
-   if (!do_copy_texsubimage(intel_context(ctx),
+   if (!do_copy_texsubimage(intel_context(ctx), target,
                             intel_texture_image(texImage),
                             internalFormat, xoffset, 0, x, y, width, 1)) {
       _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width);
@@ -290,7 +289,7 @@ intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
    /* Need to check texture is compatible with source format. 
     */
 
-   if (!do_copy_texsubimage(intel_context(ctx),
+   if (!do_copy_texsubimage(intel_context(ctx), target,
                             intel_texture_image(texImage),
                             internalFormat,
                             xoffset, yoffset, x, y, width, height)) {
index c2af74095c9f66bb78fd269cfc17a92fdc79b02a..4f5f75d0492a280e1f865bc81ad17e6719de36b5 100644 (file)
@@ -466,6 +466,7 @@ intelTexImage(GLcontext * ctx,
                                                intelImage->level,
                                                &dstRowStride,
                                                intelImage->base.ImageOffsets);
+      texImage->RowStride = dstRowStride / intelImage->mt->cpp;
    }
    else {
       /* Allocate regular memory and store the image there temporarily.   */
@@ -483,8 +484,8 @@ intelTexImage(GLcontext * ctx,
       texImage->Data = malloc(sizeInBytes);
    }
 
-   DBG("Upload image %dx%dx%d row_len %x "
-       "pitch %x\n",
+   DBG("Upload image %dx%dx%d row_len %d "
+       "pitch %d\n",
        width, height, depth, width * texelBytes, dstRowStride);
 
    /* Copy data.  Would like to know when it's ok for us to eg. use
@@ -504,6 +505,13 @@ intelTexImage(GLcontext * ctx,
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
    }
 
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      intel_generate_mipmap(ctx, target,
+                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
+                            texObj);
+   }
+
    _mesa_unmap_teximage_pbo(ctx, unpack);
 
    if (intelImage->mt) {
@@ -512,16 +520,6 @@ intelTexImage(GLcontext * ctx,
    }
 
    UNLOCK_HARDWARE(intel);
-
-#if 0
-   /* GL_SGIS_generate_mipmap -- this can be accelerated now.
-    */
-   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
-      intel_generate_mipmap(ctx, target,
-                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
-                            texObj);
-   }
-#endif
 }
 
 void
index 5410df203f468412611f2ef9345363701529f3a6..bd27b86bf323004d845ae01852f696c6fc2d6234 100644 (file)
@@ -90,14 +90,12 @@ intelTexSubimage(GLcontext * ctx,
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
    }
 
-#if 0
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
-      _mesa_generate_mipmap(ctx, target,
+      intel_generate_mipmap(ctx, target,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
-#endif
 
    _mesa_unmap_teximage_pbo(ctx, packing);
 
index 8df66ad4450b9b1018f6b5cfeea1dc606d0764f1..d260a721d9a1d2d47a7d1118794559be09205c99 100644 (file)
@@ -75,6 +75,10 @@ intel_calculate_first_last_level(struct intel_texture_object *intelObj)
    intelObj->lastLevel = lastLevel;
 }
 
+/**
+ * Copies the image's contents at its level into the object's miptree,
+ * and updates the image to point at the object's miptree.
+ */
 static void
 copy_image_data_to_tree(struct intel_context *intel,
                         struct intel_texture_object *intelObj,
index a9260c847b056b52b2c99ace361a280b0cfe8cfa..44357fbd6a3b452cfb457a99b1a7872611970ebd 100644 (file)
@@ -531,20 +531,19 @@ make_1d_mipmap(const struct gl_texture_format *format, GLint border,
 }
 
 
-/**
- * XXX need to use the tex image's row stride!
- */
 static void
 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
-               GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
-               GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
+               GLint srcWidth, GLint srcHeight,
+              const GLubyte *srcPtr, GLint srcRowStride,
+               GLint dstWidth, GLint dstHeight,
+              GLubyte *dstPtr, GLint dstRowStride)
 {
    const GLint bpt = format->TexelBytes;
    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
    const GLint dstWidthNB = dstWidth - 2 * border;
    const GLint dstHeightNB = dstHeight - 2 * border;
-   const GLint srcRowStride = bpt * srcWidth;
-   const GLint dstRowStride = bpt * dstWidth;
+   const GLint srcRowBytes = bpt * srcRowStride;
+   const GLint dstRowBytes = bpt * dstRowStride;
    const GLubyte *srcA, *srcB;
    GLubyte *dst;
    GLint row;
@@ -552,7 +551,7 @@ make_2d_mipmap(const struct gl_texture_format *format, GLint border,
    /* Compute src and dst pointers, skipping any border */
    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
    if (srcHeight > 1) 
-      srcB = srcA + srcRowStride;
+      srcB = srcA + srcRowBytes;
    else
       srcB = srcA;
    dst = dstPtr + border * ((dstWidth + 1) * bpt);
@@ -560,9 +559,9 @@ make_2d_mipmap(const struct gl_texture_format *format, GLint border,
    for (row = 0; row < dstHeightNB; row++) {
       do_row(format, srcWidthNB, srcA, srcB,
              dstWidthNB, dst);
-      srcA += 2 * srcRowStride;
-      srcB += 2 * srcRowStride;
-      dst += dstRowStride;
+      srcA += 2 * srcRowBytes;
+      srcB += 2 * srcRowBytes;
+      dst += dstRowBytes;
    }
 
    /* This is ugly but probably won't be used much */
@@ -620,9 +619,9 @@ make_2d_mipmap(const struct gl_texture_format *format, GLint border,
 static void
 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
                GLint srcWidth, GLint srcHeight, GLint srcDepth,
-               const GLubyte *srcPtr,
+               const GLubyte *srcPtr, GLint srcRowStride,
                GLint dstWidth, GLint dstHeight, GLint dstDepth,
-               GLubyte *dstPtr)
+               GLubyte *dstPtr, GLint dstRowStride)
 {
    const GLint bpt = format->TexelBytes;
    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
@@ -717,13 +716,13 @@ make_3d_mipmap(const struct gl_texture_format *format, GLint border,
    /* Luckily we can leverage the make_2d_mipmap() function here! */
    if (border > 0) {
       /* do front border image */
-      make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
-                     dstWidth, dstHeight, dstPtr);
+      make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
+                     dstWidth, dstHeight, dstPtr, dstRowStride);
       /* do back border image */
       make_2d_mipmap(format, 1, srcWidth, srcHeight,
-                     srcPtr + bytesPerSrcImage * (srcDepth - 1),
+                     srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
                      dstWidth, dstHeight,
-                     dstPtr + bytesPerDstImage * (dstDepth - 1));
+                     dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
       /* do four remaining border edges that span the image slices */
       if (srcDepth == dstDepth) {
          /* just copy border pixels from src to dst */
@@ -798,15 +797,16 @@ make_3d_mipmap(const struct gl_texture_format *format, GLint border,
 
 static void
 make_1d_stack_mipmap(const struct gl_texture_format *format, GLint border,
-                     GLint srcWidth, const GLubyte *srcPtr,
-                     GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
+                     GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride,
+                     GLint dstWidth, GLint dstHeight,
+                    GLubyte *dstPtr, GLuint dstRowStride )
 {
    const GLint bpt = format->TexelBytes;
    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
    const GLint dstWidthNB = dstWidth - 2 * border;
    const GLint dstHeightNB = dstHeight - 2 * border;
-   const GLint srcRowStride = bpt * srcWidth;
-   const GLint dstRowStride = bpt * dstWidth;
+   const GLint srcRowBytes = bpt * srcRowStride;
+   const GLint dstRowBytes = bpt * dstRowStride;
    const GLubyte *src;
    GLubyte *dst;
    GLint row;
@@ -818,8 +818,8 @@ make_1d_stack_mipmap(const struct gl_texture_format *format, GLint border,
    for (row = 0; row < dstHeightNB; row++) {
       do_row(format, srcWidthNB, src, src,
              dstWidthNB, dst);
-      src += srcRowStride;
-      dst += dstRowStride;
+      src += srcRowBytes;
+      dst += dstRowBytes;
    }
 
    if (border) {
@@ -840,17 +840,18 @@ make_1d_stack_mipmap(const struct gl_texture_format *format, GLint border,
  */
 static void
 make_2d_stack_mipmap(const struct gl_texture_format *format, GLint border,
-                     GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
+                     GLint srcWidth, GLint srcHeight,
+                    const GLubyte *srcPtr, GLint srcRowStride,
                      GLint dstWidth, GLint dstHeight, GLint dstDepth,
-                     GLubyte *dstPtr)
+                     GLubyte *dstPtr, GLint dstRowStride)
 {
    const GLint bpt = format->TexelBytes;
    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
    const GLint dstWidthNB = dstWidth - 2 * border;
    const GLint dstHeightNB = dstHeight - 2 * border;
    const GLint dstDepthNB = dstDepth - 2 * border;
-   const GLint srcRowStride = bpt * srcWidth;
-   const GLint dstRowStride = bpt * dstWidth;
+   const GLint srcRowBytes = bpt * srcRowStride;
+   const GLint dstRowBytes = bpt * dstRowStride;
    const GLubyte *srcA, *srcB;
    GLubyte *dst;
    GLint layer;
@@ -859,7 +860,7 @@ make_2d_stack_mipmap(const struct gl_texture_format *format, GLint border,
    /* Compute src and dst pointers, skipping any border */
    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
    if (srcHeight > 1) 
-      srcB = srcA + srcRowStride;
+      srcB = srcA + srcRowBytes;
    else
       srcB = srcA;
    dst = dstPtr + border * ((dstWidth + 1) * bpt);
@@ -868,9 +869,9 @@ make_2d_stack_mipmap(const struct gl_texture_format *format, GLint border,
       for (row = 0; row < dstHeightNB; row++) {
          do_row(format, srcWidthNB, srcA, srcB,
                 dstWidthNB, dst);
-         srcA += 2 * srcRowStride;
-         srcB += 2 * srcRowStride;
-         dst += dstRowStride;
+         srcA += 2 * srcRowBytes;
+         srcB += 2 * srcRowBytes;
+         dst += dstRowBytes;
       }
 
       /* This is ugly but probably won't be used much */
@@ -1132,23 +1133,28 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
          case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
          case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
             make_2d_mipmap(convertFormat, border,
-                           srcWidth, srcHeight, srcData,
-                           dstWidth, dstHeight, dstData);
+                           srcWidth, srcHeight, srcData, srcImage->RowStride,
+                           dstWidth, dstHeight, dstData, dstImage->RowStride);
             break;
          case GL_TEXTURE_3D:
             make_3d_mipmap(convertFormat, border,
-                           srcWidth, srcHeight, srcDepth, srcData,
-                           dstWidth, dstHeight, dstDepth, dstData);
+                           srcWidth, srcHeight, srcDepth,
+                          srcData, srcImage->RowStride,
+                           dstWidth, dstHeight, dstDepth,
+                          dstData, dstImage->RowStride);
             break;
          case GL_TEXTURE_1D_ARRAY_EXT:
             make_1d_stack_mipmap(convertFormat, border,
-                                 srcWidth, srcData,
-                                 dstWidth, dstHeight, dstData);
+                                 srcWidth, srcData, srcImage->RowStride,
+                                 dstWidth, dstHeight,
+                                dstData, dstImage->RowStride);
             break;
          case GL_TEXTURE_2D_ARRAY_EXT:
             make_2d_stack_mipmap(convertFormat, border,
-                                 srcWidth, srcHeight, srcData,
-                                 dstWidth, dstHeight, dstDepth, dstData);
+                                 srcWidth, srcHeight,
+                                srcData, srcImage->RowStride,
+                                 dstWidth, dstHeight,
+                                dstDepth, dstData, dstImage->RowStride);
             break;
          case GL_TEXTURE_RECTANGLE_NV:
             /* no mipmaps, do nothing */
index 94b709438892e1c96d20ae2695e3a92edba3125d..0da487ea044d88c5b129731b5c639dbea99d2861 100644 (file)
@@ -1365,7 +1365,7 @@ struct gl_texture_image
    GLboolean IsCompressed;     /**< GL_ARB_texture_compression */
    GLuint CompressedSize;      /**< GL_ARB_texture_compression */
 
-   GLuint RowStride;           /**< == Width unless IsClientData and padded */
+   GLuint RowStride;           /**< Padded width in units of texels */
    GLuint *ImageOffsets;        /**< if 3D texture: array [Depth] of offsets to
                                      each 2D slice in 'Data', in texels */
    GLvoid *Data;               /**< Image data, accessed via FetchTexel() */