Fix up paletted textures

This commit is contained in:
Luke Benstead 2023-09-06 08:01:01 +01:00
parent 12bd6f474f
commit 7ce01ad93f
6 changed files with 137 additions and 80 deletions

View File

@ -46,7 +46,9 @@ void APIENTRY glKosInitConfig(GLdcConfig* config) {
config->initial_pt_capacity = 512 * 3; config->initial_pt_capacity = 512 * 3;
config->initial_tr_capacity = 1024 * 3; config->initial_tr_capacity = 1024 * 3;
config->initial_immediate_capacity = 1024 * 3; config->initial_immediate_capacity = 1024 * 3;
config->internal_palette_format = GL_RGBA8;
// RGBA4444 is the fastest general format - 8888 will cause a perf issue
config->internal_palette_format = GL_RGBA4;
config->texture_twiddle = GL_TRUE; config->texture_twiddle = GL_TRUE;
} }

View File

@ -28,7 +28,7 @@ static GLuint _determinePVRFormat(GLint internalFormat);
static GLboolean BANKS_USED[MAX_GLDC_PALETTE_SLOTS]; // Each time a 256 colour bank is used, this is set to true static GLboolean BANKS_USED[MAX_GLDC_PALETTE_SLOTS]; // Each time a 256 colour bank is used, this is set to true
static GLboolean SUBBANKS_USED[MAX_GLDC_PALETTE_SLOTS][MAX_GLDC_4BPP_PALETTE_SLOTS]; // 4 counts of the used 16 colour banks within the 256 ones static GLboolean SUBBANKS_USED[MAX_GLDC_PALETTE_SLOTS][MAX_GLDC_4BPP_PALETTE_SLOTS]; // 4 counts of the used 16 colour banks within the 256 ones
static GLenum INTERNAL_PALETTE_FORMAT = GL_RGBA8; static GLenum INTERNAL_PALETTE_FORMAT = GL_RGBA4;
static GLboolean TEXTURE_TWIDDLE_ENABLED = GL_FALSE; static GLboolean TEXTURE_TWIDDLE_ENABLED = GL_FALSE;
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
@ -224,8 +224,8 @@ void _glSetInternalPaletteFormat(GLenum val) {
GPUSetPaletteFormat(GPU_PAL_ARGB4444); GPUSetPaletteFormat(GPU_PAL_ARGB4444);
break; break;
case GL_RGB5_A1: case GL_RGB5_A1:
GPUSetPaletteFormat(GPU_PAL_ARGB1555); GPUSetPaletteFormat(GPU_PAL_ARGB1555);
break; break;
case GL_RGB565_KOS: case GL_RGB565_KOS:
GPUSetPaletteFormat(GPU_PAL_RGB565); GPUSetPaletteFormat(GPU_PAL_RGB565);
break; break;
@ -301,15 +301,19 @@ static GLint _determineStride(GLenum format, GLenum type) {
case GL_RED: case GL_RED:
case GL_ALPHA: case GL_ALPHA:
case GL_COLOR_INDEX: case GL_COLOR_INDEX:
case GL_COLOR_INDEX8_TWID_KOS:
case GL_COLOR_INDEX4_TWID_KOS: // We return 1 for 4bpp, but it gets sorted later
case GL_COLOR_INDEX4_EXT:
case GL_COLOR_INDEX8_EXT:
return 1; return 1;
case GL_RGB: case GL_RGB:
return 3; return 3;
case GL_RGBA: case GL_RGBA:
return 4; return 4;
default: default:
_glKosThrowError(GL_INVALID_VALUE, __func__); break;
return 1;
} }
break;
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
return (format == GL_RED || format == GL_ALPHA) ? 2 : (format == GL_RGB) ? 6 : 8; return (format == GL_RED || format == GL_ALPHA) ? 2 : (format == GL_RGB) ? 6 : 8;
case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5:
@ -324,6 +328,8 @@ static GLint _determineStride(GLenum format, GLenum type) {
return 2; return 2;
} }
fprintf(stderr, "Couldn't find stride for format: 0x%x type: 0x%x\n", format, type);
_glKosThrowError(GL_INVALID_VALUE, __func__);
return -1; return -1;
} }
@ -812,13 +818,13 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
case GL_PALETTE4_RGB8_OES: case GL_PALETTE4_RGB8_OES:
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data);
ptr += 16*3; ptr += 16*3;
glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, ptr);
return; return;
case GL_PALETTE4_RGBA8_OES: case GL_PALETTE4_RGBA8_OES:
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data);
ptr += 16*4; ptr += 16*4;
glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, ptr);
return; return;
case GL_PALETTE4_R5_G6_B5_OES: case GL_PALETTE4_R5_G6_B5_OES:
@ -826,31 +832,28 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
case GL_PALETTE4_RGB5_A1_OES: case GL_PALETTE4_RGB5_A1_OES:
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data);
ptr += 16*2; ptr += 16*2;
glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, ptr);
return; return;
case GL_PALETTE8_RGB8_OES: case GL_PALETTE8_RGB8_OES:
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data);
ptr += 256*3; ptr += 256*3;
glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, ptr);
return; return;
case GL_PALETTE8_RGBA8_OES: case GL_PALETTE8_RGBA8_OES:
//
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data);
ptr += 256*4; ptr += 256*4;
glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, ptr);
return; return;
case GL_PALETTE8_RGBA4_OES: case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES: case GL_PALETTE8_RGB5_A1_OES:
case GL_PALETTE8_R5_G6_B5_OES: case GL_PALETTE8_R5_G6_B5_OES:
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data);
ptr += 256*2; ptr += 256*2;
glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, ptr);
return; return;
default: { default: {
@ -944,7 +947,10 @@ static GLint _cleanInternalFormat(GLint internalFormat) {
case GL_COLOR_INDEX4_TWID_KOS: case GL_COLOR_INDEX4_TWID_KOS:
return internalFormat; return internalFormat;
case GL_COLOR_INDEX4_EXT: case GL_COLOR_INDEX4_EXT:
return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX4_TWID_KOS : internalFormat; // FIXME: We can't auto twiddle GL_COLOR_INDEX4 -> GL_COLOR_INDEX4_TWID_KOS
// so until we can, we need to not twiddle 4bpp paletted textures automatically
// return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX4_TWID_KOS : internalFormat;
return internalFormat;
case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX8_EXT:
return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX8_TWID_KOS : internalFormat; return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX8_TWID_KOS : internalFormat;
case GL_RGB_TWID_KOS: case GL_RGB_TWID_KOS:
@ -1234,18 +1240,35 @@ static int _determineConversion(GLint internalFormat, GLenum format, GLenum type
{_rgb888_to_rgb565, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_BYTE, true, 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_UNSIGNED_BYTE, false, false},
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_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_UNSIGNED_BYTE, true, false},
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_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_UNSIGNED_BYTE, false, true},
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_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_EXT, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, false, false},
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX4_EXT, GL_BYTE, false, false},
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, 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_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, true},
/* FIXME: Implement 4bpp -> 4bpp twiddling
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, true, false},
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_BYTE, true, false}, */
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, false, false},
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_BYTE, false, false},
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_TWID_KOS, GL_UNSIGNED_BYTE, false, false},
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_TWID_KOS, GL_BYTE, false, false},
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, true, false},
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_EXT, GL_BYTE, true, false},
{NULL, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false}, {NULL, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
{NULL, GL_RGBA8, GL_RGBA, GL_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_UNSIGNED_BYTE, false, false},
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_BYTE, false, false}, {_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_BYTE, false, false},
{_rgb888_to_argb4444, GL_RGBA4, GL_RGB, GL_UNSIGNED_BYTE, false, false},
{_rgb888_to_argb4444, GL_RGBA4, GL_RGB, GL_BYTE, false, false},
{_rgba8888_to_argb4444, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
{_rgba8888_to_argb4444, GL_RGBA4, GL_RGBA, GL_BYTE, false, false},
}; };
for(size_t i = 0; i < sizeof(conversions) / sizeof(struct Entry); ++i) { for(size_t i = 0; i < sizeof(conversions) / sizeof(struct Entry); ++i) {
@ -1271,23 +1294,6 @@ static int _determineConversion(GLint internalFormat, GLenum format, GLenum type
return CONVERSION_TYPE_INVALID; return CONVERSION_TYPE_INVALID;
} }
static GLboolean _isSupportedFormat(GLenum format) {
switch(format) {
case GL_ALPHA:
case GL_LUMINANCE:
case GL_INTENSITY:
case GL_LUMINANCE_ALPHA:
case GL_RED:
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
case GL_COLOR_INDEX:
return GL_TRUE;
default:
return GL_FALSE;
}
}
GLboolean _glIsMipmapComplete(const TextureObject* obj) { GLboolean _glIsMipmapComplete(const TextureObject* obj) {
// Non-square textures can't have mipmaps // Non-square textures can't have mipmaps
@ -1366,32 +1372,40 @@ static bool _glTexImage2DValidate(GLenum target, GLint level, GLint internalForm
return false; return false;
} }
if(format != GL_COLOR_INDEX) { GLint validFormats [] = {
if(!_isSupportedFormat(format)) { GL_ALPHA,
INFO_MSG("Unsupported format"); GL_LUMINANCE,
_glKosThrowError(GL_INVALID_ENUM, __func__); GL_INTENSITY,
return false; GL_LUMINANCE_ALPHA,
} GL_RED,
GL_RGB,
GL_RGBA,
GL_BGRA,
GL_COLOR_INDEX,
GL_COLOR_INDEX4_EXT, /* Extension, this is just so glCompressedTexImage can pass-thru */
GL_COLOR_INDEX8_EXT, /* Extension, this is just so glCompressedTexImage can pass-thru */
GL_COLOR_INDEX4_TWID_KOS, /* Extension, this is just so glCompressedTexImage can pass-thru */
GL_COLOR_INDEX8_TWID_KOS, /* Extension, this is just so glCompressedTexImage can pass-thru */
0
};
if(_glCheckValidEnum(format, validFormats, __func__) != 0) {
return false;
}
if(format != GL_COLOR_INDEX4_EXT && format != GL_COLOR_INDEX4_TWID_KOS) {
/* Abuse determineStride to see if type is valid */ /* Abuse determineStride to see if type is valid */
if(_determineStride(GL_RGBA, type) == -1) { if(_determineStride(GL_RGBA, type) == -1) {
INFO_MSG(""); INFO_MSG("");
_glKosThrowError(GL_INVALID_ENUM, __func__); _glKosThrowError(GL_INVALID_ENUM, __func__);
return false; return false;
} }
}
internalFormat = _cleanInternalFormat(internalFormat); if(_cleanInternalFormat(internalFormat) == -1) {
if(internalFormat == -1) { INFO_MSG("");
INFO_MSG(""); _glKosThrowError(GL_INVALID_VALUE, __func__);
_glKosThrowError(GL_INVALID_VALUE, __func__); return false;
return false;
}
} else {
if(internalFormat != GL_COLOR_INDEX8_EXT && internalFormat != GL_COLOR_INDEX4_EXT) {
INFO_MSG("");
_glKosThrowError(GL_INVALID_ENUM, __func__);
return false;
}
} }
GLuint w = width; GLuint w = width;
@ -1461,7 +1475,12 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
return; return;
} }
GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT || internalFormat == GL_COLOR_INDEX4_EXT) ? GL_TRUE : GL_FALSE; GLboolean isPaletted = (
internalFormat == GL_COLOR_INDEX8_EXT ||
internalFormat == GL_COLOR_INDEX4_EXT ||
internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
internalFormat == GL_COLOR_INDEX8_TWID_KOS
) ? GL_TRUE : GL_FALSE;
GLenum cleanInternalFormat = _cleanInternalFormat(internalFormat); GLenum cleanInternalFormat = _cleanInternalFormat(internalFormat);
GLuint pvrFormat = _determinePVRFormat(cleanInternalFormat); GLuint pvrFormat = _determinePVRFormat(cleanInternalFormat);
GLuint originalId = active->index; GLuint originalId = active->index;
@ -1486,8 +1505,26 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
/* All colour formats are represented as shorts internally. Paletted textures /* All colour formats are represented as shorts internally. Paletted textures
* are represented by byte indexes (which look up into a color table) * are represented by byte indexes (which look up into a color table)
*/ */
GLint destStride = isPaletted ? 1 : 2; GLint destStride = _determineStrideInternal(cleanInternalFormat);
GLuint bytes = (width * height * destStride); GLint sourceStride = _determineStride(format, type);
GLuint srcBytes = (width * height * sourceStride);
GLuint destBytes = (width * height * destStride);
TextureConversionFunc conversion;
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
// Hack: If we're doing a 4bpp source (via glCompressedTexture...)
// halve the srcBytes
if(format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS) {
srcBytes /= 2;
}
/* If we're packing stuff, then the dest size is half what it would be */
if((needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK) {
destBytes /= 2;
} else if(internalFormat == GL_COLOR_INDEX4_EXT || internalFormat == GL_COLOR_INDEX4_TWID_KOS) {
destBytes /= 2;
}
if(!active->data) { if(!active->data) {
gl_assert(active); gl_assert(active);
@ -1504,9 +1541,9 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
active->mipmapCount = _glGetMipmapLevelCount(active); active->mipmapCount = _glGetMipmapLevelCount(active);
active->mipmap_bias = GL_KOS_INTERNAL_DEFAULT_MIPMAP_LOD_BIAS; active->mipmap_bias = GL_KOS_INTERNAL_DEFAULT_MIPMAP_LOD_BIAS;
active->dataStride = destStride; active->dataStride = destStride;
active->baseDataSize = bytes; active->baseDataSize = destBytes;
gl_assert(bytes); gl_assert(destBytes);
if(level > 0) { if(level > 0) {
/* If we're uploading a mipmap level, we need to allocate the full amount of space */ /* If we're uploading a mipmap level, we need to allocate the full amount of space */
@ -1540,24 +1577,19 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
GLubyte* targetData = (active->baseDataOffset == 0) ? active->data : _glGetMipmapLocation(active, level); GLubyte* targetData = (active->baseDataOffset == 0) ? active->data : _glGetMipmapLocation(active, level);
gl_assert(targetData); gl_assert(targetData);
TextureConversionFunc conversion;
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
if(needs_conversion < 0) { if(needs_conversion < 0) {
_glKosThrowError(GL_INVALID_VALUE, __func__); _glKosThrowError(GL_INVALID_VALUE, __func__);
INFO_MSG("Couldn't find necessary texture conversion\n"); INFO_MSG("Couldn't find necessary texture conversion\n");
return; return;
} else if(needs_conversion > 0) { } else if(needs_conversion > 0) {
/* Convert the data */ /* Convert the data */
GLint sourceStride = _determineStride(format, type);
GLint destStride = _determineStrideInternal(cleanInternalFormat);
if(sourceStride == -1) { if(sourceStride == -1) {
INFO_MSG("Stride was not detected\n"); INFO_MSG("Stride was not detected\n");
_glKosThrowError(GL_INVALID_OPERATION, __func__); _glKosThrowError(GL_INVALID_OPERATION, __func__);
return; return;
} }
GLubyte* conversionBuffer = (GLubyte*) memalign(32, bytes); GLubyte* conversionBuffer = (GLubyte*) memalign(32, srcBytes);
const GLubyte* src = data; const GLubyte* src = data;
GLubyte* dst = conversionBuffer; GLubyte* dst = conversionBuffer;
@ -1590,13 +1622,17 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
conversion(src, dst); conversion(src, dst);
src += sourceStride; src += sourceStride;
} }
} else if(pack) {
fprintf(stderr, "Just packing\n");
FASTCPY(conversionBuffer, data, srcBytes);
} }
if(pack) { if(pack) {
assert(isPaletted); assert(isPaletted);
fprintf(stderr, "Packing data...\n");
size_t dst_byte = 0; size_t dst_byte = 0;
for(size_t src_byte = 0; src_byte < bytes; ++src_byte) { for(size_t src_byte = 0; src_byte < srcBytes; ++src_byte) {
uint8_t v = conversionBuffer[src_byte]; uint8_t v = conversionBuffer[src_byte];
if(src_byte % 1 == 0) { if(src_byte % 1 == 0) {
@ -1610,25 +1646,28 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
} }
} }
// Halve the byte count to upload fprintf(stderr, "Packed\n");
bytes >>= 1;
} }
FASTCPY(targetData, conversionBuffer, bytes); fprintf(stderr, "Uploading data (%d)...\n", destBytes);
FASTCPY(targetData, conversionBuffer, destBytes);
free(conversionBuffer); free(conversionBuffer);
} else { } else {
/* No conversion necessary, we can just upload data directly */ /* No conversion necessary, we can just upload data directly */
gl_assert(targetData); gl_assert(targetData);
gl_assert(data); gl_assert(data);
gl_assert(bytes); gl_assert(destBytes);
/* No conversion? Just copy the data, and the pvr_format is correct */ /* No conversion? Just copy the data, and the pvr_format is correct */
FASTCPY(targetData, data, bytes); fprintf(stderr, "Uploading data (%d)...\n", destBytes);
FASTCPY(targetData, data, destBytes);
gl_assert(active->index == originalId); gl_assert(active->index == originalId);
} }
gl_assert(active->index == originalId); gl_assert(active->index == originalId);
_glGPUStateMarkDirty(); _glGPUStateMarkDirty();
fprintf(stderr, "Done\n");
} }
void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
@ -1780,13 +1819,16 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize
} }
GLint sourceStride = _determineStride(format, type); GLint sourceStride = _determineStride(format, type);
GLint destStride = _determineStrideInternal(internalFormat);
/* We always store the palette in RAM in RGBA8888. We pack when we set
* the individual colours in the PVR */
GLint destStride = 4;
gl_assert(sourceStride > -1); gl_assert(sourceStride > -1);
TextureConversionFunc convert; TextureConversionFunc convert;
int ret = _determineConversion( int ret = _determineConversion(
INTERNAL_PALETTE_FORMAT, GL_RGBA8,
format, format,
type, type,
&convert &convert
@ -1833,8 +1875,8 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize
palette->bank = -1; palette->bank = -1;
} }
palette->data = (GLubyte*) malloc(width * 4); palette->data = (GLubyte*) malloc(width * destStride);
palette->format = format; palette->format = internalFormat;
palette->width = width; palette->width = width;
palette->size = (width > 16) ? 256 : 16; palette->size = (width > 16) ? 256 : 16;
gl_assert(palette->size == 16 || palette->size == 256); gl_assert(palette->size == 16 || palette->size == 256);

View File

@ -35,8 +35,6 @@ extern const char* GLDC_VERSION;
#define GL_NEARZ_CLIPPING_KOS 0xEEFA #define GL_NEARZ_CLIPPING_KOS 0xEEFA
#define GL_UNSIGNED_BYTE_TWID_KOS 0xEEFB
/* Initialize the GL pipeline. GL will initialize the PVR. */ /* Initialize the GL pipeline. GL will initialize the PVR. */
GLAPI void APIENTRY glKosInit(); GLAPI void APIENTRY glKosInit();

View File

@ -132,7 +132,7 @@ void LoadGLTextures() {
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image, // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself. // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1->width, image1->height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE_TWID_KOS, image1->data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1->width, image1->height, 0, GL_COLOR_INDEX8_TWID_KOS, GL_UNSIGNED_BYTE, image1->data);
glGenerateMipmapEXT(GL_TEXTURE_2D); glGenerateMipmapEXT(GL_TEXTURE_2D);
free(image1); free(image1);

View File

@ -429,7 +429,7 @@ void LoadGLTextures() {
#ifndef USE_16C_PALETTE #ifndef USE_16C_PALETTE
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data);
#else #else
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, image1.data);
#endif #endif
glBindTexture(GL_TEXTURE_2D, textures[1]); // 2d texture (x and y size) glBindTexture(GL_TEXTURE_2D, textures[1]); // 2d texture (x and y size)
@ -444,7 +444,7 @@ void LoadGLTextures() {
#ifndef USE_16C_PALETTE #ifndef USE_16C_PALETTE
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data);
#else #else
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, image1.data);
#endif #endif
glBindTexture(GL_TEXTURE_2D, textures[2]); glBindTexture(GL_TEXTURE_2D, textures[2]);
@ -463,7 +463,7 @@ void LoadGLTextures() {
#ifndef USE_16C_PALETTE #ifndef USE_16C_PALETTE
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image2.data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image2.data);
#else #else
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image2.data); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, image2.data);
#endif #endif
} }

View File

@ -40,6 +40,21 @@ public:
assert_equal(alloc_block_count(pool), expected_blocks); assert_equal(alloc_block_count(pool), expected_blocks);
} }
void test_complex_case() {
uint8_t* large_pool = (uint8_t*) malloc(8 * 1024 * 1024);
alloc_init(large_pool, 8 * 1024 * 1024);
alloc_malloc(large_pool, 262144);
alloc_malloc(large_pool, 262144);
void* a1 = alloc_malloc(large_pool, 524288);
alloc_free(large_pool, a1);
alloc_malloc(large_pool, 699056);
alloc_malloc(large_pool, 128);
alloc_shutdown(large_pool);
free(large_pool);
}
void test_alloc_malloc() { void test_alloc_malloc() {
alloc_init(pool, sizeof(pool)); alloc_init(pool, sizeof(pool));