gallium: take pitch/stride into account in mipmap generation
authorBrian <brian.paul@tungstengraphics.com>
Mon, 11 Feb 2008 17:59:40 +0000 (10:59 -0700)
committerBen Skeggs <skeggsb@gmail.com>
Fri, 15 Feb 2008 02:51:11 +0000 (13:51 +1100)
src/mesa/main/mipmap.c
src/mesa/main/mipmap.h
src/mesa/state_tracker/st_gen_mipmap.c

index 721a227bb53da9169d3cd1fb517840dbbdef889e..d3d1958951807b44fefbbfbfc8592b5cf7b9cf1d 100644 (file)
@@ -447,23 +447,29 @@ make_1d_mipmap(GLenum datatype, GLuint comps, GLint border,
 
 
 /**
- * XXX need to use the tex image's row stride!
+ * Strides are in bytes.  If zero, it'll be computed as width * bpp.
  */
 static void
 make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
-               GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
-               GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
+               GLint srcWidth, GLint srcHeight,
+               GLint srcRowStride, const GLubyte *srcPtr,
+               GLint dstWidth, GLint dstHeight,
+               GLint dstRowStride, GLubyte *dstPtr)
 {
    const GLint bpt = bytes_per_pixel(datatype, comps);
    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 GLubyte *srcA, *srcB;
    GLubyte *dst;
    GLint row;
 
+   if (!srcRowStride)
+      srcRowStride = bpt * srcWidth;
+
+   if (!dstRowStride)
+      dstRowStride = bpt * dstWidth;
+
    /* Compute src and dst pointers, skipping any border */
    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
    if (srcHeight > 1) 
@@ -535,8 +541,10 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
 static void
 make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
                GLint srcWidth, GLint srcHeight, GLint srcDepth,
+               GLint srcRowStride,
                const GLubyte *srcPtr,
                GLint dstWidth, GLint dstHeight, GLint dstDepth,
+               GLint dstRowStride,
                GLubyte *dstPtr)
 {
    const GLint bpt = bytes_per_pixel(datatype, comps);
@@ -548,7 +556,6 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
    GLvoid *tmpRowA, *tmpRowB;
    GLint img, row;
    GLint bytesPerSrcImage, bytesPerDstImage;
-   GLint bytesPerSrcRow, bytesPerDstRow;
    GLint srcImageOffset, srcRowOffset;
 
    (void) srcDepthNB; /* silence warnings */
@@ -566,8 +573,10 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
    bytesPerSrcImage = srcWidth * srcHeight * bpt;
    bytesPerDstImage = dstWidth * dstHeight * bpt;
 
-   bytesPerSrcRow = srcWidth * bpt;
-   bytesPerDstRow = dstWidth * bpt;
+   if (!srcRowStride)
+      srcRowStride = srcWidth * bpt;
+   if (!dstRowStride)
+      dstRowStride = dstWidth * bpt;
 
    /* Offset between adjacent src images to be averaged together */
    srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
@@ -591,13 +600,13 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
    for (img = 0; img < dstDepthNB; img++) {
       /* first source image pointer, skipping border */
       const GLubyte *imgSrcA = srcPtr
-         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
+         + (bytesPerSrcImage + srcRowStride + border) * bpt * border
          + img * (bytesPerSrcImage + srcImageOffset);
       /* second source image pointer, skipping border */
       const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
       /* address of the dest image, skipping border */
       GLubyte *imgDst = dstPtr
-         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
+         + (bytesPerDstImage + dstRowStride + border) * bpt * border
          + img * bytesPerDstImage;
 
       /* setup the four source row pointers and the dest row pointer */
@@ -618,11 +627,11 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
          do_row(datatype, comps, srcWidthNB, tmpRowA, tmpRowB,
                 dstWidthNB, dstImgRow);
          /* advance to next rows */
-         srcImgARowA += bytesPerSrcRow + srcRowOffset;
-         srcImgARowB += bytesPerSrcRow + srcRowOffset;
-         srcImgBRowA += bytesPerSrcRow + srcRowOffset;
-         srcImgBRowB += bytesPerSrcRow + srcRowOffset;
-         dstImgRow += bytesPerDstRow;
+         srcImgARowA += srcRowStride + srcRowOffset;
+         srcImgARowB += srcRowStride + srcRowOffset;
+         srcImgBRowA += srcRowStride + srcRowOffset;
+         srcImgBRowB += srcRowStride + srcRowOffset;
+         dstImgRow += dstRowStride;
       }
    }
 
@@ -632,12 +641,14 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
    /* Luckily we can leverage the make_2d_mipmap() function here! */
    if (border > 0) {
       /* do front border image */
-      make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr,
-                     dstWidth, dstHeight, dstPtr);
+      make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, 0, srcPtr,
+                     dstWidth, dstHeight, 0, dstPtr);
       /* do back border image */
       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
+                     0, 
                      srcPtr + bytesPerSrcImage * (srcDepth - 1),
                      dstWidth, dstHeight,
+                     0,
                      dstPtr + bytesPerDstImage * (dstDepth - 1));
       /* do four remaining border edges that span the image slices */
       if (srcDepth == dstDepth) {
@@ -653,9 +664,9 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
 
             /* do border along [img][row=dstHeight-1][col=0] */
             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
-                         + (srcHeight - 1) * bytesPerSrcRow;
+                         + (srcHeight - 1) * srcRowStride;
             dst = dstPtr + (img + 1) * bytesPerDstImage
-                         + (dstHeight - 1) * bytesPerDstRow;
+                         + (dstHeight - 1) * dstRowStride;
             MEMCPY(dst, src, bpt);
 
             /* do border along [img][row=0][col=dstWidth-1] */
@@ -687,9 +698,9 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
 
             /* do border along [img][row=dstHeight-1][col=0] */
             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
-                         + (srcHeight - 1) * bytesPerSrcRow;
+                         + (srcHeight - 1) * srcRowStride;
             dst = dstPtr + (img + 1) * bytesPerDstImage
-                         + (dstHeight - 1) * bytesPerDstRow;
+                         + (dstHeight - 1) * dstRowStride;
             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
 
             /* do border along [img][row=0][col=dstWidth-1] */
@@ -755,8 +766,11 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
  */
 static void
 make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
-                     GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
+                     GLint srcWidth, GLint srcHeight,
+                     GLint srcRowStride,
+                     const GLubyte *srcPtr,
                      GLint dstWidth, GLint dstHeight, GLint dstDepth,
+                     GLint dstRowStride,
                      GLubyte *dstPtr)
 {
    const GLint bpt = bytes_per_pixel(datatype, comps);
@@ -764,13 +778,17 @@ make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint 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 GLubyte *srcA, *srcB;
    GLubyte *dst;
    GLint layer;
    GLint row;
 
+   if (!srcRowStride)
+      srcRowStride = bpt * srcWidth;
+
+   if (!dstRowStride)
+      dstRowStride = bpt * dstWidth;
+
    /* Compute src and dst pointers, skipping any border */
    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
    if (srcHeight > 1) 
@@ -849,8 +867,10 @@ _mesa_generate_mipmap_level(GLenum target,
                             GLenum datatype, GLuint comps,
                             GLint border,
                             GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                            GLint srcRowStride,
                             const GLubyte *srcData,
                             GLint dstWidth, GLint dstHeight, GLint dstDepth,
+                            GLint dstRowStride,
                             GLubyte *dstData)
 {
    switch (target) {
@@ -867,13 +887,13 @@ _mesa_generate_mipmap_level(GLenum target,
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
       make_2d_mipmap(datatype, comps, border,
-                     srcWidth, srcHeight, srcData,
-                     dstWidth, dstHeight, dstData);
+                     srcWidth, srcHeight, srcRowStride, srcData,
+                     dstWidth, dstHeight, dstRowStride, dstData);
       break;
    case GL_TEXTURE_3D:
       make_3d_mipmap(datatype, comps, border,
-                     srcWidth, srcHeight, srcDepth, srcData,
-                     dstWidth, dstHeight, dstDepth, dstData);
+                     srcWidth, srcHeight, srcDepth, srcRowStride, srcData,
+                     dstWidth, dstHeight, dstDepth, dstRowStride, dstData);
       break;
    case GL_TEXTURE_1D_ARRAY_EXT:
       make_1d_stack_mipmap(datatype, comps, border,
@@ -882,8 +902,8 @@ _mesa_generate_mipmap_level(GLenum target,
       break;
    case GL_TEXTURE_2D_ARRAY_EXT:
       make_2d_stack_mipmap(datatype, comps, border,
-                           srcWidth, srcHeight, srcData,
-                           dstWidth, dstHeight, dstDepth, dstData);
+                           srcWidth, srcHeight, srcRowStride, srcData,
+                           dstWidth, dstHeight, dstDepth, dstRowStride, dstData);
       break;
    case GL_TEXTURE_RECTANGLE_NV:
       /* no mipmaps, do nothing */
@@ -1110,9 +1130,10 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
          dstData = (GLubyte *) dstImage->Data;
       }
 
+      /* Note, 0 indicates default row strides */
       _mesa_generate_mipmap_level(target, datatype, comps, border,
-                                  srcWidth, srcHeight, srcDepth, srcData,
-                                  dstWidth, dstHeight, dstDepth, dstData);
+                                  srcWidth, srcHeight, srcDepth, 0, srcData,
+                                  dstWidth, dstHeight, dstDepth, 0, dstData);
 
       if (dstImage->IsCompressed) {
          GLubyte *temp;
index b6491f55073e613462596648e5a04fa67083efd3..44ecdddb27766aad0ca84ed7981f2d3da9740ecf 100644 (file)
@@ -34,8 +34,10 @@ _mesa_generate_mipmap_level(GLenum target,
                             GLenum datatype, GLuint comps,
                             GLint border,
                             GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                            GLint srcRowStride,
                             const GLubyte *srcData,
                             GLint dstWidth, GLint dstHeight, GLint dstDepth,
+                            GLint dstRowStride,
                             GLubyte *dstData);
 
 
index f6af37cfac3c2999dc5423787c65bb5f701fd9eb..c152c599056f6106f5a1e3e14a10eac4518570c3 100644 (file)
@@ -352,12 +352,13 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target,
                                          PIPE_BUFFER_USAGE_CPU_WRITE)
               + dstSurf->offset;
 
-      /* XXX need to take stride/pitch info into account... */
       _mesa_generate_mipmap_level(target, datatype, comps,
                    0 /*border*/,
                    pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
+                   srcSurf->pitch * srcSurf->cpp, /* stride in bytes */
                    srcData,
                    pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
+                   dstSurf->pitch * dstSurf->cpp, /* stride in bytes */
                    dstData);
 
       ws->buffer_unmap(ws, srcSurf->buffer);