diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/main/texutil.c | 857 | ||||
-rw-r--r-- | src/mesa/main/texutil.h | 28 |
2 files changed, 824 insertions, 61 deletions
diff --git a/src/mesa/main/texutil.c b/src/mesa/main/texutil.c index a9c1f365ea7..c10ebe2f3ce 100644 --- a/src/mesa/main/texutil.c +++ b/src/mesa/main/texutil.c @@ -1,4 +1,3 @@ -/* $Id: texutil.c,v 1.2 2000/03/27 18:56:26 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -39,9 +38,19 @@ /* * Texture utilities which may be useful to device drivers. + * See the texutil.h for the list of supported internal formats. + * It's expected that new formats will be added for new hardware. */ +/* + * If the system is little endian and can do 4-byte word stores on + * non 4-byte-aligned addresses then we can use this optimization. + */ +#if defined(__i386__) +#define DO_32BIT_STORES000 +#endif + /* @@ -49,7 +58,8 @@ * Input: * dstFormat - the destination internal format * dstWidth, dstHeight - the destination image size - * destImage - pointer to destination image buffer + * dstImage - pointer to destination image buffer + * dstRowStride - bytes to jump between image rows * srcWidth, srcHeight - size of texture image * srcFormat, srcType - format and datatype of source image * srcImage - pointer to user's texture image @@ -64,7 +74,7 @@ * GL_LUMINANCE GL_UNSIGNED_BYTE MESA_L8 * GL_ALPHA GL_UNSIGNED_BYTE MESA_A8 * GL_COLOR_INDEX GL_UNSIGNED_BYTE MESA_C8 - * GL_LUMINANCE_ALPHA GL_UNSIGNED_BYTE MESA_L8_A8 + * GL_LUMINANCE_ALPHA GL_UNSIGNED_BYTE MESA_A8_L8 * GL_RGB GL_UNSIGNED_BYTE MESA_R5_G6_B5 * GL_RGB GL_UNSIGNED_SHORT_5_6_5 MESA_R5_G6_B5 * GL_RGBA GL_UNSIGNED_BYTE MESA_A4_R4_G4_B4 @@ -82,7 +92,8 @@ GLboolean _mesa_convert_teximage(MesaIntTexFormat dstFormat, GLint dstWidth, GLint dstHeight, GLvoid *dstImage, - GLsizei srcWidth, GLsizei srcHeight, + GLint dstRowStride, + GLint srcWidth, GLint srcHeight, GLenum srcFormat, GLenum srcType, const GLvoid *srcImage, const struct gl_pixelstore_attrib *packing) @@ -120,7 +131,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, GLint row; for (row = 0; row < dstHeight; row++) { MEMCPY(dst, src, dstWidth * sizeof(GLubyte)); - dst += dstWidth; + dst += dstRowStride; src += srcStride; } } @@ -136,13 +147,13 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, for (col = 0; col < dstWidth; col++) { dst[col] = src[col / wScale]; } - dst += dstWidth; + dst += dstRowStride; } } } break; - case MESA_L8_A8: + case MESA_A8_L8: if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) { return GL_FALSE; } @@ -153,21 +164,21 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row, col; for (row = 0; row < dstHeight; row++) { for (col = 0; col < dstWidth; col++) { - GLubyte alpha = src[col * 2 + 0]; - GLubyte luminance = src[col * 2 + 1]; - dst[col] = ((GLushort) luminance << 8) | alpha; + GLubyte luminance = src[col * 2 + 0]; + GLubyte alpha = src[col * 2 + 1]; + dst[col] = ((GLushort) alpha << 8) | luminance; } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); src += srcStride; } } else { /* must rescale */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row, col; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -177,11 +188,11 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcFormat, srcType); for (col = 0; col < dstWidth; col++) { GLint srcCol = col / wScale; - GLubyte alpha = src[srcCol * 2 + 0]; - GLubyte luminance = src[srcCol * 2 + 1]; - dst[col] = ((GLushort) luminance << 8) | alpha; + GLubyte luminance = src[srcCol * 2 + 0]; + GLubyte alpha = src[srcCol * 2 + 1]; + dst[col] = ((GLushort) alpha << 8) | luminance; } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); src += srcStride; } } @@ -196,17 +207,17 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { MEMCPY(dst, src, dstWidth * sizeof(GLushort)); src += srcStride; - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } else { /* must rescale image */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -216,7 +227,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, for (col = 0; col < dstWidth; col++) { dst[col] = src[col / wScale]; } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } } @@ -227,7 +238,32 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; +#ifdef DO_32BIT_STORES + GLuint *dst = (GLuint *) dstImage; + GLint row; + for (row = 0; row < dstHeight; row++) { + GLint col, col3; + GLint halfDstWidth = dstWidth >> 1; + for (col = col3 = 0; col < halfDstWidth; col++, col3 += 6) { + GLubyte r0 = src[col3 + 0]; + GLubyte g0 = src[col3 + 1]; + GLubyte b0 = src[col3 + 2]; + GLubyte r1 = src[col3 + 3]; + GLubyte g1 = src[col3 + 4]; + GLubyte b1 = src[col3 + 5]; + GLuint d0 = ((r0 & 0xf8) << 8) + | ((g0 & 0xfc) << 3) + | ((b0 & 0xf8) >> 3); + GLuint d1 = ((r1 & 0xf8) << 8) + | ((g1 & 0xfc) << 3) + | ((b1 & 0xf8) >> 3); + dst[col] = (d1 << 16) | d0; + } + src += srcStride; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } +#else /* 16-bit stores */ + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint col, col3; @@ -240,12 +276,13 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, | ((b & 0xf8) >> 3); } src += srcStride; - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } +#endif } else { /* must rescale image */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -261,7 +298,78 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { + /* general case (used by Quake3) */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); +#ifdef DO_32BIT_STORES + GLuint *dst = dstImage; + GLint row; + for (row = 0; row < dstHeight; row++) { + GLint col, col4; + GLint halfDstWidth = dstWidth >> 1; + for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) { + GLubyte r0 = src[col4 + 0]; + GLubyte g0 = src[col4 + 1]; + GLubyte b0 = src[col4 + 2]; + GLubyte r1 = src[col4 + 4]; + GLubyte g1 = src[col4 + 5]; + GLubyte b1 = src[col4 + 6]; + GLuint d0 = ((r0 & 0xf8) << 8) + | ((g0 & 0xfc) << 3) + | ((b0 & 0xf8) >> 3); + GLuint d1 = ((r1 & 0xf8) << 8) + | ((g1 & 0xfc) << 3) + | ((b1 & 0xf8) >> 3); + dst[col] = (d1 << 16) | d0; + } + src += srcStride; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } +#else /* 16-bit stores */ + GLushort *dst = (GLushort *) dstImage; + GLint row; + for (row = 0; row < dstHeight; row++) { + GLint col, col4; + for (col = col4 = 0; col < dstWidth; col++, col4 += 4) { + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + dst[col] = ((r & 0xf8) << 8) + | ((g & 0xfc) << 3) + | ((b & 0xf8) >> 3); + } + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } +#endif + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) dstImage; + GLint row; + for (row = 0; row < dstHeight; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < dstWidth; col++) { + GLint col4 = (col / wScale) * 4; + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + dst[col] = ((r & 0xf8) << 8) + | ((g & 0xfc) << 3) + | ((b & 0xf8) >> 3); + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } } @@ -280,17 +388,17 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { MEMCPY(dst, src, dstWidth * sizeof(GLushort)); src += srcStride; - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } else { /* must rescale image */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -300,7 +408,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, for (col = 0; col < dstWidth; col++) { dst[col] = src[col / wScale]; } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } } @@ -311,7 +419,36 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; +#ifdef DO_32BIT_STORES + GLuint *dst = dstImage; + GLint row; + for (row = 0; row < dstHeight; row++) { + GLint col, col4; + GLint halfDstWidth = dstWidth >> 1; + for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) { + GLubyte r0 = src[col4 + 0]; + GLubyte g0 = src[col4 + 1]; + GLubyte b0 = src[col4 + 2]; + GLubyte a0 = src[col4 + 3]; + GLubyte r1 = src[col4 + 4]; + GLubyte g1 = src[col4 + 5]; + GLubyte b1 = src[col4 + 6]; + GLubyte a1 = src[col4 + 7]; + GLuint d0 = ((a0 & 0xf0) << 8) + | ((r0 & 0xf0) << 4) + | ((g0 & 0xf0) ) + | ((b0 & 0xf0) >> 4); + GLuint d1 = ((a1 & 0xf0) << 8) + | ((r1 & 0xf0) << 4) + | ((g1 & 0xf0) ) + | ((b1 & 0xf0) >> 4); + dst[col] = (d1 << 16) | d0; + } + src += srcStride; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } +#else /* 16-bit stores */ + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint col, col4; @@ -326,12 +463,13 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, | ((b & 0xf0) >> 4); } src += srcStride; - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } +#endif } else { /* must rescale image */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -349,7 +487,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, | ((g & 0xf0) ) | ((b & 0xf0) >> 4); } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } } @@ -368,17 +506,17 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { MEMCPY(dst, src, dstWidth * sizeof(GLushort)); src += srcStride; - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } else { /* must rescale image */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -388,7 +526,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, for (col = 0; col < dstWidth; col++) { dst[col] = src[col / wScale]; } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } } @@ -399,7 +537,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint srcStride = _mesa_image_row_stride(packing, srcWidth, srcFormat, srcType); - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint col, col4; @@ -414,12 +552,12 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, | ((b & 0xf8) >> 3); } src += srcStride; - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } else { /* must rescale image */ - GLushort *dst = dstImage; + GLushort *dst = (GLushort *) dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -437,7 +575,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); } - dst += dstWidth; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); } } } @@ -461,7 +599,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, for (row = 0; row < dstHeight; row++) { MEMCPY(dst, src, dstWidth * sizeof(GLuint)); src += srcStride; - dst += dstWidth; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); } } else { @@ -476,7 +614,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, for (col = 0; col < dstWidth; col++) { dst[col] = src[col / wScale]; } - dst += dstWidth; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); } } } @@ -499,12 +637,12 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, dst[col] = (a << 24) | (r << 16) | (g << 8) | b; } src += srcStride; - dst += dstWidth; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); } } else { /* must rescale image */ - GLushort *dst = dstImage; + GLuint *dst = dstImage; GLint row; for (row = 0; row < dstHeight; row++) { GLint srcRow = row / hScale; @@ -519,7 +657,565 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, GLubyte a = src[col4 + 3]; dst[col] = (a << 24) | (r << 16) | (g << 8) | b; } - dst += dstWidth; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } + } + } + else { + /* can't handle this source format/type combination */ + return GL_FALSE; + } + break; + + + default: + /* unexpected internal format! */ + return GL_FALSE; + } + return GL_TRUE; +} + + + +/* + * Replace a subregion of a texture image with new data. + * Input: + * dstFormat - destination image format + * dstXoffset, dstYoffset - destination for new subregion + * dstWidth, dstHeight - total size of dest image + * dstImage - pointer to dest image + * dstRowStride - bytes to jump between image rows + * width, height - size of region to copy/replace + * srcWidth, srcHeight - size of the corresponding gl_texture_image + * srcFormat, srcType - source image format and datatype + * srcImage - source image + * packing - source image packing information. + * Return: GL_TRUE or GL_FALSE for success, failure + * + * Notes: + * Like _mesa_convert_teximage(), we can do power-of-two image scaling + * to accomodate hardware with texture image aspect ratio constraints. + * dstWidth / srcWidth is used to compute the horizontal scaling factor and + * dstHeight / srcHeight is used to compute the vertical scaling factor. + */ +GLboolean +_mesa_convert_texsubimage(MesaIntTexFormat dstFormat, + GLint dstXoffset, GLint dstYoffset, + GLint dstWidth, GLint dstHeight, GLvoid *dstImage, + GLint dstRowStride, + GLint width, GLint height, + GLint srcWidth, GLint srcHeight, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcImage, + const struct gl_pixelstore_attrib *packing) +{ + const GLint wScale = dstWidth / srcWidth; /* must be power of two */ + const GLint hScale = dstHeight / srcHeight; /* must be power of two */ + ASSERT(dstWidth >= srcWidth); + ASSERT(dstHeight >= srcHeight); + ASSERT(dstImage); + ASSERT(srcImage); + ASSERT(packing); + + width *= wScale; + height *= hScale; + dstXoffset *= wScale; + dstYoffset *= hScale; + + /* XXX hscale != 1 and wscale != 1 not tested!!!! */ + + switch (dstFormat) { + case MESA_I8: + case MESA_L8: + case MESA_A8: + case MESA_C8: + if (srcType != GL_UNSIGNED_BYTE || + ((srcFormat != GL_INTENSITY) && + (srcFormat != GL_LUMINANCE) && + (srcFormat != GL_ALPHA) && + (srcFormat != GL_COLOR_INDEX))) { + /* bad internal format / srcFormat combination */ + return GL_FALSE; + } + else { + /* store as 8-bit texels */ + if (wScale == 1 && hScale == 1) { + /* no scaling needed - fast case */ + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLubyte *dst = (GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset; + GLint row; + for (row = 0; row < height; row++) { + MEMCPY(dst, src, width * sizeof(GLubyte)); + dst += dstRowStride; + src += srcStride; + } + } + else { + /* must rescale image */ + GLubyte *dst = (GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset; + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + dst[col] = src[col / wScale]; + } + dst += dstRowStride; + } + } + } + break; + + case MESA_A8_L8: + if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) { + return GL_FALSE; + } + else { + /* store as 16-bit texels */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row, col; + for (row = 0; row < height; row++) { + for (col = 0; col < width; col++) { + GLubyte luminance = src[col * 2 + 0]; + GLubyte alpha = src[col * 2 + 1]; + dst[col] = ((GLushort) alpha << 8) | luminance; + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + src += srcStride; + } + } + else { + /* must rescale */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row, col; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + for (col = 0; col < width; col++) { + GLint srcCol = col / wScale; + GLubyte luminance = src[srcCol * 2 + 0]; + GLubyte alpha = src[srcCol * 2 + 1]; + dst[col] = ((GLushort) alpha << 8) | luminance; + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + src += srcStride; + } + } + } + break; + + case MESA_R5_G6_B5: + if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) { + /* special, optimized case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + MEMCPY(dst, src, width * sizeof(GLushort)); + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLushort *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + dst[col] = src[col / wScale]; + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) { + /* general case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint col, col3; + for (col = col3 = 0; col < width; col++, col3 += 3) { + GLubyte r = src[col3 + 0]; + GLubyte g = src[col3 + 1]; + GLubyte b = src[col3 + 2]; + dst[col] = ((r & 0xf8) << 8) + | ((g & 0xfc) << 3) + | ((b & 0xf8) >> 3); + } + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + GLint col3 = (col / wScale) * 3; + GLubyte r = src[col3 + 0]; + GLubyte g = src[col3 + 1]; + GLubyte b = src[col3 + 2]; + dst[col] = ((r & 0xf8) << 8) + | ((g & 0xfc) << 3) + | ((b & 0xf8) >> 3); + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { + /* general case (used by Quake3) */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint col, col4; + for (col = col4 = 0; col < width; col++, col4 += 4) { + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + dst[col] = ((r & 0xf8) << 8) + | ((g & 0xfc) << 3) + | ((b & 0xf8) >> 3); + } + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + GLint col4 = (col / wScale) * 4; + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + dst[col] = ((r & 0xf8) << 8) + | ((g & 0xfc) << 3) + | ((b & 0xf8) >> 3); + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else { + /* can't handle this srcFormat/srcType combination */ + return GL_FALSE; + } + break; + + case MESA_A4_R4_G4_B4: + /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */ + if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){ + /* special, optimized case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + MEMCPY(dst, src, width * sizeof(GLushort)); + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLushort *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + dst[col] = src[col / wScale]; + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { + /* general case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint col, col4; + for (col = col4 = 0; col < width; col++, col4 += 4) { + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + GLubyte a = src[col4 + 3]; + dst[col] = ((a & 0xf0) << 8) + | ((r & 0xf0) << 4) + | ((g & 0xf0) ) + | ((b & 0xf0) >> 4); + } + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + GLint col4 = (col / wScale) * 4; + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + GLubyte a = src[col4 + 3]; + dst[col] = ((a & 0xf0) << 8) + | ((r & 0xf0) << 4) + | ((g & 0xf0) ) + | ((b & 0xf0) >> 4); + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else { + /* can't handle this format/srcType combination */ + return GL_FALSE; + } + break; + + case MESA_A1_R5_G5_B5: + /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */ + if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){ + /* special, optimized case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + MEMCPY(dst, src, width * sizeof(GLushort)); + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLushort *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + dst[col] = src[col / wScale]; + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { + /* general case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint col, col4; + for (col = col4 = 0; col < width; col++, col4 += 4) { + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + GLubyte a = src[col4 + 3]; + dst[col] = ((a & 0x80) << 8) + | ((r & 0xf8) << 7) + | ((g & 0xf8) << 2) + | ((b & 0xf8) >> 3); + } + src += srcStride; + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLushort *dst = (GLushort *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + GLint col4 = (col / wScale) * 4; + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + GLubyte a = src[col4 + 3]; + dst[col] = ((a & 0x80) << 8) + | ((r & 0xf8) << 7) + | ((g & 0xf8) << 2) + | ((b & 0xf8) >> 3); + } + dst = (GLushort *) ((GLubyte *) dst + dstRowStride); + } + } + } + else { + /* can't handle this source format/type combination */ + return GL_FALSE; + } + break; + + case MESA_A8_R8_G8_B8: + /* 32-bit texels */ + if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV){ + /* special, optimized case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLuint *dst = (GLuint *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + MEMCPY(dst, src, width * sizeof(GLuint)); + src += srcStride; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLuint *dst = (GLuint *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLuint *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + dst[col] = src[col / wScale]; + } + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } + } + } + else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { + /* general case */ + if (wScale == 1 && hScale == 1) { + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint srcStride = _mesa_image_row_stride(packing, + srcWidth, srcFormat, srcType); + GLuint *dst = (GLuint *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint col, col4; + for (col = col4 = 0; col < width; col++, col4 += 4) { + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + GLubyte a = src[col4 + 3]; + dst[col] = (a << 24) | (r << 16) | (g << 8) | b; + } + src += srcStride; + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); + } + } + else { + /* must rescale image */ + GLuint *dst = (GLuint *) ((GLubyte *) dstImage + + dstYoffset * dstRowStride + dstXoffset); + GLint row; + for (row = 0; row < height; row++) { + GLint srcRow = row / hScale; + const GLubyte *src = _mesa_image_address(packing, srcImage, + srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0); + GLint col; + for (col = 0; col < width; col++) { + GLint col4 = (col / wScale) * 4; + GLubyte r = src[col4 + 0]; + GLubyte g = src[col4 + 1]; + GLubyte b = src[col4 + 2]; + GLubyte a = src[col4 + 3]; + dst[col] = (a << 24) | (r << 16) | (g << 8) | b; + } + dst = (GLuint *) ((GLubyte *) dst + dstRowStride); } } } @@ -538,6 +1234,8 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, } + + /* * Used to convert 16-bit texels into GLubyte color components. */ @@ -609,6 +1307,14 @@ generate_lookup_tables(void) * core internal formats. This is likely to be used by glGetTexImage * and for fetching texture images when falling back to software rendering. * + * Input: + * srcFormat - source image format + * srcWidth, srcHeight - source image size + * srcImage - source image pointer + * srcRowStride - bytes to jump between image rows + * dstWidth, dstHeight - size of dest image + * dstFormat - format of dest image (must be one of Mesa's IntFormat values) + * dstImage - pointer to dest image * Notes: * This function will do power of two image down-scaling to accomodate * drivers with limited texture image aspect ratios. @@ -617,8 +1323,8 @@ generate_lookup_tables(void) void _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, GLint srcWidth, GLint srcHeight, - const GLvoid *srcImage, - GLsizei dstWidth, GLsizei dstHeight, + const GLvoid *srcImage, GLint srcRowStride, + GLint dstWidth, GLint dstHeight, GLenum dstFormat, GLubyte *dstImage) { static GLboolean firstCall = GL_TRUE; @@ -670,15 +1376,15 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, } } break; - case MESA_L8_A8: + case MESA_A8_L8: ASSERT(dstFormat == GL_LUMINANCE_ALPHA); if (wScale == 1 && hScale == 1) { GLint i, n = dstWidth * dstHeight; const GLushort *texel = (const GLushort *) srcImage; for (i = 0; i < n; i++) { const GLushort tex = *texel++; - *dstImage++ = (tex >> 8); /* luminance */ - *dstImage++ = (tex & 0xff); /* alpha */ + *dstImage++ = (tex & 0xff); /* luminance */ + *dstImage++ = (tex >> 8); /* alpha */ } } else { @@ -690,8 +1396,8 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, for (col = 0; col < dstWidth; col++) { GLint srcCol = col * wScale; const GLushort tex = src16[srcRow * srcWidth + srcCol]; - *dstImage++ = (tex >> 8); /* luminance */ - *dstImage++ = (tex & 0xff); /* alpha */ + *dstImage++ = (tex & 0xff); /* luminance */ + *dstImage++ = (tex >> 8); /* alpha */ } } } @@ -788,7 +1494,7 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, ASSERT(dstFormat == GL_RGBA); if (wScale == 1 && hScale == 1) { GLint i, n = dstWidth * dstHeight; - const GLushort *texel = (const GLushort *) srcImage; + const GLuint *texel = (const GLuint *) srcImage; for (i = 0; i < n; i++) { const GLuint tex = *texel++; *dstImage++ = (tex >> 16) & 0xff; /* R */ @@ -799,13 +1505,13 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, } else { /* rescale */ - const GLushort *src16 = (const GLushort *) srcImage; + const GLuint *src = (const GLuint *) srcImage; GLint row, col; for (row = 0; row < dstHeight; row++) { GLint srcRow = row * hScale; for (col = 0; col < dstWidth; col++) { GLint srcCol = col * wScale; - const GLuint tex = src16[srcRow * srcWidth + srcCol]; + const GLuint tex = src[srcRow * srcWidth + srcCol]; *dstImage++ = (tex >> 16) & 0xff; /* R */ *dstImage++ = (tex >> 8) & 0xff; /* G */ *dstImage++ = (tex ) & 0xff; /* B */ @@ -818,3 +1524,42 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()"); } } + + + +/* + * Given an internal Mesa driver texture format, fill in the component + * bit sizes in the given texture image struct. + */ +void +_mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat, + struct gl_texture_image *texImage) +{ + static const GLint bitSizes [][8] = { + /* format R G B A I L C */ + { MESA_I8, 0, 0, 0, 0, 8, 0, 0 }, + { MESA_L8, 0, 0, 0, 0, 0, 8, 0 }, + { MESA_A8, 0, 0, 0, 8, 0, 0, 0 }, + { MESA_C8, 0, 0, 0, 0, 0, 0, 8 }, + { MESA_A8_L8, 0, 0, 0, 8, 0, 8, 0 }, + { MESA_R5_G6_B5, 5, 6, 5, 0, 0, 0, 0 }, + { MESA_A4_R4_G4_B4, 4, 4, 4, 4, 0, 0, 0 }, + { MESA_A1_R5_G5_B5, 5, 5, 5, 1, 0, 0, 0 }, + { MESA_A8_R8_G8_B8, 8, 8, 8, 8, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0, 0, 0 } + }; + GLint i; + for (i = 0; i < bitSizes[i][0] >= 0; i++) { + if (bitSizes[i][0] == mesaFormat) { + texImage->RedBits = bitSizes[i][1]; + texImage->GreenBits = bitSizes[i][2]; + texImage->BlueBits = bitSizes[i][3]; + texImage->AlphaBits = bitSizes[i][4]; + texImage->IntensityBits = bitSizes[i][5]; + texImage->LuminanceBits = bitSizes[i][6]; + texImage->IndexBits = bitSizes[i][7]; + return; + } + } + gl_problem(NULL, "bad format in _mesa_set_teximage_component_sizes"); +} diff --git a/src/mesa/main/texutil.h b/src/mesa/main/texutil.h index 0e180af2b77..5f000be603a 100644 --- a/src/mesa/main/texutil.h +++ b/src/mesa/main/texutil.h @@ -1,4 +1,3 @@ -/* $Id: texutil.h,v 1.2 2000/03/27 18:56:26 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -39,7 +38,7 @@ typedef enum { /* ---- ---- ---- ---- ---- ---- ---- ---- */ MESA_L8, /* LLLL LLLL */ MESA_A8, /* AAAA AAAA */ MESA_C8, /* CCCC CCCC */ - MESA_L8_A8, /* LLLL LLLL AAAA AAAA */ + MESA_A8_L8, /* AAAA AAAA LLLL LLLL */ MESA_R5_G6_B5, /* RRRR RGGG GGGB BBBB */ MESA_A4_R4_G4_B4, /* AAAA RRRR GGGG BBBB */ MESA_A1_R5_G5_B5, /* ARRR RRGG GGGB BBBB */ @@ -52,19 +51,38 @@ typedef enum { /* ---- ---- ---- ---- ---- ---- ---- ---- */ extern GLboolean _mesa_convert_teximage(MesaIntTexFormat dstFormat, GLint dstWidth, GLint dstHeight, GLvoid *dstImage, - GLsizei srcWidth, GLsizei srcHeight, + GLint dstRowStride, + GLint srcWidth, GLint srcHeight, GLenum srcFormat, GLenum srcType, const GLvoid *srcImage, const struct gl_pixelstore_attrib *packing); + +extern GLboolean +_mesa_convert_texsubimage(MesaIntTexFormat dstFormat, + GLint dstXoffset, GLint dstYoffset, + GLint dstWidth, GLint dstHeight, GLvoid *dstImage, + GLint dstRowStride, + GLint width, GLint height, + GLint srcWidth, GLint srcHeight, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcImage, + const struct gl_pixelstore_attrib *packing); + + extern void _mesa_unconvert_teximage(MesaIntTexFormat srcFormat, GLint srcWidth, GLint srcHeight, - const GLvoid *srcImage, - GLsizei dstWidth, GLsizei dstHeight, + const GLvoid *srcImage, GLint srcRowStride, + GLint dstWidth, GLint dstHeight, GLenum dstFormat, GLubyte *dstImage); +extern void +_mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat, + struct gl_texture_image *texImage); + + #endif |