Continue fixing up paletted texture issues
This commit is contained in:
parent
4d39e19ed5
commit
e5a4f4f716
133
GL/texture.c
133
GL/texture.c
|
@ -297,7 +297,19 @@ static GLint _determineStride(GLenum format, GLenum type) {
|
|||
switch(type) {
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return (format == GL_RED || format == GL_ALPHA) ? 1 : (format == GL_RGB) ? 3 : 4;
|
||||
switch(format) {
|
||||
case GL_RED:
|
||||
case GL_ALPHA:
|
||||
case GL_COLOR_INDEX:
|
||||
return 1;
|
||||
case GL_RGB:
|
||||
return 3;
|
||||
case GL_RGBA:
|
||||
return 4;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return 1;
|
||||
}
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return (format == GL_RED || format == GL_ALPHA) ? 2 : (format == GL_RGB) ? 6 : 8;
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
|
@ -921,6 +933,7 @@ static GLboolean isTwiddledInternalFormat(GLint internalFormat) {
|
|||
*/
|
||||
static GLint _cleanInternalFormat(GLint internalFormat) {
|
||||
switch (internalFormat) {
|
||||
/* All of these formats are fine as they are, no conversion needed */
|
||||
case GL_RGB565_KOS:
|
||||
case GL_ARGB4444_KOS:
|
||||
case GL_ARGB1555_KOS:
|
||||
|
@ -929,10 +942,11 @@ static GLint _cleanInternalFormat(GLint internalFormat) {
|
|||
case GL_ARGB1555_TWID_KOS:
|
||||
case GL_COLOR_INDEX8_TWID_KOS:
|
||||
case GL_COLOR_INDEX4_TWID_KOS:
|
||||
case GL_COLOR_INDEX4_EXT:
|
||||
case GL_COLOR_INDEX8_EXT:
|
||||
/* All of these formats are fine as they are, no conversion needed */
|
||||
return internalFormat;
|
||||
case GL_COLOR_INDEX4_EXT:
|
||||
return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX4_TWID_KOS : internalFormat;
|
||||
case GL_COLOR_INDEX8_EXT:
|
||||
return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX8_TWID_KOS : internalFormat;
|
||||
case GL_RGB_TWID_KOS:
|
||||
return GL_RGB565_TWID_KOS;
|
||||
case GL_RGBA_TWID_KOS:
|
||||
|
@ -1174,6 +1188,16 @@ static inline void _a8_to_argb4444(const GLubyte* source, GLubyte* dest) {
|
|||
*((GLushort*) dest) = (color << 8) | color;
|
||||
}
|
||||
|
||||
|
||||
enum ConversionType {
|
||||
CONVERSION_TYPE_NONE,
|
||||
CONVERSION_TYPE_CONVERT = 1,
|
||||
CONVERSION_TYPE_TWIDDLE = 2,
|
||||
CONVERSION_TYPE_PACK = 4,
|
||||
CONVERSION_TYPE_INVALID = -1
|
||||
};
|
||||
|
||||
|
||||
/* Given an cleaned internal format, and the passed format and type, this returns:
|
||||
*
|
||||
* 0 if not conversion is necessary
|
||||
|
@ -1190,42 +1214,61 @@ static int _determineConversion(GLint internalFormat, GLenum format, GLenum type
|
|||
GLenum format;
|
||||
GLenum type;
|
||||
bool twiddle;
|
||||
bool pack; // If true, each value is packed after conversion into half-bytes
|
||||
} conversions [] = {
|
||||
{_a8_to_argb4444, GL_ARGB4444_KOS, GL_ALPHA, GL_UNSIGNED_BYTE, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false},
|
||||
{_rgba4444_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false},
|
||||
{NULL, GL_ARGB4444_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false},
|
||||
{NULL, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_BYTE, true},
|
||||
{NULL, GL_ARGB1555_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false},
|
||||
{NULL, GL_ARGB1555_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false},
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_BYTE, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false},
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false},
|
||||
{NULL, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false},
|
||||
{NULL, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_TWID_KOS, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_BYTE, true},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_BYTE, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE_TWID_KOS, false},
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false},
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_BYTE, false},
|
||||
{_a8_to_argb4444, GL_ARGB4444_KOS, GL_ALPHA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba4444_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false, false},
|
||||
{NULL, GL_ARGB4444_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false, false},
|
||||
{NULL, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS, false, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_ARGB1555_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false, false},
|
||||
{NULL, GL_ARGB1555_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS, false, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false, false},
|
||||
{NULL, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_TWID_KOS, false, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE_TWID_KOS, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false, true},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_BYTE, false, true},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE_TWID_KOS, false, true},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, true},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, true},
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_BYTE, false, false},
|
||||
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_BYTE, false, false},
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < sizeof(conversions) / sizeof(struct Entry); ++i) {
|
||||
struct Entry* e = conversions + i;
|
||||
if(e->format == format && e->internalFormat == internalFormat && e->type == type) {
|
||||
*func = e->func;
|
||||
int ret = (e->func) ? 1 : 0;
|
||||
ret += (e->twiddle) ? 2 : 0;
|
||||
|
||||
int ret = (e->func) ? CONVERSION_TYPE_CONVERT : CONVERSION_TYPE_NONE;
|
||||
|
||||
if(e->twiddle) {
|
||||
ret |= CONVERSION_TYPE_TWIDDLE;
|
||||
}
|
||||
|
||||
if(e->pack) {
|
||||
ret |= CONVERSION_TYPE_PACK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "No conversion found for format: %d, internalFormat: %d, type: %d\n", format, internalFormat, type);
|
||||
return -1;
|
||||
fprintf(stderr, "No conversion found for format: 0x%x, internalFormat: 0x%x, type: 0x%x\n", format, internalFormat, type);
|
||||
return CONVERSION_TYPE_INVALID;
|
||||
}
|
||||
|
||||
static GLboolean _isSupportedFormat(GLenum format) {
|
||||
|
@ -1446,11 +1489,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
GLint destStride = isPaletted ? 1 : 2;
|
||||
GLuint bytes = (width * height * destStride);
|
||||
|
||||
//special case 4bpp
|
||||
if(internalFormat == GL_COLOR_INDEX4_EXT){
|
||||
bytes >>= 1;
|
||||
}
|
||||
|
||||
if(!active->data) {
|
||||
gl_assert(active);
|
||||
gl_assert(width);
|
||||
|
@ -1523,7 +1561,10 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
const GLubyte* src = data;
|
||||
GLubyte* dst = conversionBuffer;
|
||||
|
||||
if(needs_conversion == 1) {
|
||||
bool pack = (needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK;
|
||||
needs_conversion &= ~CONVERSION_TYPE_PACK;
|
||||
|
||||
if(needs_conversion == CONVERSION_TYPE_CONVERT) {
|
||||
// Convert
|
||||
for(uint32_t i = 0; i < (width * height); ++i) {
|
||||
conversion(src, dst);
|
||||
|
@ -1551,6 +1592,28 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
}
|
||||
}
|
||||
|
||||
if(pack) {
|
||||
assert(isPaletted);
|
||||
|
||||
size_t dst_byte = 0;
|
||||
for(size_t src_byte = 0; src_byte < bytes; ++src_byte) {
|
||||
uint8_t v = conversionBuffer[src_byte];
|
||||
|
||||
if(src_byte % 1 == 0) {
|
||||
conversionBuffer[dst_byte] = (conversionBuffer[dst_byte] & 0xF) | ((v & 0xF0) << 4);
|
||||
} else {
|
||||
conversionBuffer[dst_byte] = (conversionBuffer[dst_byte] & 0xF0) | (v & 0xF);
|
||||
}
|
||||
|
||||
if(src_byte % 1 == 0) {
|
||||
dst_byte++;
|
||||
}
|
||||
}
|
||||
|
||||
// Halve the byte count to upload
|
||||
bytes >>= 1;
|
||||
}
|
||||
|
||||
FASTCPY(targetData, conversionBuffer, bytes);
|
||||
free(conversionBuffer);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue
Block a user