Reimplement or refactor Texturing, State, and Drawing

Things working:
 - glDrawArrays / glDrawElements et al.
 - Texturing
 - Blending

Things missing:

 - Lighting
 - Multitexturing
 - Near Z-clipping
 - Framebuffer extension
 - Immediate mode
This commit is contained in:
Luke Benstead 2018-05-11 15:39:28 +01:00
parent 1356ae352c
commit 62e001c288
18 changed files with 1565 additions and 1245 deletions

View File

@ -6,7 +6,7 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#define ALIGNED_VECTOR_INITIAL_CAPACITY 256 #define ALIGNED_VECTOR_INITIAL_CAPACITY 256u
typedef struct { typedef struct {
unsigned int size; unsigned int size;
@ -78,6 +78,12 @@ inline void* aligned_vector_at(AlignedVector* vector, const unsigned int index)
return &vector->data[index * vector->element_size]; return &vector->data[index * vector->element_size];
} }
inline void* aligned_vector_extend(AlignedVector* vector, const unsigned int additional_count) {
const unsigned int current = vector->size;
aligned_vector_resize(vector, vector->size + additional_count);
return aligned_vector_at(vector, current);
}
inline void aligned_vector_clear(AlignedVector* vector) { inline void aligned_vector_clear(AlignedVector* vector) {
vector->size = 0; vector->size = 0;
} }
@ -101,7 +107,7 @@ inline void aligned_vector_shrink_to_fit(AlignedVector* vector) {
} }
} }
void aligned_vector_cleanup(AlignedVector* vector) { inline void aligned_vector_cleanup(AlignedVector* vector) {
aligned_vector_clear(vector); aligned_vector_clear(vector);
aligned_vector_shrink_to_fit(vector); aligned_vector_shrink_to_fit(vector);
} }

View File

@ -1,9 +1,12 @@
#include "../include/gl.h" #include <stdio.h>
#include "private.h"
#include "../include/gl.h"
#include "../include/glext.h"
#include "private.h"
#include "../gl-api.h"
typedef struct { typedef struct {
void* ptr; const void* ptr;
GLenum type; GLenum type;
GLsizei stride; GLsizei stride;
GLint size; GLint size;
@ -26,6 +29,8 @@ static GLuint ENABLED_VERTEX_ATTRIBUTES = 0;
static GLubyte ACTIVE_CLIENT_TEXTURE = 0; static GLubyte ACTIVE_CLIENT_TEXTURE = 0;
void initAttributePointers() { void initAttributePointers() {
TRACE();
VERTEX_POINTER.ptr = NULL; VERTEX_POINTER.ptr = NULL;
VERTEX_POINTER.stride = 0; VERTEX_POINTER.stride = 0;
VERTEX_POINTER.type = GL_FLOAT; VERTEX_POINTER.type = GL_FLOAT;
@ -45,7 +50,7 @@ static GLuint byte_size(GLenum type) {
} }
} }
static void transformVertex(const GLfloat* src) { static void transformVertex(GLfloat* src, float* x, float* y, float* z) {
register float __x __asm__("fr12"); register float __x __asm__("fr12");
register float __y __asm__("fr13"); register float __y __asm__("fr13");
register float __z __asm__("fr14"); register float __z __asm__("fr14");
@ -56,9 +61,32 @@ static void transformVertex(const GLfloat* src) {
mat_trans_fv12() mat_trans_fv12()
src[0] = __x; *x = __x;
src[1] = __y; *y = __y;
src[2] = __z; *z = __z;
}
static void _parseColour(uint32* out, const GLubyte* in, GLint size, GLenum type) {
switch(type) {
case GL_BYTE: {
case GL_UNSIGNED_BYTE:
*out = in[3] << 24 | in[0] << 16 | in[1] << 8 | in[0];
} break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
/* FIXME!!!! */
break;
case GL_INT:
case GL_UNSIGNED_INT:
/* FIXME!!!! */
break;
case GL_FLOAT:
case GL_DOUBLE:
default: {
const GLfloat* src = (GLfloat*) in;
*out = PVR_PACK_COLOR(src[3], src[0], src[1], src[2]);
} break;
}
} }
static void _parseFloats(GLfloat* out, const GLubyte* in, GLint size, GLenum type) { static void _parseFloats(GLfloat* out, const GLubyte* in, GLint size, GLenum type) {
@ -93,49 +121,97 @@ static void _parseIndex(GLshort* out, const GLubyte* in, GLenum type) {
} }
} }
static void submitVertices(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum type, const GLvoid* indices) {
static float normal[3];
if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) { if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
return; return;
} }
_glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
const GLbyte elements = (mode == GL_QUADS) ? 4 : (mode == GL_TRIANGLES) ? 3 : (mode == GL_LINES) ? 2 : count; const GLsizei elements = (mode == GL_QUADS) ? 4 : (mode == GL_TRIANGLES) ? 3 : (mode == GL_LINES) ? 2 : count;
pvr_vertex_t vertex; // Make room for the element + the header
vertex.u = vertex.v = 0.0f; PVRCommand* dst = (PVRCommand*) aligned_vector_extend(&activePolyList()->vector, count + 1);
vertex.argb = 0xFFFFFFFF;
static GLfloat vparts[4]; // Store a pointer to the header
pvr_poly_hdr_t* hdr = (pvr_poly_hdr_t*) dst;
// Point dest at the first new vertex to populate
dst++;
// Compile
pvr_poly_cxt_t cxt = *getPVRContext();
cxt.list_type = activePolyList()->list_type;
updatePVRTextureContext(&cxt, getTexture0());
pvr_poly_compile(hdr, &cxt);
GLubyte vstride = (VERTEX_POINTER.stride) ? VERTEX_POINTER.stride : VERTEX_POINTER.size * byte_size(VERTEX_POINTER.type); GLubyte vstride = (VERTEX_POINTER.stride) ? VERTEX_POINTER.stride : VERTEX_POINTER.size * byte_size(VERTEX_POINTER.type);
GLubyte* vptr = VERTEX_POINTER.ptr; const GLubyte* vptr = VERTEX_POINTER.ptr;
for(GLuint i = 0; i < count; ++i) { GLubyte cstride = (DIFFUSE_POINTER.stride) ? DIFFUSE_POINTER.stride : DIFFUSE_POINTER.size * byte_size(DIFFUSE_POINTER.type);
GLshort idx = i; const GLubyte* cptr = DIFFUSE_POINTER.ptr;
if(indices) {
_parseIndex(&idx, indices[byte_size(type) * i], type); GLubyte uvstride = (UV_POINTER.stride) ? UV_POINTER.stride : UV_POINTER.size * byte_size(UV_POINTER.type);
const GLubyte* uvptr = UV_POINTER.ptr;
GLubyte nstride = (NORMAL_POINTER.stride) ? NORMAL_POINTER.stride : NORMAL_POINTER.size * byte_size(NORMAL_POINTER.type);
const GLubyte* nptr = NORMAL_POINTER.ptr;
const GLubyte* indices_as_bytes = (GLubyte*) indices;
for(GLuint i = first; i < count; ++i) {
pvr_vertex_t* vertex = (pvr_vertex_t*) dst;
vertex->u = vertex->v = 0.0f;
vertex->argb = PVR_PACK_COLOR(0.0f, 0.0f, 0.0f, 0.0f);
vertex->oargb = 0;
vertex->flags = PVR_CMD_VERTEX;
if(((i + 1) % elements) == 0) {
vertex->flags = PVR_CMD_VERTEX_EOL;
} }
_parseFloats(vparts, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type); GLshort idx = i;
if(indices) {
_parseIndex(&idx, &indices_as_bytes[byte_size(type) * i], type);
}
vertex.x = vparts[0]; _parseFloats(&vertex->x, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type);
vertex.y = vparts[1]; transformVertex(&vertex->x, &vertex->x, &vertex->y, &vertex->z);
vertex.z = vparts[2];
transformVertex(&vertex.x); if(ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) {
_parseColour(&vertex->argb, cptr + (idx * cstride), DIFFUSE_POINTER.size, DIFFUSE_POINTER.type);
}
if(ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG) {
_parseFloats(&vertex->u, uvptr + (idx * uvstride), UV_POINTER.size, UV_POINTER.type);
}
if(ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) {
_parseFloats(normal, nptr + (idx * nstride), NORMAL_POINTER.size, NORMAL_POINTER.type);
}
++dst;
} }
} }
GLAPI void APIENTRY glDrawElementsExp(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
submitVertices(mode, count, type, indices); TRACE();
submitVertices(mode, 0, count, type, indices);
} }
GLAPI void APIENTRY glDrawArraysExp(GLenum mode, GLint first, GLsizei count) { void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) {
submitVertices(mode, count, type, NULL); TRACE();
submitVertices(mode, first, count, GL_UNSIGNED_SHORT, NULL);
} }
GLAPI void APIENTRY glEnableClientStateExp(GLenum cap) { void APIENTRY glEnableClientState(GLenum cap) {
TRACE();
switch(cap) { switch(cap) {
case GL_VERTEX_ARRAY: case GL_VERTEX_ARRAY:
ENABLED_VERTEX_ATTRIBUTES |= VERTEX_ENABLED_FLAG; ENABLED_VERTEX_ATTRIBUTES |= VERTEX_ENABLED_FLAG;
@ -156,7 +232,9 @@ GLAPI void APIENTRY glEnableClientStateExp(GLenum cap) {
} }
} }
GLAPI void APIENTRY glDisableClientStateExp(GLenum cap) { void APIENTRY glDisableClientState(GLenum cap) {
TRACE();
switch(cap) { switch(cap) {
case GL_VERTEX_ARRAY: case GL_VERTEX_ARRAY:
ENABLED_VERTEX_ATTRIBUTES &= ~VERTEX_ENABLED_FLAG; ENABLED_VERTEX_ATTRIBUTES &= ~VERTEX_ENABLED_FLAG;
@ -177,34 +255,53 @@ GLAPI void APIENTRY glDisableClientStateExp(GLenum cap) {
} }
} }
GLAPI void APIENTRY glClientActiveTextureExp(GLenum texture) { void APIENTRY glClientActiveTextureARB(GLenum texture) {
ACTIVE_CLIENT_TEXTURE = (texture == GL_TEXTURE1) ? 1 : 0; TRACE();
if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS) {
_glKosThrowError(GL_INVALID_ENUM, "glClientActiveTextureARB");
}
if(_glKosHasError()) {
_glKosPrintError();
return;
}
ACTIVE_CLIENT_TEXTURE = (texture == GL_TEXTURE1_ARB) ? 1 : 0;
} }
GLAPI void APIENTRY glTexcoordPointerExp(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) { void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
AttribPointer* texpointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER; TRACE();
texpointer->ptr = pointer; AttribPointer* tointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER;
texpointer->stride = stride;
texpointer->type = type; tointer->ptr = pointer;
texpointer->size = size; tointer->stride = stride;
tointer->type = type;
tointer->size = size;
} }
GLAPI void APIENTRY glVertexPointerExp(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) { void APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
TRACE();
VERTEX_POINTER.ptr = pointer; VERTEX_POINTER.ptr = pointer;
VERTEX_POINTER.stride = stride; VERTEX_POINTER.stride = stride;
VERTEX_POINTER.type = type; VERTEX_POINTER.type = type;
VERTEX_POINTER.size = size; VERTEX_POINTER.size = size;
} }
GLAPI void APIENTRY glColorPointerExp(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) { void APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
TRACE();
DIFFUSE_POINTER.ptr = pointer; DIFFUSE_POINTER.ptr = pointer;
DIFFUSE_POINTER.stride = stride; DIFFUSE_POINTER.stride = stride;
DIFFUSE_POINTER.type = type; DIFFUSE_POINTER.type = type;
DIFFUSE_POINTER.size = size; DIFFUSE_POINTER.size = size;
} }
GLAPI void APIENTRY glNormalPointerExp(GLenum type, GLsizei stride, const GLvoid * pointer) { void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * pointer) {
TRACE();
NORMAL_POINTER.ptr = pointer; NORMAL_POINTER.ptr = pointer;
NORMAL_POINTER.stride = stride; NORMAL_POINTER.stride = stride;
NORMAL_POINTER.type = type; NORMAL_POINTER.type = type;

View File

@ -4,17 +4,14 @@
#include "../containers/aligned_vector.h" #include "../containers/aligned_vector.h"
#include "private.h" #include "private.h"
#include "../gl-api.h"
#define TA_SQ_ADDR (unsigned int *)(void *) \ #define TA_SQ_ADDR (unsigned int *)(void *) \
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0)) (0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
static AlignedVector OP_LIST; static PolyList OP_LIST;
static AlignedVector PT_LIST; static PolyList PT_LIST;
static AlignedVector TR_LIST; static PolyList TR_LIST;
typedef struct {
unsigned int cmd[8];
} PVRCommand;
static void pvr_list_submit(void *src, int n) { static void pvr_list_submit(void *src, int n) {
GLuint *d = TA_SQ_ADDR; GLuint *d = TA_SQ_ADDR;
@ -44,7 +41,7 @@ static void _initPVR() {
pvr_init_params_t params = { pvr_init_params_t params = {
/* Enable opaque and translucent polygons with size 32 and 32 */ /* 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 },
GL_PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */ PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
0, /* No DMA */ 0, /* No DMA */
0, /* No FSAA */ 0, /* No FSAA */
1 /* Disable translucent auto-sorting to match traditional GL */ 1 /* Disable translucent auto-sorting to match traditional GL */
@ -54,35 +51,54 @@ static void _initPVR() {
} }
AlignedVector* activePolyList() { PolyList* activePolyList() {
return &OP_LIST; if(isBlendingEnabled()) {
return &TR_LIST;
} else {
return &OP_LIST;
}
} }
/* FIXME: Rename to glKosInit when experimental is core */ void APIENTRY glKosInit() {
void glKosBoot() { TRACE();
_initPVR(); _initPVR();
initAttributePointers();
aligned_vector_init(&OP_LIST, sizeof(PVRCommand)); initAttributePointers();
aligned_vector_init(&PT_LIST, sizeof(PVRCommand)); initContext();
aligned_vector_init(&TR_LIST, sizeof(PVRCommand));
_glKosInitMatrix();
_glKosInitTextures();
OP_LIST.list_type = PVR_LIST_OP_POLY;
PT_LIST.list_type = PVR_LIST_PT_POLY;
TR_LIST.list_type = PVR_LIST_TR_POLY;
aligned_vector_init(&OP_LIST.vector, sizeof(PVRCommand));
aligned_vector_init(&PT_LIST.vector, sizeof(PVRCommand));
aligned_vector_init(&TR_LIST.vector, sizeof(PVRCommand));
} }
void glKosSwapBuffers() { void APIENTRY glKosSwapBuffers() {
TRACE();
pvr_wait_ready(); pvr_wait_ready();
pvr_scene_begin(); pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY); pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_submit(OP_LIST.data, OP_LIST.size); pvr_list_submit(OP_LIST.vector.data, OP_LIST.vector.size);
pvr_list_finish(); pvr_list_finish();
pvr_list_begin(PVR_LIST_PT_POLY); pvr_list_begin(PVR_LIST_PT_POLY);
pvr_list_submit(PT_LIST.data, PT_LIST.size); pvr_list_submit(PT_LIST.vector.data, PT_LIST.vector.size);
pvr_list_finish(); pvr_list_finish();
pvr_list_begin(PVR_LIST_TR_POLY); pvr_list_begin(PVR_LIST_TR_POLY);
pvr_list_submit(TR_LIST.data, TR_LIST.size); pvr_list_submit(TR_LIST.vector.data, TR_LIST.vector.size);
pvr_list_finish(); pvr_list_finish();
pvr_scene_finish(); pvr_scene_finish();
aligned_vector_clear(&OP_LIST.vector);
aligned_vector_clear(&PT_LIST.vector);
aligned_vector_clear(&TR_LIST.vector);
} }

View File

0
experimental/immediate.c Normal file
View File

0
experimental/lighting.c Normal file
View File

View File

@ -2,12 +2,61 @@
#define PRIVATE_H #define PRIVATE_H
#include "../include/gl.h" #include "../include/gl.h"
#include "../gl-api.h"
#include "../containers/aligned_vector.h"
#include "../containers/named_array.h"
struct AlignedVector;
AlignedVector* activePolyList(); #define TRACE_ENABLED 0
#define TRACE() if(TRACE_ENABLED) {fprintf(stderr, "%s\n", __func__);}
typedef struct {
unsigned int cmd[8];
} PVRCommand;
typedef struct {
unsigned int flags; /* Constant PVR_CMD_USERCLIP */
unsigned int d1, d2, d3; /* Ignored for this type */
unsigned int sx, /* Start x */
sy, /* Start y */
ex, /* End x */
ey; /* End y */
} PVRTileClipCommand; /* Tile Clip command for the pvr */
typedef struct {
unsigned int list_type;
AlignedVector vector;
} PolyList;
typedef struct {
GLushort width;
GLushort height;
GLuint color; /* This is the PVR texture format */
GLubyte env;
GLubyte filter;
GLubyte mip_map;
GLubyte uv_clamp;
GLuint index;
GLvoid *data;
} TextureObject;
PolyList *activePolyList();
void initAttributePointers(); void initAttributePointers();
void initContext();
pvr_poly_cxt_t* getPVRContext();
GLubyte _glKosInitTextures();
void updatePVRTextureContext(pvr_poly_cxt_t* context, TextureObject* tx1);
TextureObject* getTexture0();
TextureObject* getTexture1();
TextureObject* getBoundTexture();
GLboolean isBlendingEnabled();
#define PVR_VERTEX_BUF_SIZE 2560 * 256
#define MAX_TEXTURE_UNITS 2
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
#define mat_trans_fv12() { \ #define mat_trans_fv12() { \
__asm__ __volatile__( \ __asm__ __volatile__( \

View File

@ -1,7 +1,21 @@
#include <string.h>
#include <stdio.h>
#include <dc/pvr.h>
#include <dc/vec3f.h>
#include <dc/video.h>
#include "../include/gl.h" #include "../include/gl.h"
#include "../gl-api.h"
#include "private.h"
static pvr_poly_cxt_t GL_CONTEXT; static pvr_poly_cxt_t GL_CONTEXT;
pvr_poly_cxt_t* getPVRContext() {
return &GL_CONTEXT;
}
/* We can't just use the GL_CONTEXT for this state as the two /* We can't just use the GL_CONTEXT for this state as the two
* GL states are combined, so we store them separately and then * GL states are combined, so we store them separately and then
* calculate the appropriate PVR state from them. */ * calculate the appropriate PVR state from them. */
@ -26,36 +40,136 @@ static GLboolean DEPTH_TEST_ENABLED = GL_FALSE;
static int _calc_pvr_depth_test() { static int _calc_pvr_depth_test() {
if(!DEPTH_TEST_ENABLED) { if(!DEPTH_TEST_ENABLED) {
return PVR_DEPTH_CMP_ALWAYS; return PVR_DEPTHCMP_ALWAYS;
} }
switch(func) { switch(DEPTH_FUNC) {
case GL_NEVER: case GL_NEVER:
return PVR_DEPTH_CMP_NEVER; return PVR_DEPTHCMP_NEVER;
case GL_LESS: case GL_LESS:
return PVR_DEPTH_CMP_LESS; return PVR_DEPTHCMP_GEQUAL;
case GL_EQUAL: case GL_EQUAL:
return PVR_DEPTH_CMP_EQUAL; return PVR_DEPTHCMP_EQUAL;
case GL_LEQUAL: case GL_LEQUAL:
return PVR_DEPTH_CMP_LEQUAL; return PVR_DEPTHCMP_GREATER;
case GL_GREATER: case GL_GREATER:
return PVR_DEPTH_CMP_GREATER; return PVR_DEPTHCMP_LEQUAL;
case GL_NOTEQUAL: case GL_NOTEQUAL:
return PVR_DEPTH_CMP_NOTEQUAL; return PVR_DEPTHCMP_NOTEQUAL;
case GL_GEQUAL: case GL_GEQUAL:
return PVR_DEPTH_CMP_GEQUAL; return PVR_DEPTHCMP_LESS;
break; break;
case GL_ALWAYS: case GL_ALWAYS:
default: default:
return PVR_DEPTH_CMP_ALWAYS; return PVR_DEPTHCMP_ALWAYS;
}
}
static GLenum BLEND_SFACTOR = GL_ONE;
static GLenum BLEND_DFACTOR = GL_ZERO;
static GLboolean BLEND_ENABLED = GL_FALSE;
GLboolean isBlendingEnabled() {
return BLEND_ENABLED;
}
static int _calcPVRBlendFactor(GLenum factor) {
switch(factor) {
case GL_ZERO:
return PVR_BLEND_ZERO;
case GL_SRC_ALPHA:
case GL_SRC_COLOR:
return PVR_BLEND_SRCALPHA;
case GL_DST_COLOR:
return PVR_BLEND_DESTCOLOR;
case GL_DST_ALPHA:
return PVR_BLEND_DESTALPHA;
case GL_ONE_MINUS_DST_COLOR:
return PVR_BLEND_INVDESTCOLOR;
case GL_ONE_MINUS_SRC_COLOR:
case GL_ONE_MINUS_SRC_ALPHA:
return PVR_BLEND_INVSRCALPHA;
case GL_ONE_MINUS_DST_ALPHA:
return PVR_BLEND_INVDESTALPHA;
case GL_ONE:
default:
return PVR_BLEND_ONE;
}
}
static void _updatePVRBlend(pvr_poly_cxt_t* context) {
if(BLEND_ENABLED) {
context->gen.alpha = PVR_ALPHA_ENABLE;
context->blend.src = _calcPVRBlendFactor(BLEND_SFACTOR);
context->blend.dst = _calcPVRBlendFactor(BLEND_DFACTOR);
context->blend.src_enable = PVR_BLEND_ENABLE;
context->blend.dst_enable = PVR_BLEND_ENABLE;
context->blend.src2 = PVR_BLEND_ONE;
context->blend.dst2 = PVR_BLEND_ZERO;
context->blend.src_enable2 = PVR_BLEND_DISABLE;
context->blend.dst_enable2 = PVR_BLEND_DISABLE;
} else {
context->gen.alpha = PVR_ALPHA_DISABLE;
context->blend.src = PVR_BLEND_ONE;
context->blend.dst = PVR_BLEND_ZERO;
context->blend.src_enable = PVR_BLEND_DISABLE;
context->blend.dst_enable = PVR_BLEND_DISABLE;
context->blend.src2 = PVR_BLEND_ONE;
context->blend.dst2 = PVR_BLEND_ZERO;
context->blend.src_enable2 = PVR_BLEND_DISABLE;
context->blend.dst_enable2 = PVR_BLEND_DISABLE;
}
}
static GLboolean TEXTURES_ENABLED = GL_FALSE;
void updatePVRTextureContext(pvr_poly_cxt_t* context, TextureObject *tx1) {
if(!TEXTURES_ENABLED) {
context->txr2.enable = context->txr.enable = PVR_TEXTURE_DISABLE;
return;
}
context->txr2.enable = PVR_TEXTURE_DISABLE;
context->txr2.alpha = PVR_ALPHA_DISABLE;
if(tx1) {
context->txr.enable = PVR_TEXTURE_ENABLE;
context->txr.filter = tx1->filter;
context->txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
context->txr.width = tx1->width;
context->txr.height = tx1->height;
context->txr.base = tx1->data;
context->txr.format = tx1->color;
context->txr.env = tx1->env;
context->txr.uv_flip = PVR_UVFLIP_NONE;
context->txr.uv_clamp = tx1->uv_clamp;
} else {
context->txr.enable = PVR_TEXTURE_DISABLE;
} }
} }
void initContext() { static GLfloat CLEAR_COLOUR[3];
void initContext() {
memset(&GL_CONTEXT, 0, sizeof(pvr_poly_cxt_t));
GL_CONTEXT.list_type = PVR_LIST_OP_POLY;
GL_CONTEXT.fmt.color = PVR_CLRFMT_ARGBPACKED;
GL_CONTEXT.fmt.uv = PVR_UVFMT_32BIT;
GL_CONTEXT.gen.fog_type = PVR_FOG_DISABLE;
GL_CONTEXT.gen.color_clamp = PVR_CLRCLAMP_DISABLE;
GL_CONTEXT.gen.fog_type = PVR_FOG_DISABLE;
GL_CONTEXT.gen.color_clamp = PVR_CLRCLAMP_DISABLE;
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glCullFace(GL_CCW); glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glShadeModel(GL_SMOOTH);
glClearColor(0, 0, 0, 0);
glDisable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
@ -67,7 +181,7 @@ void initContext() {
GLAPI void APIENTRY glEnable(GLenum cap) { GLAPI void APIENTRY glEnable(GLenum cap) {
switch(cap) { switch(cap) {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
GL_CONTEXT.txr.enable = 1; TEXTURES_ENABLED = GL_TRUE;
break; break;
case GL_CULL_FACE: { case GL_CULL_FACE: {
CULLING_ENABLED = GL_TRUE; CULLING_ENABLED = GL_TRUE;
@ -77,13 +191,22 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
DEPTH_TEST_ENABLED = GL_TRUE; DEPTH_TEST_ENABLED = GL_TRUE;
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test(); GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
} break; } break;
case GL_BLEND: {
BLEND_ENABLED = GL_TRUE;
_updatePVRBlend(&GL_CONTEXT);
} break;
case GL_SCISSOR_TEST: {
GL_CONTEXT.gen.clip_mode = PVR_USERCLIP_INSIDE;
} break;
default:
break;
} }
} }
GLAPI void APIENTRY glDisable(GLenum cap) { GLAPI void APIENTRY glDisable(GLenum cap) {
switch(cap) { switch(cap) {
case GL_TEXTURE_2D: { case GL_TEXTURE_2D: {
GL_CONTEXT.txr.enabled = 0; TEXTURES_ENABLED = GL_FALSE;
} break; } break;
case GL_CULL_FACE: { case GL_CULL_FACE: {
CULLING_ENABLED = GL_FALSE; CULLING_ENABLED = GL_FALSE;
@ -93,16 +216,34 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
DEPTH_TEST_ENABLED = GL_FALSE; DEPTH_TEST_ENABLED = GL_FALSE;
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test(); GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
} break; } break;
case GL_BLEND:
BLEND_ENABLED = GL_FALSE;
_updatePVRBlend(&GL_CONTEXT);
break;
case GL_SCISSOR_TEST: {
GL_CONTEXT.gen.clip_mode = PVR_USERCLIP_DISABLE;
} break;
default:
break;
} }
} }
/* Clear Caps */ /* Clear Caps */
GLAPI void APIENTRY glClear(GLuint mode) { GLAPI void APIENTRY glClear(GLuint mode) {
if(mode & GL_COLOR_BUFFER_BIT) {
pvr_set_bg_color(CLEAR_COLOUR[0], CLEAR_COLOUR[1], CLEAR_COLOUR[2]);
}
} }
GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
if(r > 1) r = 1;
if(g > 1) g = 1;
if(b > 1) b = 1;
if(a > 1) a = 1;
CLEAR_COLOUR[0] = r * a;
CLEAR_COLOUR[1] = g * a;
CLEAR_COLOUR[2] = b * a;
} }
/* Depth Testing */ /* Depth Testing */
@ -116,6 +257,7 @@ GLAPI void APIENTRY glClearDepth(GLfloat depth) {
GLAPI void APIENTRY glDepthMask(GLboolean flag) { GLAPI void APIENTRY glDepthMask(GLboolean flag) {
GL_CONTEXT.depth.write = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE; GL_CONTEXT.depth.write = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
} }
GLAPI void APIENTRY glDepthFunc(GLenum func) { GLAPI void APIENTRY glDepthFunc(GLenum func) {
@ -133,43 +275,82 @@ GLAPI void APIENTRY glHint(GLenum target, GLenum mode) {
/* Culling */ /* Culling */
GLAPI void APIENTRY glFrontFace(GLenum mode) { GLAPI void APIENTRY glFrontFace(GLenum mode) {
FRONT_FACE = mode; FRONT_FACE = mode;
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
} }
GLAPI void APIENTRY glCullFace(GLenum mode) { GLAPI void APIENTRY glCullFace(GLenum mode) {
CULL_FACE = mode; CULL_FACE = mode;
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
} }
/* Shading - Flat or Goraud */ /* Shading - Flat or Goraud */
GLAPI void APIENTRY glShadeModel(GLenum mode) { GLAPI void APIENTRY glShadeModel(GLenum mode) {
GL_CONTEXT.gen.shading = (mode == GL_SMOOTH) ? PVR_SHADE_GOURAUD : PVR_SHADE_FLAT;
} }
/* Blending */ /* Blending */
GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) {
BLEND_SFACTOR = sfactor;
BLEND_DFACTOR = dfactor;
_updatePVRBlend(&GL_CONTEXT);
} }
/* Texturing */ void glAlphaFunc(GLenum func, GLclampf ref) {
GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { ;
} }
GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) { void glLineWidth(GLfloat width) {
;
} }
GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) { void glPolygonOffset(GLfloat factor, GLfloat units) {
;
} }
GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures) { void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) {
;
} }
GLAPI void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) { void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
;
} }
GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture) { void glPixelStorei(GLenum pname, GLint param) {
;
} }
/* Setup the hardware user clip rectangle.
The minimum clip rectangle is a 32x32 area which is dependent on the tile
size use by the tile accelerator. The PVR swithes off rendering to tiles
outside or inside the defined rectangle dependant upon the 'clipmode'
bits in the polygon header.
Clip rectangles therefore must have a size that is some multiple of 32.
glScissor(0, 0, 32, 32) allows only the 'tile' in the lower left
hand corner of the screen to be modified and glScissor(0, 0, 0, 0)
disallows modification to all 'tiles' on the screen.
*/
void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
/*!!! FIXME: Shouldn't this be added to *all* lists? */
PVRTileClipCommand *c = aligned_vector_extend(&activePolyList()->vector, 1);
GLint miny, maxx, maxy;
GLsizei gl_scissor_width = CLAMP(width, 0, vid_mode->width);
GLsizei gl_scissor_height = CLAMP(height, 0, vid_mode->height);
/* force the origin to the lower left-hand corner of the screen */
miny = (vid_mode->height - gl_scissor_height) - y;
maxx = (gl_scissor_width + x);
maxy = (gl_scissor_height + miny);
/* load command structure while mapping screen coords to TA tiles */
c->flags = PVR_CMD_USERCLIP;
c->d1 = c->d2 = c->d3 = 0;
c->sx = CLAMP(x / 32, 0, vid_mode->width / 32);
c->sy = CLAMP(miny / 32, 0, vid_mode->height / 32);
c->ex = CLAMP((maxx / 32) - 1, 0, vid_mode->width / 32);
c->ey = CLAMP((maxy / 32) - 1, 0, vid_mode->height / 32);
}

620
experimental/texture.c Normal file
View File

@ -0,0 +1,620 @@
#include "private.h"
#include "../include/glext.h"
#include <stdio.h>
#define CLAMP_U (1<<1)
#define CLAMP_V (1<<0)
static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL};
static NamedArray TEXTURE_OBJECTS;
static GLubyte ACTIVE_TEXTURE = 0;
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type);
GLubyte _glKosInitTextures() {
named_array_init(&TEXTURE_OBJECTS, sizeof(TextureObject), 256);
return 1;
}
TextureObject* getTexture0() {
return TEXTURE_UNITS[0];
}
TextureObject* getTexture1() {
return TEXTURE_UNITS[1];
}
TextureObject* getBoundTexture() {
return TEXTURE_UNITS[ACTIVE_TEXTURE];
}
GLubyte check_valid_enum(GLint param, GLenum* values, const char* func) {
GLubyte found = 0;
while(*values != 0) {
if(*values == param) {
found++;
break;
}
values++;
}
if(!found) {
_glKosThrowError(GL_INVALID_ENUM, func);
_glKosPrintError();
return 1;
}
return 0;
}
void APIENTRY glActiveTextureARB(GLenum texture) {
TRACE();
if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
_glKosThrowError(GL_INVALID_ENUM, "glActiveTextureARB");
if(_glKosHasError()) {
_glKosPrintError();
return;
}
ACTIVE_TEXTURE = texture & 0xF;
}
void APIENTRY glGenTextures(GLsizei n, GLuint *textures) {
TRACE();
while(n--) {
GLuint id = 0;
TextureObject* txr = (TextureObject*) named_array_alloc(&TEXTURE_OBJECTS, &id);
txr->index = id;
txr->width = txr->height = 0;
txr->mip_map = 0;
txr->uv_clamp = 0;
txr->env = PVR_TXRENV_MODULATEALPHA;
txr->filter = PVR_FILTER_NONE;
txr->data = NULL;
*textures = id;
textures++;
}
}
void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) {
TRACE();
while(n--) {
TextureObject* txr = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, *textures);
if(txr == TEXTURE_UNITS[ACTIVE_TEXTURE]) {
TEXTURE_UNITS[ACTIVE_TEXTURE] = NULL;
}
if(txr->data) {
pvr_mem_free(txr->data);
}
named_array_release(&TEXTURE_OBJECTS, *textures++);
}
}
void APIENTRY glBindTexture(GLenum target, GLuint texture) {
TRACE();
GLenum target_values [] = {GL_TEXTURE_2D, 0};
if(check_valid_enum(target, target_values, __func__) != 0) {
return;
}
if(texture) {
TEXTURE_UNITS[ACTIVE_TEXTURE] = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, texture);
} else {
TEXTURE_UNITS[ACTIVE_TEXTURE] = NULL;
}
}
void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) {
TRACE();
GLenum target_values [] = {GL_TEXTURE_ENV, 0};
GLenum pname_values [] = {GL_TEXTURE_ENV_MODE, 0};
GLenum param_values [] = {GL_MODULATE, GL_DECAL, GL_REPLACE, 0};
GLubyte failures = 0;
failures += check_valid_enum(target, target_values, __func__);
failures += check_valid_enum(pname, pname_values, __func__);
failures += check_valid_enum(param, param_values, __func__);
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
if(!active) {
return;
}
if(failures) {
return;
}
switch(param) {
case GL_MODULATE:
active->env = PVR_TXRENV_MODULATEALPHA;
break;
case GL_DECAL:
active->env = PVR_TXRENV_DECAL;
break;
case GL_REPLACE:
active->env = PVR_TXRENV_REPLACE;
break;
default:
break;
}
}
void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) {
glTexEnvi(target, pname, param);
}
void APIENTRY glCompressedTexImage2D(GLenum target,
GLint level,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLsizei imageSize,
const GLvoid *data) {
TRACE();
if(target != GL_TEXTURE_2D)
_glKosThrowError(GL_INVALID_ENUM, "glCompressedTexImage2D");
if(level < 0)
_glKosThrowError(GL_INVALID_VALUE, "glCompressedTexImage2D");
if(border)
_glKosThrowError(GL_INVALID_VALUE, "glCompressedTexImage2D");
if(internalformat != GL_UNSIGNED_SHORT_5_6_5_VQ_KOS)
if(internalformat != GL_UNSIGNED_SHORT_5_6_5_VQ_TWID_KOS)
if(internalformat != GL_UNSIGNED_SHORT_4_4_4_4_VQ_KOS)
if(internalformat != GL_UNSIGNED_SHORT_4_4_4_4_REV_VQ_TWID_KOS)
if(internalformat != GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_KOS)
if(internalformat != GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_TWID_KOS)
_glKosThrowError(GL_INVALID_OPERATION, "glCompressedTexImage2D");
if(TEXTURE_UNITS[ACTIVE_TEXTURE] == NULL)
_glKosThrowError(GL_INVALID_OPERATION, "glCompressedTexImage2D");
if(_glKosHasError()) {
_glKosPrintError();
return;
}
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
active->width = width;
active->height = height;
active->mip_map = level;
active->color = _determinePVRFormat(
internalformat,
internalformat /* Doesn't matter (see determinePVRFormat) */
);
/* Odds are slim new data is same size as old, so free always */
if(active->data)
pvr_mem_free(active->data);
active->data = pvr_mem_malloc(imageSize);
if(data)
sq_cpy(active->data, data, imageSize);
}
static GLint _cleanInternalFormat(GLint internalFormat) {
switch (internalFormat) {
case GL_ALPHA:
/* case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:*/
return GL_ALPHA;
case 1:
case GL_LUMINANCE:
/* case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:*/
return GL_LUMINANCE;
case 2:
case GL_LUMINANCE_ALPHA:
/* case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16: */
return GL_LUMINANCE_ALPHA;
/* case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
return GL_INTENSITY; */
case 3:
return GL_RGB;
case GL_RGB:
/* case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16: */
return GL_RGB;
case 4:
return GL_RGBA;
case GL_RGBA:
/* case GL_RGBA2:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16: */
return GL_RGBA;
/* Support ARB_texture_rg */
case GL_RED:
/* case GL_R8:
case GL_R16:
case GL_RED:
case GL_COMPRESSED_RED: */
return GL_RED;
/* case GL_RG:
case GL_RG8:
case GL_RG16:
case GL_COMPRESSED_RG:
return GL_RG;*/
default:
return -1;
}
}
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
/* Given a cleaned internalFormat, return the Dreamcast format
* that can hold it
*/
switch(internalFormat) {
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
/* OK so if we have something that requires alpha, we return 4444 unless
* the type was already 1555 (1-bit alpha) in which case we return that
*/
return (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) ?
PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED :
PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_NONTWIDDLED;
case GL_RED:
case GL_RGB:
/* No alpha? Return RGB565 which is the best we can do without using palettes */
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED;
/* Compressed and twiddled versions */
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED;
case GL_UNSIGNED_SHORT_5_6_5_VQ_KOS:
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_5_6_5_VQ_TWID_KOS:
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS:
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_VQ_TWID_KOS:
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_4_4_4_4_VQ_KOS:
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_TWID_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
default:
return 0;
}
}
typedef void (*TextureConversionFunc)(const GLubyte*, GLushort*);
static void _rgba8888_to_argb4444(const GLubyte* source, GLushort* dest) {
*dest = (source[3] & 0xF0) << 8 | (source[0] & 0xF0) << 4 | (source[1] & 0xF0) | (source[2] & 0xF0) >> 4;
}
static void _rgb888_to_rgb565(const GLubyte* source, GLushort* dest) {
*dest = ((source[0] & 0b11111000) << 8) | ((source[1] & 0b11111100) << 3) | (source[2] >> 3);
}
static void _rgba8888_to_a000(const GLubyte* source, GLushort* dest) {
*dest = ((source[3] & 0b11111000) << 8);
}
static void _r8_to_rgb565(const GLubyte* source, GLushort* dest) {
*dest = (source[0] & 0b11111000) << 8;
}
static void _rgba4444_to_argb4444(const GLubyte* source, GLushort* dest) {
GLushort* src = (GLushort*) source;
*dest = ((*src & 0x000F) << 12) | *src >> 4;
}
static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum format, GLenum type) {
switch(internalFormat) {
case GL_ALPHA: {
if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
return _rgba8888_to_a000;
} else if(type == GL_BYTE && format == GL_RGBA) {
return _rgba8888_to_a000;
}
} break;
case GL_RGB: {
if(type == GL_UNSIGNED_BYTE && format == GL_RGB) {
return _rgb888_to_rgb565;
} else if(type == GL_BYTE && format == GL_RGB) {
return _rgb888_to_rgb565;
} else if(type == GL_UNSIGNED_BYTE && format == GL_RED) {
return _r8_to_rgb565;
}
} break;
case GL_RGBA: {
if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
return _rgba8888_to_argb4444;
} else if (type == GL_BYTE && format == GL_RGBA) {
return _rgba8888_to_argb4444;
} else if(type == GL_UNSIGNED_SHORT_4_4_4_4 && format == GL_RGBA) {
return _rgba4444_to_argb4444;
}
} break;
default:
fprintf(stderr, "Unsupported conversion: %d -> %d, %d", internalFormat, format, type);
break;
}
return 0;
}
static GLint _determineStride(GLenum format, GLenum type) {
switch(type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
return (format == GL_RED) ? 1 : (format == GL_RGB) ? 3 : 4;
case GL_UNSIGNED_SHORT:
return (format == GL_RED) ? 2 : (format == GL_RGB) ? 6 : 8;
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
return 2;
}
return -1;
}
static GLboolean _isSupportedFormat(GLenum format) {
switch(format) {
case GL_RED:
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
return GL_TRUE;
default:
return GL_FALSE;
}
}
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");
}
if(!_isSupportedFormat(format)) {
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
}
/* Abuse determineStride to see if type is valid */
if(_determineStride(GL_RGBA, type) == -1) {
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
}
internalFormat = _cleanInternalFormat(internalFormat);
if(internalFormat == -1) {
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
GLint w = width;
if(w == 0 || (w & -w) != w) {
/* Width is not a power of two. Must be!*/
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
GLint h = height;
if(h == 0 || (h & -h) != h) {
/* height is not a power of two. Must be!*/
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
if(level < 0) {
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
if(border) {
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
if(!TEXTURE_UNITS[ACTIVE_TEXTURE]) {
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
}
if(_glKosHasError()) {
_glKosPrintError();
return;
}
/* Calculate the format that we need to convert the data to */
GLuint pvr_format = _determinePVRFormat(internalFormat, type);
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
if(active->data) {
/* pre-existing texture - check if changed */
if(active->width != width ||
active->height != height ||
active->mip_map != level ||
active->color != pvr_format) {
/* changed - free old texture memory */
pvr_mem_free(active->data);
active->data = NULL;
}
}
GLuint bytes = level ? glKosMipMapTexSize(width, height) : (width * height * 2);
if(!active->data) {
/* need texture memory */
active->width = width;
active->height = height;
active->mip_map = level;
active->color = pvr_format;
active->data = pvr_mem_malloc(bytes);
}
/* Let's assume we need to convert */
GLboolean needsConversion = GL_TRUE;
/*
* 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_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) {
needsConversion = GL_FALSE;
} else if(format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 && internalFormat == GL_RGB) {
needsConversion = GL_FALSE;
} else if(format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5_TWID_KOS && internalFormat == GL_RGB) {
needsConversion = GL_FALSE;
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS && internalFormat == GL_RGBA) {
needsConversion = GL_FALSE;
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS && internalFormat == GL_RGBA) {
needsConversion = GL_FALSE;
}
if(!data) {
/* No data? Do nothing! */
return;
} else if(!needsConversion) {
/* No conversion? Just copy the data, and the pvr_format is correct */
sq_cpy(active->data, data, bytes);
return;
} else {
TextureConversionFunc convert = _determineConversion(
internalFormat,
format,
type
);
if(!convert) {
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
return;
}
GLushort* dest = active->data;
const GLubyte* source = data;
GLint stride = _determineStride(format, type);
if(stride == -1) {
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
return;
}
/* Perform the conversion */
for(GLuint i = 0; i < bytes; i += 2) {
convert(source, dest);
dest++;
source += stride;
}
}
}
void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
TRACE();
TextureObject* active = getBoundTexture();
if(target == GL_TEXTURE_2D) {
switch(pname) {
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MIN_FILTER:
switch(param) {
case GL_LINEAR:
active->filter = PVR_FILTER_BILINEAR;
break;
case GL_NEAREST:
active->filter = PVR_FILTER_NEAREST;
break;
case GL_FILTER_NONE:
active->filter = PVR_FILTER_NONE;
break;
case GL_FILTER_BILINEAR:
active->filter = PVR_FILTER_BILINEAR;
break;
default:
break;
}
break;
case GL_TEXTURE_WRAP_S:
switch(param) {
case GL_CLAMP:
active->uv_clamp |= CLAMP_U;
break;
case GL_REPEAT:
active->uv_clamp &= ~CLAMP_U;
break;
}
break;
case GL_TEXTURE_WRAP_T:
switch(param) {
case GL_CLAMP:
active->uv_clamp |= CLAMP_V;
break;
case GL_REPEAT:
active->uv_clamp &= ~CLAMP_V;
break;
}
break;
}
}
}

343
gl-api.c
View File

@ -52,188 +52,188 @@ static inline void _glKosFinishRect();
//====================================================================================================// //====================================================================================================//
//== API Initialization ==// //== API Initialization ==//
void APIENTRY glKosInit() { //void APIENTRY glKosInit() {
_glKosInitPVR(); // _glKosInitPVR();
_glKosInitTextures(); // _glKosInitTextures();
_glKosInitMatrix(); // _glKosInitMatrix();
_glKosInitLighting(); // _glKosInitLighting();
_glKosInitFrameBuffers(); // _glKosInitFrameBuffers();
} //}
//====================================================================================================// //====================================================================================================//
//== Blending / Shading functions ==// //== Blending / Shading functions ==//
void APIENTRY glShadeModel(GLenum mode) { //void APIENTRY glShadeModel(GLenum mode) {
switch(mode) { // switch(mode) {
case GL_FLAT: // case GL_FLAT:
GL_KOS_SHADE_FUNC = PVR_SHADE_FLAT; // GL_KOS_SHADE_FUNC = PVR_SHADE_FLAT;
break; // break;
case GL_SMOOTH: // case GL_SMOOTH:
GL_KOS_SHADE_FUNC = PVR_SHADE_GOURAUD; // GL_KOS_SHADE_FUNC = PVR_SHADE_GOURAUD;
break; // break;
} // }
} //}
void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { //void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) {
GL_KOS_BLEND_FUNC = 0; // GL_KOS_BLEND_FUNC = 0;
switch(sfactor) { // switch(sfactor) {
case GL_ONE: // case GL_ONE:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF) << 4;
break; // break;
case GL_ZERO: // case GL_ZERO:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF) << 4;
break; // break;
case GL_SRC_COLOR: // case GL_SRC_COLOR:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF) << 4;
break; // break;
case GL_DST_COLOR: // case GL_DST_COLOR:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF) << 4;
break; // break;
case GL_SRC_ALPHA: // case GL_SRC_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA << 4); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA << 4);
break; // break;
case GL_DST_ALPHA: // case GL_DST_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF) << 4;
break; // break;
case GL_ONE_MINUS_SRC_ALPHA: // case GL_ONE_MINUS_SRC_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF) << 4;
break; // break;
case GL_ONE_MINUS_DST_ALPHA: // case GL_ONE_MINUS_DST_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF) << 4;
break; // break;
case GL_ONE_MINUS_DST_COLOR: // case GL_ONE_MINUS_DST_COLOR:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF) << 4; // GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF) << 4;
break; // break;
} // }
switch(dfactor) { // switch(dfactor) {
case GL_ONE: // case GL_ONE:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF);
break; // break;
case GL_ZERO: // case GL_ZERO:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF);
break; // break;
case GL_SRC_COLOR: // case GL_SRC_COLOR:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF);
break; // break;
case GL_DST_COLOR: // case GL_DST_COLOR:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF);
break; // break;
case GL_SRC_ALPHA: // case GL_SRC_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF);
break; // break;
case GL_DST_ALPHA: // case GL_DST_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF);
break; // break;
case GL_ONE_MINUS_SRC_ALPHA: // case GL_ONE_MINUS_SRC_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF);
break; // break;
case GL_ONE_MINUS_DST_ALPHA: // case GL_ONE_MINUS_DST_ALPHA:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF);
break; // break;
case GL_ONE_MINUS_DST_COLOR: // case GL_ONE_MINUS_DST_COLOR:
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF); // GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF);
break; // break;
} // }
} //}
//====================================================================================================// //====================================================================================================//
//== Depth / Clear functions ==// //== Depth / Clear functions ==//
void APIENTRY glClear(GLuint mode) { //void APIENTRY glClear(GLuint mode) {
if(mode & GL_COLOR_BUFFER_BIT) // if(mode & GL_COLOR_BUFFER_BIT)
pvr_set_bg_color(GL_KOS_COLOR_CLEAR[0], GL_KOS_COLOR_CLEAR[1], GL_KOS_COLOR_CLEAR[2]); // pvr_set_bg_color(GL_KOS_COLOR_CLEAR[0], GL_KOS_COLOR_CLEAR[1], GL_KOS_COLOR_CLEAR[2]);
} //}
void APIENTRY glClearColor(float r, float g, float b, float a) { //void APIENTRY glClearColor(float r, float g, float b, float a) {
if(r > 1) r = 1; // if(r > 1) r = 1;
if(g > 1) g = 1; // if(g > 1) g = 1;
if(b > 1) b = 1; // if(b > 1) b = 1;
if(a > 1) a = 1; // if(a > 1) a = 1;
GL_KOS_COLOR_CLEAR[0] = r * a; // GL_KOS_COLOR_CLEAR[0] = r * a;
GL_KOS_COLOR_CLEAR[1] = g * a; // GL_KOS_COLOR_CLEAR[1] = g * a;
GL_KOS_COLOR_CLEAR[2] = b * a; // GL_KOS_COLOR_CLEAR[2] = b * a;
} //}
//== NoOp ==// //== NoOp ==//
void APIENTRY glClearDepthf(GLfloat depth) { //void APIENTRY glClearDepthf(GLfloat depth) {
; // ;
} //}
void APIENTRY glDepthFunc(GLenum func) { //void APIENTRY glDepthFunc(GLenum func) {
switch(func) { // switch(func) {
case GL_LESS: // case GL_LESS:
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GEQUAL; // GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GEQUAL;
break; // break;
case GL_LEQUAL: // case GL_LEQUAL:
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GREATER; // GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GREATER;
break; // break;
case GL_GREATER: // case GL_GREATER:
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LEQUAL; // GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LEQUAL;
break; // break;
case GL_GEQUAL: // case GL_GEQUAL:
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LESS; // GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LESS;
break; // break;
default: // default:
GL_KOS_DEPTH_FUNC = (func & 0x0F); // GL_KOS_DEPTH_FUNC = (func & 0x0F);
} // }
} //}
void APIENTRY glDepthMask(GLboolean flag) { //void APIENTRY glDepthMask(GLboolean flag) {
GL_KOS_DEPTH_WRITE = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE; // GL_KOS_DEPTH_WRITE = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
} //}
//====================================================================================================// //====================================================================================================//
//== Culling functions ==// //== Culling functions ==//
void APIENTRY glFrontFace(GLenum mode) { //void APIENTRY glFrontFace(GLenum mode) {
switch(mode) { // switch(mode) {
case GL_CW: // case GL_CW:
case GL_CCW: // case GL_CCW:
GL_KOS_FACE_FRONT = mode; // GL_KOS_FACE_FRONT = mode;
break; // break;
} // }
} //}
void APIENTRY glCullFace(GLenum mode) { //void APIENTRY glCullFace(GLenum mode) {
switch(mode) { // switch(mode) {
case GL_FRONT: // case GL_FRONT:
case GL_BACK: // case GL_BACK:
case GL_FRONT_AND_BACK: // case GL_FRONT_AND_BACK:
GL_KOS_CULL_FUNC = mode; // GL_KOS_CULL_FUNC = mode;
break; // break;
} // }
} //}
//====================================================================================================// //====================================================================================================//
//== Vertex Attributes Submission Functions ==// //== Vertex Attributes Submission Functions ==//
@ -461,56 +461,20 @@ void APIENTRY glEnd() {
//== Misc. functions ==// //== Misc. functions ==//
/* Clamp X to [MIN,MAX]: */ /* Clamp X to [MIN,MAX]: */
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
/* Setup the hardware user clip rectangle.
The minimum clip rectangle is a 32x32 area which is dependent on the tile //void APIENTRY glHint(GLenum target, GLenum mode) {
size use by the tile accelerator. The PVR swithes off rendering to tiles // switch(target) {
outside or inside the defined rectangle dependant upon the 'clipmode' // case GL_PERSPECTIVE_CORRECTION_HINT:
bits in the polygon header. // if(mode == GL_NICEST)
// GL_KOS_SUPERSAMPLE = 1;
// else
// GL_KOS_SUPERSAMPLE = 0;
Clip rectangles therefore must have a size that is some multiple of 32. // break;
// }
glScissor(0, 0, 32, 32) allows only the 'tile' in the lower left //}
hand corner of the screen to be modified and glScissor(0, 0, 0, 0)
disallows modification to all 'tiles' on the screen.
*/
void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
pvr_cmd_tclip_t *c = _glKosVertexBufPointer();
GLint miny, maxx, maxy;
GLsizei gl_scissor_width = CLAMP(width, 0, vid_mode->width);
GLsizei gl_scissor_height = CLAMP(height, 0, vid_mode->height);
/* force the origin to the lower left-hand corner of the screen */
miny = (vid_mode->height - gl_scissor_height) - y;
maxx = (gl_scissor_width + x);
maxy = (gl_scissor_height + miny);
/* load command structure while mapping screen coords to TA tiles */
c->flags = PVR_CMD_USERCLIP;
c->d1 = c->d2 = c->d3 = 0;
c->sx = CLAMP(x / 32, 0, vid_mode->width / 32);
c->sy = CLAMP(miny / 32, 0, vid_mode->height / 32);
c->ex = CLAMP((maxx / 32) - 1, 0, vid_mode->width / 32);
c->ey = CLAMP((maxy / 32) - 1, 0, vid_mode->height / 32);
_glKosVertexBufIncrement();
}
void APIENTRY glHint(GLenum target, GLenum mode) {
switch(target) {
case GL_PERSPECTIVE_CORRECTION_HINT:
if(mode == GL_NICEST)
GL_KOS_SUPERSAMPLE = 1;
else
GL_KOS_SUPERSAMPLE = 0;
break;
}
}
//====================================================================================================// //====================================================================================================//
//== Internal API Vertex Submission functions ==// //== Internal API Vertex Submission functions ==//
@ -944,26 +908,3 @@ GLuint _glKosVertexColor() {
return GL_KOS_VERTEX_COLOR; return GL_KOS_VERTEX_COLOR;
} }
void glAlphaFunc(GLenum func, GLclampf ref) {
;
}
void glLineWidth(GLfloat width) {
;
}
void glPolygonOffset(GLfloat factor, GLfloat units) {
;
}
void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) {
;
}
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
;
}
void glPixelStorei(GLenum pname, GLint param) {
;
}

View File

@ -171,7 +171,7 @@ uint16 __glKosAverageBiPixelARGB4444(uint16 p1, uint16 p2);
void _glKosInitFrameBuffers(); void _glKosInitFrameBuffers();
/* Error Codes */ /* Error Codes */
void _glKosThrowError(GLenum error, char *functionName); void _glKosThrowError(GLenum error, const char *functionName);
void _glKosPrintError(); void _glKosPrintError();
GLubyte _glKosHasError(); GLubyte _glKosHasError();
@ -208,6 +208,7 @@ GLubyte _glKosMaxTextureUnits();
GLubyte _glKosEnabledTextureMatrix(); GLubyte _glKosEnabledTextureMatrix();
GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject(); GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject();
GL_TEXTURE_OBJECT *_glKosBoundTexObject();
GLuint _glKosActiveTextureBoundTexID(); GLuint _glKosActiveTextureBoundTexID();
void _glKosPushMultiTexObject(GL_TEXTURE_OBJECT *tex, void _glKosPushMultiTexObject(GL_TEXTURE_OBJECT *tex,

View File

@ -90,104 +90,104 @@ static inline GLushort _calculate_byte_size(GLenum type) {
//== Open GL API Public Functions ==// //== Open GL API Public Functions ==//
/* Submit a Vertex Position Pointer */ /* Submit a Vertex Position Pointer */
GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type, //GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type,
GLsizei stride, const GLvoid *pointer) { // GLsizei stride, const GLvoid *pointer) {
if(size != 2) /* Expect 2D X,Y or 3D X,Y,Z vertex... */ // if(size != 2) /* Expect 2D X,Y or 3D X,Y,Z vertex... */
if(size != 3) // if(size != 3)
_glKosThrowError(GL_INVALID_VALUE, "glVertexPointer"); // _glKosThrowError(GL_INVALID_VALUE, "glVertexPointer");
if(type != GL_FLOAT) /* Expect Floating point vertices */ // if(type != GL_FLOAT) /* Expect Floating point vertices */
_glKosThrowError(GL_INVALID_ENUM, "glVertexPointer"); // _glKosThrowError(GL_INVALID_ENUM, "glVertexPointer");
if(stride < 0) // if(stride < 0)
_glKosThrowError(GL_INVALID_VALUE, "glVertexPointer"); // _glKosThrowError(GL_INVALID_VALUE, "glVertexPointer");
if(_glKosHasError()) { // if(_glKosHasError()) {
_glKosPrintError(); // _glKosPrintError();
return; // return;
} // }
GL_KOS_VERTEX_SIZE = size; // GL_KOS_VERTEX_SIZE = size;
GL_KOS_VERTEX_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size; // GL_KOS_VERTEX_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
GL_KOS_VERTEX_POINTER = (GLubyte *)pointer; // GL_KOS_VERTEX_POINTER = (GLubyte *)pointer;
} //}
/* Submit a Vertex Normal Pointer */ ///* Submit a Vertex Normal Pointer */
GLAPI void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) { //GLAPI void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) {
if(type != GL_FLOAT) /* Expect Floating point vertices */ // if(type != GL_FLOAT) /* Expect Floating point vertices */
_glKosThrowError(GL_INVALID_ENUM, "glNormalPointer"); // _glKosThrowError(GL_INVALID_ENUM, "glNormalPointer");
if(stride < 0) // if(stride < 0)
_glKosThrowError(GL_INVALID_VALUE, "glNormalPointer"); // _glKosThrowError(GL_INVALID_VALUE, "glNormalPointer");
if(_glKosHasError()) { // if(_glKosHasError()) {
_glKosPrintError(); // _glKosPrintError();
return; // return;
} // }
GL_KOS_NORMAL_STRIDE = (stride) ? stride : _calculate_byte_size(type) * 3; // GL_KOS_NORMAL_STRIDE = (stride) ? stride : _calculate_byte_size(type) * 3;
GL_KOS_NORMAL_POINTER = (GLubyte *)pointer; // GL_KOS_NORMAL_POINTER = (GLubyte *)pointer;
} //}
/* Submit a Texture Coordinate Pointer */ ///* Submit a Texture Coordinate Pointer */
GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type, //GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type,
GLsizei stride, const GLvoid *pointer) { // GLsizei stride, const GLvoid *pointer) {
if(size != 2) /* Expect u and v */ // if(size != 2) /* Expect u and v */
_glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer"); // _glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer");
if(type != GL_FLOAT) /* Expect Floating point vertices */ // if(type != GL_FLOAT) /* Expect Floating point vertices */
_glKosThrowError(GL_INVALID_ENUM, "glTexCoordPointer"); // _glKosThrowError(GL_INVALID_ENUM, "glTexCoordPointer");
if(stride < 0) // if(stride < 0)
_glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer"); // _glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer");
if(_glKosHasError()) { // if(_glKosHasError()) {
_glKosPrintError(); // _glKosPrintError();
return; // return;
} // }
if(GL_KOS_CLIENT_ACTIVE_TEXTURE) { // if(GL_KOS_CLIENT_ACTIVE_TEXTURE) {
GL_KOS_TEXCOORD1_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size; // GL_KOS_TEXCOORD1_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
GL_KOS_TEXCOORD1_POINTER = (GLubyte *)pointer; // GL_KOS_TEXCOORD1_POINTER = (GLubyte *)pointer;
} // }
else { // else {
GL_KOS_TEXCOORD0_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size; // GL_KOS_TEXCOORD0_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
GL_KOS_TEXCOORD0_POINTER = (GLubyte *)pointer; // GL_KOS_TEXCOORD0_POINTER = (GLubyte *)pointer;
} // }
} //}
/* Submit a Color Pointer */ ///* Submit a Color Pointer */
GLAPI void APIENTRY glColorPointer(GLint size, GLenum type, //GLAPI void APIENTRY glColorPointer(GLint size, GLenum type,
GLsizei stride, const GLvoid *pointer) { // GLsizei stride, const GLvoid *pointer) {
if((type == GL_UNSIGNED_INT) && (size == 1)) { // if((type == GL_UNSIGNED_INT) && (size == 1)) {
GL_KOS_COLOR_COMPONENTS = size; // GL_KOS_COLOR_COMPONENTS = size;
GL_KOS_COLOR_POINTER = (GLubyte *)pointer; // GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
GL_KOS_COLOR_TYPE = type; // GL_KOS_COLOR_TYPE = type;
} // }
else if((type == GL_UNSIGNED_BYTE) && (size == 4)) { // else if((type == GL_UNSIGNED_BYTE) && (size == 4)) {
GL_KOS_COLOR_COMPONENTS = size; // GL_KOS_COLOR_COMPONENTS = size;
GL_KOS_COLOR_POINTER = (GLubyte *)pointer; // GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
GL_KOS_COLOR_TYPE = type; // GL_KOS_COLOR_TYPE = type;
} // }
else if((type == GL_FLOAT) && (size == 3)) { // else if((type == GL_FLOAT) && (size == 3)) {
GL_KOS_COLOR_COMPONENTS = size; // GL_KOS_COLOR_COMPONENTS = size;
GL_KOS_COLOR_POINTER = (GLubyte *)pointer; // GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
GL_KOS_COLOR_TYPE = type; // GL_KOS_COLOR_TYPE = type;
} // }
else if((type == GL_FLOAT) && (size == 4)) { // else if((type == GL_FLOAT) && (size == 4)) {
GL_KOS_COLOR_COMPONENTS = size; // GL_KOS_COLOR_COMPONENTS = size;
GL_KOS_COLOR_POINTER = (GLubyte *)pointer; // GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
GL_KOS_COLOR_TYPE = type; // GL_KOS_COLOR_TYPE = type;
} // }
else { // else {
_glKosThrowError(GL_INVALID_ENUM, "glColorPointer"); // _glKosThrowError(GL_INVALID_ENUM, "glColorPointer");
_glKosPrintError(); // _glKosPrintError();
return; // return;
} // }
GL_KOS_COLOR_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size; // GL_KOS_COLOR_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
} //}
//========================================================================================// //========================================================================================//
//== Vertex Pointer Internal API ==// //== Vertex Pointer Internal API ==//
@ -883,162 +883,162 @@ static inline void _glKosArraysFlush(GLuint count) {
//========================================================================================// //========================================================================================//
//== OpenGL Elemental Array Submission ==// //== OpenGL Elemental Array Submission ==//
GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { //GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
/* Before we process the vertex data, ensure all parameters are valid */ // /* Before we process the vertex data, ensure all parameters are valid */
if(!_glKosArraysVerifyParameter(mode, count, type, 1)) // if(!_glKosArraysVerifyParameter(mode, count, type, 1))
return; // return;
/* Compile the PVR polygon context with the currently enabled flags */ // /* Compile the PVR polygon context with the currently enabled flags */
_glKosArraysApplyHeader(); // _glKosArraysApplyHeader();
/* Destination of Output Vertex Array */ // /* Destination of Output Vertex Array */
pvr_vertex_t *dst = _glKosArraysDest(); // pvr_vertex_t *dst = _glKosArraysDest();
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
GL_KOS_INDEX_POINTER_U8 = (GLubyte *)indices; // GL_KOS_INDEX_POINTER_U8 = (GLubyte *)indices;
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
GL_KOS_INDEX_POINTER_U16 = (GLushort *)indices; // GL_KOS_INDEX_POINTER_U16 = (GLushort *)indices;
break; // break;
} // }
/* Check if Vertex Lighting is enabled. Else, check for Color Submission */ // /* Check if Vertex Lighting is enabled. Else, check for Color Submission */
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting()) // if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting())
_glKosArraysApplyLighting(dst, count); // _glKosArraysApplyLighting(dst, count);
else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) { // else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) {
switch(GL_KOS_COLOR_TYPE) { // switch(GL_KOS_COLOR_TYPE) {
case GL_FLOAT: // case GL_FLOAT:
switch(GL_KOS_COLOR_COMPONENTS) { // switch(GL_KOS_COLOR_COMPONENTS) {
case 3: // case 3:
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosElementColor3fU8(dst, count); // _glKosElementColor3fU8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosElementColor3fU16(dst, count); // _glKosElementColor3fU16(dst, count);
break; // break;
} // }
break; // break;
case 4: // case 4:
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosElementColor4fU8(dst, count); // _glKosElementColor4fU8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosElementColor4fU16(dst, count); // _glKosElementColor4fU16(dst, count);
break; // break;
} // }
break; // break;
} // }
break; // break;
case GL_UNSIGNED_INT: // case GL_UNSIGNED_INT:
if(GL_KOS_COLOR_COMPONENTS == 1) // if(GL_KOS_COLOR_COMPONENTS == 1)
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosElementColor1uiU8(dst, count); // _glKosElementColor1uiU8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosElementColor1uiU16(dst, count); // _glKosElementColor1uiU16(dst, count);
break; // break;
} // }
break; // break;
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
if(GL_KOS_COLOR_COMPONENTS == 4) // if(GL_KOS_COLOR_COMPONENTS == 4)
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosElementColor4ubU8(dst, count); // _glKosElementColor4ubU8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosElementColor4ubU16(dst, count); // _glKosElementColor4ubU16(dst, count);
break; // break;
} // }
break; // break;
} // }
} // }
else // else
_glKosArrayColor0(dst, count); /* No colors bound */ // _glKosArrayColor0(dst, count); /* No colors bound */
/* Check if Texture Coordinates are enabled */ // /* Check if Texture Coordinates are enabled */
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0)) // if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0))
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosElementTexCoord2fU8(dst, count); // _glKosElementTexCoord2fU8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosElementTexCoord2fU16(dst, count); // _glKosElementTexCoord2fU16(dst, count);
break; // break;
} // }
/* Check if Multi Texture Coordinates are enabled */ // /* Check if Multi Texture Coordinates are enabled */
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0)) // if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0))
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosElementMultiTexCoord2fU8(count); // _glKosElementMultiTexCoord2fU8(count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosElementMultiTexCoord2fU16(count); // _glKosElementMultiTexCoord2fU16(count);
break; // break;
} // }
_glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ // _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
if(!(_glKosEnabledNearZClip())) {/* Transform the element vertices */ // if(!(_glKosEnabledNearZClip())) {/* Transform the element vertices */
/* Transform vertices with perspective divide */ // /* Transform vertices with perspective divide */
_glKosArraysTransformElements(count); // _glKosArraysTransformElements(count);
/* Unpack the indexed positions into primitives for rasterization */ // /* Unpack the indexed positions into primitives for rasterization */
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosArraysUnpackElementsS8(dst, count); // _glKosArraysUnpackElementsS8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosArraysUnpackElementsS16(dst, count); // _glKosArraysUnpackElementsS16(dst, count);
break; // break;
} // }
/* Set the vertex flags for use with the PVR */ // /* Set the vertex flags for use with the PVR */
_glKosArraysApplyVertexFlags(mode, dst, count); // _glKosArraysApplyVertexFlags(mode, dst, count);
} // }
else { // else {
/* Transform vertices with no perspective divide, store w component */ // /* Transform vertices with no perspective divide, store w component */
_glKosArraysTransformClipElements(count); // _glKosArraysTransformClipElements(count);
/* Unpack the indexed positions into primitives for rasterization */ // /* Unpack the indexed positions into primitives for rasterization */
switch(type) { // switch(type) {
case GL_UNSIGNED_BYTE: // case GL_UNSIGNED_BYTE:
_glKosArraysUnpackClipElementsS8(dst, count); // _glKosArraysUnpackClipElementsS8(dst, count);
break; // break;
case GL_UNSIGNED_SHORT: // case GL_UNSIGNED_SHORT:
_glKosArraysUnpackClipElementsS16(dst, count); // _glKosArraysUnpackClipElementsS16(dst, count);
break; // break;
} // }
count = _glKosArraysApplyClipping(GL_KOS_ARRAY_BUFUV, 2, mode, count); // count = _glKosArraysApplyClipping(GL_KOS_ARRAY_BUFUV, 2, mode, count);
} // }
_glKosArraysApplyMultiTexture(mode, count); // _glKosArraysApplyMultiTexture(mode, count);
_glKosArraysFlush(count); // _glKosArraysFlush(count);
} //}
//========================================================================================// //========================================================================================//
//== Array Attribute Functions ==// //== Array Attribute Functions ==//
@ -1197,151 +1197,97 @@ static void _glKosDrawArrays2D(GLenum mode, GLint first, GLsizei count) {
_glKosArraysFlush(count); _glKosArraysFlush(count);
} }
GLAPI void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) {
/* Before we process the vertex data, ensure all parameters are valid */
if(!_glKosArraysVerifyParameter(mode, count, first, 0))
return;
GL_KOS_VERTEX_POINTER += (first * GL_KOS_VERTEX_STRIDE); /* Add Pointer Offset */ //GLAPI void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) {
GL_KOS_TEXCOORD0_POINTER += (first * GL_KOS_TEXCOORD0_STRIDE); // /* Before we process the vertex data, ensure all parameters are valid */
GL_KOS_TEXCOORD1_POINTER += (first * GL_KOS_TEXCOORD1_STRIDE); // if(!_glKosArraysVerifyParameter(mode, count, first, 0))
GL_KOS_COLOR_POINTER += (first * GL_KOS_COLOR_STRIDE); // return;
GL_KOS_NORMAL_POINTER += (first * GL_KOS_NORMAL_STRIDE);
/* Compile the PVR polygon context with the currently enabled flags */ // GL_KOS_VERTEX_POINTER += (first * GL_KOS_VERTEX_STRIDE); /* Add Pointer Offset */
_glKosArraysApplyHeader(); // GL_KOS_TEXCOORD0_POINTER += (first * GL_KOS_TEXCOORD0_STRIDE);
// GL_KOS_TEXCOORD1_POINTER += (first * GL_KOS_TEXCOORD1_STRIDE);
// GL_KOS_COLOR_POINTER += (first * GL_KOS_COLOR_STRIDE);
// GL_KOS_NORMAL_POINTER += (first * GL_KOS_NORMAL_STRIDE);
if(GL_KOS_VERTEX_SIZE == 2) // /* Compile the PVR polygon context with the currently enabled flags */
return _glKosDrawArrays2D(mode, first, count); // _glKosArraysApplyHeader();
/* Destination of Output Vertex Array */ // if(GL_KOS_VERTEX_SIZE == 2)
pvr_vertex_t *dst = _glKosArraysDest(); // return _glKosDrawArrays2D(mode, first, count);
/* Check if Vertex Lighting is enabled. Else, check for Color Submission */ // /* Destination of Output Vertex Array */
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting()) // pvr_vertex_t *dst = _glKosArraysDest();
_glKosArraysApplyLighting(dst, count);
else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) { // /* Check if Vertex Lighting is enabled. Else, check for Color Submission */
switch(GL_KOS_COLOR_TYPE) { // if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting())
case GL_FLOAT: // _glKosArraysApplyLighting(dst, count);
switch(GL_KOS_COLOR_COMPONENTS) {
case 3:
_glKosArrayColor3f(dst, count);
break;
case 4: // else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) {
_glKosArrayColor4f(dst, count); // switch(GL_KOS_COLOR_TYPE) {
break; // case GL_FLOAT:
} // switch(GL_KOS_COLOR_COMPONENTS) {
// case 3:
// _glKosArrayColor3f(dst, count);
// break;
break; // case 4:
// _glKosArrayColor4f(dst, count);
// break;
// }
case GL_UNSIGNED_INT: // break;
if(GL_KOS_COLOR_COMPONENTS == 1)
_glKosArrayColor1ui(dst, count);
break; // case GL_UNSIGNED_INT:
// if(GL_KOS_COLOR_COMPONENTS == 1)
// _glKosArrayColor1ui(dst, count);
case GL_UNSIGNED_BYTE: // break;
if(GL_KOS_COLOR_COMPONENTS == 4)
_glKosArrayColor4ub(dst, count);
break; // case GL_UNSIGNED_BYTE:
} // if(GL_KOS_COLOR_COMPONENTS == 4)
} // _glKosArrayColor4ub(dst, count);
else
_glKosArrayColor0(dst, count); /* No colors bound, color white */
/* Check if Texture Coordinates are enabled */ // break;
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0)) // }
_glKosArrayTexCoord2f(dst, count); // }
// else
// _glKosArrayColor0(dst, count); /* No colors bound, color white */
/* Check if Multi Texture Coordinates are enabled */ // /* Check if Texture Coordinates are enabled */
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0)) // if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0))
_glKosArrayMultiTexCoord2f(count); // _glKosArrayTexCoord2f(dst, count);
_glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ // /* Check if Multi Texture Coordinates are enabled */
// if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0))
// _glKosArrayMultiTexCoord2f(count);
if(!_glKosEnabledNearZClip()) { /* No NearZ Clipping Enabled */ // _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
/* Transform Vertex Positions */
_glKosArraysTransform(count);
/* Set the vertex flags for use with the PVR */ // if(!_glKosEnabledNearZClip()) { /* No NearZ Clipping Enabled */
_glKosArraysApplyVertexFlags(mode, dst, count); // /* Transform Vertex Positions */
} // _glKosArraysTransform(count);
else { /* NearZ Clipping is Enabled */
/* Transform vertices with no perspective divide, store w component */
_glKosArraysTransformClip(count);
/* Finally, clip the input vertex data into the output vertex buffer */ // /* Set the vertex flags for use with the PVR */
count = _glKosArraysApplyClipping( // _glKosArraysApplyVertexFlags(mode, dst, count);
(GLfloat *) GL_KOS_TEXCOORD1_POINTER, // }
GL_KOS_TEXCOORD1_STRIDE / 4, // else { /* NearZ Clipping is Enabled */
mode, count // /* Transform vertices with no perspective divide, store w component */
); // _glKosArraysTransformClip(count);
/* FIXME: The above function should really accept a GLbyte* and the stride directly
but that affects a lot of other code, so dividing the stride by float size
hopefully results in the same thing for now */
}
_glKosArraysApplyMultiTexture(mode, count); // /* Finally, clip the input vertex data into the output vertex buffer */
// count = _glKosArraysApplyClipping(
// (GLfloat *) GL_KOS_TEXCOORD1_POINTER,
// GL_KOS_TEXCOORD1_STRIDE / 4,
// mode, count
// );
// /* FIXME: The above function should really accept a GLbyte* and the stride directly
// but that affects a lot of other code, so dividing the stride by float size
// hopefully results in the same thing for now */
// }
_glKosArraysFlush(count); // _glKosArraysApplyMultiTexture(mode, count);
}
void APIENTRY glClientActiveTextureARB(GLenum texture) { // _glKosArraysFlush(count);
if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + _glKosMaxTextureUnits()) //}
_glKosThrowError(GL_INVALID_ENUM, "glClientActiveTextureARB");
if(_glKosHasError()) {
_glKosPrintError();
return;
}
GL_KOS_CLIENT_ACTIVE_TEXTURE = texture & 0xF;
}
void APIENTRY glEnableClientState(GLenum cap) {
switch(cap) {
case GL_VERTEX_ARRAY:
GL_KOS_VERTEX_PTR_MODE |= GL_KOS_USE_ARRAY;
break;
case GL_COLOR_ARRAY:
GL_KOS_VERTEX_PTR_MODE |= GL_KOS_USE_COLOR;
break;
case GL_NORMAL_ARRAY:
GL_KOS_VERTEX_PTR_MODE |= GL_KOS_USE_NORMAL;
break;
case GL_TEXTURE_COORD_ARRAY:
(GL_KOS_CLIENT_ACTIVE_TEXTURE) ?
(GL_KOS_VERTEX_PTR_MODE |= GL_KOS_USE_TEXTURE1):
(GL_KOS_VERTEX_PTR_MODE |= GL_KOS_USE_TEXTURE0);
break;
default:
_glKosThrowError(GL_INVALID_ENUM, "glEnableClientState");
}
}
void APIENTRY glDisableClientState(GLenum cap) {
switch(cap) {
case GL_VERTEX_ARRAY:
GL_KOS_VERTEX_PTR_MODE &= ~GL_KOS_USE_ARRAY;
break;
case GL_COLOR_ARRAY:
GL_KOS_VERTEX_PTR_MODE &= ~GL_KOS_USE_COLOR;
break;
case GL_NORMAL_ARRAY:
GL_KOS_VERTEX_PTR_MODE &= ~GL_KOS_USE_NORMAL;
break;
case GL_TEXTURE_COORD_ARRAY:
(GL_KOS_CLIENT_ACTIVE_TEXTURE) ?
(GL_KOS_VERTEX_PTR_MODE &= ~GL_KOS_USE_TEXTURE1):
(GL_KOS_VERTEX_PTR_MODE &= ~GL_KOS_USE_TEXTURE0);
break;
default:
_glKosThrowError(GL_INVALID_ENUM, "glDisableClientState");
}
}

132
gl-cap.c
View File

@ -28,91 +28,91 @@ static GLbitfield GL_KOS_ENABLE_CAP = 0;
//===============================================================================// //===============================================================================//
//== External API Functions ==// //== External API Functions ==//
void APIENTRY glEnable(GLenum cap) { //void APIENTRY glEnable(GLenum cap) {
if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosEnableLight(cap); // if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosEnableLight(cap);
switch(cap) { // switch(cap) {
case GL_TEXTURE_2D: // case GL_TEXTURE_2D:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE2D; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE2D;
break; // break;
case GL_BLEND: // case GL_BLEND:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_BLENDING; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_BLENDING;
_glKosVertexBufSwitchTR(); // _glKosVertexBufSwitchTR();
break; // break;
case GL_DEPTH_TEST: // case GL_DEPTH_TEST:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_DEPTH_TEST; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_DEPTH_TEST;
break; // break;
case GL_LIGHTING: // case GL_LIGHTING:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_LIGHTING; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_LIGHTING;
break; // break;
case GL_KOS_NEARZ_CLIPPING: // case GL_KOS_NEARZ_CLIPPING:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_ZCLIPPING; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_ZCLIPPING;
break; // break;
case GL_SCISSOR_TEST: // case GL_SCISSOR_TEST:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_SCISSOR_TEST; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_SCISSOR_TEST;
break; // break;
case GL_FOG: // case GL_FOG:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_FOG; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_FOG;
break; // break;
case GL_CULL_FACE: // case GL_CULL_FACE:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_CULLING; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_CULLING;
break; // break;
case GL_KOS_TEXTURE_MATRIX: // case GL_KOS_TEXTURE_MATRIX:
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE_MAT; // GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE_MAT;
break; // break;
} // }
} //}
void APIENTRY glDisable(GLenum cap) { //void APIENTRY glDisable(GLenum cap) {
if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosDisableLight(cap); // if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosDisableLight(cap);
switch(cap) { // switch(cap) {
case GL_TEXTURE_2D: // case GL_TEXTURE_2D:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE2D; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE2D;
break; // break;
case GL_BLEND: // case GL_BLEND:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_BLENDING; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_BLENDING;
_glKosVertexBufSwitchOP(); // _glKosVertexBufSwitchOP();
break; // break;
case GL_DEPTH_TEST: // case GL_DEPTH_TEST:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_DEPTH_TEST; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_DEPTH_TEST;
break; // break;
case GL_LIGHTING: // case GL_LIGHTING:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_LIGHTING; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_LIGHTING;
break; // break;
case GL_KOS_NEARZ_CLIPPING: // case GL_KOS_NEARZ_CLIPPING:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_ZCLIPPING; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_ZCLIPPING;
break; // break;
case GL_SCISSOR_TEST: // case GL_SCISSOR_TEST:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_SCISSOR_TEST; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_SCISSOR_TEST;
break; // break;
case GL_FOG: // case GL_FOG:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_FOG; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_FOG;
break; // break;
case GL_CULL_FACE: // case GL_CULL_FACE:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_CULLING; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_CULLING;
break; // break;
case GL_KOS_TEXTURE_MATRIX: // case GL_KOS_TEXTURE_MATRIX:
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE_MAT; // GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE_MAT;
break; // break;
} // }
} //}
GLboolean APIENTRY glIsEnabled(GLenum cap) { GLboolean APIENTRY glIsEnabled(GLenum cap) {
if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosIsLightEnabled(cap & 0xFF); if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosIsLightEnabled(cap & 0xFF);

View File

@ -25,7 +25,7 @@ static char error_function[64] = { '\0' };
Nothing in the spec requires recording multiple error flags, although it is Nothing in the spec requires recording multiple error flags, although it is
allowed by the spec. We take the easy way out for now. */ allowed by the spec. We take the easy way out for now. */
void _glKosThrowError(GLenum error, char *function) { void _glKosThrowError(GLenum error, const char *function) {
if(last_error == GL_NO_ERROR) { if(last_error == GL_NO_ERROR) {
last_error = error; last_error = error;
sprintf(error_function, "%s\n", function); sprintf(error_function, "%s\n", function);

View File

@ -14,15 +14,6 @@ typedef struct {
unsigned int cmd[8]; unsigned int cmd[8];
} pvr_cmd_t; /* Generic 32byte command for the pvr */ } pvr_cmd_t; /* Generic 32byte command for the pvr */
typedef struct {
unsigned int flags; /* Constant PVR_CMD_USERCLIP */
unsigned int d1, d2, d3; /* Ignored for this type */
unsigned int sx, /* Start x */
sy, /* Start y */
ex, /* End x */
ey; /* End y */
} pvr_cmd_tclip_t; /* Tile Clip command for the pvr */
#define GL_PVR_VERTEX_BUF_SIZE 2560 * 256 /* PVR Vertex buffer size */ #define GL_PVR_VERTEX_BUF_SIZE 2560 * 256 /* PVR Vertex buffer size */
#define GL_KOS_MAX_VERTS 1024*64 /* SH4 Vertex Count */ #define GL_KOS_MAX_VERTS 1024*64 /* SH4 Vertex Count */

View File

@ -21,8 +21,6 @@
//== Internal KOS Open GL Texture Unit Structures / Global Variables ==// //== Internal KOS Open GL Texture Unit Structures / Global Variables ==//
#define GL_KOS_MAX_TEXTURE_UNITS 2 #define GL_KOS_MAX_TEXTURE_UNITS 2
#define GL_KOS_CLAMP_U (1<<1)
#define GL_KOS_CLAMP_V (1<<0)
static GL_TEXTURE_OBJECT *GL_KOS_TEXTURE_UNIT[GL_KOS_MAX_TEXTURE_UNITS] = { NULL, NULL }; static GL_TEXTURE_OBJECT *GL_KOS_TEXTURE_UNIT[GL_KOS_MAX_TEXTURE_UNITS] = { NULL, NULL };
@ -32,20 +30,6 @@ static GLubyte GL_KOS_ACTIVE_TEXTURE = GL_TEXTURE0_ARB & 0xF;
//========================================================================================// //========================================================================================//
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type);
GLubyte _glKosInitTextures() {
named_array_init(&TEXTURE_OBJECTS, sizeof(GL_TEXTURE_OBJECT), 256);
return 1;
}
static void _glKosBindTexture(GLuint index) {
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index);
}
static void _glKosUnbindTexture() {
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = NULL;
}
GLuint _glKosTextureWidth(GLuint index) { GLuint _glKosTextureWidth(GLuint index) {
GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index); GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index);
@ -67,6 +51,10 @@ void _glKosCompileHdrTx() {
_glKosCompileHdrT(GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF]) : _glKosCompileHdr(); _glKosCompileHdrT(GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF]) : _glKosCompileHdr();
} }
GL_TEXTURE_OBJECT *_glKosBoundTexObject() {
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF];
}
GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject() { GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject() {
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE1_ARB & 0xF]; return GL_KOS_TEXTURE_UNIT[GL_TEXTURE1_ARB & 0xF];
} }
@ -92,528 +80,6 @@ GLubyte _glKosMaxTextureUnits() {
//========================================================================================// //========================================================================================//
//== Public KOS Open GL API Texture Unit Functionality ==// //== Public KOS Open GL API Texture Unit Functionality ==//
void APIENTRY glGenTextures(GLsizei n, GLuint *textures) {
while(n--) {
GLuint id = 0;
GL_TEXTURE_OBJECT* txr = (GL_TEXTURE_OBJECT*) named_array_alloc(&TEXTURE_OBJECTS, &id);
txr->index = id;
txr->width = txr->height = 0;
txr->mip_map = 0;
txr->uv_clamp = 0;
txr->env = PVR_TXRENV_MODULATEALPHA;
txr->filter = PVR_FILTER_NONE;
txr->data = NULL;
*textures = id;
textures++;
}
}
void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) {
while(n--) {
GL_TEXTURE_OBJECT* txr = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, *textures);
if(txr == GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]) {
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = NULL;
}
if(txr->data) {
pvr_mem_free(txr->data);
}
named_array_release(&TEXTURE_OBJECTS, *textures++);
}
}
void APIENTRY glBindTexture(GLenum target, GLuint texture) {
if(target != GL_TEXTURE_2D) {
_glKosThrowError(GL_INVALID_ENUM, "glBindTexture");
_glKosPrintError();
return;
}
texture ? _glKosBindTexture(texture) : _glKosUnbindTexture();
}
void APIENTRY glCompressedTexImage2D(GLenum target,
GLint level,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLsizei imageSize,
const GLvoid *data) {
if(target != GL_TEXTURE_2D)
_glKosThrowError(GL_INVALID_ENUM, "glCompressedTexImage2D");
if(level < 0)
_glKosThrowError(GL_INVALID_VALUE, "glCompressedTexImage2D");
if(border)
_glKosThrowError(GL_INVALID_VALUE, "glCompressedTexImage2D");
if(internalformat != GL_UNSIGNED_SHORT_5_6_5_VQ_KOS)
if(internalformat != GL_UNSIGNED_SHORT_5_6_5_VQ_TWID_KOS)
if(internalformat != GL_UNSIGNED_SHORT_4_4_4_4_VQ_KOS)
if(internalformat != GL_UNSIGNED_SHORT_4_4_4_4_REV_VQ_TWID_KOS)
if(internalformat != GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_KOS)
if(internalformat != GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_TWID_KOS)
_glKosThrowError(GL_INVALID_OPERATION, "glCompressedTexImage2D");
if(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] == NULL)
_glKosThrowError(GL_INVALID_OPERATION, "glCompressedTexImage2D");
if(_glKosHasError()) {
_glKosPrintError();
return;
}
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->width = width;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->height = height;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->mip_map = level;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->color = _determinePVRFormat(
internalformat,
internalformat /* Doesn't matter (see determinePVRFormat) */
);
/* Odds are slim new data is same size as old, so free always */
if(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data)
pvr_mem_free(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data);
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data = pvr_mem_malloc(imageSize);
if(data)
sq_cpy(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data, data, imageSize);
}
static GLint _cleanInternalFormat(GLint internalFormat) {
switch (internalFormat) {
case GL_ALPHA:
/* case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:*/
return GL_ALPHA;
case 1:
case GL_LUMINANCE:
/* case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:*/
return GL_LUMINANCE;
case 2:
case GL_LUMINANCE_ALPHA:
/* case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16: */
return GL_LUMINANCE_ALPHA;
/* case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
return GL_INTENSITY; */
case 3:
return GL_RGB;
case GL_RGB:
/* case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16: */
return GL_RGB;
case 4:
return GL_RGBA;
case GL_RGBA:
/* case GL_RGBA2:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16: */
return GL_RGBA;
/* Support ARB_texture_rg */
case GL_RED:
/* case GL_R8:
case GL_R16:
case GL_RED:
case GL_COMPRESSED_RED: */
return GL_RED;
/* case GL_RG:
case GL_RG8:
case GL_RG16:
case GL_COMPRESSED_RG:
return GL_RG;*/
default:
return -1;
}
}
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
/* Given a cleaned internalFormat, return the Dreamcast format
* that can hold it
*/
switch(internalFormat) {
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
/* OK so if we have something that requires alpha, we return 4444 unless
* the type was already 1555 (1-bit alpha) in which case we return that
*/
return (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) ?
PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED :
PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_NONTWIDDLED;
case GL_RED:
case GL_RGB:
/* No alpha? Return RGB565 which is the best we can do without using palettes */
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED;
/* Compressed and twiddled versions */
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED;
case GL_UNSIGNED_SHORT_5_6_5_VQ_KOS:
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_5_6_5_VQ_TWID_KOS:
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS:
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_VQ_TWID_KOS:
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_4_4_4_4_VQ_KOS:
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_TWID_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
default:
return 0;
}
}
typedef void (*TextureConversionFunc)(const GLubyte*, GLushort*);
static void _rgba8888_to_argb4444(const GLubyte* source, GLushort* dest) {
*dest = (source[3] & 0xF0) << 8 | (source[0] & 0xF0) << 4 | (source[1] & 0xF0) | (source[2] & 0xF0) >> 4;
}
static void _rgb888_to_rgb565(const GLubyte* source, GLushort* dest) {
*dest = ((source[0] & 0b11111000) << 8) | ((source[1] & 0b11111100) << 3) | (source[2] >> 3);
}
static void _rgba8888_to_a000(const GLubyte* source, GLushort* dest) {
*dest = ((source[3] & 0b11111000) << 8);
}
static void _r8_to_rgb565(const GLubyte* source, GLushort* dest) {
*dest = (source[0] & 0b11111000) << 8;
}
static void _rgba4444_to_argb4444(const GLubyte* source, GLushort* dest) {
GLushort* src = (GLushort*) source;
*dest = ((*src & 0x000F) << 12) | *src >> 4;
}
static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum format, GLenum type) {
switch(internalFormat) {
case GL_ALPHA: {
if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
return _rgba8888_to_a000;
} else if(type == GL_BYTE && format == GL_RGBA) {
return _rgba8888_to_a000;
}
} break;
case GL_RGB: {
if(type == GL_UNSIGNED_BYTE && format == GL_RGB) {
return _rgb888_to_rgb565;
} else if(type == GL_BYTE && format == GL_RGB) {
return _rgb888_to_rgb565;
} else if(type == GL_UNSIGNED_BYTE && format == GL_RED) {
return _r8_to_rgb565;
}
} break;
case GL_RGBA: {
if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
return _rgba8888_to_argb4444;
} else if (type == GL_BYTE && format == GL_RGBA) {
return _rgba8888_to_argb4444;
} else if(type == GL_UNSIGNED_SHORT_4_4_4_4 && format == GL_RGBA) {
return _rgba4444_to_argb4444;
}
} break;
default:
break;
}
return 0;
}
static GLint _determineStride(GLenum format, GLenum type) {
switch(type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
return (format == GL_RED) ? 1 : (format == GL_RGB) ? 3 : 4;
case GL_UNSIGNED_SHORT:
return (format == GL_RED) ? 2 : (format == GL_RGB) ? 6 : 8;
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
return 2;
}
return -1;
}
static GLboolean _isSupportedFormat(GLenum format) {
switch(format) {
case GL_RED:
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
return GL_TRUE;
default:
return GL_FALSE;
}
}
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *data) {
if(target != GL_TEXTURE_2D) {
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
}
if(!_isSupportedFormat(format)) {
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
}
/* Abuse determineStride to see if type is valid */
if(_determineStride(GL_RGBA, type) == -1) {
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
}
internalFormat = _cleanInternalFormat(internalFormat);
if(internalFormat == -1) {
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
GLint w = width;
if(w == 0 || (w & -w) != w) {
/* Width is not a power of two. Must be!*/
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
GLint h = height;
if(h == 0 || (h & -h) != h) {
/* height is not a power of two. Must be!*/
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
if(level < 0) {
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
if(border) {
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
}
if(!GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]) {
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
}
if(_glKosHasError()) {
_glKosPrintError();
return;
}
/* Calculate the format that we need to convert the data to */
GLuint pvr_format = _determinePVRFormat(internalFormat, type);
if(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data) {
/* pre-existing texture - check if changed */
if(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->width != width ||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->height != height ||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->mip_map != level ||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->color != pvr_format) {
/* changed - free old texture memory */
pvr_mem_free(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data);
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data = NULL;
}
}
GLuint bytes = level ? glKosMipMapTexSize(width, height) : (width * height * 2);
if(!GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data) {
/* need texture memory */
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->width = width;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->height = height;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->mip_map = level;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->color = pvr_format;
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data = pvr_mem_malloc(bytes);
}
/* Let's assume we need to convert */
GLboolean needsConversion = GL_TRUE;
/*
* 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_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) {
needsConversion = GL_FALSE;
} else if(format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 && internalFormat == GL_RGB) {
needsConversion = GL_FALSE;
} else if(format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5_TWID_KOS && internalFormat == GL_RGB) {
needsConversion = GL_FALSE;
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS && internalFormat == GL_RGBA) {
needsConversion = GL_FALSE;
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS && internalFormat == GL_RGBA) {
needsConversion = GL_FALSE;
}
if(!data) {
/* No data? Do nothing! */
return;
} else if(!needsConversion) {
/* No conversion? Just copy the data, and the pvr_format is correct */
sq_cpy(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data, data, bytes);
return;
} else {
TextureConversionFunc convert = _determineConversion(
internalFormat,
format,
type
);
if(!convert) {
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
return;
}
GLushort* dest = GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data;
const GLubyte* source = data;
GLint stride = _determineStride(format, type);
if(stride == -1) {
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
return;
}
/* Perform the conversion */
for(GLuint i = 0; i < bytes; i += 2) {
convert(source, dest);
dest++;
source += stride;
}
}
}
void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
if(target == GL_TEXTURE_2D) {
switch(pname) {
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MIN_FILTER:
switch(param) {
case GL_LINEAR:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_BILINEAR;
break;
case GL_NEAREST:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_NEAREST;
break;
case GL_FILTER_NONE:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_NONE;
break;
case GL_FILTER_BILINEAR:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_BILINEAR;
break;
default:
break;
}
break;
case GL_TEXTURE_WRAP_S:
switch(param) {
case GL_CLAMP:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp |= GL_KOS_CLAMP_U;
break;
case GL_REPEAT:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp &= ~GL_KOS_CLAMP_U;
break;
}
break;
case GL_TEXTURE_WRAP_T:
switch(param) {
case GL_CLAMP:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp |= GL_KOS_CLAMP_V;
break;
case GL_REPEAT:
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp &= ~GL_KOS_CLAMP_V;
break;
}
break;
}
}
}
void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) {
if(target != GL_TEXTURE_ENV)
_glKosThrowError(GL_INVALID_ENUM, "glTexEnvi");
if(pname != GL_TEXTURE_ENV_MODE)
_glKosThrowError(GL_INVALID_ENUM, "glTexEnvi");
if(_glKosHasError()) {
_glKosPrintError();
return;
}
if(param >= PVR_TXRENV_REPLACE && param <= PVR_TXRENV_MODULATEALPHA)
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->env = param;
}
void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) {
glTexEnvi(target, pname, param);
}
void APIENTRY glActiveTextureARB(GLenum texture) {
if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + GL_KOS_MAX_TEXTURE_UNITS)
_glKosThrowError(GL_INVALID_ENUM, "glActiveTextureARB");
if(_glKosHasError()) {
_glKosPrintError();
return;
}
GL_KOS_ACTIVE_TEXTURE = texture & 0xF;
}

View File

@ -473,8 +473,8 @@ GLAPI void APIENTRY glClear(GLuint mode);
GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
/* Depth Testing */ /* Depth Testing */
GLAPI void APIENTRY glClearDepth(GLfloat depth);
GLAPI void APIENTRY glClearDepthf(GLfloat depth); GLAPI void APIENTRY glClearDepthf(GLfloat depth);
#define glClearDepth glClearDepthf
GLAPI void APIENTRY glDepthMask(GLboolean flag); GLAPI void APIENTRY glDepthMask(GLboolean flag);
GLAPI void APIENTRY glDepthFunc(GLenum func); GLAPI void APIENTRY glDepthFunc(GLenum func);

View File

@ -1,6 +1,12 @@
#ifndef GLKOS_H #ifndef GLKOS_H
#define GLKOS_H #define GLKOS_H
void glKosSwapBuffers(); #include "gl.h"
__BEGIN_DECLS
GLAPI void APIENTRY glKosSwapBuffers();
__END_DECLS
#endif // GLKOS_H #endif // GLKOS_H