diff --git a/GL/clip.c b/GL/clip.c index 9406c89..c578192 100644 --- a/GL/clip.c +++ b/GL/clip.c @@ -152,6 +152,15 @@ static inline void markDead(ClipVertex* vert) { vert->flags = VERTEX_CMD_EOL; } +#define B000 0 +#define B111 7 +#define B100 4 +#define B010 2 +#define B001 1 +#define B101 5 +#define B011 3 +#define B110 6 + void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset, uint8_t fladeShade) { /* Room for clipping 16 triangles */ typedef struct { @@ -195,11 +204,11 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset, uint8_t fladeS uint8_t visible = ((v1->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v3->w > 0) ? 1 : 0); switch(visible) { - case 0b111: + case B111: /* All visible? Do nothing */ continue; break; - case 0b000: + case B000: /* It is not possible that this is any trangle except the first in a strip. That's because: @@ -234,12 +243,12 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset, uint8_t fladeS v3->flags = VERTEX_CMD; } break; - case 0b100: - case 0b010: - case 0b001: - case 0b101: - case 0b011: - case 0b110: + case B100: + case B010: + case B001: + case B101: + case B011: + case B110: /* Store the triangle for clipping */ TO_CLIP[CLIP_COUNT].vertex[0] = *v1; TO_CLIP[CLIP_COUNT].vertex[1] = *v2; diff --git a/GL/config.h b/GL/config.h index 117acf6..f119e9a 100644 --- a/GL/config.h +++ b/GL/config.h @@ -2,7 +2,8 @@ #define CONFIG_H -#define MAX_TEXTURE_COUNT 1088 //@Todo: or 1088 explain why increased. mrneo240 +/* This figure is derived from the needs of Quake 1 */ +#define MAX_TEXTURE_COUNT 1088 #endif // CONFIG_H diff --git a/GL/draw.c b/GL/draw.c index 77b8c35..a2749dc 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "../include/gl.h" #include "../include/glext.h" @@ -449,8 +450,8 @@ static inline PolyBuildFunc _calcBuildFunc(const GLenum type) { case GL_QUADS: return &_buildQuad; break; - case GL_POLYGON: case GL_TRIANGLE_FAN: + case GL_POLYGON: return &_buildTriangleFan; break; default: @@ -459,7 +460,7 @@ static inline PolyBuildFunc _calcBuildFunc(const GLenum type) { return &_buildStrip; } -#include + static inline void nullFloatParseFunc(GLfloat* out, const GLubyte* in) {} static inline void genElementsCommon( @@ -480,8 +481,13 @@ static inline void genElementsCommon( const FloatParseFunc normalFunc = (doLighting) ? _calcNormalParseFunc() : &nullFloatParseFunc; const IndexParseFunc indexFunc = _calcParseIndexFunc(type); + assert(vertexFunc); assert(diffuseFunc); + assert(uvFunc); + assert(stFunc); + assert(normalFunc); + assert(indexFunc); GLsizei i = 0; const GLubyte* idx = iptr; @@ -548,7 +554,6 @@ static inline void genElementsQuads( } static inline void genElementsTriangleFan( - ClipVertex* output, GLsizei count, const GLubyte* iptr, GLuint istride, GLenum type, @@ -572,7 +577,7 @@ static inline void genElementsTriangleFan( GLsizei i = 3; ClipVertex* first = &output[0]; - for(; i < count - 1; ++i) { + for(; i < count - 1; ++i) { ClipVertex* next = &output[i + 1]; ClipVertex* previous = &output[i - 1]; ClipVertex* vertex = &output[i]; @@ -625,6 +630,12 @@ static inline void genArraysCommon( const FloatParseFunc stFunc = _calcSTParseFunc(); const FloatParseFunc normalFunc = _calcNormalParseFunc(); + assert(vertexFunc); + assert(diffuseFunc); + assert(uvFunc); + assert(stFunc); + assert(normalFunc); + GLsizei i = count; ClipVertex* vertex = output; @@ -745,6 +756,7 @@ static void genArraysTriangleStrip( output[count - 1].flags = PVR_CMD_VERTEX_EOL; } +#define MAX_POLYGON_SIZE 32 static ClipVertex buffer[MAX_POLYGON_SIZE]; static void genArraysTriangleFan( @@ -757,18 +769,15 @@ static void genArraysTriangleFan( const GLubyte* nptr, GLuint nstride, GLboolean doTexture, GLboolean doMultitexture, GLboolean doLighting) { + assert(count < MAX_POLYGON_SIZE); + genArraysCommon( output, count, vptr, vstride, cptr, cstride, uvptr, uvstride, stptr, ststride, nptr, nstride, doTexture, doMultitexture, doLighting ); - #if TRACE_ENABLED - printf("%s(%s[%d]): count: %d\n",__func__, __FILE__,__LINE__, count); - #endif - assert(count <= MAX_POLYGON_SIZE); - - if(count <=3){ + if(count <= 3){ swapVertex(&output[1], &output[2]); output[2].flags = PVR_CMD_VERTEX_EOL; return; @@ -777,28 +786,15 @@ static void genArraysTriangleFan( memcpy(buffer, output, sizeof(ClipVertex) * count); // First 3 vertices are in the right place, just end early - //swapVertex(&output[1], &output[2]); output[2].flags = PVR_CMD_VERTEX_EOL; GLsizei i = 3, target = 3; ClipVertex* first = &output[0]; - #if TRACE_ENABLED - printf("%s(%s[%d]): Triangle!\n",__func__, __FILE__,__LINE__); - #endif for(; i < count; ++i) { output[target++] = *first; output[target++] = buffer[i - 1]; output[target] = buffer[i]; - #if TRACE_ENABLED - printf("%s(%s[%d]): Triangle!\n",__func__, __FILE__,__LINE__); - printf("%s(%s[%d]):\tvert(%f,%f,%f)\n",__func__, __FILE__,__LINE__, - (*first).xyz[0],(*first).xyz[1],(*first).xyz[2]); - printf("%s(%s[%d]):\tvert(%f,%f,%f)\n",__func__, __FILE__,__LINE__, - (buffer[i - 1]).xyz[0],(buffer[i - 1]).xyz[1],(buffer[i - 1]).xyz[2]); - printf("%s(%s[%d]):\tvert(%f,%f,%f)\n",__func__, __FILE__,__LINE__, - (buffer[i]).xyz[0],(buffer[i]).xyz[1],(buffer[i]).xyz[2]); - #endif output[target++].flags = PVR_CMD_VERTEX_EOL; } } @@ -1085,7 +1081,6 @@ static void push(PVRHeader* header, ClipVertex* output, const GLsizei count, Pol #define DEBUG_CLIPPING 0 static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum type, const GLvoid* indices) { - TRACE(); /* Do nothing if vertices aren't enabled */ if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) { return; @@ -1317,11 +1312,10 @@ GLuint _glGetActiveClientTexture() { } void APIENTRY glClientActiveTextureARB(GLenum texture) { - //@TODO: Uncomment - //TRACE(); + TRACE(); if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS) { - _glKosThrowError(GL_INVALID_ENUM, __func__); + _glKosThrowError(GL_INVALID_ENUM, __func__); } if(_glKosHasError()) { diff --git a/GL/error.c b/GL/error.c index 49732e5..d4b73c4 100644 --- a/GL/error.c +++ b/GL/error.c @@ -57,7 +57,7 @@ void _glKosPrintError() { } fprintf(stderr, "GL ERROR: %s when calling %s\n", _glErrorEnumAsString(last_error), error_function); - _glKosResetError(); + _glKosResetError(); } GLenum glGetError(void) { diff --git a/GL/flush.c b/GL/flush.c index 9e4cd8e..0b9dd8b 100644 --- a/GL/flush.c +++ b/GL/flush.c @@ -41,7 +41,7 @@ static void pvr_list_submit(void *src, int n) { static void _glInitPVR() { pvr_init_params_t params = { /* Enable opaque and translucent polygons with size 32 and 32 */ - { PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32 }, + {PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32}, PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */ 0, /* No DMA */ 0, /* No FSAA */ @@ -55,6 +55,8 @@ static void _glInitPVR() { PolyList* _glActivePolyList() { if(_glIsBlendingEnabled()) { return &TR_LIST; + } else if(_glIsAlphaTestEnabled()) { + return &PT_LIST; } else { return &OP_LIST; } @@ -64,6 +66,15 @@ PolyList *_glTransparentPolyList() { return &TR_LIST; } +void APIENTRY glFlush() { + +} + +void APIENTRY glFinish() { + +} + + void APIENTRY glKosInit() { TRACE(); @@ -94,14 +105,10 @@ void APIENTRY glKosSwapBuffers() { TRACE(); - PROFILER_PUSH(__func__); - - //printf("Flush:\n\tOP:%d\n\tPT:%d\n\tTR:%d\n",OP_LIST.vector.size,PT_LIST.vector.size,TR_LIST.vector.size); - //printf("Flush: glTexImage mem free:%d\n",pvr_mem_available()); + profiler_push(__func__); pvr_wait_ready(); - pvr_scene_begin(); QACR0 = QACRTA; QACR1 = QACRTA; @@ -123,12 +130,11 @@ void APIENTRY glKosSwapBuffers() { aligned_vector_clear(&PT_LIST.vector); aligned_vector_clear(&TR_LIST.vector); - #ifdef PROFILER_COMPILE - PROFILER_CHECKPOINT("scene"); - PROFILER_POP(); + profiler_checkpoint("scene"); + profiler_pop(); + if(frame_count++ > 100) { profiler_print_stats(); frame_count = 0; } - #endif } diff --git a/GL/framebuffer.c b/GL/framebuffer.c index 2e89999..c83edba 100644 --- a/GL/framebuffer.c +++ b/GL/framebuffer.c @@ -186,7 +186,7 @@ GLboolean _glCalculateAverageTexel(const GLubyte* src, const GLuint srcWidth, co *d1 = (r << 11 | g << 5 | b); } else { fprintf(stderr, "ERROR: Unsupported PVR format for mipmap generation"); - _glKosThrowError(GL_INVALID_OPERATION, __func__); + _glKosThrowError(GL_INVALID_OPERATION, __func__); _glKosPrintError(); return GL_FALSE; } diff --git a/GL/immediate.c b/GL/immediate.c index d805246..0c7e46c 100644 --- a/GL/immediate.c +++ b/GL/immediate.c @@ -83,6 +83,10 @@ void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) { glColor4f(r, g, b, a); } +void APIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue) { + glColor3f((float) red / 255, (float) green / 255, (float) blue / 255); +} + void APIENTRY glColor3fv(const GLfloat* v) { glColor3f(v[0], v[1], v[2]); } diff --git a/GL/lighting.c b/GL/lighting.c index 31eb9c1..04d2a52 100644 --- a/GL/lighting.c +++ b/GL/lighting.c @@ -7,7 +7,7 @@ static GLfloat SCENE_AMBIENT [] = {0.2, 0.2, 0.2, 1.0}; static GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE; static GLenum COLOR_CONTROL = GL_SINGLE_COLOR; -//static GLboolean TWO_SIDED_LIGHTING = GL_FALSE; +static GLboolean TWO_SIDED_LIGHTING = GL_FALSE; static GLenum COLOR_MATERIAL_MODE = GL_AMBIENT_AND_DIFFUSE; static LightSource LIGHTS[MAX_LIGHTS]; diff --git a/GL/matrix.c b/GL/matrix.c index c160806..36f1455 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -9,7 +9,7 @@ #define DEG2RAD (0.01745329251994329576923690768489) /* Viewport mapping */ -//static GLfloat gl_viewport_scale[3], gl_viewport_offset[3]; +static GLfloat gl_viewport_scale[3], gl_viewport_offset[3]; /* Depth range */ static GLclampf gl_depthrange_near, gl_depthrange_far; @@ -33,14 +33,14 @@ static const matrix_t IDENTITY = { void APIENTRY glDepthRange(GLclampf n, GLclampf f); -matrix_t* _glGetModelViewMatrix() { - return (matrix_t*)stack_top(&MATRIX_STACKS[0]); -} - matrix_t* _glGetProjectionMatrix() { return (matrix_t*) stack_top(&MATRIX_STACKS[1]); } +matrix_t* _glGetModelViewMatrix() { + return (matrix_t*) stack_top(&MATRIX_STACKS[0]); +} + void _glInitMatrices() { init_stack(&MATRIX_STACKS[0], sizeof(matrix_t), 32); init_stack(&MATRIX_STACKS[1], sizeof(matrix_t), 32); diff --git a/GL/private.h b/GL/private.h index d930f53..7465bc5 100644 --- a/GL/private.h +++ b/GL/private.h @@ -16,7 +16,6 @@ #define NORMAL_ENABLED_FLAG (1 << 4) #define MAX_TEXTURE_SIZE 1024 -#define MAX_POLYGON_SIZE 18 #define CLIP_VERTEX_INT_PADDING 6 @@ -46,8 +45,10 @@ typedef struct { /* Palette data is always stored in RAM as RGBA8888 and packed as ARGB8888 * when uploaded to the PVR */ GLubyte* data; - GLushort width; + GLushort width; /* The user specified width */ + GLushort size; /* The size of the bank (16 or 256) */ GLenum format; + GLshort bank; } TexturePalette; typedef struct { @@ -69,6 +70,9 @@ typedef struct { GLboolean isPaletted; TexturePalette* palette; + + /* When using the shared palette, this is the bank (0-3) */ + GLushort shared_bank; } TextureObject; typedef struct { @@ -142,11 +146,14 @@ TextureObject* _glGetTexture1(); TextureObject* _glGetBoundTexture(); GLubyte _glGetActiveTexture(); GLuint _glGetActiveClientTexture(); +TexturePalette* _glGetSharedPalette(GLshort bank); GLboolean _glIsSharedTexturePaletteEnabled(); -void _glApplyColorTable(); +void _glApplyColorTable(TexturePalette *palette); GLboolean _glIsBlendingEnabled(); +GLboolean _glIsAlphaTestEnabled(); + GLboolean _glIsMipmapComplete(const TextureObject* obj); GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level); GLuint _glGetMipmapLevelCount(TextureObject* obj); diff --git a/GL/state.c b/GL/state.c index ca9ec17..0cab0d8 100644 --- a/GL/state.c +++ b/GL/state.c @@ -30,6 +30,9 @@ static GLboolean COLOR_MATERIAL_ENABLED = GL_FALSE; /* Is the shared texture palette enabled? */ static GLboolean SHARED_PALETTE_ENABLED = GL_FALSE; +static GLboolean ALPHA_TEST_ENABLED = GL_FALSE; + + GLboolean _glIsSharedTexturePaletteEnabled() { return SHARED_PALETTE_ENABLED; } @@ -84,6 +87,10 @@ GLboolean _glIsBlendingEnabled() { return BLEND_ENABLED; } +GLboolean _glIsAlphaTestEnabled() { + return ALPHA_TEST_ENABLED; +} + static int _calcPVRBlendFactor(GLenum factor) { switch(factor) { case GL_ZERO: @@ -103,7 +110,7 @@ static int _calcPVRBlendFactor(GLenum factor) { case GL_ONE: return PVR_BLEND_ONE; default: - printf("Invalid blend mode: %d\n", factor); + fprintf(stderr, "Invalid blend mode: %d\n", factor); return PVR_BLEND_ONE; } } @@ -127,7 +134,7 @@ static void _updatePVRBlend(pvr_poly_cxt_t* context) { GLboolean _glCheckValidEnum(GLint param, GLenum* values, const char* func) { GLubyte found = 0; while(*values != 0) { - if(*values == param) { + if(*values == (GLenum)param) { found++; break; } @@ -135,9 +142,8 @@ GLboolean _glCheckValidEnum(GLint param, GLenum* values, const char* func) { } if(!found) { - //_glKosThrowError(GL_INVALID_ENUM, func); - //_glKosPrintError(); - printf("GL_INVALID_ENUM when calling %s\n",func); + _glKosThrowError(GL_INVALID_ENUM, func); + _glKosPrintError(); return GL_TRUE; } @@ -179,9 +185,6 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { if(tx1->isCompressed && _glIsMipmapComplete(tx1)) { enableMipmaps = GL_TRUE; } - if(tx1->isPaletted){ - enableMipmaps = GL_FALSE; - } if(enableMipmaps) { if(tx1->minFilter == GL_LINEAR_MIPMAP_NEAREST) { @@ -197,9 +200,6 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { if(tx1->minFilter == GL_LINEAR && tx1->magFilter == GL_LINEAR) { filter = PVR_FILTER_BILINEAR; } - if(tx1->isPaletted){ - filter = PVR_FILTER_NONE; - } } /* If we don't have complete mipmaps, and yet mipmapping was enabled, we disable texturing. @@ -221,6 +221,16 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { context->txr.height = tx1->height; context->txr.base = tx1->data; context->txr.format = tx1->color; + + if(tx1->isPaletted) { + if(_glIsSharedTexturePaletteEnabled()) { + TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank); + context->txr.format |= PVR_TXRFMT_8BPP_PAL((palette) ? 0 : palette->bank); + } else { + context->txr.format |= PVR_TXRFMT_8BPP_PAL((tx1->palette) ? tx1->palette->bank : 0); + } + } + context->txr.env = tx1->env; context->txr.uv_flip = PVR_UVFLIP_NONE; context->txr.uv_clamp = tx1->uv_clamp; @@ -307,11 +317,11 @@ GLAPI void APIENTRY glEnable(GLenum cap) { break; case GL_SHARED_TEXTURE_PALETTE_EXT: { SHARED_PALETTE_ENABLED = GL_TRUE; - - /* Apply the texture palette if necessary */ - //_glApplyColorTable(); //@Todo: Actually Dont. } break; + case GL_ALPHA_TEST: { + ALPHA_TEST_ENABLED = GL_TRUE; + } break; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: @@ -361,11 +371,11 @@ GLAPI void APIENTRY glDisable(GLenum cap) { break; case GL_SHARED_TEXTURE_PALETTE_EXT: { SHARED_PALETTE_ENABLED = GL_FALSE; - - /* Restore whatever palette may exist on a bound texture */ - //_glApplyColorTable(); //@Todo: Actually Dont. } break; + case GL_ALPHA_TEST: { + ALPHA_TEST_ENABLED = GL_FALSE; + } break; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: @@ -411,6 +421,14 @@ GLAPI void APIENTRY glClearDepth(GLfloat depth) { } +GLAPI void APIENTRY glDrawBuffer(GLenum mode) { + +} + +GLAPI void APIENTRY glReadBuffer(GLenum mode) { + +} + GLAPI void APIENTRY glDepthMask(GLboolean flag) { GL_CONTEXT.depth.write = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE; GL_CONTEXT.depth.comparison = _calc_pvr_depth_test(); @@ -457,8 +475,20 @@ GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { _updatePVRBlend(&GL_CONTEXT); } -void glAlphaFunc(GLenum func, GLclampf ref) { - ; +#define PT_ALPHA_REF 0x011c + +GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref) { + GLenum validFuncs[] = { + GL_GREATER, + 0 + }; + + if(_glCheckValidEnum(func, validFuncs, __func__) != 0) { + return; + } + + GLubyte val = (GLubyte)(ref * 255.0f); + PVR_SET(PT_ALPHA_REF, val); } void glLineWidth(GLfloat width) { @@ -579,6 +609,7 @@ void APIENTRY glGetFloatv(GLenum pname, GLfloat* params) { switch(pname) { case GL_PROJECTION_MATRIX: memcpy(params, _glGetProjectionMatrix(), sizeof(float) * 16); + break; case GL_MODELVIEW_MATRIX: memcpy(params, _glGetModelViewMatrix(), sizeof(float) * 16); break; @@ -625,7 +656,7 @@ void APIENTRY glGetIntegerv(GLenum pname, GLint *params) { } } break; default: - _glKosThrowError(GL_INVALID_ENUM, __func__); + _glKosThrowError(GL_INVALID_ENUM, __func__); _glKosPrintError(); break; } @@ -643,7 +674,7 @@ const GLbyte *glGetString(GLenum name) { return "GLdc 1.x"; case GL_EXTENSIONS: - return "GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette"; + return "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"; } return "GL_KOS_ERROR: ENUM Unsupported\n"; diff --git a/GL/texture.c b/GL/texture.c index d58cea2..6de433a 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -18,65 +18,107 @@ static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL}; static NamedArray TEXTURE_OBJECTS; static GLubyte ACTIVE_TEXTURE = 0; -static TexturePalette* SHARED_PALETTE = NULL; -static GLbyte CURRENT_PALETTE = 0; +static TexturePalette* SHARED_PALETTES[4] = {NULL, NULL, NULL, NULL}; static GLuint _determinePVRFormat(GLint internalFormat, GLenum type); #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 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 -void _glApplyColorTable() { +static TexturePalette* _initTexturePalette() { + TexturePalette* palette = (TexturePalette*) malloc(sizeof(TexturePalette)); + assert(palette); + memset(palette, 0x0, sizeof(TexturePalette)); + + 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; + } + } +} + +TexturePalette* _glGetSharedPalette(GLshort bank) { + assert(bank >= 0 && bank < 4); + return SHARED_PALETTES[bank]; +} + +void _glApplyColorTable(TexturePalette* src) { /* * FIXME: * * - Different palette formats (GL_RGB -> PVR_PAL_RGB565) */ - TexturePalette* src = NULL; - - if(_glIsSharedTexturePaletteEnabled()) { - src = SHARED_PALETTE; - - assert(src); - - /* Don't apply a palette if we haven't uploaded one yet */ - if(!src->data) { - return; - } - } else { - TextureObject* active = _glGetBoundTexture(); - - if(!active) { - return; //? Unload the palette? Make White? - } - - if(!active->palette || !active->palette->data) { - return; - } - - src = active->palette; - } - - /* Don't reapply the palette if it was the last one we applied */ - if(src == last_bound_palette) { + if(!src || !src->data) { return; } - last_bound_palette = src; - pvr_set_pal_format(PVR_PAL_ARGB8888); - GLushort i = 0; - - //printf("Palette Entries: %d\n",src->width); - for(; i < src->width; ++i) { + GLushort i; + GLushort offset = src->size * src->bank; + for(i = 0; i < src->width; ++i) { GLubyte* entry = &src->data[i * 4]; - //printf("#%02X%02X%02X\t\t %08X\n",entry[0],entry[1],entry[2], PACK_ARGB8888(entry[3], entry[0], entry[1], entry[2])); - pvr_set_pal_entry(i, PACK_ARGB8888(entry[3], entry[0], entry[1], entry[2])); + pvr_set_pal_entry(offset + i, PACK_ARGB8888(entry[3], entry[0], entry[1], entry[2])); } - //printf("------END------\n"); } GLubyte _glGetActiveTexture() { @@ -159,10 +201,11 @@ GLubyte _glInitTextures() { // Reserve zero so that it is never given to anyone as an ID! named_array_reserve(&TEXTURE_OBJECTS, 0); - SHARED_PALETTE = (TexturePalette*) malloc(sizeof(TexturePalette)); - SHARED_PALETTE->data = NULL; - SHARED_PALETTE->format = 0; - SHARED_PALETTE->width = 0; + SHARED_PALETTES[0] = _initTexturePalette(); + SHARED_PALETTES[1] = _initTexturePalette(); + SHARED_PALETTES[2] = _initTexturePalette(); + SHARED_PALETTES[3] = _initTexturePalette(); + return 1; } @@ -179,8 +222,7 @@ TextureObject* _glGetBoundTexture() { } void APIENTRY glActiveTextureARB(GLenum texture) { - //@TODO: Uncomment - //TRACE(); + TRACE(); if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS) _glKosThrowError(GL_INVALID_ENUM, "glActiveTextureARB"); @@ -210,6 +252,9 @@ static void _glInitializeTextureObject(TextureObject* txr, unsigned int id) { txr->palette = NULL; txr->isCompressed = GL_FALSE; txr->isPaletted = GL_FALSE; + + /* Always default to the first shared bank */ + txr->shared_bank = 0; } void APIENTRY glGenTextures(GLsizei n, GLuint *textures) { @@ -248,7 +293,7 @@ void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) { } if(txr->palette && txr->palette->data) { - pvr_mem_free(txr->palette->data); + free(txr->palette->data); txr->palette->data = NULL; } @@ -277,10 +322,8 @@ void APIENTRY glBindTexture(GLenum target, GLuint texture) { TextureObject* txr = named_array_reserve(&TEXTURE_OBJECTS, texture); _glInitializeTextureObject(txr, texture); } - TEXTURE_UNITS[ACTIVE_TEXTURE] = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, texture); - /* Apply the texture palette if necessary */ - //_glApplyColorTable(); //@Todo: Actually Dont. + TEXTURE_UNITS[ACTIVE_TEXTURE] = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, texture); } else { TEXTURE_UNITS[ACTIVE_TEXTURE] = NULL; } @@ -295,9 +338,9 @@ void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) { GLubyte failures = 0; - /*failures += _glCheckValidEnum(target, target_values, __func__); + failures += _glCheckValidEnum(target, target_values, __func__); failures += _glCheckValidEnum(pname, pname_values, __func__); - failures += _glCheckValidEnum(param, param_values, __func__);*/ + failures += _glCheckValidEnum(param, param_values, __func__); TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE]; @@ -324,7 +367,7 @@ void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) { } } -void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) { +void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLint param) { glTexEnvi(target, pname, param); } @@ -553,7 +596,7 @@ static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) { case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS: return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE; case GL_COLOR_INDEX8_EXT: - return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_8BPP_PAL(CURRENT_PALETTE); + return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_TWIDDLED; default: return 0; } @@ -568,11 +611,11 @@ static inline void _rgba8888_to_argb4444(const GLubyte* source, GLubyte* dest) { static inline void _rgba8888_to_rgba8888(const GLubyte* source, GLubyte* dest) { /* Noop */ - //GLubyte* dst = (GLubyte*) dest; - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; + GLubyte* dst = (GLubyte*) dest; + dst[0] = source[0]; + dst[1] = source[1]; + dst[2] = source[2]; + dst[3] = source[3]; } static inline void _rgba8888_to_rgb565(const GLubyte* source, GLubyte* dest) { @@ -581,11 +624,11 @@ static inline void _rgba8888_to_rgb565(const GLubyte* source, GLubyte* dest) { static inline void _rgb888_to_rgba8888(const GLubyte* source, GLubyte* dest) { /* Noop */ - //GLubyte* dst = (GLubyte*) dest; - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = 255; + GLubyte* dst = (GLubyte*) dest; + dst[0] = source[0]; + dst[1] = source[1]; + dst[2] = source[2]; + dst[3] = 255; } static inline void _rgb888_to_rgb565(const GLubyte* source, GLubyte* dest) { @@ -681,7 +724,7 @@ static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum f } break; default: - printf("Unsupported conversion: %x -> %x, %x\n", internalFormat, format, type); + fprintf(stderr, "Unsupported conversion: %x -> %x, %x\n", internalFormat, format, type); break; } return 0; @@ -694,7 +737,6 @@ static GLboolean _isSupportedFormat(GLenum format) { case GL_RGBA: case GL_BGRA: case GL_COLOR_INDEX: - case GL_LUMINANCE: return GL_TRUE; default: return GL_FALSE; @@ -716,19 +758,33 @@ GLboolean _glIsMipmapComplete(const TextureObject* obj) { return GL_TRUE; } + +static inline GLuint morton_1by1(GLuint x) { + x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210 + x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210 + x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210 + x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10 + x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 + return x; +} + +static inline GLuint morton_index(GLuint x, GLuint y) { + return (morton_1by1(y) << 1) + morton_1by1(x); +} + void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data) { TRACE(); - + if(target != GL_TEXTURE_2D) { - _glKosThrowError(GL_INVALID_ENUM, "glTexImage2D-tex2d"); + _glKosThrowError(GL_INVALID_ENUM, "glTexImage2D"); } if(format != GL_COLOR_INDEX) { if(!_isSupportedFormat(format)) { - _glKosThrowError(GL_INVALID_ENUM, "glTexImage2D-invalid_format"); + _glKosThrowError(GL_INVALID_ENUM, "glTexImage2D"); } /* Abuse determineStride to see if type is valid */ @@ -738,43 +794,43 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, internalFormat = _cleanInternalFormat(internalFormat); if(internalFormat == -1) { - _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D-internal_fmt"); + _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } } else { if(internalFormat != GL_COLOR_INDEX8_EXT) { - _glKosThrowError(GL_INVALID_ENUM, "glTexImage2D-8EXT"); + _glKosThrowError(GL_INVALID_ENUM, __func__); } } GLint w = width; if(w < 8 || (w & -w) != w) { /* Width is not a power of two. Must be!*/ - _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D-width"); + _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } GLint h = height; if(h < 8 || (h & -h) != h) { /* height is not a power of two. Must be!*/ - _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D-height"); + _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } if(level < 0) { - _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D-level"); + _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } if(border) { - _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D-border"); + _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } if(!TEXTURE_UNITS[ACTIVE_TEXTURE]) { - _glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D-active_tex"); + _glKosThrowError(GL_INVALID_OPERATION, __func__); } GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT) ? GL_TRUE : GL_FALSE; if(isPaletted && level > 0) { /* Paletted textures can't have mipmaps */ - _glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D-palette_level"); + _glKosThrowError(GL_INVALID_OPERATION, __func__); } if(_glKosHasError()) { @@ -838,52 +894,16 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, /* Let's assume we need to convert */ GLboolean needsConversion = GL_TRUE; - - GLubyte* targetData = _glGetMipmapLocation(active, level); - assert(targetData); + GLboolean needsTwiddling = GL_FALSE; /* * These are the only formats where the source format passed in matches the pvr format. * Note the REV formats + GL_BGRA will reverse to ARGB which is what the PVR supports */ if(format == GL_COLOR_INDEX) { - if(type == GL_UNSIGNED_BYTE_TWID_KOS){ - - } else { - /* Don't convert color indexes */ - /* Linear/iterative twiddling algorithm from Marcus' tatest */ - #define TWIDTAB(x) ( (x&1)|((x&2)<<1)|((x&4)<<2)|((x&8)<<3)|((x&16)<<4)| \ - ((x&32)<<5)|((x&64)<<6)|((x&128)<<7)|((x&256)<<8)|((x&512)<<9) ) - #define TWIDOUT(x, y) ( TWIDTAB((y)) | (TWIDTAB((x)) << 1) ) - - #define MIN(a, b) ( (a)<(b)? (a):(b) ) - - uint32 x, y, yout, min, mask, invert; - - min = MIN(w, h); - mask = min - 1; - invert = 0; - - uint8 * pixels; - uint16 * vtex; - pixels = (uint8 *) data; - vtex = (uint16*)targetData; - - for(y = 0; y < h; y += 2) { - if(!invert) - yout = y; - else - yout = ((h - 1) - y); - - for(x = 0; x < w; x++) { - vtex[TWIDOUT((yout & mask) / 2, x & mask) + - (x / min + yout / min)*min * min / 2] = - pixels[y * w + x] | (pixels[(y + 1) * w + x] << 8); - } - } - data = NULL; - } + /* Don't convert color indexes */ needsConversion = GL_FALSE; + needsTwiddling = type == GL_UNSIGNED_BYTE; } else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV && internalFormat == GL_RGBA) { needsConversion = GL_FALSE; } else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV && internalFormat == GL_RGBA) { @@ -898,6 +918,9 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, needsConversion = GL_FALSE; } + GLubyte* targetData = _glGetMipmapLocation(active, level); + assert(targetData); + if(!data) { /* No data? Do nothing! */ return; @@ -906,8 +929,49 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, assert(data); assert(bytes); - /* No conversion? Just copy the data, and the pvr_format is correct */ - sq_cpy(targetData, data, bytes); + if(needsTwiddling) { + /*assert(type == GL_UNSIGNED_BYTE); // Anything else needs this loop adjusting + GLuint x, y; + for(y = 0; y < height; ++y) { + for(x = 0; x < width; ++x) { + GLuint src = (y * width) + x; + GLuint dest = morton_index(x, y); + + targetData[dest] = ((GLubyte*) data)[src]; + } + } + */ + /* Don't convert color indexes */ + /* Linear/iterative twiddling algorithm from Marcus' tatest */ + #define TWIDTAB(x) ( (x&1)|((x&2)<<1)|((x&4)<<2)|((x&8)<<3)|((x&16)<<4)| \ + ((x&32)<<5)|((x&64)<<6)|((x&128)<<7)|((x&256)<<8)|((x&512)<<9) ) + #define TWIDOUT(x, y) ( TWIDTAB((y)) | (TWIDTAB((x)) << 1) ) + + #define MIN(a, b) ( (a)<(b)? (a):(b) ) + + uint32 x, y, min, mask; + + min = MIN(w, h); + mask = min - 1; + + uint8 * pixels; + uint16 * vtex; + pixels = (uint8 *) data; + vtex = (uint16*)targetData; + + for(y = 0; y < h; y += 2) { + for(x = 0; x < w; x++) { + vtex[TWIDOUT((y & mask) / 2, x & mask) + + (x / min + y / min)*min * min / 2] = + pixels[y * w + x] | (pixels[(y + 1) * w + x] << 8); + } + } + data = NULL; + } else { + /* No conversion? Just copy the data, and the pvr_format is correct */ + sq_cpy(targetData, data, bytes); + } + return; } else { TextureConversionFunc convert = _determineConversion( @@ -917,7 +981,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, ); if(!convert) { - _glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D-convert"); + _glKosThrowError(GL_INVALID_OPERATION, __func__); return; } @@ -931,7 +995,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, assert(stride > -1); if(stride == -1) { - _glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D-stride"); + _glKosThrowError(GL_INVALID_OPERATION, __func__); return; } @@ -944,7 +1008,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, source += stride; } } - //printf("GLdc: glTexImage mem free:%d\n",pvr_mem_available()); } void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { @@ -1012,6 +1075,11 @@ void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { break; } + break; + case GL_SHARED_TEXTURE_BANK_KOS: + active->shared_bank = param; + break; + default: break; } } @@ -1022,7 +1090,16 @@ void APIENTRY glTexParameterf(GLenum target, GLenum pname, GLint param) { } GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data) { - GLenum validTargets[] = {GL_TEXTURE_2D, GL_SHARED_TEXTURE_PALETTE_EXT, 0}; + GLenum 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 + }; + GLenum validInternalFormats[] = {GL_RGB8, GL_RGBA8, 0}; GLenum validFormats[] = {GL_RGB, GL_RGBA, 0}; GLenum validTypes[] = {GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, 0}; @@ -1068,12 +1145,19 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize TexturePalette* palette = NULL; - if(target == GL_SHARED_TEXTURE_PALETTE_EXT) { - palette = SHARED_PALETTE; + /* 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 { TextureObject* active = _glGetBoundTexture(); if(!active->palette) { - active->palette = (TexturePalette*) malloc(sizeof(TexturePalette)); + active->palette = _initTexturePalette(); } palette = active->palette; @@ -1082,15 +1166,32 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize assert(palette); if(target) { - //pvr_mem_free(palette->data); free(palette->data); palette->data = NULL; } - //palette->data = (GLubyte*) pvr_mem_malloc(width * 4); + if(palette->bank > -1) { + _glReleasePaletteSlot(palette->bank, palette->size); + palette->bank = -1; + } + palette->data = (GLubyte*) malloc(width * 4); palette->format = format; 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* dst = (GLubyte*) palette->data; @@ -1107,10 +1208,7 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize dst += 4; } - - /* Colour table might have changed the active palette, so wipe last_bound_palette before reapplying */ - last_bound_palette = NULL; - _glApplyColorTable(); + _glApplyColorTable(palette); } GLAPI void APIENTRY glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) { @@ -1133,23 +1231,27 @@ GLAPI void APIENTRY glGetColorTableParameterfvEXT(GLenum target, GLenum pname, G _glKosPrintError(); } -void APIENTRY glKosSetPalette( GLenum palette ) { - switch(palette) { - case GL_EXT_PALLETE_0_8BPP: - CURRENT_PALETTE = 0; - break; - case GL_EXT_PALLETE_1_8BPP: - CURRENT_PALETTE = 1; - break; - case GL_EXT_PALLETE_2_8BPP: - CURRENT_PALETTE = 2; - break; - case GL_EXT_PALLETE_3_8BPP: - CURRENT_PALETTE = 3; - break; - } +GLAPI void APIENTRY glTexSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { } -GLbyte APIENTRY glKosGetPalette() { - return CURRENT_PALETTE; +GLAPI void APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + +} + +GLAPI void APIENTRY glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { + +} + +GLAPI void APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + +} + +GLAPI void APIENTRY glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) { + +} + +GLAPI void APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { + } diff --git a/include/gl.h b/include/gl.h index beaec7d..5872240 100644 --- a/include/gl.h +++ b/include/gl.h @@ -112,10 +112,10 @@ __BEGIN_DECLS /* Texture Environment */ #define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_REPLACE 0x0 -#define GL_MODULATE 0x1 -#define GL_DECAL 0x2 -#define GL_MODULATEALPHA 0x3 +#define GL_REPLACE 0x1E01 +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 + /* TextureMagFilter */ #define GL_NEAREST 0x2600 @@ -393,6 +393,9 @@ __BEGIN_DECLS /* Initialize the GL pipeline. GL will initialize the PVR. */ GLAPI void APIENTRY glKosInit(); +GLAPI void APIENTRY glFlush(); +GLAPI void APIENTRY glFinish(); + /* Start Submission of Primitive Data */ /* Currently Supported Primitive Types: -GL_POINTS ( does NOT work with glDrawArrays )( ZClipping NOT supported ) @@ -413,6 +416,7 @@ GLAPI void APIENTRY glTexCoord2fv(const GLfloat *uv); GLAPI void APIENTRY glColor1ui(GLuint argb); GLAPI void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a); GLAPI void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b); +GLAPI void APIENTRY glColor3ub(GLubyte r, GLubyte g, GLubyte b); GLAPI void APIENTRY glColor3fv(const GLfloat *rgb); GLAPI void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); GLAPI void APIENTRY glColor4fv(const GLfloat *rgba); @@ -462,6 +466,9 @@ GLAPI void APIENTRY glDisable(GLenum cap); GLAPI void APIENTRY glClear(GLuint mode); GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); +GLAPI void APIENTRY glReadBuffer(GLenum mode); +GLAPI void APIENTRY glDrawBuffer(GLenum mode); + /* Depth Testing */ GLAPI void APIENTRY glClearDepth(GLfloat depth); GLAPI void APIENTRY glClearDepthf(GLfloat depth); @@ -486,7 +493,7 @@ GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor); /* Texturing */ GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLint param); GLAPI GLboolean APIENTRY glIsTexture(GLuint texture); GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures); @@ -524,6 +531,13 @@ GLAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalForma GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data); +GLAPI void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); + /* GL Array API - Only GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_QUADS are supported */ GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type, diff --git a/include/glkos.h b/include/glkos.h index 1aad6c2..b809f73 100644 --- a/include/glkos.h +++ b/include/glkos.h @@ -34,14 +34,36 @@ __BEGIN_DECLS #define GL_UNSIGNED_BYTE_TWID_KOS 0xEEFB -#define GL_EXT_PALLETE_0_8BPP 0xEFA0 -#define GL_EXT_PALLETE_1_8BPP 0xEFA1 -#define GL_EXT_PALLETE_2_8BPP 0xEFA2 -#define GL_EXT_PALLETE_3_8BPP 0xEFA3 GLAPI void APIENTRY glKosSwapBuffers(); -GLAPI void APIENTRY glKosSetPalette( GLenum palette ); +/* + * CUSTOM EXTENSION multiple_shared_palette_KOS + * + * This extension allows using up to 4 different shared palettes + * with ColorTableEXT. The following constants are provided + * to use as targets for ColorTableExt: + * + * - SHARED_TEXTURE_PALETTE_0_KOS + * - SHARED_TEXTURE_PALETTE_1_KOS + * - SHARED_TEXTURE_PALETTE_2_KOS + * - SHARED_TEXTURE_PALETTE_3_KOS + * + * In this use case SHARED_TEXTURE_PALETTE_0_KOS is interchangable with SHARED_TEXTURE_PALETTE_EXT + * (both refer to the first shared palette). + * + * To select which palette a texture uses, a new pname is accepted by TexParameteri: SHARED_TEXTURE_BANK_KOS + * 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 + +/* Pass to glTexParameteri to set the shared bank */ +#define GL_SHARED_TEXTURE_BANK_KOS 0xEF00 + __END_DECLS