Cleaned up and slightly optimized the texture upload code.
authorFelix Kuehling <fxkuehl@gmx.de>
Mon, 8 Mar 2004 23:01:47 +0000 (23:01 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Mon, 8 Mar 2004 23:01:47 +0000 (23:01 +0000)
src/mesa/drivers/dri/savage/savagetex.c

index 0ce2a96..488d838 100644 (file)
@@ -50,6 +50,8 @@
  *
  *    4 2
  *    x 1
+ *
+ * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
  */
 static const savageTileInfo tileInfo_pro[5] = {
     {64, 64,  8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
@@ -84,8 +86,8 @@ static const savageTileInfo tileInfo_s3d_s4[5] = {
  * \param srcStride    Byte stride of rows in the source data
  * \param dest         Pointer to destination
  *
- * Processes rows of source data linearly and scatters them into the
- * subtiles.
+ * Writes linearly to the destination memory in order to exploit write
+ * combining.
  *
  * For a complete tile wInSub and hInSub are set to the same values as
  * in tileInfo. If the source image is smaller than a whole tile in
@@ -96,114 +98,157 @@ static const savageTileInfo tileInfo_s3d_s4[5] = {
 static void savageUploadTile (const savageTileInfo *tileInfo,
                              GLuint wInSub, GLuint hInSub, GLuint bpp,
                              GLubyte *src, GLuint srcStride, GLubyte *dest) {
-    GLuint destStride = tileInfo->subWidth * tileInfo->subHeight * bpp;
     GLuint subStride = tileInfo->subWidth * bpp;
-    GLubyte *srcRow = src, *destSRow = dest, *destRow = dest;
+    GLubyte *srcSRow = src, *srcSTile = src;
     GLuint sx, sy, y;
-    /* iterate over subtile rows */
     for (sy = 0; sy < hInSub; ++sy) {
-       destRow = destSRow;
-       /* iterate over pixel rows within the subtile row */
-       for (y = 0; y < tileInfo->subHeight; ++y) {
-           src = srcRow;
-           dest = destRow;
-           /* iterate over subtile columns */
-           for (sx = 0; sx < wInSub; ++sx) {
+       srcSTile = srcSRow;
+       for (sx = 0; sx < wInSub; ++sx) {
+           src = srcSTile;
+           for (y = 0; y < tileInfo->subHeight; ++y) {
                memcpy (dest, src, subStride);
-               src += subStride;
-               dest += destStride;
+               src += srcStride;
+               dest += subStride;
            }
-           srcRow += srcStride;
-           destRow += subStride;
+           srcSTile += subStride;
        }
-       destSRow += destStride * wInSub;
+       srcSRow += srcStride * tileInfo->subHeight;
     }
 }
 
-/** \brief Upload a texture image that is smaller than 8x8 pixels.
+/** \brief Upload a image that is smaller than 8 pixels in either dimension.
+ *
+ * \param tileInfo    Pointer to tiling information
+ * \param width       Width of the image
+ * \param height      Height of the image
+ * \param bpp         Bytes per pixel
+ * \param src         Pointer to source data
+ * \param dest        Pointer to destination
+ *
+ * This function handles all the special cases that need to be taken
+ * care off. The caller may need to call this function multiple times
+ * with the destination offset in different ways since small texture
+ * images must be repeated in order to fill a whole tile (or 4x4 for
+ * the last 3 levels).
  *
- * \param tileInfo
- * \param width
- * \param height
- * \param bpp
- * \param src
- * \param dest
+ * FIXME: Repeating inside this function would be more efficient.
  */
 static void savageUploadTiny (const savageTileInfo *tileInfo,
                              GLuint width, GLuint height, GLuint bpp,
                              GLubyte *src, GLubyte *dest) {
     GLuint size = MAX2(width, height);
-    GLuint offset = (size <= 2 ? tileInfo->tinyOffset[size-1] : 0);
-    GLuint wInSub = width / tileInfo->subWidth;
-
-#if 0
-    /* Fill the file with a test pattern */
-    GLuint i;
-    GLushort *sdest = (GLushort*)dest;
-    if (offset)
-       sdest += 0x20;
-    for (i = 0; i < tileInfo->subWidth*tileInfo->subHeight; ++i) {
-       GLuint x = i;
-       GLuint mask = 0;
-       GLushort val = 0;
-       switch (i & 3) {
-       case 0: mask = 1; break;
-       case 1: mask = 2; break;
-       case 2: mask = 4; break;
-       case 3: mask = 7; break;
-       }
-       if (mask & 1)
-           val |= x;
-       if (mask & 2)
-           val |= x*2 << 5;
-       if (mask & 4)
-           val |= x << (5+6);
-       *sdest++ = val;
-    }
-#else
-    if (wInSub > 1) { /* several subtiles wide but less than a subtile high */
-       GLuint destStride = tileInfo->subWidth * tileInfo->subHeight * bpp;
-       GLuint subStride = tileInfo->subWidth * bpp;
+
+    if (width > tileInfo->subWidth) { /* assert: height <= subtile height */
+       GLuint wInSub = width / tileInfo->subWidth;
        GLuint srcStride = width * bpp;
-       GLubyte *srcRow = src, *destRow = dest;
+       GLuint subStride = tileInfo->subWidth * bpp;
+       GLuint subSkip = (tileInfo->subHeight - height) * subStride;
+       GLubyte *srcSTile = src;
        GLuint sx, y;
-       for (y = 0; y < height; ++y) {
-           src = srcRow;
-           dest = destRow;
-           /* iterate over subtile columns */
-           for (sx = 0; sx < wInSub; ++sx) {
+       for (sx = 0; sx < wInSub; ++sx) {
+           src = srcSTile;
+           for (y = 0; y < height; ++y) {
                memcpy (dest, src, subStride);
-               src += subStride;
-               dest += destStride;
+               src += srcStride;
+               dest += subStride;
            }
-           srcRow += srcStride;
-           destRow += subStride;
-           /* if the subtile width is 4 skip every other tile */
-           if ((y & 7) == 7 && tileInfo->subWidth == 4)
-               destRow += destStride;
+           dest += subSkip;
+           srcSTile += subStride;
        }
-    } else if (size > 4) { /* not the last 3 mipmap levels */
+    } else if (size > 4) { /* a tile or less wide, except the last 3 levels */
+       GLuint srcStride = width * bpp;
+       GLuint subStride = tileInfo->subWidth * bpp;
+       /* if the subtile width is 4 we have to skip every other subtile */
+       GLuint subSkip = tileInfo->subWidth == 4 ?
+           subStride * tileInfo->subHeight : 0;
        GLuint y;
        for (y = 0; y < height; ++y) {
-           memcpy (dest, src, bpp*width);
-           src += width * bpp;
-           dest += tileInfo->subWidth * bpp;
-           /* if the subtile width is 4 skip every other tile */
-           if ((y & 7) == 7 && tileInfo->subWidth == 4)
-               dest += tileInfo->subHeight * tileInfo->subWidth * bpp;
+           memcpy (dest, src, srcStride);
+           src += srcStride;
+           dest += subStride;
+           if ((y & 7) == 7)
+               dest += subSkip;
        }
     } else { /* the last 3 mipmap levels */
+       GLuint offset = (size <= 2 ? tileInfo->tinyOffset[size-1] : 0);
+       GLuint subStride = tileInfo->subWidth * bpp;
        GLuint y;
        dest += offset;
        for (y = 0; y < height; ++y) {
            memcpy (dest, src, bpp*width);
            src += width * bpp;
-           dest += tileInfo->subWidth * bpp;
+           dest += subStride;
        }
     }
-#endif
 }
 
+/** \brief Upload an image from mesa's internal copy.
+ */
+static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
+{
+    const struct gl_texture_image *image = t->image[level].image;
+    const savageTileInfo *tileInfo = t->tileInfo;
+    GLuint width = image->Width2, height = image->Height2;
+    GLuint bpp = t->texelBytes;
+
+    /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
+     * this using normal textured triangles.
+     *
+     * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
+     */
+    if(image->Border != 0) 
+       fprintf (stderr, "Not supported texture border %d.\n",
+                (int) image->Border);
+
+    if (width >= 8 && height >= tileInfo->subHeight) {
+       if (width >= tileInfo->width && height >= tileInfo->height) {
+           GLuint wInTiles = width / tileInfo->width;
+           GLuint hInTiles = height / tileInfo->height;
+           GLubyte *srcTRow = image->Data, *src;
+           GLubyte *dest = (GLubyte *)(t->BufAddr + t->image[level].offset);
+           GLuint x, y;
+           for (y = 0; y < hInTiles; ++y) {
+               src = srcTRow;
+               for (x = 0; x < wInTiles; ++x) {
+                   savageUploadTile (tileInfo,
+                                     tileInfo->wInSub, tileInfo->hInSub, bpp,
+                                     src, width * bpp, dest);
+                   src += tileInfo->width * bpp;
+                   dest += 2048; /* tile size is always 2k */
+               }
+               srcTRow += width * tileInfo->height * bpp;
+           }
+       } else {
+           savageUploadTile (tileInfo, width / tileInfo->subWidth,
+                             height / tileInfo->subHeight, bpp,
+                             image->Data, width * bpp,
+                             (GLubyte *)(t->BufAddr+t->image[level].offset));
+       }
+    } else {
+       GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
+       if (width > 4 || height > 4) {
+           minWidth = tileInfo->subWidth;
+           minHeight = tileInfo->subHeight;
+       } else {
+           minWidth = 4;
+           minHeight = 4;
+       }
+       hRepeat = width  >= minWidth  ? 1 : minWidth  / width;
+       vRepeat = height >= minHeight ? 1 : minHeight / height;
+       for (y = 0; y < vRepeat; ++y) {
+           GLuint offset = y * tileInfo->subWidth*height * bpp;
+           for (x = 0; x < hRepeat; ++x) {
+               savageUploadTiny (tileInfo, width, height, bpp, image->Data,
+                                 (GLubyte *)(t->BufAddr +
+                                             t->image[level].offset+offset));
+               offset += width * bpp;
+           }
+       }
+    }
+}
+
+/** \brief Compute the destination size of a texture image
+ */
 static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {
     /* full subtiles */
     if (width >= 8 && height >= 8)
@@ -533,74 +578,6 @@ static void savageSwapOutTexObj(savageContextPtr imesa, savageTextureObjectPtr t
 
 
 
-/* Upload an image from mesa's internal copy.
- */
-static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
-{
-   const struct gl_texture_image *image = t->image[level].image;
-   const savageTileInfo *tileInfo = t->tileInfo;
-   GLuint width = image->Width2, height = image->Height2;
-   GLuint bpp = t->texelBytes;
-
-   /* Need triangle (rather than pixel) fallbacks to simulate this using
-    * normal textured triangles.
-    *
-    * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
-    * 
-    */
-
-   if(image->Border != 0) 
-       fprintf (stderr, "Not supported texture border %d.\n",
-               (int) image->Border);
-
-   if (width >= 8 && height >= tileInfo->subHeight) {
-       if (width >= tileInfo->width && height >= tileInfo->height) {
-          GLuint wInTiles = width / tileInfo->width;
-          GLuint hInTiles = height / tileInfo->height;
-          GLubyte *srcTRow = image->Data, *src;
-          GLubyte *dest = (GLubyte *)(t->BufAddr + t->image[level].offset);
-          GLuint x, y;
-          for (y = 0; y < hInTiles; ++y) {
-              src = srcTRow;
-              for (x = 0; x < wInTiles; ++x) {
-                  savageUploadTile (tileInfo,
-                                    tileInfo->wInSub, tileInfo->hInSub, bpp,
-                                    src, width * bpp, dest);
-                  src += tileInfo->width * bpp;
-                  dest += 2048; /* tile size is always 2k */
-              }
-              srcTRow += width * tileInfo->height * bpp;
-          }
-       } else {
-          savageUploadTile (tileInfo, width / tileInfo->subWidth,
-                            height / tileInfo->subHeight, bpp,
-                            image->Data, width * bpp,
-                            (GLubyte *)(t->BufAddr + t->image[level].offset));
-       }
-   } else {
-       GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
-       if (width > 4 || height > 4) {
-          minWidth = tileInfo->subWidth;
-          minHeight = tileInfo->subHeight;
-       } else {
-          minWidth = 4;
-          minHeight = 4;
-       }
-       hRepeat = width  >= minWidth  ? 1 : minWidth  / width;
-       vRepeat = height >= minHeight ? 1 : minHeight / height;
-       for (y = 0; y < vRepeat; ++y)
-          for (x = 0; x < hRepeat; ++x) {
-              GLuint offset = (y * tileInfo->subWidth*height +
-                               x * width) * bpp;
-              savageUploadTiny (tileInfo, width, height, bpp, image->Data,
-                                (GLubyte *)(t->BufAddr +
-                                            t->image[level].offset + offset));
-          }
-   }
-}
-
-
-
 void savagePrintLocalLRU( savageContextPtr imesa , GLuint heap) 
 {
    savageTextureObjectPtr t;