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