|
|
|
@@ -1,4 +1,4 @@ |
|
|
|
/* $Id: texutil.c,v 1.1 2000/03/24 20:54:21 brianp Exp $ */ |
|
|
|
/* $Id: texutil.c,v 1.2 2000/03/27 18:56:26 brianp Exp $ */ |
|
|
|
|
|
|
|
/* |
|
|
|
* Mesa 3-D graphics library |
|
|
|
@@ -29,6 +29,7 @@ |
|
|
|
#include "all.h" |
|
|
|
#else |
|
|
|
#include "glheader.h" |
|
|
|
#include "context.h" |
|
|
|
#include "image.h" |
|
|
|
#include "mem.h" |
|
|
|
#include "texutil.h" |
|
|
|
@@ -535,3 +536,285 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat, |
|
|
|
} |
|
|
|
return GL_TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Used to convert 16-bit texels into GLubyte color components. |
|
|
|
*/ |
|
|
|
static GLubyte R5G6B5toRed[0xffff]; |
|
|
|
static GLubyte R5G6B5toGreen[0xffff]; |
|
|
|
static GLubyte R5G6B5toBlue[0xffff]; |
|
|
|
|
|
|
|
static GLubyte A4R4G4B4toRed[0xffff]; |
|
|
|
static GLubyte A4R4G4B4toGreen[0xffff]; |
|
|
|
static GLubyte A4R4G4B4toBlue[0xffff]; |
|
|
|
static GLubyte A4R4G4B4toAlpha[0xffff]; |
|
|
|
|
|
|
|
static GLubyte A1R5G5B5toRed[0xffff]; |
|
|
|
static GLubyte A1R5G5B5toGreen[0xffff]; |
|
|
|
static GLubyte A1R5G5B5toBlue[0xffff]; |
|
|
|
static GLubyte A1R5G5B5toAlpha[0xffff]; |
|
|
|
|
|
|
|
static void |
|
|
|
generate_lookup_tables(void) |
|
|
|
{ |
|
|
|
GLint i; |
|
|
|
for (i = 0; i <= 0xffff; i++) { |
|
|
|
GLint r = (i >> 8) & 0xf8; |
|
|
|
GLint g = (i >> 3) & 0xfc; |
|
|
|
GLint b = (i << 3) & 0xf8; |
|
|
|
r = r * 255 / 0xf8; |
|
|
|
g = g * 255 / 0xfc; |
|
|
|
b = b * 255 / 0xf8; |
|
|
|
R5G6B5toRed[i] = r; |
|
|
|
R5G6B5toGreen[i] = g; |
|
|
|
R5G6B5toBlue[i] = b; |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i <= 0xffff; i++) { |
|
|
|
GLint r = (i >> 8) & 0xf; |
|
|
|
GLint g = (i >> 4) & 0xf; |
|
|
|
GLint b = (i ) & 0xf; |
|
|
|
GLint a = (i >> 12) & 0xf; |
|
|
|
r = r * 255 / 0xf; |
|
|
|
g = g * 255 / 0xf; |
|
|
|
b = b * 255 / 0xf; |
|
|
|
a = a * 255 / 0xf; |
|
|
|
A4R4G4B4toRed[i] = r; |
|
|
|
A4R4G4B4toGreen[i] = g; |
|
|
|
A4R4G4B4toBlue[i] = b; |
|
|
|
A4R4G4B4toAlpha[i] = b; |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i <= 0xffff; i++) { |
|
|
|
GLint r = (i >> 10) & 0xf8; |
|
|
|
GLint g = (i >> 5) & 0xf8; |
|
|
|
GLint b = (i ) & 0xf8; |
|
|
|
GLint a = (i >> 15) & 0x1; |
|
|
|
r = r * 255 / 0xf8; |
|
|
|
g = g * 255 / 0xf8; |
|
|
|
b = b * 255 / 0xf8; |
|
|
|
a = a * 255; |
|
|
|
A1R5G5B5toRed[i] = r; |
|
|
|
A1R5G5B5toGreen[i] = g; |
|
|
|
A1R5G5B5toBlue[i] = b; |
|
|
|
A1R5G5B5toAlpha[i] = b; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Convert a texture image from an internal format to one of Mesa's |
|
|
|
* core internal formats. This is likely to be used by glGetTexImage |
|
|
|
* and for fetching texture images when falling back to software rendering. |
|
|
|
* |
|
|
|
* Notes: |
|
|
|
* This function will do power of two image down-scaling to accomodate |
|
|
|
* drivers with limited texture image aspect ratios. |
|
|
|
* The implicit dest data type is GL_UNSIGNED_BYTE. |
|
|
|
*/ |
|
|
|
void |
|
|
|
_mesa_unconvert_teximage(MesaIntTexFormat srcFormat, |
|
|
|
GLint srcWidth, GLint srcHeight, |
|
|
|
const GLvoid *srcImage, |
|
|
|
GLsizei dstWidth, GLsizei dstHeight, |
|
|
|
GLenum dstFormat, GLubyte *dstImage) |
|
|
|
{ |
|
|
|
static GLboolean firstCall = GL_TRUE; |
|
|
|
const GLint wScale = srcWidth / dstWidth; /* must be power of two */ |
|
|
|
const GLint hScale = srcHeight / dstHeight; /* must be power of two */ |
|
|
|
ASSERT(srcWidth >= dstWidth); |
|
|
|
ASSERT(srcHeight >= dstHeight); |
|
|
|
ASSERT(dstImage); |
|
|
|
ASSERT(srcImage); |
|
|
|
|
|
|
|
if (firstCall) { |
|
|
|
generate_lookup_tables(); |
|
|
|
firstCall = GL_FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
switch (srcFormat) { |
|
|
|
case MESA_I8: |
|
|
|
case MESA_L8: |
|
|
|
case MESA_A8: |
|
|
|
case MESA_C8: |
|
|
|
#ifdef DEBUG |
|
|
|
if (srcFormat == MESA_I8) { |
|
|
|
ASSERT(dstFormat == GL_INTENSITY); |
|
|
|
} |
|
|
|
else if (srcFormat == MESA_L8) { |
|
|
|
ASSERT(dstFormat == GL_LUMINANCE); |
|
|
|
} |
|
|
|
else if (srcFormat == MESA_A8) { |
|
|
|
ASSERT(dstFormat == GL_ALPHA); |
|
|
|
} |
|
|
|
else if (srcFormat == MESA_C8) { |
|
|
|
ASSERT(dstFormat == GL_COLOR_INDEX); |
|
|
|
} |
|
|
|
#endif |
|
|
|
if (wScale == 1 && hScale == 1) { |
|
|
|
/* easy! */ |
|
|
|
MEMCPY(dstImage, srcImage, dstWidth * dstHeight * sizeof(GLubyte)); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* rescale */ |
|
|
|
const GLubyte *src8 = (const GLubyte *) srcImage; |
|
|
|
GLint row, col; |
|
|
|
for (row = 0; row < dstHeight; row++) { |
|
|
|
GLint srcRow = row * hScale; |
|
|
|
for (col = 0; col < dstWidth; col++) { |
|
|
|
GLint srcCol = col * wScale; |
|
|
|
*dstImage++ = src8[srcRow * srcWidth + srcCol]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case MESA_L8_A8: |
|
|
|
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 */ |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
/* rescale */ |
|
|
|
const GLushort *src16 = (const GLushort *) 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 GLushort tex = src16[srcRow * srcWidth + srcCol]; |
|
|
|
*dstImage++ = (tex >> 8); /* luminance */ |
|
|
|
*dstImage++ = (tex & 0xff); /* alpha */ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case MESA_R5_G6_B5: |
|
|
|
ASSERT(dstFormat == GL_RGB); |
|
|
|
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++ = R5G6B5toRed[tex]; |
|
|
|
*dstImage++ = R5G6B5toGreen[tex]; |
|
|
|
*dstImage++ = R5G6B5toBlue[tex]; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
/* rescale */ |
|
|
|
const GLushort *src16 = (const GLushort *) 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 GLushort tex = src16[srcRow * srcWidth + srcCol]; |
|
|
|
*dstImage++ = R5G6B5toRed[tex]; |
|
|
|
*dstImage++ = R5G6B5toGreen[tex]; |
|
|
|
*dstImage++ = R5G6B5toBlue[tex]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case MESA_A4_R4_G4_B4: |
|
|
|
ASSERT(dstFormat == GL_RGBA); |
|
|
|
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++ = A4R4G4B4toRed[tex]; |
|
|
|
*dstImage++ = A4R4G4B4toGreen[tex]; |
|
|
|
*dstImage++ = A4R4G4B4toBlue[tex]; |
|
|
|
*dstImage++ = A4R4G4B4toAlpha[tex]; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
/* rescale */ |
|
|
|
const GLushort *src16 = (const GLushort *) 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 GLushort tex = src16[srcRow * srcWidth + srcCol]; |
|
|
|
*dstImage++ = A4R4G4B4toRed[tex]; |
|
|
|
*dstImage++ = A4R4G4B4toGreen[tex]; |
|
|
|
*dstImage++ = A4R4G4B4toBlue[tex]; |
|
|
|
*dstImage++ = A4R4G4B4toAlpha[tex]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case MESA_A1_R5_G5_B5: |
|
|
|
ASSERT(dstFormat == GL_RGBA); |
|
|
|
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++ = A1R5G5B5toRed[tex]; |
|
|
|
*dstImage++ = A1R5G5B5toGreen[tex]; |
|
|
|
*dstImage++ = A1R5G5B5toBlue[tex]; |
|
|
|
*dstImage++ = A1R5G5B5toAlpha[tex]; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
/* rescale */ |
|
|
|
const GLushort *src16 = (const GLushort *) 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 GLushort tex = src16[srcRow * srcWidth + srcCol]; |
|
|
|
*dstImage++ = A1R5G5B5toRed[tex]; |
|
|
|
*dstImage++ = A1R5G5B5toGreen[tex]; |
|
|
|
*dstImage++ = A1R5G5B5toBlue[tex]; |
|
|
|
*dstImage++ = A1R5G5B5toAlpha[tex]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case MESA_A8_R8_G8_B8: |
|
|
|
ASSERT(dstFormat == GL_RGBA); |
|
|
|
if (wScale == 1 && hScale == 1) { |
|
|
|
GLint i, n = dstWidth * dstHeight; |
|
|
|
const GLushort *texel = (const GLushort *) srcImage; |
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
const GLuint tex = *texel++; |
|
|
|
*dstImage++ = (tex >> 16) & 0xff; /* R */ |
|
|
|
*dstImage++ = (tex >> 8) & 0xff; /* G */ |
|
|
|
*dstImage++ = (tex ) & 0xff; /* B */ |
|
|
|
*dstImage++ = (tex >> 24) & 0xff; /* A */ |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
/* rescale */ |
|
|
|
const GLushort *src16 = (const GLushort *) 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]; |
|
|
|
*dstImage++ = (tex >> 16) & 0xff; /* R */ |
|
|
|
*dstImage++ = (tex >> 8) & 0xff; /* G */ |
|
|
|
*dstImage++ = (tex ) & 0xff; /* B */ |
|
|
|
*dstImage++ = (tex >> 24) & 0xff; /* A */ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()"); |
|
|
|
} |
|
|
|
} |