Rewrote tiled texture upload. Small mipmap levels work correctly now.
authorFelix Kuehling <fxkuehl@gmx.de>
Sun, 7 Mar 2004 20:41:42 +0000 (20:41 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sun, 7 Mar 2004 20:41:42 +0000 (20:41 +0000)
src/mesa/drivers/dri/savage/savagetex.c
src/mesa/drivers/dri/savage/savagetex.h

index e2a28ae50ae046e276ca55e5da80442bb1e5d079..f92d3ba4d5c88850e6189e5014bd76fb9c475f4b 100644 (file)
 
 #include "swrast/swrast.h"
 
-/* declarations of static and inline functions */
-__inline GLuint GetTiledCoordinates8(GLuint iBufferWidth, GLint x, GLint y);
-static GLuint GetTiledCoordinates16_4( GLint iBufferWidth,GLint x,GLint y );
-static GLuint GetTiledCoordinates16_8( GLint iBufferWidth,GLint x,GLint y );
-static GLuint GetTiledCoordinates32_4( GLint iBufferWidth, GLint x,   GLint y );
-static GLuint GetTiledCoordinates32_8( GLint iBufferWidth, GLint x,   GLint y );
-__inline GLuint GetTiledCoordinates( GLint iDepth,GLint iBufferWidth,GLint x,GLint y );
-__inline void savageUploadImage(savageTextureObjectPtr t, GLuint level, GLuint startx, GLuint starty, GLuint reloc);
-__inline void  savageTileTex(savageTextureObjectPtr tex, GLuint level);
-
-/* tile sizes depending on texel color depth */
-GLuint gTileWidth[5] =
-{
-    64,    /* 4-bit */ 
-    64,    /* 8-bit */
-    64,    /* 16-bit */
-    0,     /* 24-bit */
-    32     /* 32-bit */
+/* Size 1, 2 and 4 images are packed into the last subtile. Each image
+ * is repeated to fill a 4x4 pixel area. The figure below shows the
+ * layout of those 4x4 pixel areas in the 8x8 subtile.
+ *
+ *    4 2
+ *    x 1
+ */
+static const savageTileInfo tileInfo_pro[5] = {
+    {64, 64, 8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
+    {64, 32, 8, 4, 8, 8, {0x24, 0x04}}, /* 8-bit */
+    {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
+    { 0,  0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
+    {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
 };
 
-GLuint gTileHeight[5] = 
-{
-    64,   /* 4-bit */
-    32,   /* 8-bit */
-    16,   /* 16-bit */
-    0,    /* 24-bit */
-    16    /* 32-bit */
+/* Size 1, 2 and 4 images are packed into the last two subtiles. Each
+ * image is repeated to fill a 4x4 pixel area. The figures below show
+ * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
+ *
+ * second last subtile: 4   last subtile: 2
+ *                      x                 1
+ */
+static const savageTileInfo tileInfo_s3d_s4[5] = {
+    {64, 64, 16, 8, 4, 8, {0x18, 0x10}}, /* 4-bit */
+    {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
+    {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
+    { 0,  0,  0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
+    {32, 16,  8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
 };
 
-__inline GLuint GetTiledCoordinates8(GLuint iBufferWidth, GLint x, GLint y)
-{
-    GLint x10, x106, x52;
-    GLint y20, y105, y43;
-    GLuint uWidthInTiles;
-
-    uWidthInTiles = (iBufferWidth + 63) >> 6;
-    x10 = x & 0x3;
-    x52 = (x & 0x3c) >> 2;
-    x106 = (x & 0x7c0) >> 6;
-
-    y20 = y & 0x7;
-    y43 = (y & 0x18) >> 3;
-    y105 = (y & 0x7e0) >> 5;
-    
-    return ( x10         |
-            (y20 << 2)   |
-           (x52 << 5)   |
-           (y43 << 9)   |
-           ((y105 * uWidthInTiles) + x106) << 11 );
-}
-
-/* 4-pixel wide subtiles */
-static GLuint GetTiledCoordinates16_4( GLint iBufferWidth,
-                                              GLint x,
-                                              GLint y )
-{
-    GLint  x106;
-    GLint  x10;
-    GLint  x52;
-    GLint  y104;
-    GLint  y20;
-    GLint  y3;
-    GLuint uiWidthInTiles;
-
-    /*
-    // calculating tiled address
-    */
-
-    uiWidthInTiles = (iBufferWidth + 63) >> 6;
-
-    x10  =  x & 0x3;
-    x52  = (x & 0x3c ) >> 2;
-    x106 = (x & 0x7c0) >> 6;
-
-    y20  =  y & 0x7;
-    y3   = (y & 8    ) >> 3;
-    y104 = (y & 0x7f0) >> 4;
-
-    return( (x10 << 1)  |
-            (y20 << 3)  |
-            (x52 << 6)  |
-            (y3  << 10) |
-            ((y104 * uiWidthInTiles) + x106) << 11 );
-}
-/* 8-pixel wide subtiles */
-static GLuint GetTiledCoordinates16_8( GLint iBufferWidth,
-                                              GLint x,
-                                              GLint y )
-{
-    GLint  x106;
-    GLint  x20;
-    GLint  x53;
-    GLint  y104;
-    GLint  y20;
-    GLint  y3;
-    GLuint uiWidthInTiles;
-
-    /*
-    // calculating tiled address
-    */
-
-    uiWidthInTiles = (iBufferWidth + 63) >> 6;
-
-    x20  =  x & 0x7;
-    x53  = (x & 0x38 ) >> 3;
-    x106 = (x & 0x7c0) >> 6;
-
-    y20  =  y & 0x7;
-    y3   = (y & 8    ) >> 3;
-    y104 = (y & 0x7f0) >> 4;
-
-    return( (x20 << 1)  |
-            (y20 << 4)  |
-            (x53 << 7)  |
-            (y3  << 10) |
-            ((y104 * uiWidthInTiles) + x106) << 11 );
-}
-/* function pointer set to the correct version in savageDDInitTextureFuncs */
-GLuint (*GetTiledCoordinates16) (GLint, GLint, GLint);
-
-/* 4-pixel wide subtiles */
-static GLuint GetTiledCoordinates32_4( GLint iBufferWidth,
-                                              GLint x,
-                                              GLint y )
-{
-    GLint  x10;
-    GLint  y20;
-    GLuint uiWidthInTiles;
-    GLint  x42;
-    GLint  x105;
-    GLint  y3;
-    GLint  y104;
-
-    /*
-    // calculating tiled address
-    */
-
-    uiWidthInTiles = (iBufferWidth + 31) >> 5;
-
-    x10  =  x & 0x3;
-    x42  = (x & 0x1c ) >> 2;
-    x105 = (x & 0x7e0) >> 5;
-
-    y20  =  y & 0x7;
-    y3   = (y & 8    ) >> 3;
-    y104 = (y & 0x7f0) >> 4;
-
-    return( (x10 << 2)  |
-            (y20 << 4)  |
-            (x42 << 7)  |
-            (y3  << 10) |
-            ((y104 * uiWidthInTiles) + x105) << 11 );
-}
-/* 8-pixel wide subtiles */
-static GLuint GetTiledCoordinates32_8( GLint iBufferWidth,
-                                              GLint x,
-                                              GLint y )
-{
-    GLint  x20;
-    GLint  y20;
-    GLuint uiWidthInTiles;
-    GLint  x43;
-    GLint  x105;
-    GLint  y3;
-    GLint  y104;
-
-    /*
-    // calculating tiled address
-    */
-
-    uiWidthInTiles = (iBufferWidth + 31) >> 5;
-
-    x20  =  x & 0x7;
-    x43  = (x & 0x18 ) >> 3;
-    x105 = (x & 0x7e0) >> 5;
-
-    y20  =  y & 0x7;
-    y3   = (y & 8    ) >> 3;
-    y104 = (y & 0x7f0) >> 4;
-
-    return( (x20 << 2)  |
-            (y20 << 5)  |
-            (x43 << 8)  |
-            (y3  << 10) |
-            ((y104 * uiWidthInTiles) + x105) << 11 );
-}
-/* function pointer set to the correct version in savageDDInitTextureFuncs */
-GLuint (*GetTiledCoordinates32) (GLint, GLint, GLint);
-
-__inline GLuint GetTiledCoordinates( GLint iDepth,
-                                            GLint iBufferWidth,
-                                            GLint x,
-                                            GLint y )
-{
-    /*
-    // don't check for 4 since we only have 3 types of fb
-    */
-
-    if (iDepth == 16)
-    {
-        return( GetTiledCoordinates16( iBufferWidth, x, y ) );
-    }
-    else if (iDepth == 32)
-    {
-        return( GetTiledCoordinates32( iBufferWidth, x, y ) );
-    }
-    else
-    {
-        return( GetTiledCoordinates8( iBufferWidth, x, y ) );
+/** \brief Upload a complete tile from src (srcStride) to dest
+ *
+ * \param tileInfo     Pointer to tiling information
+ * \param wInSub       Width of source/dest image in subtiles
+ * \param hInSub       Height of source/dest image in subtiles
+ * \param bpp          Bytes per pixel
+ * \param src          Pointer to source data
+ * \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.
+ *
+ * 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
+ * one or both dimensions then they are set to the values of the
+ * source image. This only works as long as the source image is bigger
+ * than 8x8 pixels.
+ */
+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;
+    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) {
+               memcpy (dest, src, subStride);
+               src += subStride;
+               dest += destStride;
+           }
+           srcRow += srcStride;
+           destRow += subStride;
+       }
+       destSRow += destStride * wInSub;
     }
-} 
-
-__inline void savageUploadImage(savageTextureObjectPtr t, GLuint level, GLuint startx, GLuint starty, GLuint reloc)
-{
-    GLuint uMaxTileWidth = gTileWidth[t->texelBytes]; 
-    GLuint x, y, w, row, col;    
-    const struct gl_texture_image *image = t->image[level].image;
-    GLubyte * dst, * src, * pBuffer;
-    GLint xAdd, yAdd;
-    GLuint uRowSeparator, uChunk = MIN_TILE_CHUNK, uWrap;
-
-  
-    pBuffer = (GLubyte *)(t->BufAddr + t->image[level].offset);
-    src = (GLubyte *)image->Data;
-    x = startx;
-    y = starty;
-    w = image->Width;
+}
 
-    if(image->Format ==  GL_COLOR_INDEX)
-    {
-        if(w < MIN_TILE_CHUNK)
-       {
-            w = MIN_TILE_CHUNK;
-        }
-        else
-        {
-           if((w > 64 ) && (image->Height <= 16))
-            {
-                reloc = GL_TRUE;
-                 if(image->Height == 16)
-                {
-                    uChunk = MIN_TILE_CHUNK << 1;
-                }
-           }
-       }  
-
-       if(!reloc & (w > (64 / 2)))
-       {
-           for(row = 0; row < image->Height; row++)
-           {
-               for(col = 0; col < image->Width; col++)    
-               {
-                   dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + col, y + row);
-                   memcpy (dst, src, t->texelBytes);
-                   src += t->texelBytes;
-                }
-           }
+/** \brief Upload a texture image that is smaller than 8x8 pixels.
+ *
+ * \param tileInfo
+ * \param width
+ * \param height
+ * \param bpp
+ * \param src
+ * \param dest
+ */
+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;
        }
-        else
-        {
-           if(reloc & (w > 64))
-           {
-             uWrap = ((w + 63) >> 6) - 1;
-               for(row = 0; row < image->Height; row++)
-               {
-                   for(col = 0; col < image->Width; col++)    
-                   {
-                       xAdd = (col / (4 * 64)) * 64 + col % 64;
-                        yAdd = row + ((col / 64) & 3) * uChunk;
-                       dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, 64, x + xAdd, y + yAdd);
-                       memcpy (dst, src, t->texelBytes);
-                       src += t->texelBytes;
-                    }
-               }
-           }
-            else
-           {
-               uRowSeparator = 64 * MIN_TILE_CHUNK / w;
-               for(row = 0; row < image->Height; row++)
-               {
-                   xAdd = (w * (row / MIN_TILE_CHUNK)) % 64;
-                    yAdd = row % MIN_TILE_CHUNK + MIN_TILE_CHUNK * (row / uRowSeparator);
-                   for(col = 0; col < image->Width; col++)    
-                   {
-                       dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + xAdd, y + yAdd);
-                       memcpy (dst, src, t->texelBytes);
-                       src += t->texelBytes;
-                    }
-               }
-           }
-        }
+       if (mask & 1)
+           val |= x;
+       if (mask & 2)
+           val |= x*2 << 5;
+       if (mask & 4)
+           val |= x << (5+6);
+       *sdest++ = val;
     }
-    else
-    {
-        if(w < MIN_TILE_CHUNK)
-       {
-            w = MIN_TILE_CHUNK;
-        }
-        else
-        {
-           if((w > uMaxTileWidth ) && (image->Height <= 8))
-            {
-                reloc = GL_TRUE;
+#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;
+       GLuint srcStride = width * bpp;
+       GLubyte *srcRow = src, *destRow = dest;
+       GLuint sx, y;
+       for (y = 0; y < height; ++y) {
+           src = srcRow;
+           dest = destRow;
+           /* iterate over subtile columns */
+           for (sx = 0; sx < wInSub; ++sx) {
+               memcpy (dest, src, subStride);
+               src += subStride;
+               dest += destStride;
            }
+           srcRow += srcStride;
+           destRow += subStride;
+           /* if the subtile width is 4 skip every other tile */
+           if ((y & 7) == 7 && tileInfo->subWidth == 4)
+               destRow += destStride;
        }
-       if(!reloc & (w > uMaxTileWidth / 2))
-       {
-           for(row = 0; row < image->Height; row++)
-           {
-               for(col = 0; col < image->Width; col++)    
-               {
-                   dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + col, y + row);
-                   memcpy (dst, src, t->texelBytes);
-                   src += t->texelBytes;
-                }
-           }
+    } else if (size > 4) { /* not the last 3 mipmap levels */
+       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;
+       }
+    } else { /* the last 3 mipmap levels */
+       GLuint y;
+       dest += offset;
+       for (y = 0; y < height; ++y) {
+           memcpy (dest, src, bpp*width);
+           src += width * bpp;
+           dest += tileInfo->subWidth * bpp;
        }
-        else
-        {
-           if(reloc & (w > uMaxTileWidth))
-           {
-               for(row = 0; row < image->Height; row++)
-               {
-                   for(col = 0; col < image->Width; col++)    
-                   {
-                       xAdd = (col / (2 * uMaxTileWidth)) * uMaxTileWidth + col % uMaxTileWidth;
-                        yAdd = row + ((col / uMaxTileWidth) & 1) * MIN_TILE_CHUNK;
-                       dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + xAdd, y + yAdd);
-                       memcpy (dst, src, t->texelBytes);
-                       src += t->texelBytes;
-                    }
-               }
-           }
-            else
-           {
-               uRowSeparator = uMaxTileWidth * MIN_TILE_CHUNK / w;
-               for(row = 0; row < image->Height; row++)
-               {
-                    yAdd = row % MIN_TILE_CHUNK + MIN_TILE_CHUNK * (row / uRowSeparator);
-                    xAdd = (w * (row / MIN_TILE_CHUNK)) % uMaxTileWidth;
-                   for(col = 0; col < image->Width; col++)    
-                   {
-                       dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + col + xAdd, y + yAdd);
-                       memcpy (dst, src, t->texelBytes);
-                       src += t->texelBytes;
-                    }
-               }
-           }
-        }
     }
-}        
-
-
-
-__inline void  savageTileTex(savageTextureObjectPtr tex, GLuint level)
-{
-    GLuint uWidth, uHeight;
-    GLint  xOffset, yOffset;
-    GLint  xStart=0, yStart=0;
-    GLint  minSize;
-    GLuint xRepeat, yRepeat;
-    GLuint startCol, startRow;
-    GLuint reloc;
-
-    const struct gl_texture_image *image = tex->image[level].image;
-    
-    reloc = GL_FALSE;
-    uWidth = image->Width2;
-    uHeight = image->Height2;
-
-    if((uWidth > 4) || (uHeight > 4))
-        minSize = MIN_TILE_CHUNK;
-    else
-        minSize = MIPMAP_CHUNK;
-    if(image->Width >= minSize)
-        xRepeat = 1;
-    else
-        xRepeat = minSize / image->Width;
+#endif
+}
 
-    if(image->Height >= minSize)
-        yRepeat = 1;
+static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {
+    /* full subtiles */
+    if (width >= 8 && height >= 8)
+       return width * height * bpp;
+    /* special case for the last three mipmap levels: the hardware computes
+     * the offset internally */
+    else if (width <= 4 && height <= 4)
+       return 0;
+    /* partially filled sub tiles waste memory
+     * on Savage3D and Savage4 with subtile width 4 every other subtile is
+     * skipped if width < 8 so we can assume a uniform subtile width of 8 */
+    else if (width >= 8)
+       return width * 8 * bpp;
+    else if (height >= 8)
+       return 8 * height * bpp;
     else
-    {
-        yRepeat = minSize / image->Height;
-        if(minSize == MIN_TILE_CHUNK)
-            reloc = GL_TRUE;
-    }
-  
-    if(((uWidth < 4) && (uHeight < 4)) && (tex->texelBytes >= 2))
-    { 
-        if((uWidth == 2) || (uHeight == 2))
-        {
-            xStart = 4;
-            yStart = 0;
-        }
-
-        else
-        {
-            xStart = 4;
-            yStart = 4;
-        }
-    }
-    for(xOffset = 0; xOffset < xRepeat; xOffset++)
-    {
-        for(yOffset = 0; yOffset < yRepeat; yOffset++)
-        {
-           startCol = image->Width * xOffset + xStart;
-            startRow = image->Height * yOffset + yStart;
-            savageUploadImage(tex,level, startCol, startRow, reloc);
-       }
-    }
+       return 64 * bpp;
 }
 
 static void savageSetTexWrapping(savageTextureObjectPtr tex, GLenum s, GLenum t)
@@ -656,7 +421,7 @@ static void savageSetTexImages( savageContextPtr imesa,
 {
    savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
-   GLuint offset, width, pitch, i, textureFormat, log_pitch;
+   GLuint offset, i, textureFormat, size;
 
    assert(t);
    assert(image);
@@ -692,28 +457,39 @@ static void savageSetTexImages( savageContextPtr imesa,
       break;
    default:
       _mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
+      return;
    }
 
+   /* Select tiling format depending on the chipset and bytes per texel */
+   if (imesa->savageScreen->chipset <= S3_SAVAGE4)
+       t->tileInfo = &tileInfo_s3d_s4[t->texelBytes];
+   else
+       t->tileInfo = &tileInfo_pro[t->texelBytes];
+
    /* Figure out the size now (and count the levels).  Upload won't be done
     * until later.
     */ 
-   width = image->Width * t->texelBytes;
-   for (pitch = 2, log_pitch=1 ; pitch < width ; pitch *= 2 )
-      log_pitch++;
-   
    t->dirty_images = 0;
-
    offset = 0;
+   size = 1;
    for ( i = 0 ; i < SAVAGE_TEX_MAXLEVELS && tObj->Image[0][i] ; i++ ) {
-      t->image[i].image = tObj->Image[0][i];
+      image = tObj->Image[0][i];
+      t->image[i].image = image;
       t->image[i].offset = offset;
       t->image[i].internalFormat = textureFormat;
       t->dirty_images |= (1<<i);
-      offset += t->image[i].image->Height * pitch;
-      pitch = pitch >> 1;
+      size = savageTexImageSize (image->Width2, image->Height2,
+                                t->texelBytes);
+      offset += size;
    }
 
    t->totalSize = offset;
+   /* the last three mipmap levels don't add to the offset. They are packed
+    * into 64 pixels. */
+   if (size == 0)
+       t->totalSize += 64 * t->texelBytes;
+   /* 2k-aligned */
+   t->totalSize = (t->totalSize + 2047UL) & ~2047UL;
    t->max_level = i-1;
    t->min_level = 0;
 }
@@ -762,7 +538,9 @@ static void savageSwapOutTexObj(savageContextPtr imesa, savageTextureObjectPtr t
 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.
@@ -775,7 +553,50 @@ static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
        fprintf (stderr, "Not supported texture border %d.\n",
                (int) image->Border);
 
-   savageTileTex(t, level);
+   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));
+          }
+   }
 }
 
 
@@ -1689,24 +1510,14 @@ static void savageUpdateTextureState_s3d( GLcontext *ctx )
                         SAVAGE_UPLOAD_TEX0);
     }
 }
-static void savageUpdateTextureState_first( GLcontext *ctx)
+void savageUpdateTextureState( GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
-    if (imesa->savageScreen->chipset <= S3_SAVAGE4) {
-       GetTiledCoordinates16 = GetTiledCoordinates16_4;
-       GetTiledCoordinates32 = GetTiledCoordinates32_4;
-    } else {
-       GetTiledCoordinates16 = GetTiledCoordinates16_8;
-       GetTiledCoordinates32 = GetTiledCoordinates32_8;
-    }
     if (imesa->savageScreen->chipset >= S3_SAVAGE4)
-       savageUpdateTextureState = savageUpdateTextureState_s4;
+       savageUpdateTextureState_s4 (ctx);
     else
-       savageUpdateTextureState = savageUpdateTextureState_s3d;
-    savageUpdateTextureState (ctx);
+       savageUpdateTextureState_s3d (ctx);
 }
-void (*savageUpdateTextureState)( GLcontext *ctx ) =
-    savageUpdateTextureState_first;
 
 
 
index 9ff85e2e321238731872d65b6b65d7dc865be6c9..d26f625f4ddf05db14f166e8021f30e524facb64 100644 (file)
@@ -61,12 +61,20 @@ typedef struct  {
     GLuint hwPhysAddress;
 } savage_texture_parameter_t;
 
+/** \brief Texture tiling information */
+typedef struct savage_tileinfo_t {
+    GLuint width, height;       /**< tile width and height */
+    GLuint wInSub, hInSub;      /**< tile width and height in subtiles */
+    GLuint subWidth, subHeight; /**< subtile width and height */
+    GLuint tinyOffset[2];       /**< internal offsets size 1 and 2 images */
+} savageTileInfo, *savageTileInfoPtr;
+
 struct savage_texture_object_t {
    struct savage_texture_object_t *next, *prev;
    struct gl_texture_object *globj;
    GLuint age;   
    
-     
+   const savageTileInfo *tileInfo;
    GLuint texelBytes;
    GLuint totalSize;
    GLuint bound;
@@ -100,7 +108,7 @@ struct savage_texture_object_t {
 #define __HWParseTexEnvCombine(imesa, flag0, TexCtrl, TexBlendCtrl)
 
 
-extern void (*savageUpdateTextureState)( GLcontext *ctx );
+void savageUpdateTextureState( GLcontext *ctx );
 void savageDDInitTextureFuncs( struct dd_function_table *functions );
 
 void savageDestroyTexObj( savageContextPtr imesa, savageTextureObjectPtr t);