Allocate palette slots on a FIFO basis
This commit is contained in:
parent
4d6cea59b7
commit
864dc45d10
|
@ -96,6 +96,10 @@ void APIENTRY glKosSwapBuffers() {
|
||||||
|
|
||||||
profiler_push(__func__);
|
profiler_push(__func__);
|
||||||
|
|
||||||
|
/* We only want to apply the colour table *at most* once per frame
|
||||||
|
* so it's best we do it here */
|
||||||
|
_glApplyColorTable();
|
||||||
|
|
||||||
pvr_wait_ready();
|
pvr_wait_ready();
|
||||||
|
|
||||||
pvr_scene_begin();
|
pvr_scene_begin();
|
||||||
|
|
|
@ -45,8 +45,10 @@ typedef struct {
|
||||||
/* Palette data is always stored in RAM as RGBA8888 and packed as ARGB8888
|
/* Palette data is always stored in RAM as RGBA8888 and packed as ARGB8888
|
||||||
* when uploaded to the PVR */
|
* when uploaded to the PVR */
|
||||||
GLubyte* data;
|
GLubyte* data;
|
||||||
GLushort width;
|
GLushort width; /* The user specified width */
|
||||||
|
GLushort size; /* The size of the bank (16 or 256) */
|
||||||
GLenum format;
|
GLenum format;
|
||||||
|
GLshort bank;
|
||||||
} TexturePalette;
|
} TexturePalette;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -300,9 +300,6 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
|
||||||
break;
|
break;
|
||||||
case GL_SHARED_TEXTURE_PALETTE_EXT: {
|
case GL_SHARED_TEXTURE_PALETTE_EXT: {
|
||||||
SHARED_PALETTE_ENABLED = GL_TRUE;
|
SHARED_PALETTE_ENABLED = GL_TRUE;
|
||||||
|
|
||||||
/* Apply the texture palette if necessary */
|
|
||||||
_glApplyColorTable();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_LIGHT0:
|
case GL_LIGHT0:
|
||||||
|
@ -354,9 +351,6 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
|
||||||
break;
|
break;
|
||||||
case GL_SHARED_TEXTURE_PALETTE_EXT: {
|
case GL_SHARED_TEXTURE_PALETTE_EXT: {
|
||||||
SHARED_PALETTE_ENABLED = GL_FALSE;
|
SHARED_PALETTE_ENABLED = GL_FALSE;
|
||||||
|
|
||||||
/* Restore whatever palette may exist on a bound texture */
|
|
||||||
_glApplyColorTable();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_LIGHT0:
|
case GL_LIGHT0:
|
||||||
|
|
113
GL/texture.c
113
GL/texture.c
|
@ -20,12 +20,84 @@ static GLubyte ACTIVE_TEXTURE = 0;
|
||||||
|
|
||||||
static TexturePalette* SHARED_PALETTE = NULL;
|
static TexturePalette* SHARED_PALETTE = NULL;
|
||||||
|
|
||||||
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type);
|
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type, GLshort bank);
|
||||||
|
|
||||||
#define PACK_ARGB8888(a,r,g,b) ( ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF) )
|
#define PACK_ARGB8888(a,r,g,b) ( ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF) )
|
||||||
|
|
||||||
static TexturePalette* last_bound_palette = NULL;
|
static TexturePalette* last_bound_palette = NULL;
|
||||||
|
|
||||||
|
static GLboolean BANKS_USED[4]; // Each time a 256 colour bank is used, this is set to true
|
||||||
|
static GLboolean SUBBANKS_USED[4][16]; // 4 counts of the used 16 colour banks within the 256 ones
|
||||||
|
|
||||||
|
|
||||||
|
static TexturePalette* _initTexturePalette() {
|
||||||
|
TexturePalette* palette = (TexturePalette*) malloc(sizeof(TexturePalette));
|
||||||
|
assert(palette);
|
||||||
|
|
||||||
|
palette->data = NULL;
|
||||||
|
palette->format = 0;
|
||||||
|
palette->width = 0;
|
||||||
|
palette->bank = -1;
|
||||||
|
palette->size = 0;
|
||||||
|
return palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLshort _glGenPaletteSlot(GLushort size) {
|
||||||
|
GLushort i, j;
|
||||||
|
|
||||||
|
assert(size == 16 || size == 256);
|
||||||
|
|
||||||
|
if(size == 16) {
|
||||||
|
for(i = 0; i < 4; ++i) {
|
||||||
|
for(j = 0; j < 16; ++j) {
|
||||||
|
if(!SUBBANKS_USED[i][j]) {
|
||||||
|
BANKS_USED[i] = GL_TRUE;
|
||||||
|
SUBBANKS_USED[i][j] = GL_TRUE;
|
||||||
|
return (i * 16) + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(i = 0; i < 4; ++i) {
|
||||||
|
if(!BANKS_USED[i]) {
|
||||||
|
BANKS_USED[i] = GL_TRUE;
|
||||||
|
for(j = 0; j < 16; ++j) {
|
||||||
|
SUBBANKS_USED[i][j] = GL_TRUE;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "GL ERROR: No palette slots remain\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _glReleasePaletteSlot(GLshort slot, GLushort size) {
|
||||||
|
GLushort i;
|
||||||
|
|
||||||
|
assert(size == 16 || size == 256);
|
||||||
|
if(size == 16) {
|
||||||
|
GLushort bank = slot / 4;
|
||||||
|
GLushort subbank = slot % 4;
|
||||||
|
|
||||||
|
SUBBANKS_USED[bank][subbank] = GL_FALSE;
|
||||||
|
for(i = 0; i < 16; ++i) {
|
||||||
|
if(SUBBANKS_USED[bank][i]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BANKS_USED[bank] = GL_FALSE;
|
||||||
|
} else {
|
||||||
|
BANKS_USED[slot] = GL_FALSE;
|
||||||
|
for(i = 0; i < 16; ++i) {
|
||||||
|
SUBBANKS_USED[slot][i] = GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _glApplyColorTable() {
|
void _glApplyColorTable() {
|
||||||
/*
|
/*
|
||||||
* FIXME:
|
* FIXME:
|
||||||
|
@ -153,10 +225,7 @@ GLubyte _glInitTextures() {
|
||||||
// Reserve zero so that it is never given to anyone as an ID!
|
// Reserve zero so that it is never given to anyone as an ID!
|
||||||
named_array_reserve(&TEXTURE_OBJECTS, 0);
|
named_array_reserve(&TEXTURE_OBJECTS, 0);
|
||||||
|
|
||||||
SHARED_PALETTE = (TexturePalette*) malloc(sizeof(TexturePalette));
|
SHARED_PALETTE = _initTexturePalette();
|
||||||
SHARED_PALETTE->data = NULL;
|
|
||||||
SHARED_PALETTE->format = 0;
|
|
||||||
SHARED_PALETTE->width = 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,9 +341,6 @@ void APIENTRY glBindTexture(GLenum target, GLuint texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEXTURE_UNITS[ACTIVE_TEXTURE] = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, texture);
|
TEXTURE_UNITS[ACTIVE_TEXTURE] = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, texture);
|
||||||
|
|
||||||
/* Apply the texture palette if necessary */
|
|
||||||
_glApplyColorTable();
|
|
||||||
} else {
|
} else {
|
||||||
TEXTURE_UNITS[ACTIVE_TEXTURE] = NULL;
|
TEXTURE_UNITS[ACTIVE_TEXTURE] = NULL;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +474,8 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||||
active->height = height;
|
active->height = height;
|
||||||
active->color = _determinePVRFormat(
|
active->color = _determinePVRFormat(
|
||||||
internalFormat,
|
internalFormat,
|
||||||
internalFormat /* Doesn't matter (see determinePVRFormat) */
|
internalFormat , /* Doesn't matter (see determinePVRFormat) */
|
||||||
|
0
|
||||||
);
|
);
|
||||||
active->mipmapCount = _glGetMipmapLevelCount(active);
|
active->mipmapCount = _glGetMipmapLevelCount(active);
|
||||||
active->mipmap = (mipmapped) ? ~0 : (1 << level); /* Set only a single bit if this wasn't mipmapped otherwise set all */
|
active->mipmap = (mipmapped) ? ~0 : (1 << level); /* Set only a single bit if this wasn't mipmapped otherwise set all */
|
||||||
|
@ -496,7 +563,7 @@ static GLint _cleanInternalFormat(GLint internalFormat) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
|
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type, GLshort bank) {
|
||||||
/* Given a cleaned internalFormat, return the Dreamcast format
|
/* Given a cleaned internalFormat, return the Dreamcast format
|
||||||
* that can hold it
|
* that can hold it
|
||||||
*/
|
*/
|
||||||
|
@ -547,7 +614,7 @@ static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
|
||||||
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS:
|
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS:
|
||||||
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
case GL_COLOR_INDEX8_EXT:
|
case GL_COLOR_INDEX8_EXT:
|
||||||
return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_TWIDDLED;
|
return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_8BPP_PAL(bank);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -790,7 +857,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the format that we need to convert the data to */
|
/* Calculate the format that we need to convert the data to */
|
||||||
GLuint pvr_format = _determinePVRFormat(internalFormat, type);
|
GLuint pvr_format = _determinePVRFormat(internalFormat, type, 0);
|
||||||
|
|
||||||
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||||
|
|
||||||
|
@ -1061,7 +1128,7 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize
|
||||||
} else {
|
} else {
|
||||||
TextureObject* active = _glGetBoundTexture();
|
TextureObject* active = _glGetBoundTexture();
|
||||||
if(!active->palette) {
|
if(!active->palette) {
|
||||||
active->palette = (TexturePalette*) malloc(sizeof(TexturePalette));
|
active->palette = _initTexturePalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
palette = active->palette;
|
palette = active->palette;
|
||||||
|
@ -1074,9 +1141,28 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize
|
||||||
palette->data = NULL;
|
palette->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(palette->bank > -1) {
|
||||||
|
_glReleasePaletteSlot(palette->bank, palette->size);
|
||||||
|
palette->bank = -1;
|
||||||
|
}
|
||||||
|
|
||||||
palette->data = (GLubyte*) malloc(width * 4);
|
palette->data = (GLubyte*) malloc(width * 4);
|
||||||
palette->format = format;
|
palette->format = format;
|
||||||
palette->width = width;
|
palette->width = width;
|
||||||
|
palette->size = (width > 16) ? 256 : 16;
|
||||||
|
assert(palette->size == 16 || palette->size == 256);
|
||||||
|
|
||||||
|
palette->bank = _glGenPaletteSlot(palette->size);
|
||||||
|
|
||||||
|
if(palette->bank < 0) {
|
||||||
|
/* We ran out of slots! */
|
||||||
|
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||||
|
_glKosPrintError();
|
||||||
|
|
||||||
|
free(palette->data);
|
||||||
|
palette->format = palette->width = palette->size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GLubyte* src = (GLubyte*) data;
|
GLubyte* src = (GLubyte*) data;
|
||||||
GLubyte* dst = (GLubyte*) palette->data;
|
GLubyte* dst = (GLubyte*) palette->data;
|
||||||
|
@ -1096,7 +1182,6 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize
|
||||||
|
|
||||||
/* Colour table might have changed the active palette, so wipe last_bound_palette before reapplying */
|
/* Colour table might have changed the active palette, so wipe last_bound_palette before reapplying */
|
||||||
last_bound_palette = NULL;
|
last_bound_palette = NULL;
|
||||||
_glApplyColorTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLAPI void APIENTRY glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) {
|
GLAPI void APIENTRY glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user