#include <GL/gl.h>
-#include "mm.h"
+#include "main/mm.h"
#include "savagecontext.h"
#include "savagetex.h"
#include "savagetris.h"
#include "savageioctl.h"
-#include "simple_list.h"
-#include "enums.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
#include "savage_bci.h"
-#include "macros.h"
-#include "texformat.h"
-#include "texstore.h"
-#include "texobj.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "main/texstore.h"
+#include "main/texobj.h"
+#include "main/convolve.h"
+#include "main/colormac.h"
#include "swrast/swrast.h"
#include "xmlpool.h"
+#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
+
+/* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get
+ * somewhere close to software rendering.
+ */
+#define SAVAGE4_LOD_OFFSET 10
+
+/* 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. */
+
/* 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.
* Yuck! 8-bit texture formats use 4x8 subtiles. See below.
*/
static const savageTileInfo tileInfo_pro[5] = {
- {64, 64, 8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
+ {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 */
- { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
+ {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
{32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
};
* x 1
*/
static const savageTileInfo tileInfo_s3d_s4[5] = {
- {64, 64, 16, 8, 4, 8, {0x18, 0x10}}, /* 4-bit */
+ {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 */
- { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
+ {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
{32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
};
* \param w width in bytes
*/
#define SUBTILE_FUNC(w,h) \
-static __inline GLubyte *savageUploadSubtile_##w##x##h \
+static INLINE GLubyte *savageUploadSubtile_##w##x##h \
(GLubyte *dest, GLubyte *src, GLuint srcStride) \
{ \
GLuint y; \
SUBTILE_FUNC(16, 8)
SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
-/** \brief Table of subtile upload functions
- *
- * Indexed by the binary logarithm of the width in bytes.
- */
-static GLubyte *(*savageSubtileTab[]) (GLubyte *, GLubyte *, GLuint) = {
- NULL,
- savageUploadSubtile_2x8,
- savageUploadSubtile_4x8,
- savageUploadSubtile_8x8,
- savageUploadSubtile_16x8,
- savageUploadSubtile_32x8
-};
+SUBTILE_FUNC(8, 2) /* DXT1 */
+SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 */
/** \brief Upload a complete tile from src (srcStride) to dest
*
GLubyte *src, GLuint srcStride, GLubyte *dest) {
GLuint subStride = tileInfo->subWidth * bpp;
GLubyte *srcSRow = src, *srcSTile = src;
- GLubyte *(*subtileFunc) (GLubyte *, GLubyte *, GLuint) =
- savageSubtileTab[(tileInfo->subWidth == 4 ? 2 : 3) +
- ((bpp == 1) ? 0 : (bpp == 2) ? 1 : 2)];
+ 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) {
* 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(width, height);
+ 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;
/* if the subtile width is 4 we have to skip every other subtile */
- GLuint subSkip = tileInfo->subWidth == 4 ?
+ 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 & 7) == 7)
+ if ((y & skipRemainder) == skipRemainder)
dest += subSkip;
}
} else { /* the last 3 mipmap levels */
{
const struct gl_texture_image *image = t->base.tObj->Image[0][level];
const savageTileInfo *tileInfo = t->tileInfo;
- GLuint width = image->Width2, height = image->Height2;
+ 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.
fprintf (stderr, "Not supported texture border %d.\n",
(int) image->Border);
- if (width >= 8 && height >= tileInfo->subHeight) {
+ 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;
+ }
+
+ if (pixWidth >= 8 && pixHeight >= 8) {
GLuint *dirtyPtr = t->image[level].dirtyTiles;
GLuint dirtyMask = 1;
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,
bpp, src, width * bpp, dest);
}
src += tileInfo->width * bpp;
- dest += tileInfo->width * bpp * height;
+ dest += tileStride;
if (dirtyMask == 1<<31) {
dirtyMask = 1;
dirtyPtr++;
}
} else {
GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
- if (width > 4 || height > 4) {
+ 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;
- } else {
- minWidth = 4;
- minHeight = 4;
}
hRepeat = width >= minWidth ? 1 : minWidth / width;
vRepeat = height >= minHeight ? 1 : minHeight / height;
for (y = 0; y < vRepeat; ++y) {
GLuint offset = y * tileInfo->subWidth*height * bpp;
for (x = 0; x < hRepeat; ++x) {
- savageUploadTiny (tileInfo, width, height, bpp, image->Data,
+ savageUploadTiny (tileInfo, pixWidth, pixHeight,
+ width, height, bpp, image->Data,
(GLubyte *)(t->bufAddr +
t->image[level].offset+offset));
offset += width * bpp;
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;
+}
+
/** \brief Compute the number of (partial) tiles of a texture image
*/
static GLuint savageTexImageTiles (GLuint width, GLuint height,
/* Need a fallback ?
*/
-static void savageSetTexBorderColor(savageTexObjPtr t, GLubyte color[4])
+static void savageSetTexBorderColor(savageTexObjPtr t, const GLfloat color[4])
{
/* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
/*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
- savageSetTexBorderColor(t,texObj->_BorderChan);
+ savageSetTexBorderColor(t,texObj->BorderColor);
}
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.
+ */
+
+#if 0
+/* Using MESA_FORMAT_RGBA8888 to store alpha-only textures should
+ * work but is space inefficient.
+ */
+
+static GLboolean
+_savage_texstore_a1114444(TEXSTORE_PARAMS);
+
+static GLboolean
+_savage_texstore_a1118888(TEXSTORE_PARAMS);
+
+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(TEXSTORE_PARAMS)
+{
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ baseInternalFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ 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++) {
+ GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * texelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * texelBytes;
+ 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;
+ }
+ }
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+_savage_texstore_a1118888(TEXSTORE_PARAMS)
+{
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ baseInternalFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ 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++) {
+ GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * texelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * texelBytes;
+ 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;
+ }
+ }
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+#endif
+
+
/* Called by the _mesa_store_teximage[123]d() functions. */
-static const struct gl_texture_format *
+static gl_format
savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
switch ( type ) {
case GL_UNSIGNED_INT_10_10_10_2:
case GL_UNSIGNED_INT_2_10_10_10_REV:
- return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
+ return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return &_mesa_texformat_argb4444;
+ return MESA_FORMAT_ARGB4444;
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return &_mesa_texformat_argb1555;
+ return MESA_FORMAT_ARGB1555;
default:
- return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
}
case 3:
switch ( type ) {
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return &_mesa_texformat_argb4444;
+ return MESA_FORMAT_ARGB4444;
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return &_mesa_texformat_argb1555;
+ return MESA_FORMAT_ARGB1555;
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_6_5_REV:
- return &_mesa_texformat_rgb565;
+ return MESA_FORMAT_RGB565;
default:
- return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+ return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
}
case GL_RGBA8:
case GL_RGBA12:
case GL_RGBA16:
return !force16bpt ?
- &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
case GL_RGB10_A2:
return !force16bpt ?
- &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
+ MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
case GL_RGBA4:
case GL_RGBA2:
- return &_mesa_texformat_argb4444;
+ return MESA_FORMAT_ARGB4444;
case GL_RGB5_A1:
- return &_mesa_texformat_argb1555;
+ return MESA_FORMAT_ARGB1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
- return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+ return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
- return &_mesa_texformat_rgb565;
+ return MESA_FORMAT_RGB565;
case GL_ALPHA:
case GL_COMPRESSED_ALPHA:
- return isSavage4 ? &_mesa_texformat_a8 : (
- do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+#if 0
+ return isSavage4 ? MESA_FORMAT_a8 : (
+ do32bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
+#else
+ if (isSavage4)
+ return MESA_FORMAT_A8;
+ else if (do32bpt)
+ return MESA_FORMAT_ARGB8888;
+ else
+ return MESA_FORMAT_ARGB4444;
+#endif
case GL_ALPHA4:
- return isSavage4 ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444;
+#if 0
+ return isSavage4 ? MESA_FORMAT_a8 : &_savage_texformat_a1114444;
+#else
+ if (isSavage4)
+ return MESA_FORMAT_A8;
+ else
+ return MESA_FORMAT_ARGB4444;
+#endif
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
- return isSavage4 ? &_mesa_texformat_a8 : (
- !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
-
+#if 0
+ return isSavage4 ? MESA_FORMAT_a8 : (
+ !force16bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
+#else
+ if (isSavage4)
+ return MESA_FORMAT_A8;
+ else if (force16bpt)
+ return MESA_FORMAT_ARGB4444;
+ else
+ return MESA_FORMAT_ARGB8888;
+#endif
case 1:
case GL_LUMINANCE:
case GL_COMPRESSED_LUMINANCE:
/* no alpha, but use argb1555 in 16bit case to get pure grey values */
- return isSavage4 ? &_mesa_texformat_l8 : (
- do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
+ return isSavage4 ? MESA_FORMAT_L8 : (
+ do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555);
case GL_LUMINANCE4:
- return isSavage4 ? &_mesa_texformat_l8 : &_mesa_texformat_argb1555;
+ return isSavage4 ? MESA_FORMAT_L8 : MESA_FORMAT_ARGB1555;
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
- return isSavage4 ? &_mesa_texformat_l8 : (
- !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
+ return isSavage4 ? MESA_FORMAT_L8 : (
+ !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555);
case 2:
case GL_LUMINANCE_ALPHA:
case GL_COMPRESSED_LUMINANCE_ALPHA:
/* Savage4 has a al44 texture format. But it's not supported by Mesa. */
- return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
- return &_mesa_texformat_argb4444;
+ return MESA_FORMAT_ARGB4444;
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
- return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
-
+ return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_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_FORMAT_i8 : (
+ do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444);
+ case GL_INTENSITY4:
+ return isSavage4 ? MESA_FORMAT_i8 : MESA_FORMAT_ARGB4444;
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return isSavage4 ? MESA_FORMAT_i8 : (
+ !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444);
+#else
case GL_INTENSITY:
case GL_COMPRESSED_INTENSITY:
- return isSavage4 ? &_mesa_texformat_i8 : (
- do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+ return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
case GL_INTENSITY4:
- return isSavage4 ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
+ return MESA_FORMAT_ARGB4444;
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
- return isSavage4 ? &_mesa_texformat_i8 : (
- !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+ return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
+#endif
+
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return MESA_FORMAT_RGB_DXT1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return MESA_FORMAT_RGBA_DXT1;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return MESA_FORMAT_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_FORMAT_RGBA_DXT1;
+ /* fall through */
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return MESA_FORMAT_RGBA_DXT5;
+
/*
case GL_COLOR_INDEX:
case GL_COLOR_INDEX1_EXT:
*/
default:
_mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
- return NULL;
+ return MESA_FORMAT_NONE;
}
}
{
savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- GLuint offset, i, textureFormat, size;
+ GLuint offset, i, textureFormat, tileIndex, size;
GLint firstLevel, lastLevel;
assert(t);
assert(image);
- switch (image->TexFormat->MesaFormat) {
+ switch (image->TexFormat) {
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__);
}
t->hwFormat = textureFormat;
- /* Select tiling format depending on the chipset and bytes per texel */
+ /* Select tiling format depending on the chipset and texture format */
if (imesa->savageScreen->chipset <= S3_SAVAGE4)
- t->tileInfo = &tileInfo_s3d_s4[t->texelBytes];
+ t->tileInfo = &tileInfo_s3d_s4[tileIndex];
else
- t->tileInfo = &tileInfo_pro[t->texelBytes];
+ t->tileInfo = &tileInfo_pro[tileIndex];
/* Compute which mipmap levels we really want to send to the hardware.
*/
t->image[i].offset = offset;
image = tObj->Image[0][i];
- size = savageTexImageSize (image->Width2, image->Height2,
- t->texelBytes);
+ if (t->texelBytes >= 8)
+ size = savageCompressedTexImageSize (image->Width2, image->Height2,
+ t->texelBytes);
+ else
+ size = savageTexImageSize (image->Width2, image->Height2,
+ t->texelBytes);
offset += size;
}
/* the last three mipmap levels don't add to the offset. They are packed
* into 64 pixels. */
if (size == 0)
- t->base.totalSize += 64 * t->texelBytes;
+ t->base.totalSize += (t->texelBytes >= 8 ? 4 : 64) * t->texelBytes;
/* 2k-aligned (really needed?) */
t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL;
}
ofs = t->base.memBlock->ofs;
t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
- t->bufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
+ t->bufAddr = (GLubyte *)imesa->savageScreen->texVirtual[heap] + ofs;
imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
}
if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
fprintf(stderr, "Texture upload: |");
- savageFlushVertices (imesa);
- LOCK_HARDWARE(imesa);
- savageFlushCmdBufLocked (imesa, GL_FALSE);
- WAIT_IDLE_EMPTY_LOCKED(imesa);
+ /* 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->drm_version.minor >= 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);
+ }
for (i = 0 ; i < numLevels ; i++) {
const GLint j = t->base.firstLevel + i; /* the texObj's level */
}
+static void
+savage4_set_wrap_mode( savageContextPtr imesa, unsigned unit,
+ GLenum s_mode, GLenum t_mode )
+{
+ 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;
+ }
+
+ 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;
+ }
+}
+
+
+/**
+ * Sets the hardware bits for the specified GL texture filter modes.
+ *
+ * \todo
+ * Does the Savage4 have the ability to select the magnification filter?
+ */
+static void
+savage4_set_filter_mode( savageContextPtr imesa, unsigned unit,
+ GLenum minFilter, GLenum magFilter )
+{
+ (void) magFilter;
+
+ 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;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
+ break;
+
+ case GL_LINEAR_MIPMAP_NEAREST:
+ imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
+ imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
+ break;
+
+ 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 )
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.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_1D_BIT|TEXTURE_2D_BIT))
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:
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->setup.sWrapMode == GL_REPEAT ? 0 : 1;
- imesa->regs.s4.texCtrl[0].ni.vMode =
- t->setup.tWrapMode == GL_REPEAT ? 0 : 1;
-
- switch (t->setup.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;
- }
+ savage4_set_wrap_mode( imesa, 0, t->setup.sWrapMode, t->setup.tWrapMode );
+ savage4_set_filter_mode( imesa, 0, t->setup.minFilter, t->setup.magFilter );
if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
(imesa->regs.s4.texCtrl[0].ni.dBias != 0))
{
- int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0);
+ int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0) +
+ SAVAGE4_LOD_OFFSET;
if (bias < -256)
bias = -256;
else if (bias > 255)
if (imesa->regs.s4.texDescr.ni.tex1En)
imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
- imesa->regs.s4.texAddr[0].ui = (u_int32_t) t->setup.physAddr | 0x2;
+ imesa->regs.s4.texAddr[0].ui = (uint32_t) t->setup.physAddr | 0x2;
if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[0].ui |= 0x1;
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.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;
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->setup.sWrapMode == GL_REPEAT ? 0 : 1;
- imesa->regs.s4.texCtrl[1].ni.vMode =
- t->setup.tWrapMode == GL_REPEAT ? 0 : 1;
+ 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->setup.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) ||
(imesa->regs.s4.texCtrl[1].ni.dBias != 0))
{
- int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0);
+ int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0) +
+ SAVAGE4_LOD_OFFSET;
if (bias < -256)
bias = -256;
else if (bias > 255)
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 = (u_int32_t) t->setup.physAddr | 2;
+ imesa->regs.s4.texAddr[1].ui = (uint32_t) t->setup.physAddr | 2;
if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[1].ui |= 0x1;
}
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.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_1D_BIT|TEXTURE_2D_BIT))
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->setup.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->setup.minFilter) {
case GL_NEAREST:
assert (t->hwFormat <= 7);
imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
- imesa->regs.s3d.texAddr.ui = (u_int32_t) t->setup.physAddr | 2;
+ imesa->regs.s3d.texAddr.ui = (uint32_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->drm_version.minor >= 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;
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;
savageUpdateTexState_s3d( ctx );
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,
{
savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
if (t) {
- /* Do nothing. Marking the image as dirty below is sufficient. */
+ savageTexImageChanged (t);
} else {
t = savageAllocTexObj(texObj);
if (!t) {
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 {
{
savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
if (t) {
- /* Do nothing. Marking the image as dirty below is sufficient. */
+ savageTexImageChanged (t);
} else {
t = savageAllocTexObj(texObj);
if (!t) {
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 {
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;
+}
+
static void savageTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
break;
case GL_TEXTURE_BORDER_COLOR:
- savageSetTexBorderColor(t,tObj->_BorderChan);
+ savageSetTexBorderColor(t,tObj->BorderColor);
break;
default:
savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
if (t) {
- if (t->bound) {
- FLUSH_BATCH(imesa);
- }
+ if (t->bound)
+ savageTimestampTextures(imesa);
driDestroyTextureObject(t);
}
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 = driIsTextureResident;
functions->TexParameter = savageTexParameter;
+
+ /* Texel fetching with our custom texture formats works just like
+ * the standard argb formats. */
+#if 0
+ _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;
+#endif
}