diff --git a/GL/draw.c b/GL/draw.c index edebc33..ee822d3 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -1333,7 +1333,7 @@ GLuint _glGetActiveClientTexture() { void APIENTRY glClientActiveTextureARB(GLenum texture) { TRACE(); - if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS) { + if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_GLDC_TEXTURE_UNITS) { _glKosThrowError(GL_INVALID_ENUM, __func__); return; } diff --git a/GL/flush.c b/GL/flush.c index f9fa7df..bd5602a 100644 --- a/GL/flush.c +++ b/GL/flush.c @@ -46,7 +46,7 @@ void APIENTRY glKosInitConfig(GLdcConfig* config) { config->initial_pt_capacity = 512 * 3; config->initial_tr_capacity = 1024 * 3; config->initial_immediate_capacity = 1024 * 3; - config->internal_palette_format = GL_RGBA4; + config->internal_palette_format = GL_RGBA8; } void APIENTRY glKosInitEx(GLdcConfig* config) { diff --git a/GL/immediate.c b/GL/immediate.c index 9482c33..a71cd16 100644 --- a/GL/immediate.c +++ b/GL/immediate.c @@ -175,7 +175,7 @@ void APIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z) { vert->x = x; vert->y = y; - vert->z = z; + vert->z = z; vert->u = UV_COORD[0]; vert->v = UV_COORD[1]; vert->s = ST_COORD[0]; diff --git a/GL/lighting.c b/GL/lighting.c index 06e3bc5..4667669 100644 --- a/GL/lighting.c +++ b/GL/lighting.c @@ -27,7 +27,7 @@ static GLenum COLOR_MATERIAL_MODE = GL_AMBIENT_AND_DIFFUSE; static GLenum COLOR_MATERIAL_MASK = AMBIENT_MASK | DIFFUSE_MASK; -static LightSource LIGHTS[MAX_LIGHTS]; +static LightSource LIGHTS[MAX_GLDC_LIGHTS]; static GLuint ENABLED_LIGHT_COUNT = 0; static Material MATERIAL; @@ -37,7 +37,7 @@ static void recalcEnabledLights() { GLubyte i; ENABLED_LIGHT_COUNT = 0; - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { if(LIGHTS[i].isEnabled) { ENABLED_LIGHT_COUNT++; } @@ -57,7 +57,7 @@ void _glInitLights() { MATERIAL.exponent = 0.0f; GLubyte i; - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { memcpy(LIGHTS[i].ambient, ZERO, sizeof(GLfloat) * 4); memcpy(LIGHTS[i].diffuse, ONE, sizeof(GLfloat) * 4); memcpy(LIGHTS[i].specular, ONE, sizeof(GLfloat) * 4); @@ -97,7 +97,7 @@ GL_FORCE_INLINE void _glPrecalcLightingValues(GLuint mask) { GLshort i; if(mask & AMBIENT_MASK) { - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { LIGHTS[i].ambientMaterial[0] = LIGHTS[i].ambient[0] * MATERIAL.ambient[0]; LIGHTS[i].ambientMaterial[1] = LIGHTS[i].ambient[1] * MATERIAL.ambient[1]; LIGHTS[i].ambientMaterial[2] = LIGHTS[i].ambient[2] * MATERIAL.ambient[2]; @@ -106,7 +106,7 @@ GL_FORCE_INLINE void _glPrecalcLightingValues(GLuint mask) { } if(mask & DIFFUSE_MASK) { - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { LIGHTS[i].diffuseMaterial[0] = LIGHTS[i].diffuse[0] * MATERIAL.diffuse[0]; LIGHTS[i].diffuseMaterial[1] = LIGHTS[i].diffuse[1] * MATERIAL.diffuse[1]; LIGHTS[i].diffuseMaterial[2] = LIGHTS[i].diffuse[2] * MATERIAL.diffuse[2]; @@ -115,7 +115,7 @@ GL_FORCE_INLINE void _glPrecalcLightingValues(GLuint mask) { } if(mask & SPECULAR_MASK) { - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { LIGHTS[i].specularMaterial[0] = LIGHTS[i].specular[0] * MATERIAL.specular[0]; LIGHTS[i].specularMaterial[1] = LIGHTS[i].specular[1] * MATERIAL.specular[1]; LIGHTS[i].specularMaterial[2] = LIGHTS[i].specular[2] * MATERIAL.specular[2]; @@ -173,7 +173,7 @@ void APIENTRY glLightModeliv(GLenum pname, const GLint* params) { void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) { GLubyte idx = light & 0xF; - if(idx >= MAX_LIGHTS) { + if(idx >= MAX_GLDC_LIGHTS) { return; } @@ -227,7 +227,7 @@ void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) { void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) { GLubyte idx = light & 0xF; - if(idx >= MAX_LIGHTS) { + if(idx >= MAX_GLDC_LIGHTS) { return; } @@ -495,7 +495,7 @@ void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count const float Ny = data->n[1]; const float Nz = data->n[2]; - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { if(!LIGHTS[i].isEnabled) { continue; } diff --git a/GL/matrix.c b/GL/matrix.c index e01298d..74768d0 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -288,11 +288,19 @@ void APIENTRY glFrustum(GLfloat left, GLfloat right, /* Multiply the current matrix by an arbitrary matrix */ void glMultMatrixf(const GLfloat *m) { - Matrix4x4 TEMP; - MEMCPY4(TEMP, m, sizeof(Matrix4x4)); + Matrix4x4 TEMP __attribute__((aligned(32))); + const Matrix4x4 *pMatrix; + + if (((GLint)m)&0xf){ /* Unaligned matrix */ + pMatrix = &TEMP; + MEMCPY4(TEMP, m, sizeof(Matrix4x4)); + } + else{ + pMatrix = (const Matrix4x4*) m; + } UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); - MultiplyMatrix4x4((const Matrix4x4*) &TEMP); + MultiplyMatrix4x4(pMatrix); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); if(MATRIX_MODE == GL_MODELVIEW) { diff --git a/GL/private.h b/GL/private.h index 2bcee46..46287dd 100644 --- a/GL/private.h +++ b/GL/private.h @@ -14,6 +14,11 @@ #include "../containers/aligned_vector.h" #include "../containers/named_array.h" +#define MAX_GLDC_4BPP_PALETTE_SLOTS 16 +#define MAX_GLDC_PALETTE_SLOTS 4 +#define MAX_GLDC_SHARED_PALETTES (MAX_GLDC_PALETTE_SLOTS*MAX_GLDC_4BPP_PALETTE_SLOTS) + + extern void* memcpy4 (void *dest, const void *src, size_t count); #define GL_NO_INSTRUMENT inline __attribute__((no_instrument_function)) @@ -508,8 +513,8 @@ GLuint _glFreeContiguousTextureMemory(); void _glApplyScissor(bool force); -#define MAX_TEXTURE_UNITS 2 -#define MAX_LIGHTS 8 +#define MAX_GLDC_TEXTURE_UNITS 2 +#define MAX_GLDC_LIGHTS 8 /* This is from KOS pvr_buffers.c */ #define PVR_MIN_Z 0.0001f diff --git a/GL/state.c b/GL/state.c index 0af9b77..5cf1fae 100644 --- a/GL/state.c +++ b/GL/state.c @@ -236,9 +236,20 @@ void _glUpdatePVRTextureContext(PolyContext *context, GLshort textureUnit) { if(tx1->isPaletted) { if(_glIsSharedTexturePaletteEnabled()) { TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank); - context->txr.format |= GPUPaletteSelect8BPP(palette->bank); - } else { - context->txr.format |= GPUPaletteSelect8BPP((tx1->palette) ? tx1->palette->bank : 0); + if (palette->size != 16){ + context->txr.format |= GPUPaletteSelect8BPP(palette->bank); + } + else{ + context->txr.format |= GPUPaletteSelect4BPP(palette->bank); + } + } + else { + if (tx1->palette->size != 16){ + context->txr.format |= GPUPaletteSelect8BPP((tx1->palette) ? tx1->palette->bank : 0); + } + else{ + context->txr.format |= GPUPaletteSelect4BPP((tx1->palette) ? tx1->palette->bank : 0); + } } } @@ -291,7 +302,7 @@ void _glInitContext() { glDisable(GL_LIGHTING); GLubyte i; - for(i = 0; i < MAX_LIGHTS; ++i) { + for(i = 0; i < MAX_GLDC_LIGHTS; ++i) { glDisable(GL_LIGHT0 + i); } } @@ -739,7 +750,7 @@ void APIENTRY glGetFloatv(GLenum pname, GLfloat* params) { void APIENTRY glGetIntegerv(GLenum pname, GLint *params) { switch(pname) { case GL_MAX_LIGHTS: - *params = MAX_LIGHTS; + *params = MAX_GLDC_LIGHTS; break; case GL_TEXTURE_BINDING_2D: *params = (_glGetBoundTexture()) ? _glGetBoundTexture()->index : 0; @@ -799,7 +810,7 @@ const GLubyte *glGetString(GLenum name) { return (const GLubyte*) "1.2 (partial) - GLdc 1.1"; case GL_EXTENSIONS: - return (const GLubyte*) "GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette, GL_KOS_multiple_shared_palette, GL_ARB_vertex_array_bgra, GL_ARB_vertex_type_2_10_10_10_rev, GL_KOS_texture_memory_management, GL_ATI_meminfo"; + return (const GLubyte*)"GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_OES_compressed_paletted_texture, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette, GL_KOS_multiple_shared_palette, GL_ARB_vertex_array_bgra, GL_ARB_vertex_type_2_10_10_10_rev, GL_KOS_texture_memory_management, GL_ATI_meminfo"; } return (const GLubyte*) "GL_KOS_ERROR: ENUM Unsupported\n"; diff --git a/GL/texture.c b/GL/texture.c index 55b283c..7846757 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -18,17 +18,18 @@ #define CLAMP_U (1<<1) #define CLAMP_V (1<<0) -static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL}; +static TextureObject* TEXTURE_UNITS[MAX_GLDC_TEXTURE_UNITS] = {NULL, NULL}; static NamedArray TEXTURE_OBJECTS; GLubyte ACTIVE_TEXTURE = 0; -static TexturePalette* SHARED_PALETTES[4] = {NULL, NULL, NULL, NULL}; +static TexturePalette* SHARED_PALETTES[MAX_GLDC_SHARED_PALETTES]; static GLuint _determinePVRFormat(GLint internalFormat, GLenum type); -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 GLenum INTERNAL_PALETTE_FORMAT = GL_RGBA4; +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 GLenum INTERNAL_PALETTE_FORMAT = GL_RGBA8; static void* YALLOC_BASE = NULL; static size_t YALLOC_SIZE = 0; @@ -63,20 +64,21 @@ static GLshort _glGenPaletteSlot(GLushort size) { assert(size == 16 || size == 256); if(size == 16) { - for(i = 0; i < 4; ++i) { - for(j = 0; j < 16; ++j) { + for(i = 0; i < MAX_GLDC_PALETTE_SLOTS; ++i) { + for(j = 0; j < MAX_GLDC_4BPP_PALETTE_SLOTS; ++j) { if(!SUBBANKS_USED[i][j]) { BANKS_USED[i] = GL_TRUE; SUBBANKS_USED[i][j] = GL_TRUE; - return (i * 16) + j; + return (i * MAX_GLDC_4BPP_PALETTE_SLOTS) + j; } } } - } else { - for(i = 0; i < 4; ++i) { + } + else { + for(i = 0; i < MAX_GLDC_PALETTE_SLOTS; ++i) { if(!BANKS_USED[i]) { BANKS_USED[i] = GL_TRUE; - for(j = 0; j < 16; ++j) { + for(j = 0; j < MAX_GLDC_4BPP_PALETTE_SLOTS; ++j) { SUBBANKS_USED[i][j] = GL_TRUE; } return i; @@ -88,25 +90,54 @@ static GLshort _glGenPaletteSlot(GLushort size) { return -1; } -static void _glReleasePaletteSlot(GLshort slot, GLushort size) { - GLushort i; +GLushort _glFreePaletteSlots(GLushort size) +{ + GLushort i, j , slots = 0; assert(size == 16 || size == 256); + if(size == 16) { - GLushort bank = slot / 4; - GLushort subbank = slot % 4; + for(i = 0; i < MAX_GLDC_PALETTE_SLOTS; ++i) { + for(j = 0; j < MAX_GLDC_4BPP_PALETTE_SLOTS; ++j) { + if(!SUBBANKS_USED[i][j]) { + slots++; + } + } + } + } else { + for(i = 0; i < MAX_GLDC_PALETTE_SLOTS; ++i) { + if(!BANKS_USED[i]) { + slots++; + } + } + } + + return slots; +} + +static void _glReleasePaletteSlot(GLshort slot, GLushort size) +{ + GLushort i, j; + + assert(size == 16 || size == 256); + + + if (size == 16) { + GLushort bank = slot / MAX_GLDC_PALETTE_SLOTS; + GLushort subbank = slot % MAX_GLDC_PALETTE_SLOTS; SUBBANKS_USED[bank][subbank] = GL_FALSE; - for(i = 0; i < 16; ++i) { - if(SUBBANKS_USED[bank][i]) { + + for (i = 0; i < MAX_GLDC_4BPP_PALETTE_SLOTS; ++i) { + if (SUBBANKS_USED[bank][i]) { return; } } - BANKS_USED[bank] = GL_FALSE; - } else { + } + else { BANKS_USED[slot] = GL_FALSE; - for(i = 0; i < 16; ++i) { + for (i = 0; i < MAX_GLDC_4BPP_PALETTE_SLOTS; ++i) { SUBBANKS_USED[slot][i] = GL_FALSE; } } @@ -139,6 +170,30 @@ static void GPUTextureTwiddle8PPP(void* src, void* dst, uint32_t w, uint32_t h) } } +static void GPUTextureTwiddle4PPP(void* src, void* dst, uint32_t w, uint32_t h) { + uint32_t x, y, yout, min, mask; + + min = MIN(w, h); + mask = min - 1; + + uint8_t* pixels; + uint16_t* vtex; + pixels = (uint8_t*) src; + vtex = (uint16_t*) dst; + + for(y = 0; y < h; y += 2) { + yout = y; + for (x = 0; x < w; x += 2) { + vtex[TWIDOUT((x & mask) / 2, (yout & mask) / 2) + + (x / min + yout / min) * min * min / 4] = + vtex[TWIDOUT((x & mask) / 2, (yout & mask) / 2) + + (x / min + yout / min) * min * min / 4] = + ((pixels[(x + y * w) >> 1] & 15) << 8) | ((pixels[(x + (y + 1) * w) >> 1] & 15) << 12) | + ((pixels[(x + y * w) >> 1] >> 4) << 0) | ((pixels[(x + (y + 1) * w) >> 1] >> 4) << 4); + } + } +} + static void GPUTextureTwiddle16BPP(void * src, void* dst, uint32_t w, uint32_t h) { uint32_t x, y, yout, min, mask; @@ -161,39 +216,55 @@ static void GPUTextureTwiddle16BPP(void * src, void* dst, uint32_t w, uint32_t h } TexturePalette* _glGetSharedPalette(GLshort bank) { - assert(bank >= 0 && bank < 4); + assert(bank >= 0 && bank < MAX_GLDC_SHARED_PALETTES); return SHARED_PALETTES[bank]; } - void _glSetInternalPaletteFormat(GLenum val) { INTERNAL_PALETTE_FORMAT = val; - if(INTERNAL_PALETTE_FORMAT == GL_RGBA4) { - GPUSetPaletteFormat(GPU_PAL_ARGB4444); - } else { - assert(INTERNAL_PALETTE_FORMAT == GL_RGBA8); - GPUSetPaletteFormat(GPU_PAL_ARGB8888); + switch(INTERNAL_PALETTE_FORMAT){ + case GL_RGBA8: + GPUSetPaletteFormat(GPU_PAL_ARGB8888); + break; + case GL_RGBA4: + GPUSetPaletteFormat(GPU_PAL_ARGB4444); + break; + case GL_RGB5_A1: + GPUSetPaletteFormat(GPU_PAL_ARGB1555); + break; + case GL_RGB565_KOS: + GPUSetPaletteFormat(GPU_PAL_RGB565); + break; + default: + assert(0); + } } - void _glApplyColorTable(TexturePalette* src) { - /* - * FIXME: - * - * - Different palette formats (GL_RGB -> PVR_PAL_RGB565) - */ if(!src || !src->data) { return; } GLushort i; GLushort offset = src->size * src->bank; + for(i = 0; i < src->width; ++i) { GLubyte* entry = &src->data[i * 4]; - if(INTERNAL_PALETTE_FORMAT == GL_RGBA8) { - GPUSetPaletteEntry(offset + i, PACK_ARGB8888(entry[3], entry[0], entry[1], entry[2])); - } else { - GPUSetPaletteEntry(offset + i, PACK_ARGB4444(entry[3], entry[0], entry[1], entry[2])); + + switch(INTERNAL_PALETTE_FORMAT) + { + case GL_RGBA8: + GPUSetPaletteEntry(offset + i, PACK_ARGB8888(entry[3], entry[0], entry[1], entry[2])); + break; + case GL_RGBA4: + GPUSetPaletteEntry(offset + i, PACK_ARGB4444(entry[3], entry[0], entry[1], entry[2])); + break; + case GL_RGB5_A1: + GPUSetPaletteEntry(offset + i, PACK_ARGB1555(entry[3], entry[0], entry[1], entry[2])); + break; + case GL_RGB565_KOS: + GPUSetPaletteEntry(offset + i, PACK_RGB565(entry[0], entry[1], entry[2])); + break; } } } @@ -364,19 +435,38 @@ static GLuint _glGetMipmapDataSize(TextureObject* obj) { return imageSize + offset; } + +void _glResetSharedPalettes() +{ + uint32_t i; + + for (i=0; i < MAX_GLDC_SHARED_PALETTES;i++){ + + MEMSET4(SHARED_PALETTES[i], 0x0, sizeof(TexturePalette)); + SHARED_PALETTES[i]->bank = -1; + } + + memset((void*) BANKS_USED, 0x0, sizeof(BANKS_USED)); + memset((void*) SUBBANKS_USED, 0x0, sizeof(SUBBANKS_USED)); + +} GLubyte _glInitTextures() { + + uint32_t i; + named_array_init(&TEXTURE_OBJECTS, sizeof(TextureObject), MAX_TEXTURE_COUNT); // Reserve zero so that it is never given to anyone as an ID! named_array_reserve(&TEXTURE_OBJECTS, 0); - SHARED_PALETTES[0] = _initTexturePalette(); - SHARED_PALETTES[1] = _initTexturePalette(); - SHARED_PALETTES[2] = _initTexturePalette(); - SHARED_PALETTES[3] = _initTexturePalette(); + for (i=0; i < MAX_GLDC_SHARED_PALETTES;i++){ + SHARED_PALETTES[i] = _initTexturePalette(); + } - memset((void*) BANKS_USED, 0x0, sizeof(BANKS_USED)); - memset((void*) SUBBANKS_USED, 0x0, sizeof(SUBBANKS_USED)); + _glResetSharedPalettes(); + + //memset((void*) BANKS_USED, 0x0, sizeof(BANKS_USED)); + //memset((void*) SUBBANKS_USED, 0x0, sizeof(SUBBANKS_USED)); size_t vram_free = GPUMemoryAvailable(); YALLOC_SIZE = vram_free - PVR_MEM_BUFFER_SIZE; /* Take all but 64kb VRAM */ @@ -406,7 +496,7 @@ TextureObject* _glGetBoundTexture() { void APIENTRY glActiveTextureARB(GLenum texture) { TRACE(); - if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS) { + if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_GLDC_TEXTURE_UNITS) { _glKosThrowError(GL_INVALID_ENUM, "glActiveTextureARB"); return; } @@ -476,6 +566,11 @@ void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) { } if(txr->palette && txr->palette->data) { + + if (txr->palette->bank > -1) { + _glReleasePaletteSlot(txr->palette->bank, txr->palette->size); + txr->palette->bank = -1; + } free(txr->palette->data); txr->palette->data = NULL; } @@ -616,6 +711,8 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target, } GLboolean mipmapped = GL_FALSE; + //GLboolean paletted = GL_FALSE; + GLbyte *ptr = (GLbyte*)data; switch(internalFormat) { case GL_COMPRESSED_ARGB_1555_VQ_KOS: @@ -633,6 +730,50 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target, case GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS: mipmapped = GL_TRUE; break; + case GL_PALETTE4_RGB8_OES: + glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data); + ptr += 16*3; + glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); + return; + + case GL_PALETTE4_RGBA8_OES: + glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data); + ptr += 16*4; + glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); + return; + + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 16, internalFormat, GL_UNSIGNED_BYTE, data); + ptr += 16*2; + glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX4_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); + return; + + case GL_PALETTE8_RGB8_OES: + glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data); + ptr += 256*3; + glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); + return; + + + case GL_PALETTE8_RGBA8_OES: + // + glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data); + ptr += 256*4; + glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); + return; + + + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + case GL_PALETTE8_R5_G6_B5_OES: + + glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, internalFormat, GL_UNSIGNED_BYTE, data); + ptr += 256*2; + glTexImage2D(GL_TEXTURE_2D, level, GL_COLOR_INDEX8_EXT, width, height, border, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ptr); + return; + default: { _glKosThrowError(GL_INVALID_OPERATION, __func__); return; @@ -824,9 +965,21 @@ static GLint _cleanInternalFormat(GLint internalFormat) { typedef void (*TextureConversionFunc)(const GLubyte*, GLubyte*); GL_FORCE_INLINE void _rgba8888_to_argb4444(const GLubyte* source, GLubyte* dest) { - *((GLushort*) dest) = (source[3] & 0xF0) << 8 | (source[0] & 0xF0) << 4 | (source[1] & 0xF0) | (source[2] & 0xF0) >> 4; + + *((GLushort*) dest) = (source[1] & 0xF0) << 8 | (source[2] & 0xF0) << 4 | (source[0] & 0xF0) | (source[3] & 0xF0) >> 4; } +GL_FORCE_INLINE void _rgba8888_to_rgba4444(const GLubyte* source, GLubyte* dest) { + + *((GLushort*) dest) = (source[3] & 0xF0) << 8 | (source[2] & 0xF0) << 4 | (source[1] & 0xF0) | (source[0] & 0xF0) >> 4; +} + +GL_FORCE_INLINE void _rgb888_to_argb4444(const GLubyte* source, GLubyte* dest) { + + *((GLushort*) dest) = 0xF << 8 | (source[0] & 0xF0) << 4 | (source[1] & 0xF0) | (source[2] & 0xF0) >> 4; +} + + GL_FORCE_INLINE void _rgba8888_to_rgba8888(const GLubyte* source, GLubyte* dest) { /* Noop */ GLubyte* dst = (GLubyte*) dest; @@ -836,7 +989,15 @@ GL_FORCE_INLINE void _rgba8888_to_rgba8888(const GLubyte* source, GLubyte* dest) dst[3] = source[3]; } +GL_FORCE_INLINE void _rgba4444_to_rgba4444(const GLubyte* source, GLubyte* dest) { + /* Noop */ + GLubyte* dst = (GLubyte*) dest; + dst[0] = source[0]; + dst[1] = source[1]; +} + GL_FORCE_INLINE void _rgba8888_to_rgb565(const GLubyte* source, GLubyte* dest) { + *((GLushort*) dest) = ((source[0] & 0b11111000) << 8) | ((source[1] & 0b11111100) << 3) | (source[2] >> 3); } @@ -849,10 +1010,23 @@ GL_FORCE_INLINE void _rgb888_to_rgba8888(const GLubyte* source, GLubyte* dest) { dst[3] = 255; } +GL_FORCE_INLINE void _rgb888_to_rgba4444(const GLubyte* source, GLubyte* dest) { + *((GLushort*) dest) = 0xF << 8 | (source[2] & 0xF0) << 4 | (source[1] & 0xF0) | (source[0] & 0xF0) >> 4; +} + GL_FORCE_INLINE void _rgb888_to_rgb565(const GLubyte* source, GLubyte* dest) { *((GLushort*) dest) = ((source[0] & 0b11111000) << 8) | ((source[1] & 0b11111100) << 3) | (source[2] >> 3); } +GL_FORCE_INLINE void _rgb565_to_rgb8888(const GLubyte* source, GLubyte* dest) { + GLushort src = *((GLushort*) source); + + dest[3] = (src & 0x1f) << 3; + dest[2] = ((src >> 5) & 0x3f) <<2; + dest[1] = ((src >> 11) & 0x1f) <<3; + dest[0] = 0xff; +} + GL_FORCE_INLINE void _rgba8888_to_a000(const GLubyte* source, GLubyte* dest) { *((GLushort*) dest) = ((source[3] & 0b11111000) << 8); } @@ -870,10 +1044,20 @@ GL_FORCE_INLINE void _rgba4444_to_rgba8888(const GLubyte* source, GLubyte* dest) GLushort src = *((GLushort*) source); GLubyte* dst = (GLubyte*) dest; - dst[0] = ((src & 0xF000) >> 12) * 2; - dst[1] = ((src & 0x0F00) >> 8) * 2; - dst[2] = ((src & 0x00F0) >> 4) * 2; - dst[3] = ((src & 0x000F)) * 2; + dst[0] = (src & 0xf) << 4; + dst[1] = ((src >> 4) & 0xf) << 4; + dst[2] = ((src >> 8) & 0xf) << 4; + dst[3] = (src >> 12) << 4; +} + +GL_FORCE_INLINE void _rgba5551_to_rgba8888(const GLubyte* source, GLubyte* dest) { + GLushort src = *((GLushort*) source); + GLubyte* dst = (GLubyte*) dest; + + dst[0] = (src & 0x1f) << 3; + dst[1] = ((src >> 5) & 0x1f) << 3; + dst[2] = ((src >> 5) & 0x1f) << 3; + dst[3] = (src >> 15) << 7; } GL_FORCE_INLINE void _i8_to_i8(const GLubyte* source, GLubyte* dest) { @@ -882,8 +1066,10 @@ GL_FORCE_INLINE void _i8_to_i8(const GLubyte* source, GLubyte* dest) { *dst = *source; } -static inline void _alpha8_to_argb4444(const GLubyte* source, GLubyte* dest) { - *((GLushort*) dest) = (*source & 0xF0) << 8 | (0xFF & 0xF0) << 4 | (0xFF & 0xF0) | (0xFF & 0xF0) >> 4; +static inline void _a8_to_argb4444(const GLubyte* source, GLubyte* dest) { + GLushort color = *source & 0xf0; + color |= (color >> 4); + *((GLushort*) dest) = (color << 8) | color; } static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum format, GLenum type) { @@ -891,7 +1077,8 @@ static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum f case GL_ALPHA: { if(format == GL_ALPHA) { /* Dreamcast doesn't really support GL_ALPHA internally, so store as argb with each rgb value as white */ - return _alpha8_to_argb4444; + /* Applying alpha values to all channels seems a better option*/ + return _a8_to_argb4444; } else if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) { return _rgba8888_to_a000; } else if(type == GL_BYTE && format == GL_RGBA) { @@ -924,19 +1111,43 @@ static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum f return _rgba4444_to_argb4444; } } break; - case GL_RGBA8: { + case GL_RGBA8: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565_KOS: + if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) { return _rgba8888_to_rgba8888; - } else if (type == GL_BYTE && format == GL_RGBA) { + } + else + if (type == GL_BYTE && format == GL_RGBA) { return _rgba8888_to_rgba8888; - } else if(type == GL_UNSIGNED_BYTE && format == GL_RGB) { + } + else + if(type == GL_UNSIGNED_BYTE && format == GL_RGB) { return _rgb888_to_rgba8888; - } else if (type == GL_BYTE && format == GL_RGB) { + } + else + if (type == GL_BYTE && format == GL_RGB) { return _rgb888_to_rgba8888; - } else if(type == GL_UNSIGNED_SHORT_4_4_4_4 && format == GL_RGBA) { + } + else + if(type == GL_UNSIGNED_SHORT_4_4_4_4 && format == GL_RGBA) { return _rgba4444_to_rgba8888; } - } break; + else + if(type == GL_UNSIGNED_BYTE && format == GL_RGBA4) { + return _rgba4444_to_rgba8888; + } + else + if(type == GL_UNSIGNED_BYTE && format == GL_RGB5_A1) { + return _rgba5551_to_rgba8888; + } + else + if(type == GL_UNSIGNED_BYTE && format == GL_RGB565_KOS) { + return _rgb565_to_rgb8888; + } + break; case GL_COLOR_INDEX8_EXT: if(format == GL_COLOR_INDEX) { switch(type) { @@ -1050,6 +1261,12 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, return; } + if (width > 1024 || height > 1024){ + INFO_MSG("Invalid texture size"); + _glKosThrowError(GL_INVALID_VALUE, __func__); + return; + } + if(format != GL_COLOR_INDEX) { if(!_isSupportedFormat(format)) { INFO_MSG("Unsupported format"); @@ -1071,7 +1288,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, return; } } else { - if(internalFormat != GL_COLOR_INDEX8_EXT) { + if(internalFormat != GL_COLOR_INDEX8_EXT && internalFormat != GL_COLOR_INDEX4_EXT) { INFO_MSG(""); _glKosThrowError(GL_INVALID_ENUM, __func__); return; @@ -1129,7 +1346,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, return; } - GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT) ? GL_TRUE : GL_FALSE; + GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT || internalFormat == GL_COLOR_INDEX4_EXT) ? GL_TRUE : GL_FALSE; /* Calculate the format that we need to convert the data to */ GLuint pvr_format = _determinePVRFormat(internalFormat, type); @@ -1161,6 +1378,11 @@ 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) { assert(active); assert(width); @@ -1302,8 +1524,14 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, if(internalFormat == GL_COLOR_INDEX8_EXT) { GPUTextureTwiddle8PPP((void*) pixels, targetData, width, height); - } else { - GPUTextureTwiddle16BPP((void*) pixels, targetData, width, height); + } + else{ + if(internalFormat == GL_COLOR_INDEX4_EXT) { + GPUTextureTwiddle4PPP((void*) pixels, targetData, width, height); + } + else { + GPUTextureTwiddle16BPP((void*) pixels, targetData, width, height); + } } /* We make sure we remove nontwiddled and add twiddled. We could always @@ -1403,18 +1631,21 @@ void APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) { } GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data) { + GLint validTargets[] = { GL_TEXTURE_2D, GL_SHARED_TEXTURE_PALETTE_EXT, - GL_SHARED_TEXTURE_PALETTE_0_KOS, - GL_SHARED_TEXTURE_PALETTE_1_KOS, - GL_SHARED_TEXTURE_PALETTE_2_KOS, - GL_SHARED_TEXTURE_PALETTE_3_KOS, - 0 - }; + GL_SHARED_TEXTURE_PALETTE_0_KOS,GL_SHARED_TEXTURE_PALETTE_1_KOS,GL_SHARED_TEXTURE_PALETTE_2_KOS,GL_SHARED_TEXTURE_PALETTE_3_KOS,GL_SHARED_TEXTURE_PALETTE_4_KOS,GL_SHARED_TEXTURE_PALETTE_5_KOS,GL_SHARED_TEXTURE_PALETTE_6_KOS,GL_SHARED_TEXTURE_PALETTE_7_KOS,GL_SHARED_TEXTURE_PALETTE_8_KOS,GL_SHARED_TEXTURE_PALETTE_9_KOS, + GL_SHARED_TEXTURE_PALETTE_10_KOS,GL_SHARED_TEXTURE_PALETTE_11_KOS,GL_SHARED_TEXTURE_PALETTE_12_KOS,GL_SHARED_TEXTURE_PALETTE_13_KOS,GL_SHARED_TEXTURE_PALETTE_14_KOS,GL_SHARED_TEXTURE_PALETTE_15_KOS,GL_SHARED_TEXTURE_PALETTE_16_KOS,GL_SHARED_TEXTURE_PALETTE_17_KOS,GL_SHARED_TEXTURE_PALETTE_18_KOS,GL_SHARED_TEXTURE_PALETTE_19_KOS, + GL_SHARED_TEXTURE_PALETTE_20_KOS,GL_SHARED_TEXTURE_PALETTE_21_KOS,GL_SHARED_TEXTURE_PALETTE_22_KOS,GL_SHARED_TEXTURE_PALETTE_23_KOS,GL_SHARED_TEXTURE_PALETTE_24_KOS,GL_SHARED_TEXTURE_PALETTE_25_KOS,GL_SHARED_TEXTURE_PALETTE_26_KOS,GL_SHARED_TEXTURE_PALETTE_27_KOS,GL_SHARED_TEXTURE_PALETTE_28_KOS,GL_SHARED_TEXTURE_PALETTE_29_KOS, + GL_SHARED_TEXTURE_PALETTE_30_KOS,GL_SHARED_TEXTURE_PALETTE_31_KOS,GL_SHARED_TEXTURE_PALETTE_32_KOS,GL_SHARED_TEXTURE_PALETTE_33_KOS,GL_SHARED_TEXTURE_PALETTE_34_KOS,GL_SHARED_TEXTURE_PALETTE_35_KOS,GL_SHARED_TEXTURE_PALETTE_36_KOS,GL_SHARED_TEXTURE_PALETTE_37_KOS,GL_SHARED_TEXTURE_PALETTE_38_KOS,GL_SHARED_TEXTURE_PALETTE_39_KOS, + GL_SHARED_TEXTURE_PALETTE_40_KOS,GL_SHARED_TEXTURE_PALETTE_41_KOS,GL_SHARED_TEXTURE_PALETTE_42_KOS,GL_SHARED_TEXTURE_PALETTE_43_KOS,GL_SHARED_TEXTURE_PALETTE_44_KOS,GL_SHARED_TEXTURE_PALETTE_45_KOS,GL_SHARED_TEXTURE_PALETTE_46_KOS,GL_SHARED_TEXTURE_PALETTE_47_KOS,GL_SHARED_TEXTURE_PALETTE_48_KOS,GL_SHARED_TEXTURE_PALETTE_49_KOS, + GL_SHARED_TEXTURE_PALETTE_50_KOS,GL_SHARED_TEXTURE_PALETTE_51_KOS,GL_SHARED_TEXTURE_PALETTE_52_KOS,GL_SHARED_TEXTURE_PALETTE_53_KOS,GL_SHARED_TEXTURE_PALETTE_54_KOS,GL_SHARED_TEXTURE_PALETTE_55_KOS,GL_SHARED_TEXTURE_PALETTE_56_KOS,GL_SHARED_TEXTURE_PALETTE_57_KOS,GL_SHARED_TEXTURE_PALETTE_58_KOS,GL_SHARED_TEXTURE_PALETTE_59_KOS, + GL_SHARED_TEXTURE_PALETTE_60_KOS,GL_SHARED_TEXTURE_PALETTE_61_KOS,GL_SHARED_TEXTURE_PALETTE_62_KOS,GL_SHARED_TEXTURE_PALETTE_63_KOS, + 0}; - GLint validInternalFormats[] = {GL_RGB8, GL_RGBA8, 0}; - GLint validFormats[] = {GL_RGB, GL_RGBA, 0}; + GLint validInternalFormats[] = {GL_RGB8, GL_RGBA8, GL_RGBA4, 0}; + GLint validFormats[] = {GL_RGB, GL_RGBA,GL_RGB5_A1, GL_RGB5_A1, GL_RGB565_KOS, GL_RGBA4, 0}; GLint validTypes[] = {GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, 0}; if(_glCheckValidEnum(target, validTargets, __func__) != 0) { @@ -1425,6 +1656,33 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize return; } + switch(format){ + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE8_RGBA8_OES: + format = GL_RGBA; + break; + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE8_RGB8_OES: + format = GL_RGB; + break; + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE8_R5_G6_B5_OES: + case GL_UNSIGNED_SHORT_5_6_5: + format = GL_RGB565_KOS; + break; + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGB5_A1_OES: + case GL_UNSIGNED_SHORT_5_5_5_1: + format = GL_RGB5_A1; + break; + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_UNSIGNED_SHORT_4_4_4_4: + format = GL_RGBA4; + break; + + } + if(_glCheckValidEnum(format, validFormats, __func__) != 0) { return; } @@ -1444,7 +1702,7 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize assert(sourceStride > -1); TextureConversionFunc convert = _determineConversion( - GL_RGBA8, /* We always store palettes in this format */ + INTERNAL_PALETTE_FORMAT, format, type ); @@ -1456,21 +1714,25 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize TexturePalette* palette = NULL; + GLboolean sharedPaletteUsed = GL_FALSE; + /* Custom extension - allow uploading to one of 4 custom palettes */ if(target == GL_SHARED_TEXTURE_PALETTE_EXT || target == GL_SHARED_TEXTURE_PALETTE_0_KOS) { palette = SHARED_PALETTES[0]; - } else if(target == GL_SHARED_TEXTURE_PALETTE_1_KOS) { - palette = SHARED_PALETTES[1]; - } else if(target == GL_SHARED_TEXTURE_PALETTE_2_KOS) { - palette = SHARED_PALETTES[2]; - } else if(target == GL_SHARED_TEXTURE_PALETTE_3_KOS) { - palette = SHARED_PALETTES[3]; - } else { + sharedPaletteUsed = GL_TRUE; + } + + for (GLbyte i = 1; i < MAX_GLDC_SHARED_PALETTES; ++i) { + if (target == GL_SHARED_TEXTURE_PALETTE_0_KOS + i) { + palette = SHARED_PALETTES[i]; + sharedPaletteUsed = GL_TRUE; + } + } + if (sharedPaletteUsed == GL_FALSE){ TextureObject* active = _glGetBoundTexture(); if(!active->palette) { active->palette = _initTexturePalette(); } - palette = active->palette; } @@ -1623,6 +1885,9 @@ GLAPI void APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height _GL_UNUSED(pixels); assert(0 && "Not Implemented"); } +GLuint _glMaxTextureMemory() { + return YALLOC_SIZE; +} GLuint _glFreeTextureMemory() { return yalloc_count_free(YALLOC_BASE); diff --git a/include/GL/glext.h b/include/GL/glext.h index 210d86b..dacaea6 100644 --- a/include/GL/glext.h +++ b/include/GL/glext.h @@ -161,6 +161,22 @@ GLAPI void APIENTRY glGetColorTableEXT(GLenum target, GLenum format, GLenum type GLAPI void APIENTRY glGetColorTableParameterivEXT(GLenum target, GLenum pname, GLint *params); GLAPI void APIENTRY glGetColorTableParameterfvEXT(GLenum target, GLenum pname, GLfloat *params); +/* ext OES_compressed_paletted_texture */ + +/* PixelInternalFormat */ +//Ozzy: used MesaGL definitions please adjust if it causes probs. +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 + + /* Loads VQ compressed texture from SH4 RAM into PVR VRAM */ /* internalformat must be one of the following constants: GL_UNSIGNED_SHORT_5_6_5_VQ diff --git a/include/GL/glkos.h b/include/GL/glkos.h index a46277e..e2ef11a 100644 --- a/include/GL/glkos.h +++ b/include/GL/glkos.h @@ -88,6 +88,7 @@ GLAPI void APIENTRY glKosInitConfig(GLdcConfig* config); GLAPI void APIENTRY glKosInitEx(GLdcConfig* config); GLAPI void APIENTRY glKosSwapBuffers(); + /* * CUSTOM EXTENSION multiple_shared_palette_KOS * @@ -107,20 +108,90 @@ GLAPI void APIENTRY glKosSwapBuffers(); * by default textures use shared palette 0. */ + #define GL_SHARED_TEXTURE_PALETTE_0_KOS 0xEEFC #define GL_SHARED_TEXTURE_PALETTE_1_KOS 0xEEFD #define GL_SHARED_TEXTURE_PALETTE_2_KOS 0xEEFE #define GL_SHARED_TEXTURE_PALETTE_3_KOS 0xEEFF +#define GL_SHARED_TEXTURE_PALETTE_4_KOS 0xEF00 +#define GL_SHARED_TEXTURE_PALETTE_5_KOS 0xEF01 +#define GL_SHARED_TEXTURE_PALETTE_6_KOS 0xEF02 +#define GL_SHARED_TEXTURE_PALETTE_7_KOS 0xEF03 +#define GL_SHARED_TEXTURE_PALETTE_8_KOS 0xEF04 +#define GL_SHARED_TEXTURE_PALETTE_9_KOS 0xEF05 + +#define GL_SHARED_TEXTURE_PALETTE_10_KOS 0xEF06 +#define GL_SHARED_TEXTURE_PALETTE_11_KOS 0xEF07 +#define GL_SHARED_TEXTURE_PALETTE_12_KOS 0xEF08 +#define GL_SHARED_TEXTURE_PALETTE_13_KOS 0xEF09 +#define GL_SHARED_TEXTURE_PALETTE_14_KOS 0xEF0A +#define GL_SHARED_TEXTURE_PALETTE_15_KOS 0xEF0B +#define GL_SHARED_TEXTURE_PALETTE_16_KOS 0xEF0C +#define GL_SHARED_TEXTURE_PALETTE_17_KOS 0xEF0D +#define GL_SHARED_TEXTURE_PALETTE_18_KOS 0xEF0E +#define GL_SHARED_TEXTURE_PALETTE_19_KOS 0xEF0F + +#define GL_SHARED_TEXTURE_PALETTE_20_KOS 0xEF10 +#define GL_SHARED_TEXTURE_PALETTE_21_KOS 0xEF11 +#define GL_SHARED_TEXTURE_PALETTE_22_KOS 0xEF12 +#define GL_SHARED_TEXTURE_PALETTE_23_KOS 0xEF13 +#define GL_SHARED_TEXTURE_PALETTE_24_KOS 0xEF14 +#define GL_SHARED_TEXTURE_PALETTE_25_KOS 0xEF15 +#define GL_SHARED_TEXTURE_PALETTE_26_KOS 0xEF16 +#define GL_SHARED_TEXTURE_PALETTE_27_KOS 0xEF17 +#define GL_SHARED_TEXTURE_PALETTE_28_KOS 0xEF18 +#define GL_SHARED_TEXTURE_PALETTE_29_KOS 0xEF19 + +#define GL_SHARED_TEXTURE_PALETTE_30_KOS 0xEF1A +#define GL_SHARED_TEXTURE_PALETTE_31_KOS 0xEF1B +#define GL_SHARED_TEXTURE_PALETTE_32_KOS 0xEF1C +#define GL_SHARED_TEXTURE_PALETTE_33_KOS 0xEF1D +#define GL_SHARED_TEXTURE_PALETTE_34_KOS 0xEF1E +#define GL_SHARED_TEXTURE_PALETTE_35_KOS 0xEF1F +#define GL_SHARED_TEXTURE_PALETTE_36_KOS 0xEF20 +#define GL_SHARED_TEXTURE_PALETTE_37_KOS 0xEF21 +#define GL_SHARED_TEXTURE_PALETTE_38_KOS 0xEF22 +#define GL_SHARED_TEXTURE_PALETTE_39_KOS 0xEF23 + +#define GL_SHARED_TEXTURE_PALETTE_40_KOS 0xEF24 +#define GL_SHARED_TEXTURE_PALETTE_41_KOS 0xEF25 +#define GL_SHARED_TEXTURE_PALETTE_42_KOS 0xEF26 +#define GL_SHARED_TEXTURE_PALETTE_43_KOS 0xEF27 +#define GL_SHARED_TEXTURE_PALETTE_44_KOS 0xEF28 +#define GL_SHARED_TEXTURE_PALETTE_45_KOS 0xEF29 +#define GL_SHARED_TEXTURE_PALETTE_46_KOS 0xEF2A +#define GL_SHARED_TEXTURE_PALETTE_47_KOS 0xEF2B +#define GL_SHARED_TEXTURE_PALETTE_48_KOS 0xEF2C +#define GL_SHARED_TEXTURE_PALETTE_49_KOS 0xEF2D + +#define GL_SHARED_TEXTURE_PALETTE_50_KOS 0xEF2E +#define GL_SHARED_TEXTURE_PALETTE_51_KOS 0xEF2F +#define GL_SHARED_TEXTURE_PALETTE_52_KOS 0xEF30 +#define GL_SHARED_TEXTURE_PALETTE_53_KOS 0xEF31 +#define GL_SHARED_TEXTURE_PALETTE_54_KOS 0xEF32 +#define GL_SHARED_TEXTURE_PALETTE_55_KOS 0xEF33 +#define GL_SHARED_TEXTURE_PALETTE_56_KOS 0xEF34 +#define GL_SHARED_TEXTURE_PALETTE_57_KOS 0xEF35 +#define GL_SHARED_TEXTURE_PALETTE_58_KOS 0xEF36 +#define GL_SHARED_TEXTURE_PALETTE_59_KOS 0xEF37 + +#define GL_SHARED_TEXTURE_PALETTE_60_KOS 0xEF38 +#define GL_SHARED_TEXTURE_PALETTE_61_KOS 0xEF39 +#define GL_SHARED_TEXTURE_PALETTE_62_KOS 0xEF3A +#define GL_SHARED_TEXTURE_PALETTE_63_KOS 0xEF3B /* Pass to glTexParameteri to set the shared bank */ -#define GL_SHARED_TEXTURE_BANK_KOS 0xEF00 +#define GL_SHARED_TEXTURE_BANK_KOS 0xEF3C /* Memory allocation extension (GL_KOS_texture_memory_management) */ GLAPI GLvoid APIENTRY glDefragmentTextureMemory_KOS(void); -#define GL_FREE_TEXTURE_MEMORY_KOS 0xEF01 -#define GL_USED_TEXTURE_MEMORY_KOS 0xEF02 -#define GL_FREE_CONTIGUOUS_TEXTURE_MEMORY_KOS 0xEF03 +#define GL_FREE_TEXTURE_MEMORY_KOS 0xEF3D +#define GL_USED_TEXTURE_MEMORY_KOS 0xEF3E +#define GL_FREE_CONTIGUOUS_TEXTURE_MEMORY_KOS 0xEF3F + +//for palette internal format (glfcConfig) +#define GL_RGB565_KOS 0xEF40 __END_DECLS diff --git a/samples/paletted_pcx/main.c b/samples/paletted_pcx/main.c index bfbff3d..6f47491 100644 --- a/samples/paletted_pcx/main.c +++ b/samples/paletted_pcx/main.c @@ -24,19 +24,24 @@ #define IMG_ALPHA_PATH "../samples/paletted_pcx/romdisk/NeHe-Alpha.pcx" #endif +/* using 4bpp textures from BMP files instead of 8bpp from PCX files */ +#define USE_16C_PALETTE + /* floats for x rotation, y rotation, z rotation */ float xrot, yrot, zrot; int textures[3]; typedef struct { - unsigned int height; - unsigned int width; - unsigned int palette_width; + uint32_t height; + uint32_t width; + uint32_t palette_width; char* palette; char* data; } Image; +#ifndef USE_16C_PALETTE + #pragma pack(push) #pragma pack(1) @@ -140,11 +145,234 @@ int LoadPalettedPCX(const char* filename, Image* image) { return 1; } +#else + +#define BMP_BI_RGB 0L +#define BMP_BI_UNCOMPRESSED 0L +#define BMP_BI_RLE8 1L +#define BMP_BI_RLE4 2L +#define BMP_BI_BITFIELDS 3L + +#pragma pack(push) +#pragma pack(1) + +typedef struct BITMAP_FILE_HEADER +{ + uint16_t Type; + uint32_t Size; + uint16_t Reserved1; + uint16_t Reserved2; + uint32_t OffBits; +} BITMAP_FILE_HEADER; + +typedef struct BITMAP_INFO_HEADER +{ + uint32_t Size; + int32_t Width; + int32_t Height; + uint16_t Planes; + uint16_t BitCount; + uint32_t Compression; + uint32_t SizeImage; + int32_t XPelsPerMeter; + int32_t YPelsPerMeter; + uint32_t ClrUsed; + uint32_t ClrImportant; +} BITMAP_INFO_HEADER; + +typedef struct RGB_QUAD +{ + uint8_t Blue; + uint8_t Green; + uint8_t Red; + uint8_t Reserved; +} RGB_QUAD; + +typedef struct BITMAP_INFO +{ + BITMAP_INFO_HEADER Header; + RGB_QUAD Colors[1]; +} BITMAP_INFO; + +#pragma pack(pop) + +/* some global variables used to load a 4bpp BMP file */ +static BITMAP_FILE_HEADER BmpFileHeader; +static BITMAP_INFO_HEADER BmpInfoHeader; +static RGB_QUAD BmpRgbQuad[256]; +static uint8_t BmpPal[256 * 3]; + +int BMP_Infos(FILE *pFile, uint32_t *width, uint32_t *height) +{ + if (!pFile) + return 0; + + if (fread(&BmpFileHeader.Type, 1, 2, pFile) != 2) + return 0; + if (fread(&BmpFileHeader.Size, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpFileHeader.Reserved1, 1, 2, pFile) != 2) + return 0; + if (fread(&BmpFileHeader.Reserved2, 1, 2, pFile) != 2) + return 0; + if (fread(&BmpFileHeader.OffBits, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.Size, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.Width, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.Height, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.Planes, 1, 2, pFile) != 2) + return 0; + if (fread(&BmpInfoHeader.BitCount, 1, 2, pFile) != 2) + return 0; + if (fread(&BmpInfoHeader.Compression, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.SizeImage, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.XPelsPerMeter, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.YPelsPerMeter, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.ClrUsed, 1, 4, pFile) != 4) + return 0; + if (fread(&BmpInfoHeader.ClrImportant, 1, 4, pFile) != 4) + return 0; + + *width = (uint32_t)BmpInfoHeader.Width; + *height = (uint32_t)BmpInfoHeader.Height; + + return 1; +} + + +int BMP_GetPalette(FILE *pFile) +{ + int32_t i,bitCount; + + if (BmpInfoHeader.BitCount == 4) { + + if (!BmpInfoHeader.ClrImportant) { + BmpInfoHeader.ClrImportant = 16; + } + bitCount = BmpInfoHeader.ClrImportant * sizeof(RGB_QUAD); + + if (fread(BmpRgbQuad, 1, bitCount, pFile) != bitCount){ + return 0; + } + + for (i = 0; i < BmpInfoHeader.ClrImportant; i++) { + + BmpPal[i * 3] = (uint8_t)BmpRgbQuad[i].Red; + BmpPal[i * 3 + 1] = (uint8_t)BmpRgbQuad[i].Green; + BmpPal[i * 3 + 2] = (uint8_t)BmpRgbQuad[i].Blue; + } + return 1; + } + return 0; +} + +/* maybe not the best BMP loader... */ +int BMP_Depack(FILE *pFile,char *pZone) +{ + char PadRead[4]; + int32_t i, j, Offset, PadSize, pix, c; + + if (BmpInfoHeader.Compression != BMP_BI_RGB) + return 0; + + PadSize = (BmpInfoHeader.Width & 3); + + PadSize = (4 - (BmpInfoHeader.Width & 3)) & 3; + + for (i = BmpInfoHeader.Height - 1; (i > -1); i--) { + Offset = i * BmpInfoHeader.Width / 2; + + if (PadSize < 4) { + for (j = 0; (j < BmpInfoHeader.Width / 2); j++) { + if (!fread(&c, 1, 1, pFile)) { + return 0; + } + pZone[Offset + j] = c; + } + } + + if (PadSize) { + if (fread(PadRead, PadSize, 1, pFile) != PadSize) { + return 0; + } + } + } + + if (i != -1) { + return 0; + } + + return 1; +} + + +int LoadPalettedBMP(const char* filename, Image* image) +{ + FILE *fp; + uint32_t bytes; + + if (filename == NULL || image == NULL) { + printf("Invalid NULL argument\n"); + return 0; + } + + fp = fopen(filename, "rb"); + if (fp == NULL) { + printf("Unable to open file\n"); + return 0; + } + + if (!BMP_Infos(fp, &image->width, &image->height)) { + printf("Error reading BMP:%s header\n",filename); + return 0; + } + + if (!BMP_GetPalette(fp)) { + printf("Only 16c BMP are supported for this sample"); + return 0; + } + + /* store palette information */ + image->palette = BmpPal; + image->palette_width = 16; + + + bytes = sizeof(char) * image->width * image->height; + /* 4bpp is half byte size*/ + bytes >>= 1; + + image->data = (char*)malloc(bytes); + if (image->data == NULL) { + printf("Error allocating image data"); + return 0; + } + + if (!BMP_Depack(fp, image->data)) { + printf("Error depacking BMP:%s",filename); + return 0; + } + + fclose(fp); + + return 1; +} + + +#endif + // Load Bitmaps And Convert To Textures void LoadGLTextures() { // Load Texture Image image1, image2; +#ifndef USE_16C_PALETTE if(!LoadPalettedPCX(IMG_PATH, &image1)) { exit(1); } @@ -152,6 +380,15 @@ void LoadGLTextures() { if(!LoadPalettedPCX(IMG_ALPHA_PATH, &image2)) { exit(1); } +#else + if (!LoadPalettedBMP("/rd/NeHe.bmp", &image1)) { + exit(1); + } + + if (!LoadPalettedBMP("/rd/NeHe-Alpha.bmp", &image2)) { + exit(1); + } +#endif glEnable(GL_SHARED_TEXTURE_PALETTE_EXT); @@ -178,7 +415,11 @@ void LoadGLTextures() { // 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. +#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); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data); +#endif glBindTexture(GL_TEXTURE_2D, textures[1]); // 2d texture (x and y size) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); // scale linearly when image bigger than texture @@ -189,7 +430,11 @@ void LoadGLTextures() { // 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. +#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); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data); +#endif glBindTexture(GL_TEXTURE_2D, textures[2]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -204,8 +449,11 @@ void LoadGLTextures() { } glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, image2.palette_width, GL_RGBA, GL_UNSIGNED_BYTE, new_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); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image2.data); +#endif } /* A general OpenGL initialization function. Sets all of the initial parameters. */ diff --git a/samples/paletted_pcx/romdisk/NeHe-Alpha.bmp b/samples/paletted_pcx/romdisk/NeHe-Alpha.bmp new file mode 100644 index 0000000..db96b15 Binary files /dev/null and b/samples/paletted_pcx/romdisk/NeHe-Alpha.bmp differ diff --git a/samples/paletted_pcx/romdisk/NeHe.bmp b/samples/paletted_pcx/romdisk/NeHe.bmp index 6b3db10..6a92446 100644 Binary files a/samples/paletted_pcx/romdisk/NeHe.bmp and b/samples/paletted_pcx/romdisk/NeHe.bmp differ diff --git a/samples/paletted_pcx/romdisk/NeHe.tex b/samples/paletted_pcx/romdisk/NeHe.tex deleted file mode 100644 index 26ee1b4..0000000 Binary files a/samples/paletted_pcx/romdisk/NeHe.tex and /dev/null differ diff --git a/samples/paletted_pcx/romdisk/NeHe.tex.pal b/samples/paletted_pcx/romdisk/NeHe.tex.pal deleted file mode 100644 index f1159f0..0000000 Binary files a/samples/paletted_pcx/romdisk/NeHe.tex.pal and /dev/null differ