#include "texstore.h"
#include "texobj.h"
-#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 */
-};
-
-GLuint gTileHeight[5] =
-{
- 64, /* 4-bit */
- 32, /* 8-bit */
- 16, /* 16-bit */
- 0, /* 24-bit */
- 16 /* 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
- */
+#include "convolve.h"
+#include "colormac.h"
- uiWidthInTiles = (iBufferWidth + 63) >> 6;
+#include "swrast/swrast.h"
- x10 = x & 0x3;
- x52 = (x & 0x3c ) >> 2;
- x106 = (x & 0x7c0) >> 6;
+#include "xmlpool.h"
- y20 = y & 0x7;
- y3 = (y & 8 ) >> 3;
- y104 = (y & 0x7f0) >> 4;
+#define TILE_INDEX_DXT1 0
+#define TILE_INDEX_8 1
+#define TILE_INDEX_16 2
+#define TILE_INDEX_DXTn 3
+#define TILE_INDEX_32 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
- */
+/* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get
+ * somewhere close to software rendering.
+ */
+#define SAVAGE4_LOD_OFFSET 10
- uiWidthInTiles = (iBufferWidth + 63) >> 6;
+/* Tile info for S3TC formats counts in 4x4 blocks instead of texels.
+ * In DXT1 each block is encoded in 64 bits. In DXT3 and 5 each block is
+ * encoded in 128 bits. */
- x20 = x & 0x7;
- x53 = (x & 0x38 ) >> 3;
- x106 = (x & 0x7c0) >> 6;
+/* 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
+ *
+ * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
+ */
+static const savageTileInfo tileInfo_pro[5] = {
+ {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
+ {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
+ {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
+ {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
+ {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
+};
- y20 = y & 0x7;
- y3 = (y & 8 ) >> 3;
- y104 = (y & 0x7f0) >> 4;
+/* 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] = {
+ {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
+ {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
+ {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
+ {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
+ {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
+};
- return( (x20 << 1) |
- (y20 << 4) |
- (x53 << 7) |
- (y3 << 10) |
- ((y104 * uiWidthInTiles) + x106) << 11 );
+/** \brief Template for subtile uploads.
+ * \param h height in pixels
+ * \param w width in bytes
+ */
+#define SUBTILE_FUNC(w,h) \
+static __inline GLubyte *savageUploadSubtile_##w##x##h \
+(GLubyte *dest, GLubyte *src, GLuint srcStride) \
+{ \
+ GLuint y; \
+ for (y = 0; y < h; ++y) { \
+ memcpy (dest, src, w); \
+ src += srcStride; \
+ dest += w; \
+ } \
+ return dest; \
}
-/* 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;
+SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
+SUBTILE_FUNC(4, 8)
+SUBTILE_FUNC(8, 8)
+SUBTILE_FUNC(16, 8)
+SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
- y20 = y & 0x7;
- y3 = (y & 8 ) >> 3;
- y104 = (y & 0x7f0) >> 4;
+SUBTILE_FUNC(8, 2) /* DXT1 */
+SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 */
- return( (x10 << 2) |
- (y20 << 4) |
- (x42 << 7) |
- (y3 << 10) |
- ((y104 * uiWidthInTiles) + x105) << 11 );
+/** \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
+ *
+ * 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
+ * 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 subStride = tileInfo->subWidth * bpp;
+ GLubyte *srcSRow = src, *srcSTile = src;
+ GLubyte *(*subtileFunc) (GLubyte *, GLubyte *, GLuint);
+ GLuint sx, sy;
+ switch (subStride) {
+ case 2: subtileFunc = savageUploadSubtile_2x8; break;
+ case 4: subtileFunc = savageUploadSubtile_4x8; break;
+ case 8: subtileFunc = tileInfo->subHeight == 8 ?
+ savageUploadSubtile_8x8 : savageUploadSubtile_8x2; break;
+ case 16: subtileFunc = tileInfo->subHeight == 8 ?
+ savageUploadSubtile_16x8 : savageUploadSubtile_16x2; break;
+ case 32: subtileFunc = savageUploadSubtile_32x8; break;
+ default: assert(0);
+ }
+ for (sy = 0; sy < hInSub; ++sy) {
+ srcSTile = srcSRow;
+ for (sx = 0; sx < wInSub; ++sx) {
+ src = srcSTile;
+ dest = subtileFunc (dest, src, srcStride);
+ srcSTile += subStride;
+ }
+ srcSRow += srcStride * tileInfo->subHeight;
+ }
}
-/* 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 );
+/** \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).
+ *
+ * FIXME: Repeating inside this function would be more efficient.
+ */
+static void savageUploadTiny (const savageTileInfo *tileInfo,
+ GLuint pixWidth, GLuint pixHeight,
+ GLuint width, GLuint height, GLuint bpp,
+ GLubyte *src, GLubyte *dest) {
+ GLuint size = MAX2(pixWidth, pixHeight);
+
+ if (width > tileInfo->subWidth) { /* assert: height <= subtile height */
+ GLuint wInSub = width / tileInfo->subWidth;
+ GLuint srcStride = width * bpp;
+ GLuint subStride = tileInfo->subWidth * bpp;
+ GLuint subSkip = (tileInfo->subHeight - height) * subStride;
+ GLubyte *srcSTile = src;
+ GLuint sx, y;
+ for (sx = 0; sx < wInSub; ++sx) {
+ src = srcSTile;
+ for (y = 0; y < height; ++y) {
+ memcpy (dest, src, subStride);
+ src += srcStride;
+ dest += subStride;
+ }
+ dest += subSkip;
+ srcSTile += subStride;
+ }
+ } 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 skipRemainder = tileInfo->subHeight - 1;
+ GLuint y;
+ for (y = 0; y < height; ++y) {
+ memcpy (dest, src, srcStride);
+ src += srcStride;
+ dest += subStride;
+ if ((y & skipRemainder) == skipRemainder)
+ 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 += subStride;
+ }
+ }
}
-/* 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 )
+/** \brief Upload an image from mesa's internal copy.
+ */
+static void savageUploadTexLevel( savageTexObjPtr t, int level )
{
- /*
- // 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 ) );
+ const struct gl_texture_image *image = t->base.tObj->Image[0][level];
+ const savageTileInfo *tileInfo = t->tileInfo;
+ GLuint pixWidth = image->Width2, pixHeight = image->Height2;
+ GLuint bpp = t->texelBytes;
+ GLuint width, height;
+
+ /* 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 (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||
+ t->hwFormat == TFT_S3TC4Bit) {
+ width = (pixWidth+3) / 4;
+ height = (pixHeight+3) / 4;
+ } else {
+ width = pixWidth;
+ height = pixHeight;
}
-}
-
-__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 (pixWidth >= 8 && pixHeight >= 8) {
+ GLuint *dirtyPtr = t->image[level].dirtyTiles;
+ GLuint dirtyMask = 1;
+
+ 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) {
+ if (*dirtyPtr & dirtyMask) {
+ savageUploadTile (tileInfo,
+ tileInfo->wInSub, tileInfo->hInSub,
+ bpp, src, width * bpp, dest);
+ }
+ src += tileInfo->width * bpp;
+ dest += 2048; /* tile size is always 2k */
+ if (dirtyMask == 1<<31) {
+ dirtyMask = 1;
+ dirtyPtr++;
+ } else
+ dirtyMask <<= 1;
+ }
+ srcTRow += width * tileInfo->height * bpp;
}
- }
-
- 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;
- }
+ } else if (width >= tileInfo->width) {
+ GLuint wInTiles = width / tileInfo->width;
+ GLubyte *src = image->Data;
+ GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
+ GLuint tileStride = tileInfo->width * bpp * height;
+ savageContextPtr imesa = (savageContextPtr)t->base.heap->driverContext;
+ GLuint x;
+ /* Savage3D-based chips seem so use a constant tile stride
+ * of 2048 for vertically incomplete tiles, but only if
+ * the color depth is 32bpp. Nobody said this was supposed
+ * to be logical!
+ */
+ if (bpp == 4 && imesa->savageScreen->chipset < S3_SAVAGE4)
+ tileStride = 2048;
+ for (x = 0; x < wInTiles; ++x) {
+ if (*dirtyPtr & dirtyMask) {
+ savageUploadTile (tileInfo,
+ tileInfo->wInSub,
+ height / tileInfo->subHeight,
+ bpp, src, width * bpp, dest);
+ }
+ src += tileInfo->width * bpp;
+ dest += tileStride;
+ if (dirtyMask == 1<<31) {
+ dirtyMask = 1;
+ dirtyPtr++;
+ } else
+ dirtyMask <<= 1;
}
+ } else {
+ savageUploadTile (tileInfo, width / tileInfo->subWidth,
+ height / tileInfo->subHeight, bpp,
+ image->Data, width * bpp,
+ (GLubyte *)(t->bufAddr+t->image[level].offset));
}
- 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;
- }
- }
- }
- }
- }
- else
- {
- if(w < MIN_TILE_CHUNK)
- {
- w = MIN_TILE_CHUNK;
- }
- else
- {
- if((w > uMaxTileWidth ) && (image->Height <= 8))
- {
- reloc = GL_TRUE;
- }
+ } else {
+ GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
+ if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||
+ t->hwFormat == TFT_S3TC4Bit)
+ minWidth = minHeight = 1;
+ else
+ minWidth = minHeight = 4;
+ if (width > minWidth || height > minHeight) {
+ minWidth = tileInfo->subWidth;
+ minHeight = tileInfo->subHeight;
}
- 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;
- }
+ 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, pixWidth, pixHeight,
+ width, height, bpp, image->Data,
+ (GLubyte *)(t->bufAddr +
+ t->image[level].offset+offset));
+ offset += width * 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;
- }
- }
- }
- }
}
-}
+}
+/** \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)
+ 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
+ return 64 * bpp;
+}
+/** \brief Compute the destination size of a compressed texture image
+ */
+static GLuint savageCompressedTexImageSize (GLuint width, GLuint height,
+ GLuint bpp) {
+ width = (width+3) / 4;
+ height = (height+3) / 4;
+ /* full subtiles */
+ if (width >= 2 && height >= 2)
+ return width * height * bpp;
+ /* special case for the last three mipmap levels: the hardware computes
+ * the offset internally */
+ else if (width <= 1 && height <= 1)
+ 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 >= 2)
+ return width * 2 * bpp;
+ else if (height >= 2)
+ return 2 * height * bpp;
+ else
+ return 4 * bpp;
+}
-__inline void savageTileTex(savageTextureObjectPtr tex, GLuint level)
+/** \brief Compute the number of (partial) tiles of a texture image
+ */
+static GLuint savageTexImageTiles (GLuint width, GLuint height,
+ const savageTileInfo *tileInfo)
{
- 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;
+ return (width + tileInfo->width - 1) / tileInfo->width *
+ (height + tileInfo->height - 1) / tileInfo->height;
+}
- if((uWidth > 4) || (uHeight > 4))
- minSize = MIN_TILE_CHUNK;
- else
- minSize = MIPMAP_CHUNK;
-
- if(image->Width >= minSize)
- xRepeat = 1;
- else
- xRepeat = minSize / image->Width;
+/** \brief Mark dirty tiles
+ *
+ * Some care must be taken because tileInfo may not be set or not
+ * up-to-date. So we check if tileInfo is initialized and if the number
+ * of tiles in the bit vector matches the number of tiles computed from
+ * the current tileInfo.
+ */
+static void savageMarkDirtyTiles (savageTexObjPtr t, GLuint level,
+ GLuint totalWidth, GLuint totalHeight,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height)
+{
+ GLuint wInTiles, hInTiles;
+ GLuint x0, y0, x1, y1;
+ GLuint x, y;
+ if (!t->tileInfo)
+ return;
+ wInTiles = (totalWidth + t->tileInfo->width - 1) / t->tileInfo->width;
+ hInTiles = (totalHeight + t->tileInfo->height - 1) / t->tileInfo->height;
+ if (wInTiles * hInTiles != t->image[level].nTiles)
+ return;
- if(image->Height >= minSize)
- yRepeat = 1;
- 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;
- }
+ x0 = xoffset / t->tileInfo->width;
+ y0 = yoffset / t->tileInfo->height;
+ x1 = (xoffset + width - 1) / t->tileInfo->width;
+ y1 = (yoffset + height - 1) / t->tileInfo->height;
+
+ for (y = y0; y <= y1; ++y) {
+ GLuint *ptr = t->image[level].dirtyTiles + (y * wInTiles + x0) / 32;
+ GLuint mask = 1 << (y * wInTiles + x0) % 32;
+ for (x = x0; x <= x1; ++x) {
+ *ptr |= mask;
+ if (mask == (1<<31)) {
+ ptr++;
+ mask = 1;
+ } else {
+ mask <<= 1;
+ }
+ }
+ }
+}
- 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);
- }
- }
+/** \brief Mark all tiles as dirty
+ */
+static void savageMarkAllTiles (savageTexObjPtr t, GLuint level)
+{
+ GLuint words = (t->image[level].nTiles + 31) / 32;
+ if (words)
+ memset(t->image[level].dirtyTiles, ~0, words*sizeof(GLuint));
}
-static void savageSetTexWrapping(savageTextureObjectPtr tex, GLenum s, GLenum t)
+
+static void savageSetTexWrapping(savageTexObjPtr tex, GLenum s, GLenum t)
{
- tex->texParams.sWrapMode = s;
- tex->texParams.tWrapMode = t;
+ tex->setup.sWrapMode = s;
+ tex->setup.tWrapMode = t;
}
-static void savageSetTexFilter(savageTextureObjectPtr t,
- GLenum minf, GLenum magf)
+static void savageSetTexFilter(savageTexObjPtr t, GLenum minf, GLenum magf)
{
- t->texParams.minFilter = minf;
- t->texParams.magFilter = magf;
+ t->setup.minFilter = minf;
+ t->setup.magFilter = magf;
}
/* Need a fallback ?
*/
-static void savageSetTexBorderColor(savageTextureObjectPtr t, GLubyte color[4])
+static void savageSetTexBorderColor(savageTexObjPtr t, GLubyte color[4])
{
/* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
- t->texParams.boarderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]);
+ /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
}
-static savageTextureObjectPtr
+static savageTexObjPtr
savageAllocTexObj( struct gl_texture_object *texObj )
{
- savageTextureObjectPtr t;
+ savageTexObjPtr t;
- t = (savageTextureObjectPtr) calloc(1,sizeof(*t));
+ t = (savageTexObjPtr) calloc(1,sizeof(*t));
texObj->DriverData = t;
if ( t != NULL ) {
+ GLuint i;
/* Initialize non-image-dependent parts of the state:
*/
- t->globj = texObj;
+ t->base.tObj = texObj;
+ t->base.dirty_images[0] = 0;
+ t->dirtySubImages = 0;
+ t->tileInfo = NULL;
+
+ /* Initialize dirty tiles bit vectors
+ */
+ for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i)
+ t->image[i].nTiles = 0;
/* FIXME Something here to set initial values for other parts of
* FIXME t->setup?
*/
- make_empty_list( t );
+ make_empty_list( &t->base );
savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
return t;
}
+/* Mesa texture formats for alpha-images on Savage3D/IX/MX
+ *
+ * Promoting texture images to ARGB888 or ARGB4444 doesn't work
+ * because we can't tell the hardware to ignore the color components
+ * and only use the alpha component. So we define our own texture
+ * formats that promote to ARGB8888 or ARGB4444 and set the color
+ * components to white. This way we get the correct result. */
+static GLboolean
+_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
+ GLenum baseInternalFormat,
+ const struct gl_texture_format *dstFormat,
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride, GLint dstImageStride,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking);
+static GLboolean
+_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
+ GLenum baseInternalFormat,
+ const struct gl_texture_format *dstFormat,
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride, GLint dstImageStride,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking);
+
+static struct gl_texture_format _savage_texformat_a1114444 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 4, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _savage_texstore_a1114444, /* StoreTexImageFunc */
+ NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
+ * savageDDInitTextureFuncs */
+};
+static struct gl_texture_format _savage_texformat_a1118888 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _savage_texstore_a1118888, /* StoreTexImageFunc */
+ NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
+ * savageDDInitTextureFuncs */
+};
+
+static GLboolean
+_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
+ GLenum baseInternalFormat,
+ const struct gl_texture_format *dstFormat,
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride, GLint dstImageStride,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking)
+{
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ baseInternalFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstZoffset * dstImageStride
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ GLint img, row, col;
+
+ ASSERT(dstFormat == &_savage_texformat_a1114444);
+ ASSERT(baseInternalFormat == GL_ALPHA);
+
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUI = (GLushort *) dstRow;
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[0]),
+ 255, 255, 255 );
+ src += 1;
+ }
+ dstRow += dstRowStride;
+ }
+ dstImage += dstImageStride;
+ }
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+static GLboolean
+_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
+ GLenum baseInternalFormat,
+ const struct gl_texture_format *dstFormat,
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride, GLint dstImageStride,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking)
+{
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ baseInternalFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstZoffset * dstImageStride
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ GLint img, row, col;
+
+ ASSERT(dstFormat == &_savage_texformat_a1118888);
+ ASSERT(baseInternalFormat == GL_ALPHA);
+
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[0]),
+ 255, 255, 255 );
+ src += 1;
+ }
+ dstRow += dstRowStride;
+ }
+ dstImage += dstImageStride;
+ }
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
/* Called by the _mesa_store_teximage[123]d() functions. */
static const struct gl_texture_format *
savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
- const GLboolean do32bpt = GL_FALSE;
- const GLboolean force16bpt = GL_FALSE;
+ const GLboolean do32bpt =
+ ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
+ const GLboolean force16bpt =
+ ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
const GLboolean isSavage4 = (imesa->savageScreen->chipset >= S3_SAVAGE4);
(void) format;
- (void) type;
switch ( internalFormat ) {
case 4:
case GL_ALPHA:
case GL_COMPRESSED_ALPHA:
return isSavage4 ? &_mesa_texformat_a8 : (
- do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+ do32bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
case GL_ALPHA4:
- return isSavage4 ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444;
+ return isSavage4 ? &_mesa_texformat_a8 : &_savage_texformat_a1114444;
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
return isSavage4 ? &_mesa_texformat_a8 : (
- !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+ !force16bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
-
+#if 0
+ /* TFT_I8 produces garbage on ProSavageDDR and subsequent texture
+ * disable keeps rendering garbage. Disabled for now. */
case GL_INTENSITY:
case GL_COMPRESSED_INTENSITY:
return isSavage4 ? &_mesa_texformat_i8 : (
case GL_INTENSITY16:
return isSavage4 ? &_mesa_texformat_i8 : (
!force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+#else
+ case GL_INTENSITY:
+ case GL_COMPRESSED_INTENSITY:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ case GL_INTENSITY4:
+ return &_mesa_texformat_argb4444;
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return !force16bpt ? &_mesa_texformat_argb8888 :
+ &_mesa_texformat_argb4444;
+#endif
+
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgb_dxt1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgba_dxt1;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return &_mesa_texformat_rgba_dxt3;
+
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ if (!isSavage4)
+ /* Not the best choice but Savage3D/MX/IX don't support DXT3 or DXT5. */
+ return &_mesa_texformat_rgba_dxt1;
+ /* fall through */
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return &_mesa_texformat_rgba_dxt5;
+
/*
case GL_COLOR_INDEX:
case GL_COLOR_INDEX1_EXT:
static void savageSetTexImages( savageContextPtr imesa,
const struct gl_texture_object *tObj )
{
- savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
+ savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- GLuint offset, width, pitch, i, textureFormat, log_pitch;
+ GLuint offset, i, textureFormat, tileIndex, size;
+ GLint firstLevel, lastLevel;
assert(t);
assert(image);
switch (image->TexFormat->MesaFormat) {
case MESA_FORMAT_ARGB8888:
textureFormat = TFT_ARGB8888;
- t->texelBytes = 4;
+ t->texelBytes = tileIndex = 4;
break;
case MESA_FORMAT_ARGB1555:
textureFormat = TFT_ARGB1555;
- t->texelBytes = 2;
+ t->texelBytes = tileIndex = 2;
break;
case MESA_FORMAT_ARGB4444:
textureFormat = TFT_ARGB4444;
- t->texelBytes = 2;
+ t->texelBytes = tileIndex = 2;
break;
case MESA_FORMAT_RGB565:
textureFormat = TFT_RGB565;
- t->texelBytes = 2;
+ t->texelBytes = tileIndex = 2;
break;
case MESA_FORMAT_L8:
textureFormat = TFT_L8;
- t->texelBytes = 1;
+ t->texelBytes = tileIndex = 1;
break;
case MESA_FORMAT_I8:
textureFormat = TFT_I8;
- t->texelBytes = 1;
+ t->texelBytes = tileIndex = 1;
break;
case MESA_FORMAT_A8:
textureFormat = TFT_A8;
- t->texelBytes = 1;
+ t->texelBytes = tileIndex = 1;
+ break;
+ case MESA_FORMAT_RGB_DXT1:
+ textureFormat = TFT_S3TC4Bit;
+ tileIndex = TILE_INDEX_DXT1;
+ t->texelBytes = 8;
+ break;
+ case MESA_FORMAT_RGBA_DXT1:
+ textureFormat = TFT_S3TC4Bit;
+ tileIndex = TILE_INDEX_DXT1;
+ t->texelBytes = 8;
+ break;
+ case MESA_FORMAT_RGBA_DXT3:
+ textureFormat = TFT_S3TC4A4Bit;
+ tileIndex = TILE_INDEX_DXTn;
+ t->texelBytes = 16;
+ break;
+ case MESA_FORMAT_RGBA_DXT5:
+ textureFormat = TFT_S3TC4CA4Bit;
+ tileIndex = TILE_INDEX_DXTn;
+ t->texelBytes = 16;
break;
default:
_mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
+ return;
}
+ t->hwFormat = textureFormat;
- /* 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;
+ /* Select tiling format depending on the chipset and texture format */
+ if (imesa->savageScreen->chipset <= S3_SAVAGE4)
+ t->tileInfo = &tileInfo_s3d_s4[tileIndex];
+ else
+ t->tileInfo = &tileInfo_pro[tileIndex];
+ /* Compute which mipmap levels we really want to send to the hardware.
+ */
+ driCalculateTextureFirstLastLevel( &t->base );
+ firstLevel = t->base.firstLevel;
+ lastLevel = t->base.lastLevel;
+
+ /* Figure out the size now (and count the levels). Upload won't be
+ * done until later. If the number of tiles changes, it means that
+ * this function is called for the first time on this tex object or
+ * the image or the destination color format changed. So all tiles
+ * are marked as dirty.
+ */
offset = 0;
- for ( i = 0 ; i < SAVAGE_TEX_MAXLEVELS && tObj->Image[0][i] ; i++ ) {
- t->image[i].image = tObj->Image[0][i];
- 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;
- }
-
- t->totalSize = offset;
- t->max_level = i-1;
- t->min_level = 0;
-}
-
-void savageDestroyTexObj(savageContextPtr imesa, savageTextureObjectPtr t)
-{
- if (!t) return;
+ size = 1;
+ for ( i = firstLevel ; i <= lastLevel && tObj->Image[0][i] ; i++ ) {
+ GLuint nTiles;
+ nTiles = savageTexImageTiles (image->Width2, image->Height2, t->tileInfo);
+ if (t->image[i].nTiles != nTiles) {
+ GLuint words = (nTiles + 31) / 32;
+ if (t->image[i].nTiles != 0) {
+ free(t->image[i].dirtyTiles);
+ }
+ t->image[i].dirtyTiles = malloc(words*sizeof(GLuint));
+ memset(t->image[i].dirtyTiles, ~0, words*sizeof(GLuint));
+ }
+ t->image[i].nTiles = nTiles;
- /* This is sad - need to sync *in case* we upload a texture
- * to this newly free memory...
- */
- if (t->MemBlock) {
- mmFreeMem(t->MemBlock);
- t->MemBlock = 0;
+ t->image[i].offset = offset;
- if (t->age > imesa->dirtyAge)
- imesa->dirtyAge = t->age;
+ image = tObj->Image[0][i];
+ if (t->texelBytes >= 8)
+ size = savageCompressedTexImageSize (image->Width2, image->Height2,
+ t->texelBytes);
+ else
+ size = savageTexImageSize (image->Width2, image->Height2,
+ t->texelBytes);
+ offset += size;
}
- if (t->globj)
- t->globj->DriverData = 0;
-
- remove_from_list(t);
- free(t);
+ t->base.lastLevel = i-1;
+ t->base.totalSize = offset;
+ /* the last three mipmap levels don't add to the offset. They are packed
+ * into 64 pixels. */
+ if (size == 0)
+ t->base.totalSize += (t->texelBytes >= 8 ? 4 : 64) * t->texelBytes;
+ /* 2k-aligned (really needed?) */
+ t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL;
}
-
-static void savageSwapOutTexObj(savageContextPtr imesa, savageTextureObjectPtr t)
+void savageDestroyTexObj(savageContextPtr imesa, savageTexObjPtr t)
{
- if (t->MemBlock) {
- mmFreeMem(t->MemBlock);
- t->MemBlock = 0;
+ GLuint i;
- if (t->age > imesa->dirtyAge)
- imesa->dirtyAge = t->age;
- }
+ /* Free dirty tiles bit vectors */
+ for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i) {
+ if (t->image[i].nTiles)
+ free (t->image[i].dirtyTiles);
+ }
- t->dirty_images = ~0;
- move_to_tail(&(imesa->SwappedOut), t);
+ /* See if it was the driver's current object.
+ */
+ if ( imesa != NULL )
+ {
+ for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ )
+ {
+ if ( &t->base == imesa->CurrentTexObj[ i ] ) {
+ assert( t->base.bound & (1 << i) );
+ imesa->CurrentTexObj[ i ] = NULL;
+ }
+ }
+ }
}
-
-
-/* Upload an image from mesa's internal copy.
+/* Upload a texture's images to one of the texture heaps. May have to
+ * eject our own and/or other client's texture objects to make room
+ * for the upload.
*/
-static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
+static void savageUploadTexImages( savageContextPtr imesa, savageTexObjPtr t )
{
- const struct gl_texture_image *image = t->image[level].image;
-
-
- /* 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);
-
- savageTileTex(t, level);
-}
+ const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+ GLuint i;
+ assert(t);
-
-void savagePrintLocalLRU( savageContextPtr imesa , GLuint heap)
-{
- savageTextureObjectPtr t;
- int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]);
-
- foreach( t, &imesa->TexObjList[heap] ) {
- if (!t->globj)
- fprintf(stderr, "Placeholder %d at %x sz %x\n",
- t->MemBlock->ofs / sz,
- t->MemBlock->ofs,
- t->MemBlock->size);
- else
- fprintf(stderr, "Texture (bound %d) at %x sz %x\n",
- t->bound,
- t->MemBlock->ofs,
- t->MemBlock->size);
-
- }
-}
-
-void savagePrintGlobalLRU( savageContextPtr imesa , GLuint heap)
-{
- int i, j;
-
- drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
-
-
- for (i = 0, j = SAVAGE_NR_TEX_REGIONS ; i < SAVAGE_NR_TEX_REGIONS ; i++) {
- fprintf(stderr, "list[%d] age %d next %d prev %d\n",
- j, list[j].age, list[j].next, list[j].prev);
- j = list[j].next;
- if (j == SAVAGE_NR_TEX_REGIONS) break;
- }
+ LOCK_HARDWARE(imesa);
- if (j != SAVAGE_NR_TEX_REGIONS)
- fprintf(stderr, "Loop detected in global LRU\n");
- for (i = 0 ; i < SAVAGE_NR_TEX_REGIONS ; i++)
- {
- fprintf(stderr,"list[%d] age %d next %d prev %d\n",
- i, list[i].age, list[i].next, list[i].prev);
- }
-}
-
-
-void savageResetGlobalLRU( savageContextPtr imesa, GLuint heap )
-{
- drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
- int sz = 1 << imesa->savageScreen->logTextureGranularity[heap];
- int i;
-
- /* (Re)initialize the global circular LRU list. The last element
- * in the array (SAVAGE_NR_TEX_REGIONS) is the sentinal. Keeping it
- * at the end of the array allows it to be addressed rationally
- * when looking up objects at a particular location in texture
- * memory.
+ /* Do we need to eject LRU texture objects?
*/
- for (i = 0 ; (i+1) * sz <= imesa->savageScreen->textureSize[heap]; i++) {
- list[i].prev = i-1;
- list[i].next = i+1;
- list[i].age = 0;
- }
-
- i--;
- list[0].prev = SAVAGE_NR_TEX_REGIONS;
- list[i].prev = i-1;
- list[i].next = SAVAGE_NR_TEX_REGIONS;
- list[SAVAGE_NR_TEX_REGIONS].prev = i;
- list[SAVAGE_NR_TEX_REGIONS].next = 0;
- imesa->sarea->texAge[heap] = 0;
-}
-
+ if (!t->base.memBlock) {
+ GLint heap;
+ GLuint ofs;
+
+ heap = driAllocateTexture(imesa->textureHeaps, imesa->lastTexHeap,
+ (driTextureObject *)t);
+ if (heap == -1) {
+ UNLOCK_HARDWARE(imesa);
+ return;
+ }
-static void savageUpdateTexLRU( savageContextPtr imesa, savageTextureObjectPtr t )
-{
- int i;
- int heap = t->heap;
- int logsz = imesa->savageScreen->logTextureGranularity[heap];
- int start = t->MemBlock->ofs >> logsz;
- int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
- drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
-
- imesa->texAge[heap] = ++imesa->sarea->texAge[heap];
+ ofs = t->base.memBlock->ofs;
+ t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
+ t->bufAddr = (GLubyte *)imesa->savageScreen->texVirtual[heap] + ofs;
+ imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
+ }
- /* Update our local LRU
+ /* Let the world know we've used this memory recently.
*/
- move_to_head( &(imesa->TexObjList[heap]), t );
+ driUpdateTextureLRU( &t->base );
+ UNLOCK_HARDWARE(imesa);
+
+ if (t->base.dirty_images[0] || t->dirtySubImages) {
+ if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
+ fprintf(stderr, "Texture upload: |");
+
+ /* Heap timestamps are only reliable with Savage DRM 2.3.x or
+ * later. Earlier versions had only 16 bit time stamps which
+ * would wrap too frequently. */
+ if (imesa->savageScreen->driScrnPriv->drmMinor >= 3) {
+ unsigned int heap = t->base.heap->heapId;
+ LOCK_HARDWARE(imesa);
+ savageWaitEvent (imesa, imesa->textureHeaps[heap]->timestamp);
+ } else {
+ savageFlushVertices (imesa);
+ LOCK_HARDWARE(imesa);
+ savageFlushCmdBufLocked (imesa, GL_FALSE);
+ WAIT_IDLE_EMPTY_LOCKED(imesa);
+ }
- /* Update the global LRU
- */
- for (i = start ; i <= end ; i++) {
+ for (i = 0 ; i < numLevels ; i++) {
+ const GLint j = t->base.firstLevel + i; /* the texObj's level */
+ if (t->base.dirty_images[0] & (1 << j)) {
+ savageMarkAllTiles(t, j);
+ if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
+ fprintf (stderr, "*");
+ } else if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) {
+ if (t->dirtySubImages & (1 << j))
+ fprintf (stderr, ".");
+ else
+ fprintf (stderr, " ");
+ }
+ if ((t->base.dirty_images[0] | t->dirtySubImages) & (1 << j))
+ savageUploadTexLevel( t, j );
+ }
- list[i].in_use = 1;
- list[i].age = imesa->texAge[heap];
+ UNLOCK_HARDWARE(imesa);
+ t->base.dirty_images[0] = 0;
+ t->dirtySubImages = 0;
- /* remove_from_list(i)
- */
- list[(unsigned)list[i].next].prev = list[i].prev;
- list[(unsigned)list[i].prev].next = list[i].next;
-
- /* insert_at_head(list, i)
- */
- list[i].prev = SAVAGE_NR_TEX_REGIONS;
- list[i].next = list[SAVAGE_NR_TEX_REGIONS].next;
- list[(unsigned)list[SAVAGE_NR_TEX_REGIONS].next].prev = i;
- list[SAVAGE_NR_TEX_REGIONS].next = i;
+ if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
+ fprintf(stderr, "|\n");
}
}
-/* Called for every shared texture region which has increased in age
- * since we last held the lock.
- *
- * Figures out which of our textures have been ejected by other clients,
- * and pushes a placeholder texture onto the LRU list to represent
- * the other client's textures.
- */
-void savageTexturesGone( savageContextPtr imesa,
- GLuint heap,
- GLuint offset,
- GLuint size,
- GLuint in_use )
+static void
+savage4_set_wrap_mode( savageContextPtr imesa, unsigned unit,
+ GLenum s_mode, GLenum t_mode )
{
- savageTextureObjectPtr t, tmp;
-
- foreach_s ( t, tmp, &imesa->TexObjList[heap] ) {
-
- if (t->MemBlock->ofs >= offset + size ||
- t->MemBlock->ofs + t->MemBlock->size <= offset)
- continue;
-
- /* It overlaps - kick it off. Need to hold onto the currently bound
- * objects, however.
- */
- if (t->bound)
- savageSwapOutTexObj( imesa, t );
- else
- savageDestroyTexObj( imesa, t );
- }
-
-
- if (in_use) {
- t = (savageTextureObjectPtr) calloc(1,sizeof(*t));
- if (!t) return;
+ switch( s_mode ) {
+ case GL_REPEAT:
+ imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Wrap;
+ break;
+ case GL_CLAMP:
+ case GL_CLAMP_TO_EDGE:
+ imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Clamp;
+ break;
+ case GL_MIRRORED_REPEAT:
+ imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Mirror;
+ break;
+ }
- t->heap = heap;
- t->MemBlock = mmAllocMem( imesa->texHeap[heap], size, 0, offset);
- if(!t->MemBlock)
- {
- free(t);
- return;
- }
- insert_at_head( &imesa->TexObjList[heap], t );
- }
+ switch( t_mode ) {
+ case GL_REPEAT:
+ imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Wrap;
+ break;
+ case GL_CLAMP:
+ case GL_CLAMP_TO_EDGE:
+ imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Clamp;
+ break;
+ case GL_MIRRORED_REPEAT:
+ imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Mirror;
+ break;
+ }
}
-
-
-
-/* This is called with the lock held. May have to eject our own and/or
- * other client's texture objects to make room for the upload.
+/**
+ * Sets the hardware bits for the specified GL texture filter modes.
+ *
+ * \todo
+ * Does the Savage4 have the ability to select the magnification filter?
*/
-int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t )
+static void
+savage4_set_filter_mode( savageContextPtr imesa, unsigned unit,
+ GLenum minFilter, GLenum magFilter )
{
- int heap;
- int i;
- int ofs;
-
- heap = t->heap = SAVAGE_CARD_HEAP;
-
- /* Do we need to eject LRU texture objects?
- */
- if (!t->MemBlock) {
- while (1)
- {
- t->MemBlock = mmAllocMem( imesa->texHeap[heap], t->totalSize, 12, 0 );
- if (t->MemBlock)
- break;
- else
- {
- heap = t->heap = SAVAGE_AGP_HEAP;
- t->MemBlock = mmAllocMem( imesa->texHeap[heap], t->totalSize, 12, 0 );
-
- if (t->MemBlock)
- break;
- }
-
- if (imesa->TexObjList[heap].prev->bound) {
- fprintf(stderr, "Hit bound texture in upload\n");
- savagePrintLocalLRU( imesa,heap );
- return -1;
- }
-
- if (imesa->TexObjList[heap].prev == &(imesa->TexObjList[heap])) {
- fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
- mmDumpMemInfo( imesa->texHeap[heap] );
- return -1;
- }
-
- savageDestroyTexObj( imesa, imesa->TexObjList[heap].prev );
- }
-
- ofs = t->MemBlock->ofs;
- t->texParams.hwPhysAddress = imesa->savageScreen->textureOffset[heap] + ofs;
- t->BufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
- imesa->dirty |= SAVAGE_UPLOAD_CTX;
- }
-
- /* Let the world know we've used this memory recently.
- */
- savageUpdateTexLRU( imesa, t );
+ (void) magFilter;
- if (t->dirty_images) {
- if (SAVAGE_DEBUG & DEBUG_VERBOSE_LRU)
- fprintf(stderr, "*");
-
- for (i = t->min_level ; i <= t->max_level ; i++)
- if (t->dirty_images & (1<<i))
- savageUploadTexLevel( t, i );
- }
+ switch (minFilter) {
+ case GL_NEAREST:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
+ break;
+ case GL_LINEAR:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
+ break;
- t->dirty_images = 0;
- return 0;
-}
+ case GL_NEAREST_MIPMAP_NEAREST:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
+ break;
-static void savageTexSetUnit( savageTextureObjectPtr t, GLuint unit )
-{
- if (t->current_unit == unit) return;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
+ break;
- t->current_unit = unit;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Trilin;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
+ break;
+ }
}
-
-
static void savageUpdateTex0State_s4( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
struct gl_texture_object *tObj;
- savageTextureObjectPtr t;
+ struct gl_texture_image *image;
+ savageTexObjPtr t;
GLuint format;
/* disable */
- if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
- imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
- imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
- imesa->regs.s4.texCtrl[0].ui = 0x20f040;
- imesa->regs.s4.texAddr[0].ui = 0;
+ imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
+ imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
+ imesa->regs.s4.texCtrl[0].ui = 0x20f040;
+ if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
return;
- }
tObj = ctx->Texture.Unit[0]._Current;
- if (ctx->Texture.Unit[0]._ReallyEnabled != TEXTURE_2D_BIT ||
- tObj->Image[0][tObj->BaseLevel]->Border > 0) {
- /* 1D or 3D texturing enabled, or texture border - fallback */
+ if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
+ || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ /* 3D texturing enabled, or texture border - fallback */
FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
return;
}
return;
}
- if (t->current_unit != 0)
- savageTexSetUnit( t, 0 );
-
- imesa->CurrentTexObj[0] = t;
- t->bound |= 1;
+ imesa->CurrentTexObj[0] = &t->base;
+ t->base.bound |= 1;
- if (t->dirty_images) {
+ if (t->base.dirty_images[0] || t->dirtySubImages) {
savageSetTexImages(imesa, tObj);
- savageUploadTexImages(imesa, imesa->CurrentTexObj[0]);
+ savageUploadTexImages(imesa, t);
}
- if (t->MemBlock)
- savageUpdateTexLRU( imesa, t );
+ driUpdateTextureLRU( &t->base );
- format = tObj->Image[0][tObj->BaseLevel]->Format;
+ format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
switch (ctx->Texture.Unit[0].EnvMode) {
case GL_REPLACE:
break;
case GL_BLEND:
+ imesa->regs.s4.texBlendColor.ui = imesa->texEnvColor;
switch (format)
{
&imesa->regs.s4.texBlendCtrl[0]);
break;
- /*
- GL_ADD
- */
case GL_ADD:
- printf("Add\n");
imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
- imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
+ switch (format)
+ {
+ case GL_ALPHA:
+ imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
+ break;
+
+ case GL_LUMINANCE:
+ case GL_RGB:
+ imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
+ break;
+
+ case GL_INTENSITY:
+ imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
+ break;
+ }
__HWEnvCombineSingleUnitScale(imesa, 0, 0,
&imesa->regs.s4.texBlendCtrl[0]);
break;
break;
}
- imesa->regs.s4.texCtrl[0].ni.uMode = !(t->texParams.sWrapMode & 0x01);
- imesa->regs.s4.texCtrl[0].ni.vMode = !(t->texParams.tWrapMode & 0x01);
+ savage4_set_wrap_mode( imesa, 0, t->setup.sWrapMode, t->setup.tWrapMode );
+ savage4_set_filter_mode( imesa, 0, t->setup.minFilter, t->setup.magFilter );
- switch (t->texParams.minFilter)
- {
- case GL_NEAREST:
- imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Point;
- imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_FALSE;
- break;
-
- case GL_LINEAR:
- imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Bilin;
- imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_FALSE;
- break;
-
- case GL_NEAREST_MIPMAP_NEAREST:
- imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Point;
- imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
- break;
-
- case GL_LINEAR_MIPMAP_NEAREST:
- imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Bilin;
- imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
- break;
-
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
- imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Trilin;
- imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
- break;
- }
-
- if((ctx->Texture.Unit[0].LodBias !=0.0F) &&
+ if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
(imesa->regs.s4.texCtrl[0].ni.dBias != 0))
{
- union {
- GLfloat f;
- GLint i;
- } bias;
- GLuint ul;
-
- bias.f = ctx->Texture.Unit[0].LodBias;
-
- /* if the value is >= 15.9375 determine whether >= 16
- or <0
- */
- if(((bias.i) & 0x7FFFFFFF) >= 0x417F0000)
- {
- if((bias.i) & 0x80000000)
- {
- ul=0x101;
- }
- else
- {
- ul=0xff;
- }
- }
- else
- {
- ul=(GLuint)(bias.f*16.0);
- }
-
- ul &= 0x1FF;
- imesa->regs.s4.texCtrl[0].ni.dBias = ul;
+ int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0) +
+ SAVAGE4_LOD_OFFSET;
+ if (bias < -256)
+ bias = -256;
+ else if (bias > 255)
+ bias = 255;
+ imesa->regs.s4.texCtrl[0].ni.dBias = bias & 0x1ff;
}
+ image = tObj->Image[0][tObj->BaseLevel];
imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
- imesa->regs.s4.texDescr.ni.tex0Width = t->image[0].image->WidthLog2;
- imesa->regs.s4.texDescr.ni.tex0Height = t->image[0].image->HeightLog2;
- imesa->regs.s4.texDescr.ni.tex0Fmt = t->image[0].internalFormat;
- imesa->regs.s4.texCtrl[0].ni.dMax = t->max_level;
+ imesa->regs.s4.texDescr.ni.tex0Width = image->WidthLog2;
+ imesa->regs.s4.texDescr.ni.tex0Height = image->HeightLog2;
+ imesa->regs.s4.texDescr.ni.tex0Fmt = t->hwFormat;
+ imesa->regs.s4.texCtrl[0].ni.dMax = t->base.lastLevel - t->base.firstLevel;
if (imesa->regs.s4.texDescr.ni.tex1En)
imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
- imesa->regs.s4.texAddr[0].ui = (GLuint) t->texParams.hwPhysAddress | 0x2;
- if(t->heap == SAVAGE_AGP_HEAP)
+ imesa->regs.s4.texAddr[0].ui = (u_int32_t) t->setup.physAddr | 0x2;
+ if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[0].ui |= 0x1;
return;
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
struct gl_texture_object *tObj;
- savageTextureObjectPtr t;
+ struct gl_texture_image *image;
+ savageTexObjPtr t;
GLuint format;
/* disable */
return;
}
- if (ctx->Texture.Unit[1]._ReallyEnabled == 0) {
- imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
- imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
- imesa->regs.s4.texCtrl[1].ui = 0x20f040;
- imesa->regs.s4.texAddr[1].ui = 0;
- imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
+ imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
+ imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
+ imesa->regs.s4.texCtrl[1].ui = 0x20f040;
+ imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
+ if (ctx->Texture.Unit[1]._ReallyEnabled == 0)
return;
- }
tObj = ctx->Texture.Unit[1]._Current;
- if (ctx->Texture.Unit[1]._ReallyEnabled != TEXTURE_2D_BIT ||
- tObj->Image[0][tObj->BaseLevel]->Border > 0) {
- /* 1D or 3D texturing enabled, or texture border - fallback */
+ if ((ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
+ || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ /* 3D texturing enabled, or texture border - fallback */
FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
return;
}
return;
}
- if (t->current_unit != 1)
- savageTexSetUnit( t, 1 );
+ imesa->CurrentTexObj[1] = &t->base;
- imesa->CurrentTexObj[1] = t;
+ t->base.bound |= 2;
- t->bound |= 2;
-
- if (t->dirty_images) {
+ if (t->base.dirty_images[0] || t->dirtySubImages) {
savageSetTexImages(imesa, tObj);
- savageUploadTexImages(imesa, imesa->CurrentTexObj[1]);
+ savageUploadTexImages(imesa, t);
}
- if (t->MemBlock)
- savageUpdateTexLRU( imesa, t );
+ driUpdateTextureLRU( &t->base );
- format = tObj->Image[0][tObj->BaseLevel]->Format;
+ format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
switch (ctx->Texture.Unit[1].EnvMode) {
case GL_REPLACE:
__HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
break;
-/*#if GL_EXT_texture_env_add*/
case GL_ADD:
imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
- imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
+ switch (format)
+ {
+ case GL_ALPHA:
+ imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
+ break;
+
+ case GL_LUMINANCE:
+ case GL_RGB:
+ imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
+ break;
+
+ case GL_INTENSITY:
+ imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
+ break;
+ }
__HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
break;
-/*#endif*/
#if GL_ARB_texture_env_combine
case GL_COMBINE_ARB:
break;
default:
- fprintf(stderr, "unkown tex 1 env mode\n");
+ fprintf(stderr, "unknown tex 1 env mode\n");
exit(1);
break;
}
- imesa->regs.s4.texCtrl[1].ni.uMode = !(t->texParams.sWrapMode & 0x01);
- imesa->regs.s4.texCtrl[1].ni.vMode = !(t->texParams.tWrapMode & 0x01);
+ savage4_set_wrap_mode( imesa, 1, t->setup.sWrapMode, t->setup.tWrapMode );
+ savage4_set_filter_mode( imesa, 1, t->setup.minFilter, t->setup.magFilter );
- switch (t->texParams.minFilter)
- {
- case GL_NEAREST:
- imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Point;
- imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_FALSE;
- break;
-
- case GL_LINEAR:
- imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Bilin;
- imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_FALSE;
- break;
-
- case GL_NEAREST_MIPMAP_NEAREST:
- imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Point;
- imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
- break;
-
- case GL_LINEAR_MIPMAP_NEAREST:
- imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Bilin;
- imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
- break;
-
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
- imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Trilin;
- imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
- break;
- }
-
- if((ctx->Texture.Unit[1].LodBias !=0.0F)&&
+ if((ctx->Texture.Unit[1].LodBias !=0.0F) ||
(imesa->regs.s4.texCtrl[1].ni.dBias != 0))
{
- union {
- GLfloat f;
- GLint i;
- } bias;
- GLuint ul;
-
- bias.f = ctx->Texture.Unit[1].LodBias;
-
- /* if the value is >= 15.9375 determine whether >= 16
- or <0
- */
- if(((bias.i) & 0x7FFFFFFF) >= 0x417F0000)
- {
- if((bias.i) & 0x80000000)
- {
- ul=0x101;
- }
- else
- {
- ul=0xff;
- }
- }
- else
- {
- ul=(GLuint)(bias.f*16.0);
- }
-
- ul &= 0x1FF;
- imesa->regs.s4.texCtrl[1].ni.dBias = ul;
+ int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0) +
+ SAVAGE4_LOD_OFFSET;
+ if (bias < -256)
+ bias = -256;
+ else if (bias > 255)
+ bias = 255;
+ imesa->regs.s4.texCtrl[1].ni.dBias = bias & 0x1ff;
}
+ image = tObj->Image[0][tObj->BaseLevel];
imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
- imesa->regs.s4.texDescr.ni.tex1Width = t->image[0].image->WidthLog2;
- imesa->regs.s4.texDescr.ni.tex1Height = t->image[0].image->HeightLog2;
- imesa->regs.s4.texDescr.ni.tex1Fmt = t->image[0].internalFormat;
- imesa->regs.s4.texCtrl[1].ni.dMax = t->max_level;
+ imesa->regs.s4.texDescr.ni.tex1Width = image->WidthLog2;
+ imesa->regs.s4.texDescr.ni.tex1Height = image->HeightLog2;
+ imesa->regs.s4.texDescr.ni.tex1Fmt = t->hwFormat;
+ imesa->regs.s4.texCtrl[1].ni.dMax = t->base.lastLevel - t->base.firstLevel;
imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
- imesa->regs.s4.texAddr[1].ui = (GLuint) t->texParams.hwPhysAddress| 2;
- if(t->heap == SAVAGE_AGP_HEAP)
+ imesa->regs.s4.texAddr[1].ui = (u_int32_t) t->setup.physAddr | 2;
+ if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[1].ui |= 0x1;
}
static void savageUpdateTexState_s3d( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
struct gl_texture_object *tObj;
- savageTextureObjectPtr t;
+ struct gl_texture_image *image;
+ savageTexObjPtr t;
GLuint format;
/* disable */
- if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
- imesa->regs.s3d.texCtrl.ui = 0;
- imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
- imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
- imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
- imesa->regs.s3d.texAddr.ui = 0;
+ imesa->regs.s3d.texCtrl.ui = 0;
+ imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
+ imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
+ imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
+ if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
return;
- }
tObj = ctx->Texture.Unit[0]._Current;
- if (ctx->Texture.Unit[0]._ReallyEnabled != TEXTURE_2D_BIT ||
- tObj->Image[0][tObj->BaseLevel]->Border > 0) {
- /* 1D or 3D texturing enabled, or texture border - fallback */
+ if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
+ || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ /* 3D texturing enabled, or texture border - fallback */
FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
return;
}
return;
}
- if (t->current_unit != 0)
- savageTexSetUnit( t, 0 );
-
- imesa->CurrentTexObj[0] = t;
- t->bound |= 1;
+ imesa->CurrentTexObj[0] = &t->base;
+ t->base.bound |= 1;
- if (t->dirty_images) {
+ if (t->base.dirty_images[0] || t->dirtySubImages) {
savageSetTexImages(imesa, tObj);
- savageUploadTexImages(imesa, imesa->CurrentTexObj[0]);
+ savageUploadTexImages(imesa, t);
}
- if (t->MemBlock)
- savageUpdateTexLRU( imesa, t );
+ driUpdateTextureLRU( &t->base );
- format = tObj->Image[0][tObj->BaseLevel]->Format;
+ format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
/* FIXME: copied from utah-glx, probably needs some tuning */
switch (ctx->Texture.Unit[0].EnvMode) {
case GL_DECAL:
- imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
+ imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECALALPHA_S3D;
break;
case GL_REPLACE:
- imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
+ switch (format) {
+ case GL_ALPHA: /* FIXME */
+ imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 4;
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
+ break;
+ case GL_INTENSITY:
+ imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
+ }
break;
- case GL_BLEND: /* FIXIT */
+ case GL_BLEND: /* hardware can't do GL_BLEND */
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+ return;
case GL_MODULATE:
imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
break;
default:
- fprintf(stderr, "unkown tex env mode\n");
+ fprintf(stderr, "unknown tex env mode\n");
/*exit(1);*/
break;
}
- imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
- imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-
- /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
- truth. */
+ /* The Savage3D can't handle different wrapping modes in s and t.
+ * If they are not the same, fall back to software. */
+ if (t->setup.sWrapMode != t->setup.tWrapMode) {
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+ return;
+ }
imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
- if (t->texParams.sWrapMode == GL_CLAMP)
- imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Clamp;
- else
- imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Wrap;
+ imesa->regs.s3d.texCtrl.ni.wrapMode =
+ (t->setup.sWrapMode == GL_REPEAT) ? TAM_Wrap : TAM_Clamp;
- switch (t->texParams.minFilter) {
+ switch (t->setup.minFilter) {
case GL_NEAREST:
imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
}
*/
- /* LOD bias makes corruption of small mipmap levels worse on Savage IX
- * but doesn't show the desired effect with the lodbias mesa demo. */
- imesa->regs.s3d.texCtrl.ni.dBias = 0;
+ if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
+ (imesa->regs.s3d.texCtrl.ni.dBias != 0))
+ {
+ int bias = (int)(ctx->Texture.Unit[0].LodBias * 16.0);
+ if (bias < -256)
+ bias = -256;
+ else if (bias > 255)
+ bias = 255;
+ imesa->regs.s3d.texCtrl.ni.dBias = bias & 0x1ff;
+ }
+ image = tObj->Image[0][tObj->BaseLevel];
imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
- imesa->regs.s3d.texDescr.ni.texWidth = t->image[0].image->WidthLog2;
- imesa->regs.s3d.texDescr.ni.texHeight = t->image[0].image->HeightLog2;
- assert (t->image[0].internalFormat <= 7);
- imesa->regs.s3d.texDescr.ni.texFmt = t->image[0].internalFormat;
-
- imesa->regs.s3d.texAddr.ni.addr = (GLuint) t->texParams.hwPhysAddress >> 3;
- if(t->heap == SAVAGE_AGP_HEAP) {
- imesa->regs.s3d.texAddr.ni.inSysTex = 1;
- imesa->regs.s3d.texAddr.ni.inAGPTex = 1;
- } else {
- imesa->regs.s3d.texAddr.ni.inSysTex = 0;
- imesa->regs.s3d.texAddr.ni.inAGPTex = 1;
- }
+ imesa->regs.s3d.texDescr.ni.texWidth = image->WidthLog2;
+ imesa->regs.s3d.texDescr.ni.texHeight = image->HeightLog2;
+ assert (t->hwFormat <= 7);
+ imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
+
+ imesa->regs.s3d.texAddr.ui = (u_int32_t) t->setup.physAddr | 2;
+ if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
+ imesa->regs.s3d.texAddr.ui |= 0x1;
}
+static void savageTimestampTextures( savageContextPtr imesa )
+{
+ /* Timestamp current texture objects for texture heap aging.
+ * Only useful with long-lived 32-bit event tags available
+ * with Savage DRM 2.3.x or later. */
+ if ((imesa->CurrentTexObj[0] || imesa->CurrentTexObj[1]) &&
+ imesa->savageScreen->driScrnPriv->drmMinor >= 3) {
+ unsigned int e;
+ FLUSH_BATCH(imesa);
+ e = savageEmitEvent(imesa, SAVAGE_WAIT_3D);
+ if (imesa->CurrentTexObj[0])
+ imesa->CurrentTexObj[0]->timestamp = e;
+ if (imesa->CurrentTexObj[1])
+ imesa->CurrentTexObj[1]->timestamp = e;
+ }
+}
+
static void savageUpdateTextureState_s4( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ /* When a texture is about to change or be disabled, timestamp the
+ * old texture(s). We'll have to wait for this time stamp before
+ * uploading anything to the same texture heap.
+ */
+ if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
+ ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
+ (imesa->CurrentTexObj[1] && ctx->Texture.Unit[1]._ReallyEnabled &&
+ ctx->Texture.Unit[1]._Current->DriverData != imesa->CurrentTexObj[1]) ||
+ (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled) ||
+ (imesa->CurrentTexObj[1] && !ctx->Texture.Unit[1]._ReallyEnabled))
+ savageTimestampTextures(imesa);
+
if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound &= ~2;
imesa->CurrentTexObj[0] = 0;
imesa->CurrentTexObj[1] = 0;
- FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
savageUpdateTex0State_s4( ctx );
savageUpdateTex1State_s4( ctx );
- imesa->dirty |= (SAVAGE_UPLOAD_CTX |
- SAVAGE_UPLOAD_TEX0 |
+ imesa->dirty |= (SAVAGE_UPLOAD_TEX0 |
SAVAGE_UPLOAD_TEX1);
}
static void savageUpdateTextureState_s3d( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ /* When a texture is about to change or be disabled, timestamp the
+ * old texture(s). We'll have to wait for this time stamp before
+ * uploading anything to the same texture heap.
+ */
+ if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
+ ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
+ (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled))
+ savageTimestampTextures(imesa);
+
if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
imesa->CurrentTexObj[0] = 0;
- if (ctx->Texture.Unit[1]._ReallyEnabled) {
- FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
- } else {
- FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
- savageUpdateTexState_s3d( ctx );
- imesa->dirty |= (SAVAGE_UPLOAD_CTX |
- SAVAGE_UPLOAD_TEX0);
- }
+ savageUpdateTexState_s3d( ctx );
+ imesa->dirty |= (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;
- }
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
+ FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_FALSE);
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;
struct gl_texture_unit *texUnit =
&ctx->Texture.Unit[ctx->Texture.CurrentUnit];
const GLfloat *fc = texUnit->EnvColor;
- GLuint r, g, b, a, col;
+ GLuint r, g, b, a;
CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
- col = ((a << 24) |
- (r << 16) |
- (g << 8) |
- (b << 0));
+ imesa->texEnvColor = ((a << 24) | (r << 16) |
+ (g << 8) | (b << 0));
}
}
+/* Update the heap's time stamp, so the new image is not uploaded
+ * while the old one is still in use. If the texture that is going to
+ * be changed is currently bound, we need to timestamp the texture
+ * first. */
+static void savageTexImageChanged (savageTexObjPtr t) {
+ if (t->base.heap) {
+ if (t->base.bound)
+ savageTimestampTextures(
+ (savageContextPtr)t->base.heap->driverContext);
+ if (t->base.timestamp > t->base.heap->timestamp)
+ t->base.heap->timestamp = t->base.timestamp;
+ }
+}
+
+static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
+ if (t) {
+ savageTexImageChanged (t);
+ } else {
+ t = savageAllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ return;
+ }
+ }
+ _mesa_store_teximage1d( ctx, target, level, internalFormat,
+ width, border, format, type,
+ pixels, packing, texObj, texImage );
+ t->base.dirty_images[0] |= (1 << level);
+ SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void savageTexSubImage1D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
+ assert( t ); /* this _should_ be true */
+ if (t) {
+ savageTexImageChanged (t);
+ savageMarkDirtyTiles(t, level, texImage->Width2, 1,
+ xoffset, 0, width, 1);
+ } else {
+ t = savageAllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
+ return;
+ }
+ t->base.dirty_images[0] |= (1 << level);
+ }
+ _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+ format, type, pixels, packing, texObj,
+ texImage);
+ t->dirtySubImages |= (1 << level);
+ SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
- savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
+ savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
if (t) {
- savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
+ savageTexImageChanged (t);
} else {
t = savageAllocTexObj(texObj);
if (!t) {
_mesa_store_teximage2d( ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, packing, texObj, texImage );
- t->dirty_images |= (1 << level);
+ t->base.dirty_images[0] |= (1 << level);
SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
}
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
- savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
+ savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
assert( t ); /* this _should_ be true */
if (t) {
- savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
+ savageTexImageChanged (t);
+ savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
+ xoffset, yoffset, width, height);
} else {
t = savageAllocTexObj(texObj);
if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
return;
}
+ t->base.dirty_images[0] |= (1 << level);
}
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
- t->dirty_images |= (1 << level);
+ t->dirtySubImages |= (1 << level);
+ SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void
+savageCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
+ if (t) {
+ savageTexImageChanged (t);
+ } else {
+ t = savageAllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ return;
+ }
+ }
+ _mesa_store_compressed_teximage2d( ctx, target, level, internalFormat,
+ width, height, border, imageSize,
+ data, texObj, texImage );
+ t->base.dirty_images[0] |= (1 << level);
+ SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void
+savageCompressedTexSubImage2D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
+ assert( t ); /* this _should_ be true */
+ if (t) {
+ savageTexImageChanged (t);
+ savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
+ xoffset, yoffset, width, height);
+ } else {
+ t = savageAllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
+ return;
+ }
+ t->base.dirty_images[0] |= (1 << level);
+ }
+ _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset,
+ width, height, format, imageSize,
+ data, texObj, texImage);
+ t->dirtySubImages |= (1 << level);
SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
}
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
- savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
+ savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
- if (!t || target != GL_TEXTURE_2D)
+ if (!t || (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D))
return;
switch (pname) {
{
savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
- assert( (target != GL_TEXTURE_2D) || (tObj->DriverData != NULL) );
+ assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) ||
+ (tObj->DriverData != NULL) );
imesa->new_state |= SAVAGE_NEW_TEXTURE;
}
static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
- savageTextureObjectPtr t = (savageTextureObjectPtr)tObj->DriverData;
+ driTextureObject *t = (driTextureObject *)tObj->DriverData;
savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
if (t) {
+ if (t->bound)
+ savageTimestampTextures(imesa);
- if (t->bound) {
- imesa->CurrentTexObj[t->bound-1] = 0;
- imesa->new_state |= SAVAGE_NEW_TEXTURE;
- }
-
- savageDestroyTexObj(imesa,t);
- tObj->DriverData=0;
+ driDestroyTextureObject(t);
}
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, tObj);
}
-static GLboolean savageIsTextureResident( GLcontext *ctx,
- struct gl_texture_object *t )
-{
- savageTextureObjectPtr mt;
-
-/* LOCK_HARDWARE; */
- mt = (savageTextureObjectPtr)t->DriverData;
-/* UNLOCK_HARDWARE; */
-
- return mt && mt->MemBlock;
-}
-
-
static struct gl_texture_object *
savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
{
{
functions->TexEnv = savageTexEnv;
functions->ChooseTextureFormat = savageChooseTextureFormat;
+ functions->TexImage1D = savageTexImage1D;
+ functions->TexSubImage1D = savageTexSubImage1D;
functions->TexImage2D = savageTexImage2D;
functions->TexSubImage2D = savageTexSubImage2D;
+ functions->CompressedTexImage2D = savageCompressedTexImage2D;
+ functions->CompressedTexSubImage2D = savageCompressedTexSubImage2D;
functions->BindTexture = savageBindTexture;
functions->NewTextureObject = savageNewTextureObject;
functions->DeleteTexture = savageDeleteTexture;
- functions->IsTextureResident = savageIsTextureResident;
+ functions->IsTextureResident = driIsTextureResident;
functions->TexParameter = savageTexParameter;
+
+ /* Texel fetching with our custom texture formats works just like
+ * the standard argb formats. */
+ _savage_texformat_a1114444.FetchTexel1D = _mesa_texformat_argb4444.FetchTexel1D;
+ _savage_texformat_a1114444.FetchTexel2D = _mesa_texformat_argb4444.FetchTexel2D;
+ _savage_texformat_a1114444.FetchTexel3D = _mesa_texformat_argb4444.FetchTexel3D;
+ _savage_texformat_a1114444.FetchTexel1Df= _mesa_texformat_argb4444.FetchTexel1Df;
+ _savage_texformat_a1114444.FetchTexel2Df= _mesa_texformat_argb4444.FetchTexel2Df;
+ _savage_texformat_a1114444.FetchTexel3Df= _mesa_texformat_argb4444.FetchTexel3Df;
+
+ _savage_texformat_a1118888.FetchTexel1D = _mesa_texformat_argb8888.FetchTexel1D;
+ _savage_texformat_a1118888.FetchTexel2D = _mesa_texformat_argb8888.FetchTexel2D;
+ _savage_texformat_a1118888.FetchTexel3D = _mesa_texformat_argb8888.FetchTexel3D;
+ _savage_texformat_a1118888.FetchTexel1Df= _mesa_texformat_argb8888.FetchTexel1Df;
+ _savage_texformat_a1118888.FetchTexel2Df= _mesa_texformat_argb8888.FetchTexel2Df;
+ _savage_texformat_a1118888.FetchTexel3Df= _mesa_texformat_argb8888.FetchTexel3Df;
}