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:
parent
1356ae352c
commit
62e001c288
|
@ -6,7 +6,7 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define ALIGNED_VECTOR_INITIAL_CAPACITY 256
|
||||
#define ALIGNED_VECTOR_INITIAL_CAPACITY 256u
|
||||
|
||||
typedef struct {
|
||||
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];
|
||||
}
|
||||
|
||||
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) {
|
||||
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_shrink_to_fit(vector);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include "../include/gl.h"
|
||||
#include "private.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../include/glext.h"
|
||||
#include "private.h"
|
||||
#include "../gl-api.h"
|
||||
|
||||
typedef struct {
|
||||
void* ptr;
|
||||
const void* ptr;
|
||||
GLenum type;
|
||||
GLsizei stride;
|
||||
GLint size;
|
||||
|
@ -26,6 +29,8 @@ static GLuint ENABLED_VERTEX_ATTRIBUTES = 0;
|
|||
static GLubyte ACTIVE_CLIENT_TEXTURE = 0;
|
||||
|
||||
void initAttributePointers() {
|
||||
TRACE();
|
||||
|
||||
VERTEX_POINTER.ptr = NULL;
|
||||
VERTEX_POINTER.stride = 0;
|
||||
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 __y __asm__("fr13");
|
||||
register float __z __asm__("fr14");
|
||||
|
@ -56,9 +61,32 @@ static void transformVertex(const GLfloat* src) {
|
|||
|
||||
mat_trans_fv12()
|
||||
|
||||
src[0] = __x;
|
||||
src[1] = __y;
|
||||
src[2] = __z;
|
||||
*x = __x;
|
||||
*y = __y;
|
||||
*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) {
|
||||
|
@ -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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_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;
|
||||
vertex.u = vertex.v = 0.0f;
|
||||
vertex.argb = 0xFFFFFFFF;
|
||||
// Make room for the element + the header
|
||||
PVRCommand* dst = (PVRCommand*) aligned_vector_extend(&activePolyList()->vector, count + 1);
|
||||
|
||||
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* vptr = VERTEX_POINTER.ptr;
|
||||
const GLubyte* vptr = VERTEX_POINTER.ptr;
|
||||
|
||||
GLubyte cstride = (DIFFUSE_POINTER.stride) ? DIFFUSE_POINTER.stride : DIFFUSE_POINTER.size * byte_size(DIFFUSE_POINTER.type);
|
||||
const GLubyte* cptr = DIFFUSE_POINTER.ptr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for(GLuint i = 0; i < count; ++i) {
|
||||
GLshort idx = i;
|
||||
if(indices) {
|
||||
_parseIndex(&idx, indices[byte_size(type) * i], type);
|
||||
_parseIndex(&idx, &indices_as_bytes[byte_size(type) * i], type);
|
||||
}
|
||||
|
||||
_parseFloats(vparts, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type);
|
||||
_parseFloats(&vertex->x, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type);
|
||||
transformVertex(&vertex->x, &vertex->x, &vertex->y, &vertex->z);
|
||||
|
||||
vertex.x = vparts[0];
|
||||
vertex.y = vparts[1];
|
||||
vertex.z = vparts[2];
|
||||
if(ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) {
|
||||
_parseColour(&vertex->argb, cptr + (idx * cstride), DIFFUSE_POINTER.size, DIFFUSE_POINTER.type);
|
||||
}
|
||||
|
||||
transformVertex(&vertex.x);
|
||||
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) {
|
||||
submitVertices(mode, count, type, indices);
|
||||
void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
|
||||
TRACE();
|
||||
|
||||
submitVertices(mode, 0, count, type, indices);
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glDrawArraysExp(GLenum mode, GLint first, GLsizei count) {
|
||||
submitVertices(mode, count, type, NULL);
|
||||
void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
TRACE();
|
||||
|
||||
submitVertices(mode, first, count, GL_UNSIGNED_SHORT, NULL);
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glEnableClientStateExp(GLenum cap) {
|
||||
void APIENTRY glEnableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
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) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES &= ~VERTEX_ENABLED_FLAG;
|
||||
|
@ -177,34 +255,53 @@ GLAPI void APIENTRY glDisableClientStateExp(GLenum cap) {
|
|||
}
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glClientActiveTextureExp(GLenum texture) {
|
||||
ACTIVE_CLIENT_TEXTURE = (texture == GL_TEXTURE1) ? 1 : 0;
|
||||
void APIENTRY glClientActiveTextureARB(GLenum texture) {
|
||||
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) {
|
||||
AttribPointer* texpointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER;
|
||||
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
texpointer->ptr = pointer;
|
||||
texpointer->stride = stride;
|
||||
texpointer->type = type;
|
||||
texpointer->size = size;
|
||||
AttribPointer* tointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER;
|
||||
|
||||
tointer->ptr = pointer;
|
||||
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.stride = stride;
|
||||
VERTEX_POINTER.type = type;
|
||||
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.stride = stride;
|
||||
DIFFUSE_POINTER.type = type;
|
||||
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.stride = stride;
|
||||
NORMAL_POINTER.type = type;
|
||||
|
|
|
@ -4,17 +4,14 @@
|
|||
|
||||
#include "../containers/aligned_vector.h"
|
||||
#include "private.h"
|
||||
#include "../gl-api.h"
|
||||
|
||||
#define TA_SQ_ADDR (unsigned int *)(void *) \
|
||||
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
|
||||
|
||||
static AlignedVector OP_LIST;
|
||||
static AlignedVector PT_LIST;
|
||||
static AlignedVector TR_LIST;
|
||||
|
||||
typedef struct {
|
||||
unsigned int cmd[8];
|
||||
} PVRCommand;
|
||||
static PolyList OP_LIST;
|
||||
static PolyList PT_LIST;
|
||||
static PolyList TR_LIST;
|
||||
|
||||
static void pvr_list_submit(void *src, int n) {
|
||||
GLuint *d = TA_SQ_ADDR;
|
||||
|
@ -44,7 +41,7 @@ static void _initPVR() {
|
|||
pvr_init_params_t params = {
|
||||
/* Enable opaque and translucent polygons with size 32 and 32 */
|
||||
{ PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32 },
|
||||
GL_PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
|
||||
PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
|
||||
0, /* No DMA */
|
||||
0, /* No FSAA */
|
||||
1 /* Disable translucent auto-sorting to match traditional GL */
|
||||
|
@ -54,35 +51,54 @@ static void _initPVR() {
|
|||
}
|
||||
|
||||
|
||||
AlignedVector* activePolyList() {
|
||||
PolyList* activePolyList() {
|
||||
if(isBlendingEnabled()) {
|
||||
return &TR_LIST;
|
||||
} else {
|
||||
return &OP_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Rename to glKosInit when experimental is core */
|
||||
void glKosBoot() {
|
||||
void APIENTRY glKosInit() {
|
||||
TRACE();
|
||||
|
||||
_initPVR();
|
||||
initAttributePointers();
|
||||
|
||||
aligned_vector_init(&OP_LIST, sizeof(PVRCommand));
|
||||
aligned_vector_init(&PT_LIST, sizeof(PVRCommand));
|
||||
aligned_vector_init(&TR_LIST, sizeof(PVRCommand));
|
||||
initAttributePointers();
|
||||
initContext();
|
||||
|
||||
_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_scene_begin();
|
||||
|
||||
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_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_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_scene_finish();
|
||||
|
||||
aligned_vector_clear(&OP_LIST.vector);
|
||||
aligned_vector_clear(&PT_LIST.vector);
|
||||
aligned_vector_clear(&TR_LIST.vector);
|
||||
}
|
||||
|
|
0
experimental/framebuffer.c
Normal file
0
experimental/framebuffer.c
Normal file
0
experimental/immediate.c
Normal file
0
experimental/immediate.c
Normal file
0
experimental/lighting.c
Normal file
0
experimental/lighting.c
Normal file
|
@ -2,12 +2,61 @@
|
|||
#define PRIVATE_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 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() { \
|
||||
__asm__ __volatile__( \
|
||||
|
|
|
@ -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 "../gl-api.h"
|
||||
#include "private.h"
|
||||
|
||||
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
|
||||
* GL states are combined, so we store them separately and then
|
||||
* calculate the appropriate PVR state from them. */
|
||||
|
@ -26,36 +40,136 @@ static GLboolean DEPTH_TEST_ENABLED = GL_FALSE;
|
|||
|
||||
static int _calc_pvr_depth_test() {
|
||||
if(!DEPTH_TEST_ENABLED) {
|
||||
return PVR_DEPTH_CMP_ALWAYS;
|
||||
return PVR_DEPTHCMP_ALWAYS;
|
||||
}
|
||||
|
||||
switch(func) {
|
||||
switch(DEPTH_FUNC) {
|
||||
case GL_NEVER:
|
||||
return PVR_DEPTH_CMP_NEVER;
|
||||
return PVR_DEPTHCMP_NEVER;
|
||||
case GL_LESS:
|
||||
return PVR_DEPTH_CMP_LESS;
|
||||
return PVR_DEPTHCMP_GEQUAL;
|
||||
case GL_EQUAL:
|
||||
return PVR_DEPTH_CMP_EQUAL;
|
||||
return PVR_DEPTHCMP_EQUAL;
|
||||
case GL_LEQUAL:
|
||||
return PVR_DEPTH_CMP_LEQUAL;
|
||||
return PVR_DEPTHCMP_GREATER;
|
||||
case GL_GREATER:
|
||||
return PVR_DEPTH_CMP_GREATER;
|
||||
return PVR_DEPTHCMP_LEQUAL;
|
||||
case GL_NOTEQUAL:
|
||||
return PVR_DEPTH_CMP_NOTEQUAL;
|
||||
return PVR_DEPTHCMP_NOTEQUAL;
|
||||
case GL_GEQUAL:
|
||||
return PVR_DEPTH_CMP_GEQUAL;
|
||||
return PVR_DEPTHCMP_LESS;
|
||||
break;
|
||||
case GL_ALWAYS:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
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_CULL_FACE);
|
||||
|
@ -67,7 +181,7 @@ void initContext() {
|
|||
GLAPI void APIENTRY glEnable(GLenum cap) {
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D:
|
||||
GL_CONTEXT.txr.enable = 1;
|
||||
TEXTURES_ENABLED = GL_TRUE;
|
||||
break;
|
||||
case GL_CULL_FACE: {
|
||||
CULLING_ENABLED = GL_TRUE;
|
||||
|
@ -77,13 +191,22 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
|
|||
DEPTH_TEST_ENABLED = GL_TRUE;
|
||||
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
|
||||
} 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) {
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D: {
|
||||
GL_CONTEXT.txr.enabled = 0;
|
||||
TEXTURES_ENABLED = GL_FALSE;
|
||||
} break;
|
||||
case GL_CULL_FACE: {
|
||||
CULLING_ENABLED = GL_FALSE;
|
||||
|
@ -93,16 +216,34 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
|
|||
DEPTH_TEST_ENABLED = GL_FALSE;
|
||||
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
|
||||
} 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 */
|
||||
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) {
|
||||
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 */
|
||||
|
@ -116,6 +257,7 @@ GLAPI void APIENTRY glClearDepth(GLfloat depth) {
|
|||
|
||||
GLAPI void APIENTRY glDepthMask(GLboolean flag) {
|
||||
GL_CONTEXT.depth.write = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
|
||||
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glDepthFunc(GLenum func) {
|
||||
|
@ -133,43 +275,82 @@ GLAPI void APIENTRY glHint(GLenum target, GLenum mode) {
|
|||
/* Culling */
|
||||
GLAPI void APIENTRY glFrontFace(GLenum mode) {
|
||||
FRONT_FACE = mode;
|
||||
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glCullFace(GLenum mode) {
|
||||
CULL_FACE = mode;
|
||||
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
|
||||
}
|
||||
|
||||
/* Shading - Flat or Goraud */
|
||||
GLAPI void APIENTRY glShadeModel(GLenum mode) {
|
||||
|
||||
GL_CONTEXT.gen.shading = (mode == GL_SMOOTH) ? PVR_SHADE_GOURAUD : PVR_SHADE_FLAT;
|
||||
}
|
||||
|
||||
/* Blending */
|
||||
GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||
|
||||
BLEND_SFACTOR = sfactor;
|
||||
BLEND_DFACTOR = dfactor;
|
||||
_updatePVRBlend(&GL_CONTEXT);
|
||||
}
|
||||
|
||||
/* Texturing */
|
||||
GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
|
||||
void glAlphaFunc(GLenum func, GLclampf ref) {
|
||||
;
|
||||
}
|
||||
|
||||
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
620
experimental/texture.c
Normal 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
343
gl-api.c
|
@ -52,188 +52,188 @@ static inline void _glKosFinishRect();
|
|||
//====================================================================================================//
|
||||
//== API Initialization ==//
|
||||
|
||||
void APIENTRY glKosInit() {
|
||||
_glKosInitPVR();
|
||||
//void APIENTRY glKosInit() {
|
||||
// _glKosInitPVR();
|
||||
|
||||
_glKosInitTextures();
|
||||
// _glKosInitTextures();
|
||||
|
||||
_glKosInitMatrix();
|
||||
// _glKosInitMatrix();
|
||||
|
||||
_glKosInitLighting();
|
||||
// _glKosInitLighting();
|
||||
|
||||
_glKosInitFrameBuffers();
|
||||
}
|
||||
// _glKosInitFrameBuffers();
|
||||
//}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Blending / Shading functions ==//
|
||||
|
||||
void APIENTRY glShadeModel(GLenum mode) {
|
||||
switch(mode) {
|
||||
case GL_FLAT:
|
||||
GL_KOS_SHADE_FUNC = PVR_SHADE_FLAT;
|
||||
break;
|
||||
//void APIENTRY glShadeModel(GLenum mode) {
|
||||
// switch(mode) {
|
||||
// case GL_FLAT:
|
||||
// GL_KOS_SHADE_FUNC = PVR_SHADE_FLAT;
|
||||
// break;
|
||||
|
||||
case GL_SMOOTH:
|
||||
GL_KOS_SHADE_FUNC = PVR_SHADE_GOURAUD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// case GL_SMOOTH:
|
||||
// GL_KOS_SHADE_FUNC = PVR_SHADE_GOURAUD;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||
GL_KOS_BLEND_FUNC = 0;
|
||||
//void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||
// GL_KOS_BLEND_FUNC = 0;
|
||||
|
||||
switch(sfactor) {
|
||||
case GL_ONE:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF) << 4;
|
||||
break;
|
||||
// switch(sfactor) {
|
||||
// case GL_ONE:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_ZERO:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF) << 4;
|
||||
break;
|
||||
// case GL_ZERO:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_SRC_COLOR:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF) << 4;
|
||||
break;
|
||||
// case GL_SRC_COLOR:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_DST_COLOR:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF) << 4;
|
||||
break;
|
||||
// case GL_DST_COLOR:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_SRC_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA << 4);
|
||||
break;
|
||||
// case GL_SRC_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA << 4);
|
||||
// break;
|
||||
|
||||
case GL_DST_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF) << 4;
|
||||
break;
|
||||
// case GL_DST_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF) << 4;
|
||||
break;
|
||||
// case GL_ONE_MINUS_SRC_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_ONE_MINUS_DST_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF) << 4;
|
||||
break;
|
||||
// case GL_ONE_MINUS_DST_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF) << 4;
|
||||
// break;
|
||||
|
||||
case GL_ONE_MINUS_DST_COLOR:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF) << 4;
|
||||
break;
|
||||
}
|
||||
// case GL_ONE_MINUS_DST_COLOR:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF) << 4;
|
||||
// break;
|
||||
// }
|
||||
|
||||
switch(dfactor) {
|
||||
case GL_ONE:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF);
|
||||
break;
|
||||
// switch(dfactor) {
|
||||
// case GL_ONE:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_ONE & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_ZERO:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF);
|
||||
break;
|
||||
// case GL_ZERO:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_ZERO & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_SRC_COLOR:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF);
|
||||
break;
|
||||
// case GL_SRC_COLOR:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_DST_COLOR:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF);
|
||||
break;
|
||||
// case GL_DST_COLOR:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTCOLOR & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_SRC_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF);
|
||||
break;
|
||||
// case GL_SRC_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_SRCALPHA & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_DST_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF);
|
||||
break;
|
||||
// case GL_DST_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_DESTALPHA & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF);
|
||||
break;
|
||||
// case GL_ONE_MINUS_SRC_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVSRCALPHA & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_ONE_MINUS_DST_ALPHA:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF);
|
||||
break;
|
||||
// case GL_ONE_MINUS_DST_ALPHA:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTALPHA & 0XF);
|
||||
// break;
|
||||
|
||||
case GL_ONE_MINUS_DST_COLOR:
|
||||
GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// case GL_ONE_MINUS_DST_COLOR:
|
||||
// GL_KOS_BLEND_FUNC |= (PVR_BLEND_INVDESTCOLOR & 0XF);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Depth / Clear functions ==//
|
||||
|
||||
void APIENTRY glClear(GLuint mode) {
|
||||
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]);
|
||||
}
|
||||
//void APIENTRY glClear(GLuint mode) {
|
||||
// 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]);
|
||||
//}
|
||||
|
||||
void APIENTRY glClearColor(float r, float g, float b, float a) {
|
||||
if(r > 1) r = 1;
|
||||
//void APIENTRY glClearColor(float r, float g, float b, float a) {
|
||||
// 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[1] = g * a;
|
||||
GL_KOS_COLOR_CLEAR[2] = b * a;
|
||||
}
|
||||
// GL_KOS_COLOR_CLEAR[0] = r * a;
|
||||
// GL_KOS_COLOR_CLEAR[1] = g * a;
|
||||
// GL_KOS_COLOR_CLEAR[2] = b * a;
|
||||
//}
|
||||
|
||||
//== NoOp ==//
|
||||
void APIENTRY glClearDepthf(GLfloat depth) {
|
||||
;
|
||||
}
|
||||
//void APIENTRY glClearDepthf(GLfloat depth) {
|
||||
// ;
|
||||
//}
|
||||
|
||||
void APIENTRY glDepthFunc(GLenum func) {
|
||||
switch(func) {
|
||||
case GL_LESS:
|
||||
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GEQUAL;
|
||||
break;
|
||||
//void APIENTRY glDepthFunc(GLenum func) {
|
||||
// switch(func) {
|
||||
// case GL_LESS:
|
||||
// GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GEQUAL;
|
||||
// break;
|
||||
|
||||
case GL_LEQUAL:
|
||||
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GREATER;
|
||||
break;
|
||||
// case GL_LEQUAL:
|
||||
// GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GREATER;
|
||||
// break;
|
||||
|
||||
case GL_GREATER:
|
||||
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LEQUAL;
|
||||
break;
|
||||
// case GL_GREATER:
|
||||
// GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LEQUAL;
|
||||
// break;
|
||||
|
||||
case GL_GEQUAL:
|
||||
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LESS;
|
||||
break;
|
||||
// case GL_GEQUAL:
|
||||
// GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LESS;
|
||||
// break;
|
||||
|
||||
default:
|
||||
GL_KOS_DEPTH_FUNC = (func & 0x0F);
|
||||
}
|
||||
}
|
||||
// default:
|
||||
// GL_KOS_DEPTH_FUNC = (func & 0x0F);
|
||||
// }
|
||||
//}
|
||||
|
||||
void APIENTRY glDepthMask(GLboolean flag) {
|
||||
GL_KOS_DEPTH_WRITE = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
|
||||
}
|
||||
//void APIENTRY glDepthMask(GLboolean flag) {
|
||||
// GL_KOS_DEPTH_WRITE = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
|
||||
//}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Culling functions ==//
|
||||
|
||||
void APIENTRY glFrontFace(GLenum mode) {
|
||||
switch(mode) {
|
||||
case GL_CW:
|
||||
case GL_CCW:
|
||||
GL_KOS_FACE_FRONT = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//void APIENTRY glFrontFace(GLenum mode) {
|
||||
// switch(mode) {
|
||||
// case GL_CW:
|
||||
// case GL_CCW:
|
||||
// GL_KOS_FACE_FRONT = mode;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
void APIENTRY glCullFace(GLenum mode) {
|
||||
switch(mode) {
|
||||
case GL_FRONT:
|
||||
case GL_BACK:
|
||||
case GL_FRONT_AND_BACK:
|
||||
GL_KOS_CULL_FUNC = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//void APIENTRY glCullFace(GLenum mode) {
|
||||
// switch(mode) {
|
||||
// case GL_FRONT:
|
||||
// case GL_BACK:
|
||||
// case GL_FRONT_AND_BACK:
|
||||
// GL_KOS_CULL_FUNC = mode;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Vertex Attributes Submission Functions ==//
|
||||
|
@ -461,56 +461,20 @@ void APIENTRY glEnd() {
|
|||
//== Misc. functions ==//
|
||||
|
||||
/* 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
|
||||
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.
|
||||
//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;
|
||||
|
||||
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 ==//
|
||||
|
@ -944,26 +908,3 @@ GLuint _glKosVertexColor() {
|
|||
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) {
|
||||
;
|
||||
}
|
||||
|
|
3
gl-api.h
3
gl-api.h
|
@ -171,7 +171,7 @@ uint16 __glKosAverageBiPixelARGB4444(uint16 p1, uint16 p2);
|
|||
void _glKosInitFrameBuffers();
|
||||
|
||||
/* Error Codes */
|
||||
void _glKosThrowError(GLenum error, char *functionName);
|
||||
void _glKosThrowError(GLenum error, const char *functionName);
|
||||
void _glKosPrintError();
|
||||
GLubyte _glKosHasError();
|
||||
|
||||
|
@ -208,6 +208,7 @@ GLubyte _glKosMaxTextureUnits();
|
|||
GLubyte _glKosEnabledTextureMatrix();
|
||||
|
||||
GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject();
|
||||
GL_TEXTURE_OBJECT *_glKosBoundTexObject();
|
||||
GLuint _glKosActiveTextureBoundTexID();
|
||||
|
||||
void _glKosPushMultiTexObject(GL_TEXTURE_OBJECT *tex,
|
||||
|
|
608
gl-arrays.c
608
gl-arrays.c
|
@ -90,104 +90,104 @@ static inline GLushort _calculate_byte_size(GLenum type) {
|
|||
//== Open GL API Public Functions ==//
|
||||
|
||||
/* Submit a Vertex Position Pointer */
|
||||
GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type,
|
||||
GLsizei stride, const GLvoid *pointer) {
|
||||
if(size != 2) /* Expect 2D X,Y or 3D X,Y,Z vertex... */
|
||||
if(size != 3)
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glVertexPointer");
|
||||
//GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type,
|
||||
// GLsizei stride, const GLvoid *pointer) {
|
||||
// if(size != 2) /* Expect 2D X,Y or 3D X,Y,Z vertex... */
|
||||
// if(size != 3)
|
||||
// _glKosThrowError(GL_INVALID_VALUE, "glVertexPointer");
|
||||
|
||||
if(type != GL_FLOAT) /* Expect Floating point vertices */
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glVertexPointer");
|
||||
// if(type != GL_FLOAT) /* Expect Floating point vertices */
|
||||
// _glKosThrowError(GL_INVALID_ENUM, "glVertexPointer");
|
||||
|
||||
if(stride < 0)
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glVertexPointer");
|
||||
// if(stride < 0)
|
||||
// _glKosThrowError(GL_INVALID_VALUE, "glVertexPointer");
|
||||
|
||||
if(_glKosHasError()) {
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
// if(_glKosHasError()) {
|
||||
// _glKosPrintError();
|
||||
// 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_POINTER = (GLubyte *)pointer;
|
||||
}
|
||||
// GL_KOS_VERTEX_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
|
||||
// GL_KOS_VERTEX_POINTER = (GLubyte *)pointer;
|
||||
//}
|
||||
|
||||
/* Submit a Vertex Normal Pointer */
|
||||
GLAPI void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) {
|
||||
if(type != GL_FLOAT) /* Expect Floating point vertices */
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glNormalPointer");
|
||||
///* Submit a Vertex Normal Pointer */
|
||||
//GLAPI void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) {
|
||||
// if(type != GL_FLOAT) /* Expect Floating point vertices */
|
||||
// _glKosThrowError(GL_INVALID_ENUM, "glNormalPointer");
|
||||
|
||||
if(stride < 0)
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glNormalPointer");
|
||||
// if(stride < 0)
|
||||
// _glKosThrowError(GL_INVALID_VALUE, "glNormalPointer");
|
||||
|
||||
if(_glKosHasError()) {
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
// if(_glKosHasError()) {
|
||||
// _glKosPrintError();
|
||||
// return;
|
||||
// }
|
||||
|
||||
GL_KOS_NORMAL_STRIDE = (stride) ? stride : _calculate_byte_size(type) * 3;
|
||||
GL_KOS_NORMAL_POINTER = (GLubyte *)pointer;
|
||||
}
|
||||
// GL_KOS_NORMAL_STRIDE = (stride) ? stride : _calculate_byte_size(type) * 3;
|
||||
// GL_KOS_NORMAL_POINTER = (GLubyte *)pointer;
|
||||
//}
|
||||
|
||||
/* Submit a Texture Coordinate Pointer */
|
||||
GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type,
|
||||
GLsizei stride, const GLvoid *pointer) {
|
||||
if(size != 2) /* Expect u and v */
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer");
|
||||
///* Submit a Texture Coordinate Pointer */
|
||||
//GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type,
|
||||
// GLsizei stride, const GLvoid *pointer) {
|
||||
// if(size != 2) /* Expect u and v */
|
||||
// _glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer");
|
||||
|
||||
if(type != GL_FLOAT) /* Expect Floating point vertices */
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexCoordPointer");
|
||||
// if(type != GL_FLOAT) /* Expect Floating point vertices */
|
||||
// _glKosThrowError(GL_INVALID_ENUM, "glTexCoordPointer");
|
||||
|
||||
if(stride < 0)
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer");
|
||||
// if(stride < 0)
|
||||
// _glKosThrowError(GL_INVALID_VALUE, "glTexCoordPointer");
|
||||
|
||||
if(_glKosHasError()) {
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
// if(_glKosHasError()) {
|
||||
// _glKosPrintError();
|
||||
// return;
|
||||
// }
|
||||
|
||||
if(GL_KOS_CLIENT_ACTIVE_TEXTURE) {
|
||||
GL_KOS_TEXCOORD1_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
|
||||
GL_KOS_TEXCOORD1_POINTER = (GLubyte *)pointer;
|
||||
}
|
||||
else {
|
||||
GL_KOS_TEXCOORD0_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
|
||||
GL_KOS_TEXCOORD0_POINTER = (GLubyte *)pointer;
|
||||
}
|
||||
}
|
||||
// if(GL_KOS_CLIENT_ACTIVE_TEXTURE) {
|
||||
// GL_KOS_TEXCOORD1_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
|
||||
// GL_KOS_TEXCOORD1_POINTER = (GLubyte *)pointer;
|
||||
// }
|
||||
// else {
|
||||
// GL_KOS_TEXCOORD0_STRIDE = (stride) ? stride : _calculate_byte_size(type) * size;
|
||||
// GL_KOS_TEXCOORD0_POINTER = (GLubyte *)pointer;
|
||||
// }
|
||||
//}
|
||||
|
||||
/* Submit a Color Pointer */
|
||||
GLAPI void APIENTRY glColorPointer(GLint size, GLenum type,
|
||||
GLsizei stride, const GLvoid *pointer) {
|
||||
if((type == GL_UNSIGNED_INT) && (size == 1)) {
|
||||
GL_KOS_COLOR_COMPONENTS = size;
|
||||
GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
GL_KOS_COLOR_TYPE = type;
|
||||
}
|
||||
else if((type == GL_UNSIGNED_BYTE) && (size == 4)) {
|
||||
GL_KOS_COLOR_COMPONENTS = size;
|
||||
GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
GL_KOS_COLOR_TYPE = type;
|
||||
}
|
||||
else if((type == GL_FLOAT) && (size == 3)) {
|
||||
GL_KOS_COLOR_COMPONENTS = size;
|
||||
GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
GL_KOS_COLOR_TYPE = type;
|
||||
}
|
||||
else if((type == GL_FLOAT) && (size == 4)) {
|
||||
GL_KOS_COLOR_COMPONENTS = size;
|
||||
GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
GL_KOS_COLOR_TYPE = type;
|
||||
}
|
||||
else {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glColorPointer");
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
///* Submit a Color Pointer */
|
||||
//GLAPI void APIENTRY glColorPointer(GLint size, GLenum type,
|
||||
// GLsizei stride, const GLvoid *pointer) {
|
||||
// if((type == GL_UNSIGNED_INT) && (size == 1)) {
|
||||
// GL_KOS_COLOR_COMPONENTS = size;
|
||||
// GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
// GL_KOS_COLOR_TYPE = type;
|
||||
// }
|
||||
// else if((type == GL_UNSIGNED_BYTE) && (size == 4)) {
|
||||
// GL_KOS_COLOR_COMPONENTS = size;
|
||||
// GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
// GL_KOS_COLOR_TYPE = type;
|
||||
// }
|
||||
// else if((type == GL_FLOAT) && (size == 3)) {
|
||||
// GL_KOS_COLOR_COMPONENTS = size;
|
||||
// GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
// GL_KOS_COLOR_TYPE = type;
|
||||
// }
|
||||
// else if((type == GL_FLOAT) && (size == 4)) {
|
||||
// GL_KOS_COLOR_COMPONENTS = size;
|
||||
// GL_KOS_COLOR_POINTER = (GLubyte *)pointer;
|
||||
// GL_KOS_COLOR_TYPE = type;
|
||||
// }
|
||||
// else {
|
||||
// _glKosThrowError(GL_INVALID_ENUM, "glColorPointer");
|
||||
// _glKosPrintError();
|
||||
// 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 ==//
|
||||
|
||||
|
@ -883,162 +883,162 @@ static inline void _glKosArraysFlush(GLuint count) {
|
|||
//========================================================================================//
|
||||
//== OpenGL Elemental Array Submission ==//
|
||||
|
||||
GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
|
||||
/* Before we process the vertex data, ensure all parameters are valid */
|
||||
if(!_glKosArraysVerifyParameter(mode, count, type, 1))
|
||||
return;
|
||||
//GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
|
||||
// /* Before we process the vertex data, ensure all parameters are valid */
|
||||
// if(!_glKosArraysVerifyParameter(mode, count, type, 1))
|
||||
// return;
|
||||
|
||||
/* Compile the PVR polygon context with the currently enabled flags */
|
||||
_glKosArraysApplyHeader();
|
||||
// /* Compile the PVR polygon context with the currently enabled flags */
|
||||
// _glKosArraysApplyHeader();
|
||||
|
||||
/* Destination of Output Vertex Array */
|
||||
pvr_vertex_t *dst = _glKosArraysDest();
|
||||
// /* Destination of Output Vertex Array */
|
||||
// pvr_vertex_t *dst = _glKosArraysDest();
|
||||
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
GL_KOS_INDEX_POINTER_U8 = (GLubyte *)indices;
|
||||
break;
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// GL_KOS_INDEX_POINTER_U8 = (GLubyte *)indices;
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
GL_KOS_INDEX_POINTER_U16 = (GLushort *)indices;
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// GL_KOS_INDEX_POINTER_U16 = (GLushort *)indices;
|
||||
// break;
|
||||
// }
|
||||
|
||||
/* Check if Vertex Lighting is enabled. Else, check for Color Submission */
|
||||
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting())
|
||||
_glKosArraysApplyLighting(dst, count);
|
||||
// /* Check if Vertex Lighting is enabled. Else, check for Color Submission */
|
||||
// if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting())
|
||||
// _glKosArraysApplyLighting(dst, count);
|
||||
|
||||
else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) {
|
||||
switch(GL_KOS_COLOR_TYPE) {
|
||||
case GL_FLOAT:
|
||||
switch(GL_KOS_COLOR_COMPONENTS) {
|
||||
case 3:
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosElementColor3fU8(dst, count);
|
||||
break;
|
||||
// else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) {
|
||||
// switch(GL_KOS_COLOR_TYPE) {
|
||||
// case GL_FLOAT:
|
||||
// switch(GL_KOS_COLOR_COMPONENTS) {
|
||||
// case 3:
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosElementColor3fU8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosElementColor3fU16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosElementColor3fU16(dst, count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
// break;
|
||||
|
||||
case 4:
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosElementColor4fU8(dst, count);
|
||||
break;
|
||||
// case 4:
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosElementColor4fU8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosElementColor4fU16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosElementColor4fU16(dst, count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_INT:
|
||||
if(GL_KOS_COLOR_COMPONENTS == 1)
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosElementColor1uiU8(dst, count);
|
||||
break;
|
||||
// case GL_UNSIGNED_INT:
|
||||
// if(GL_KOS_COLOR_COMPONENTS == 1)
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosElementColor1uiU8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosElementColor1uiU16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosElementColor1uiU16(dst, count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_BYTE:
|
||||
if(GL_KOS_COLOR_COMPONENTS == 4)
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosElementColor4ubU8(dst, count);
|
||||
break;
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// if(GL_KOS_COLOR_COMPONENTS == 4)
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosElementColor4ubU8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosElementColor4ubU16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosElementColor4ubU16(dst, count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_glKosArrayColor0(dst, count); /* No colors bound */
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// _glKosArrayColor0(dst, count); /* No colors bound */
|
||||
|
||||
/* Check if Texture Coordinates are enabled */
|
||||
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0))
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosElementTexCoord2fU8(dst, count);
|
||||
break;
|
||||
// /* Check if Texture Coordinates are enabled */
|
||||
// if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0))
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosElementTexCoord2fU8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosElementTexCoord2fU16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosElementTexCoord2fU16(dst, count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
/* Check if Multi Texture Coordinates are enabled */
|
||||
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0))
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosElementMultiTexCoord2fU8(count);
|
||||
break;
|
||||
// /* Check if Multi Texture Coordinates are enabled */
|
||||
// if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0))
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosElementMultiTexCoord2fU8(count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosElementMultiTexCoord2fU16(count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosElementMultiTexCoord2fU16(count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
_glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
|
||||
// _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
|
||||
|
||||
if(!(_glKosEnabledNearZClip())) {/* Transform the element vertices */
|
||||
/* Transform vertices with perspective divide */
|
||||
_glKosArraysTransformElements(count);
|
||||
// if(!(_glKosEnabledNearZClip())) {/* Transform the element vertices */
|
||||
// /* Transform vertices with perspective divide */
|
||||
// _glKosArraysTransformElements(count);
|
||||
|
||||
/* Unpack the indexed positions into primitives for rasterization */
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosArraysUnpackElementsS8(dst, count);
|
||||
break;
|
||||
// /* Unpack the indexed positions into primitives for rasterization */
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosArraysUnpackElementsS8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosArraysUnpackElementsS16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosArraysUnpackElementsS16(dst, count);
|
||||
// break;
|
||||
// }
|
||||
|
||||
/* Set the vertex flags for use with the PVR */
|
||||
_glKosArraysApplyVertexFlags(mode, dst, count);
|
||||
}
|
||||
else {
|
||||
/* Transform vertices with no perspective divide, store w component */
|
||||
_glKosArraysTransformClipElements(count);
|
||||
// /* Set the vertex flags for use with the PVR */
|
||||
// _glKosArraysApplyVertexFlags(mode, dst, count);
|
||||
// }
|
||||
// else {
|
||||
// /* Transform vertices with no perspective divide, store w component */
|
||||
// _glKosArraysTransformClipElements(count);
|
||||
|
||||
/* Unpack the indexed positions into primitives for rasterization */
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosArraysUnpackClipElementsS8(dst, count);
|
||||
break;
|
||||
// /* Unpack the indexed positions into primitives for rasterization */
|
||||
// switch(type) {
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// _glKosArraysUnpackClipElementsS8(dst, count);
|
||||
// break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosArraysUnpackClipElementsS16(dst, count);
|
||||
break;
|
||||
}
|
||||
// case GL_UNSIGNED_SHORT:
|
||||
// _glKosArraysUnpackClipElementsS16(dst, count);
|
||||
// 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 ==//
|
||||
|
@ -1197,151 +1197,97 @@ static void _glKosDrawArrays2D(GLenum mode, GLint first, GLsizei 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 */
|
||||
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);
|
||||
//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;
|
||||
|
||||
/* Compile the PVR polygon context with the currently enabled flags */
|
||||
_glKosArraysApplyHeader();
|
||||
// GL_KOS_VERTEX_POINTER += (first * GL_KOS_VERTEX_STRIDE); /* Add Pointer Offset */
|
||||
// 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)
|
||||
return _glKosDrawArrays2D(mode, first, count);
|
||||
// /* Compile the PVR polygon context with the currently enabled flags */
|
||||
// _glKosArraysApplyHeader();
|
||||
|
||||
/* Destination of Output Vertex Array */
|
||||
pvr_vertex_t *dst = _glKosArraysDest();
|
||||
// if(GL_KOS_VERTEX_SIZE == 2)
|
||||
// return _glKosDrawArrays2D(mode, first, count);
|
||||
|
||||
/* Check if Vertex Lighting is enabled. Else, check for Color Submission */
|
||||
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting())
|
||||
_glKosArraysApplyLighting(dst, count);
|
||||
// /* Destination of Output Vertex Array */
|
||||
// pvr_vertex_t *dst = _glKosArraysDest();
|
||||
|
||||
else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) {
|
||||
switch(GL_KOS_COLOR_TYPE) {
|
||||
case GL_FLOAT:
|
||||
switch(GL_KOS_COLOR_COMPONENTS) {
|
||||
case 3:
|
||||
_glKosArrayColor3f(dst, count);
|
||||
break;
|
||||
// /* Check if Vertex Lighting is enabled. Else, check for Color Submission */
|
||||
// if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_NORMAL) && _glKosEnabledLighting())
|
||||
// _glKosArraysApplyLighting(dst, count);
|
||||
|
||||
case 4:
|
||||
_glKosArrayColor4f(dst, count);
|
||||
break;
|
||||
}
|
||||
// else if(GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_COLOR) {
|
||||
// switch(GL_KOS_COLOR_TYPE) {
|
||||
// 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:
|
||||
if(GL_KOS_COLOR_COMPONENTS == 1)
|
||||
_glKosArrayColor1ui(dst, count);
|
||||
// break;
|
||||
|
||||
break;
|
||||
// case GL_UNSIGNED_INT:
|
||||
// if(GL_KOS_COLOR_COMPONENTS == 1)
|
||||
// _glKosArrayColor1ui(dst, count);
|
||||
|
||||
case GL_UNSIGNED_BYTE:
|
||||
if(GL_KOS_COLOR_COMPONENTS == 4)
|
||||
_glKosArrayColor4ub(dst, count);
|
||||
// break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_glKosArrayColor0(dst, count); /* No colors bound, color white */
|
||||
// case GL_UNSIGNED_BYTE:
|
||||
// if(GL_KOS_COLOR_COMPONENTS == 4)
|
||||
// _glKosArrayColor4ub(dst, count);
|
||||
|
||||
/* Check if Texture Coordinates are enabled */
|
||||
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0))
|
||||
_glKosArrayTexCoord2f(dst, count);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// _glKosArrayColor0(dst, count); /* No colors bound, color white */
|
||||
|
||||
/* Check if Multi Texture Coordinates are enabled */
|
||||
if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE1) && (_glKosEnabledTexture2D() >= 0))
|
||||
_glKosArrayMultiTexCoord2f(count);
|
||||
// /* Check if Texture Coordinates are enabled */
|
||||
// if((GL_KOS_VERTEX_PTR_MODE & GL_KOS_USE_TEXTURE0) && (_glKosEnabledTexture2D() >= 0))
|
||||
// _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 */
|
||||
/* Transform Vertex Positions */
|
||||
_glKosArraysTransform(count);
|
||||
// _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
|
||||
|
||||
/* Set the vertex flags for use with the PVR */
|
||||
_glKosArraysApplyVertexFlags(mode, dst, count);
|
||||
}
|
||||
else { /* NearZ Clipping is Enabled */
|
||||
/* Transform vertices with no perspective divide, store w component */
|
||||
_glKosArraysTransformClip(count);
|
||||
// if(!_glKosEnabledNearZClip()) { /* No NearZ Clipping Enabled */
|
||||
// /* Transform Vertex Positions */
|
||||
// _glKosArraysTransform(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 */
|
||||
}
|
||||
// /* Set the vertex flags for use with the PVR */
|
||||
// _glKosArraysApplyVertexFlags(mode, dst, count);
|
||||
// }
|
||||
// else { /* NearZ Clipping is Enabled */
|
||||
// /* Transform vertices with no perspective divide, store w component */
|
||||
// _glKosArraysTransformClip(count);
|
||||
|
||||
_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) {
|
||||
if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + _glKosMaxTextureUnits())
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glClientActiveTextureARB");
|
||||
// _glKosArraysFlush(count);
|
||||
//}
|
||||
|
||||
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
132
gl-cap.c
|
@ -28,91 +28,91 @@ static GLbitfield GL_KOS_ENABLE_CAP = 0;
|
|||
//===============================================================================//
|
||||
//== External API Functions ==//
|
||||
|
||||
void APIENTRY glEnable(GLenum cap) {
|
||||
if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosEnableLight(cap);
|
||||
//void APIENTRY glEnable(GLenum cap) {
|
||||
// if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosEnableLight(cap);
|
||||
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE2D;
|
||||
break;
|
||||
// switch(cap) {
|
||||
// case GL_TEXTURE_2D:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE2D;
|
||||
// break;
|
||||
|
||||
case GL_BLEND:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_BLENDING;
|
||||
_glKosVertexBufSwitchTR();
|
||||
break;
|
||||
// case GL_BLEND:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_BLENDING;
|
||||
// _glKosVertexBufSwitchTR();
|
||||
// break;
|
||||
|
||||
case GL_DEPTH_TEST:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_DEPTH_TEST;
|
||||
break;
|
||||
// case GL_DEPTH_TEST:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_DEPTH_TEST;
|
||||
// break;
|
||||
|
||||
case GL_LIGHTING:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_LIGHTING;
|
||||
break;
|
||||
// case GL_LIGHTING:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_LIGHTING;
|
||||
// break;
|
||||
|
||||
case GL_KOS_NEARZ_CLIPPING:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_ZCLIPPING;
|
||||
break;
|
||||
// case GL_KOS_NEARZ_CLIPPING:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_ZCLIPPING;
|
||||
// break;
|
||||
|
||||
case GL_SCISSOR_TEST:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_SCISSOR_TEST;
|
||||
break;
|
||||
// case GL_SCISSOR_TEST:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_SCISSOR_TEST;
|
||||
// break;
|
||||
|
||||
case GL_FOG:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_FOG;
|
||||
break;
|
||||
// case GL_FOG:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_FOG;
|
||||
// break;
|
||||
|
||||
case GL_CULL_FACE:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_CULLING;
|
||||
break;
|
||||
// case GL_CULL_FACE:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_CULLING;
|
||||
// break;
|
||||
|
||||
case GL_KOS_TEXTURE_MATRIX:
|
||||
GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE_MAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// case GL_KOS_TEXTURE_MATRIX:
|
||||
// GL_KOS_ENABLE_CAP |= GL_KOS_ENABLE_TEXTURE_MAT;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
void APIENTRY glDisable(GLenum cap) {
|
||||
if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosDisableLight(cap);
|
||||
//void APIENTRY glDisable(GLenum cap) {
|
||||
// if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosDisableLight(cap);
|
||||
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE2D;
|
||||
break;
|
||||
// switch(cap) {
|
||||
// case GL_TEXTURE_2D:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE2D;
|
||||
// break;
|
||||
|
||||
case GL_BLEND:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_BLENDING;
|
||||
_glKosVertexBufSwitchOP();
|
||||
break;
|
||||
// case GL_BLEND:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_BLENDING;
|
||||
// _glKosVertexBufSwitchOP();
|
||||
// break;
|
||||
|
||||
case GL_DEPTH_TEST:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_DEPTH_TEST;
|
||||
break;
|
||||
// case GL_DEPTH_TEST:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_DEPTH_TEST;
|
||||
// break;
|
||||
|
||||
case GL_LIGHTING:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_LIGHTING;
|
||||
break;
|
||||
// case GL_LIGHTING:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_LIGHTING;
|
||||
// break;
|
||||
|
||||
case GL_KOS_NEARZ_CLIPPING:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_ZCLIPPING;
|
||||
break;
|
||||
// case GL_KOS_NEARZ_CLIPPING:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_ZCLIPPING;
|
||||
// break;
|
||||
|
||||
case GL_SCISSOR_TEST:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_SCISSOR_TEST;
|
||||
break;
|
||||
// case GL_SCISSOR_TEST:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_SCISSOR_TEST;
|
||||
// break;
|
||||
|
||||
case GL_FOG:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_FOG;
|
||||
break;
|
||||
// case GL_FOG:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_FOG;
|
||||
// break;
|
||||
|
||||
case GL_CULL_FACE:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_CULLING;
|
||||
break;
|
||||
// case GL_CULL_FACE:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_CULLING;
|
||||
// break;
|
||||
|
||||
case GL_KOS_TEXTURE_MATRIX:
|
||||
GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE_MAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// case GL_KOS_TEXTURE_MATRIX:
|
||||
// GL_KOS_ENABLE_CAP &= ~GL_KOS_ENABLE_TEXTURE_MAT;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
GLboolean APIENTRY glIsEnabled(GLenum cap) {
|
||||
if(cap >= GL_LIGHT0 && cap <= GL_LIGHT15) return _glKosIsLightEnabled(cap & 0xFF);
|
||||
|
|
|
@ -25,7 +25,7 @@ static char error_function[64] = { '\0' };
|
|||
Nothing in the spec requires recording multiple error flags, although it is
|
||||
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) {
|
||||
last_error = error;
|
||||
sprintf(error_function, "%s\n", function);
|
||||
|
|
9
gl-pvr.h
9
gl-pvr.h
|
@ -14,15 +14,6 @@ typedef struct {
|
|||
unsigned int cmd[8];
|
||||
} 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_KOS_MAX_VERTS 1024*64 /* SH4 Vertex Count */
|
||||
|
||||
|
|
542
gl-texture.c
542
gl-texture.c
|
@ -21,8 +21,6 @@
|
|||
//== Internal KOS Open GL Texture Unit Structures / Global Variables ==//
|
||||
|
||||
#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 };
|
||||
|
@ -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) {
|
||||
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();
|
||||
}
|
||||
|
||||
GL_TEXTURE_OBJECT *_glKosBoundTexObject() {
|
||||
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF];
|
||||
}
|
||||
|
||||
GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject() {
|
||||
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE1_ARB & 0xF];
|
||||
}
|
||||
|
@ -92,528 +80,6 @@ GLubyte _glKosMaxTextureUnits() {
|
|||
//========================================================================================//
|
||||
//== 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;
|
||||
}
|
||||
|
|
|
@ -473,8 +473,8 @@ GLAPI void APIENTRY glClear(GLuint mode);
|
|||
GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
|
||||
/* Depth Testing */
|
||||
GLAPI void APIENTRY glClearDepth(GLfloat depth);
|
||||
GLAPI void APIENTRY glClearDepthf(GLfloat depth);
|
||||
#define glClearDepth glClearDepthf
|
||||
GLAPI void APIENTRY glDepthMask(GLboolean flag);
|
||||
GLAPI void APIENTRY glDepthFunc(GLenum func);
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#ifndef GLKOS_H
|
||||
#define GLKOS_H
|
||||
|
||||
void glKosSwapBuffers();
|
||||
#include "gl.h"
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
GLAPI void APIENTRY glKosSwapBuffers();
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // GLKOS_H
|
||||
|
|
Loading…
Reference in New Issue
Block a user