-/* $Id: texutil.c,v 1.2 2000/03/27 18:56:26 brianp Exp $ */
/*
* Mesa 3-D graphics library
/*
* 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
+
/*
* 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
* 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
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)
GLint row;
for (row = 0; row < dstHeight; row++) {
MEMCPY(dst, src, dstWidth * sizeof(GLubyte));
- dst += dstWidth;
+ dst += dstRowStride;
src += srcStride;
}
}
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;
}
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;
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;
}
}
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;
for (col = 0; col < dstWidth; col++) {
dst[col] = src[col / wScale];
}
- dst += dstWidth;
+ dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
}
}
}
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;
| ((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;
| ((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);
}
}
}
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;
for (col = 0; col < dstWidth; col++) {
dst[col] = src[col / wScale];
}
- dst += dstWidth;
+ dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
}
}
}
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;
| ((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;
| ((g & 0xf0) )
| ((b & 0xf0) >> 4);
}
- dst += dstWidth;
+ dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
}
}
}
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;
for (col = 0; col < dstWidth; col++) {
dst[col] = src[col / wScale];
}
- dst += dstWidth;
+ dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
}
}
}
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;
| ((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;
| ((g & 0xf8) << 2)
| ((b & 0xf8) >> 3);
}
- dst += dstWidth;
+ dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
}
}
}
for (row = 0; row < dstHeight; row++) {
MEMCPY(dst, src, dstWidth * sizeof(GLuint));
src += srcStride;
- dst += dstWidth;
+ dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
}
}
else {
for (col = 0; col < dstWidth; col++) {
dst[col] = src[col / wScale];
}
- dst += dstWidth;
+ dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
}
}
}
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;
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);
}
}
}
}
+
+
/*
* Used to convert 16-bit texels into GLubyte color components.
*/
* 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.
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;
}
}
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 {
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 */
}
}
}
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 */
}
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 */
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");
+}