Merge pull request #7 from Kazade/experimental
Complete rewrite of libGL, now called GLdc
This commit is contained in:
commit
dd75ae3caf
429
GL/draw.c
Normal file
429
GL/draw.c
Normal file
|
@ -0,0 +1,429 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../include/glext.h"
|
||||
#include "private.h"
|
||||
|
||||
typedef struct {
|
||||
const void* ptr;
|
||||
GLenum type;
|
||||
GLsizei stride;
|
||||
GLint size;
|
||||
} AttribPointer;
|
||||
|
||||
|
||||
static AttribPointer VERTEX_POINTER;
|
||||
static AttribPointer UV_POINTER;
|
||||
static AttribPointer ST_POINTER;
|
||||
static AttribPointer NORMAL_POINTER;
|
||||
static AttribPointer DIFFUSE_POINTER;
|
||||
|
||||
#define VERTEX_ENABLED_FLAG (1 << 0)
|
||||
#define UV_ENABLED_FLAG (1 << 1)
|
||||
#define ST_ENABLED_FLAG (1 << 2)
|
||||
#define DIFFUSE_ENABLED_FLAG (1 << 3)
|
||||
#define NORMAL_ENABLED_FLAG (1 << 4)
|
||||
|
||||
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;
|
||||
VERTEX_POINTER.size = 4;
|
||||
|
||||
DIFFUSE_POINTER.ptr = NULL;
|
||||
DIFFUSE_POINTER.stride = 0;
|
||||
DIFFUSE_POINTER.type = GL_FLOAT;
|
||||
DIFFUSE_POINTER.size = 4;
|
||||
|
||||
UV_POINTER.ptr = NULL;
|
||||
UV_POINTER.stride = 0;
|
||||
UV_POINTER.type = GL_FLOAT;
|
||||
UV_POINTER.size = 4;
|
||||
|
||||
ST_POINTER.ptr = NULL;
|
||||
ST_POINTER.stride = 0;
|
||||
ST_POINTER.type = GL_FLOAT;
|
||||
ST_POINTER.size = 4;
|
||||
|
||||
NORMAL_POINTER.ptr = NULL;
|
||||
NORMAL_POINTER.stride = 0;
|
||||
NORMAL_POINTER.type = GL_FLOAT;
|
||||
NORMAL_POINTER.size = 3;
|
||||
}
|
||||
|
||||
static GLuint byte_size(GLenum type) {
|
||||
switch(type) {
|
||||
case GL_BYTE: return sizeof(GLbyte);
|
||||
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
|
||||
case GL_SHORT: return sizeof(GLshort);
|
||||
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
|
||||
case GL_INT: return sizeof(GLint);
|
||||
case GL_UNSIGNED_INT: return sizeof(GLuint);
|
||||
case GL_DOUBLE: return sizeof(GLdouble);
|
||||
case GL_FLOAT:
|
||||
default: return sizeof(GLfloat);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
__x = src[0];
|
||||
__y = src[1];
|
||||
__z = src[2];
|
||||
|
||||
mat_trans_fv12()
|
||||
|
||||
*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) {
|
||||
GLubyte i;
|
||||
|
||||
switch(type) {
|
||||
case GL_SHORT: {
|
||||
GLshort* inp = (GLshort*) in;
|
||||
for(i = 0; i < size; ++i) {
|
||||
out[i] = (GLfloat) inp[i];
|
||||
}
|
||||
} break;
|
||||
case GL_INT: {
|
||||
GLint* inp = (GLint*) in;
|
||||
for(i = 0; i < size; ++i) {
|
||||
out[i] = (GLfloat) inp[i];
|
||||
}
|
||||
} break;
|
||||
case GL_FLOAT:
|
||||
case GL_DOUBLE: /* Double == Float */
|
||||
default: {
|
||||
const GLfloat* ptr = (const GLfloat*) in;
|
||||
for(i = 0; i < size; ++i) out[i] = ptr[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _parseIndex(GLshort* out, const GLubyte* in, GLenum type) {
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
*out = (GLshort) *in;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
default:
|
||||
*out = *((GLshort*) in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* There was a bug in this macro that shipped with Kos
|
||||
* which has now been fixed. But just in case...
|
||||
*/
|
||||
#undef mat_trans_single3_nodiv
|
||||
#define mat_trans_single3_nodiv(x, y, z) { \
|
||||
register float __x __asm__("fr12") = (x); \
|
||||
register float __y __asm__("fr13") = (y); \
|
||||
register float __z __asm__("fr14") = (z); \
|
||||
__asm__ __volatile__( \
|
||||
"fldi1 fr15\n" \
|
||||
"ftrv xmtrx, fv12\n" \
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z) \
|
||||
: "0" (__x), "1" (__y), "2" (__z) \
|
||||
: "fr15"); \
|
||||
x = __x; y = __y; z = __z; \
|
||||
}
|
||||
|
||||
#undef mat_trans_normal3
|
||||
#define mat_trans_normal3(x, y, z) { \
|
||||
register float __x __asm__("fr8") = (x); \
|
||||
register float __y __asm__("fr9") = (y); \
|
||||
register float __z __asm__("fr10") = (z); \
|
||||
__asm__ __volatile__( \
|
||||
"fldi0 fr11\n" \
|
||||
"ftrv xmtrx, fv8\n" \
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z) \
|
||||
: "0" (__x), "1" (__y), "2" (__z) \
|
||||
: "fr11"); \
|
||||
x = __x; y = __y; z = __z; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void transformToEyeSpace(GLfloat* point) {
|
||||
_matrixLoadModelView();
|
||||
mat_trans_single3_nodiv(point[0], point[1], point[2]);
|
||||
}
|
||||
|
||||
|
||||
inline void transformNormalToEyeSpace(GLfloat* normal) {
|
||||
_matrixLoadNormal();
|
||||
mat_trans_normal3(normal[0], normal[1], normal[2]);
|
||||
}
|
||||
|
||||
|
||||
static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum type, const GLvoid* indices) {
|
||||
static GLfloat normal[3] = {0.0f, 0.0f, -1.0f};
|
||||
static GLfloat eye_P[3];
|
||||
static GLfloat eye_N[3];
|
||||
|
||||
if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const GLsizei elements = (mode == GL_QUADS) ? 4 : (mode == GL_TRIANGLES) ? 3 : (mode == GL_LINES) ? 2 : count;
|
||||
|
||||
// Make room for the element + the header
|
||||
PVRCommand* dst = (PVRCommand*) aligned_vector_extend(&activePolyList()->vector, count + 1);
|
||||
|
||||
// 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);
|
||||
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;
|
||||
|
||||
GLboolean lighting_enabled = isLightingEnabled();
|
||||
|
||||
GLushort i;
|
||||
for(i = first; i < count; ++i) {
|
||||
pvr_vertex_t* vertex = (pvr_vertex_t*) dst;
|
||||
vertex->u = vertex->v = 0.0f;
|
||||
vertex->argb = 0;
|
||||
vertex->oargb = 0;
|
||||
vertex->flags = PVR_CMD_VERTEX;
|
||||
|
||||
if(((i + 1) % elements) == 0) {
|
||||
vertex->flags = PVR_CMD_VERTEX_EOL;
|
||||
}
|
||||
|
||||
GLshort idx = i;
|
||||
if(indices) {
|
||||
_parseIndex(&idx, &indices_as_bytes[byte_size(type) * i], type);
|
||||
}
|
||||
|
||||
_parseFloats(&vertex->x, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type);
|
||||
|
||||
if(ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) {
|
||||
_parseColour(&vertex->argb, cptr + (idx * cstride), DIFFUSE_POINTER.size, DIFFUSE_POINTER.type);
|
||||
}
|
||||
|
||||
if(ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG) {
|
||||
_parseFloats(&vertex->u, uvptr + (idx * uvstride), UV_POINTER.size, UV_POINTER.type);
|
||||
}
|
||||
|
||||
if(ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) {
|
||||
_parseFloats(normal, nptr + (idx * nstride), NORMAL_POINTER.size, NORMAL_POINTER.type);
|
||||
} else {
|
||||
normal[0] = normal[1] = 0.0f;
|
||||
normal[2] = -1.0f;
|
||||
}
|
||||
|
||||
if(lighting_enabled) {
|
||||
/* We ignore diffuse colour when lighting is enabled. If GL_COLOR_MATERIAL is enabled
|
||||
* then the lighting calculation should possibly take it into account */
|
||||
GLfloat contribution [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GLfloat to_add [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* Transform the vertex and normal into eye-space */
|
||||
eye_P[0] = vertex->x;
|
||||
eye_P[1] = vertex->y;
|
||||
eye_P[2] = vertex->z;
|
||||
|
||||
eye_N[0] = normal[0];
|
||||
eye_N[1] = normal[1];
|
||||
eye_N[2] = normal[2];
|
||||
|
||||
transformToEyeSpace(eye_P);
|
||||
transformNormalToEyeSpace(eye_N);
|
||||
|
||||
GLubyte j;
|
||||
for(j = 0; j < MAX_LIGHTS; ++j) {
|
||||
if(isLightEnabled(j)) {
|
||||
calculateLightingContribution(j, eye_P, eye_N, to_add);
|
||||
|
||||
contribution[0] += to_add[0];
|
||||
contribution[1] += to_add[1];
|
||||
contribution[2] += to_add[2];
|
||||
contribution[3] += to_add[3];
|
||||
}
|
||||
}
|
||||
|
||||
vertex->argb = PVR_PACK_COLOR(contribution[3], contribution[0], contribution[1], contribution[2]);
|
||||
}
|
||||
|
||||
_applyRenderMatrix(); /* Apply the Render Matrix Stack */
|
||||
transformVertex(&vertex->x, &vertex->x, &vertex->y, &vertex->z);
|
||||
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
|
||||
TRACE();
|
||||
|
||||
if(checkImmediateModeInactive(__func__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
submitVertices(mode, 0, count, type, indices);
|
||||
}
|
||||
|
||||
void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
TRACE();
|
||||
|
||||
if(checkImmediateModeInactive(__func__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
submitVertices(mode, first, count, GL_UNSIGNED_SHORT, NULL);
|
||||
}
|
||||
|
||||
void APIENTRY glEnableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES |= VERTEX_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES |= NORMAL_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ENABLED_VERTEX_ATTRIBUTES |= ST_ENABLED_FLAG):
|
||||
(ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glEnableClientState");
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glDisableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES &= ~VERTEX_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES &= ~DIFFUSE_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
ENABLED_VERTEX_ATTRIBUTES &= ~NORMAL_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ENABLED_VERTEX_ATTRIBUTES &= ~ST_ENABLED_FLAG):
|
||||
(ENABLED_VERTEX_ATTRIBUTES &= ~UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glDisableClientState");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
AttribPointer* tointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER;
|
||||
|
||||
tointer->ptr = pointer;
|
||||
tointer->stride = stride;
|
||||
tointer->type = type;
|
||||
tointer->size = size;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
NORMAL_POINTER.ptr = pointer;
|
||||
NORMAL_POINTER.stride = stride;
|
||||
NORMAL_POINTER.type = type;
|
||||
NORMAL_POINTER.size = 3;
|
||||
}
|
|
@ -9,7 +9,6 @@
|
|||
*/
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -25,7 +24,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);
|
105
GL/flush.c
Normal file
105
GL/flush.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
|
||||
|
||||
#include <kos.h>
|
||||
|
||||
#include "../containers/aligned_vector.h"
|
||||
#include "private.h"
|
||||
|
||||
#define TA_SQ_ADDR (unsigned int *)(void *) \
|
||||
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
|
||||
|
||||
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;
|
||||
GLuint *s = src;
|
||||
|
||||
/* fill/write queues as many times necessary */
|
||||
while(n--) {
|
||||
__asm__("pref @%0" : : "r"(s + 8)); /* prefetch 32 bytes for next loop */
|
||||
d[0] = *(s++);
|
||||
d[1] = *(s++);
|
||||
d[2] = *(s++);
|
||||
d[3] = *(s++);
|
||||
d[4] = *(s++);
|
||||
d[5] = *(s++);
|
||||
d[6] = *(s++);
|
||||
d[7] = *(s++);
|
||||
__asm__("pref @%0" : : "r"(d));
|
||||
d += 8;
|
||||
}
|
||||
|
||||
/* Wait for both store queues to complete */
|
||||
d = (GLuint *)0xe0000000;
|
||||
d[0] = d[8] = 0;
|
||||
}
|
||||
|
||||
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 },
|
||||
PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
|
||||
0, /* No DMA */
|
||||
0, /* No FSAA */
|
||||
1 /* Disable translucent auto-sorting to match traditional GL */
|
||||
};
|
||||
|
||||
pvr_init(¶ms);
|
||||
}
|
||||
|
||||
|
||||
PolyList* activePolyList() {
|
||||
if(isBlendingEnabled()) {
|
||||
return &TR_LIST;
|
||||
} else {
|
||||
return &OP_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glKosInit() {
|
||||
TRACE();
|
||||
|
||||
_initPVR();
|
||||
|
||||
initMatrices();
|
||||
initAttributePointers();
|
||||
initContext();
|
||||
initLights();
|
||||
initImmediateMode();
|
||||
|
||||
_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 APIENTRY glKosSwapBuffers() {
|
||||
TRACE();
|
||||
|
||||
pvr_wait_ready();
|
||||
|
||||
pvr_scene_begin();
|
||||
pvr_list_begin(PVR_LIST_OP_POLY);
|
||||
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.vector.data, PT_LIST.vector.size);
|
||||
pvr_list_finish();
|
||||
|
||||
pvr_list_begin(PVR_LIST_TR_POLY);
|
||||
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);
|
||||
}
|
74
GL/fog.c
Normal file
74
GL/fog.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
#include <limits.h>
|
||||
#include "private.h"
|
||||
|
||||
static GLfloat FOG_START = 0.0f;
|
||||
static GLfloat FOG_END = 1.0f;
|
||||
static GLfloat FOG_DENSITY = 1.0f;
|
||||
static GLenum FOG_MODE = GL_EXP;
|
||||
static GLfloat FOG_COLOR [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
static void updatePVRFog() {
|
||||
if(FOG_MODE == GL_LINEAR) {
|
||||
pvr_fog_table_linear(FOG_START, FOG_END);
|
||||
} else if(FOG_MODE == GL_EXP) {
|
||||
pvr_fog_table_exp(FOG_DENSITY);
|
||||
} else if(FOG_MODE == GL_EXP2) {
|
||||
pvr_fog_table_exp2(FOG_DENSITY);
|
||||
}
|
||||
pvr_fog_table_color(FOG_COLOR[3], FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2]);
|
||||
}
|
||||
|
||||
void APIENTRY glFogf(GLenum pname, GLfloat param) {
|
||||
switch(pname) {
|
||||
case GL_FOG_MODE: {
|
||||
FOG_MODE = (GLenum) param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_DENSITY: {
|
||||
FOG_DENSITY = param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_START: {
|
||||
FOG_START = param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_END: {
|
||||
FOG_END = param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_INDEX:
|
||||
default: {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogi(GLenum pname, GLint param) {
|
||||
glFogf(pname, (GLfloat) param);
|
||||
}
|
||||
|
||||
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
|
||||
if(pname == GL_FOG_COLOR) {
|
||||
FOG_COLOR[0] = params[0];
|
||||
FOG_COLOR[1] = params[1];
|
||||
FOG_COLOR[2] = params[2];
|
||||
FOG_COLOR[3] = params[3];
|
||||
updatePVRFog();
|
||||
} else {
|
||||
glFogf(pname, *params);
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
|
||||
if(pname == GL_FOG_COLOR) {
|
||||
FOG_COLOR[0] = ((GLfloat) params[0]) / (GLfloat) INT_MAX;
|
||||
FOG_COLOR[1] = ((GLfloat) params[1]) / (GLfloat) INT_MAX;
|
||||
FOG_COLOR[2] = ((GLfloat) params[2]) / (GLfloat) INT_MAX;
|
||||
FOG_COLOR[3] = ((GLfloat) params[3]) / (GLfloat) INT_MAX;
|
||||
updatePVRFog();
|
||||
} else {
|
||||
glFogi(pname, *params);
|
||||
}
|
||||
}
|
33
GL/framebuffer.c
Normal file
33
GL/framebuffer.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "private.h"
|
||||
|
||||
static GLuint ACTIVE_FRAMEBUFFER = 0;
|
||||
static NamedArray FRAMEBUFFERS;
|
||||
|
||||
|
||||
void APIENTRY glGenFramebuffersEXT(GLsizei n, GLuint* framebuffers) {
|
||||
|
||||
}
|
||||
|
||||
void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers) {
|
||||
|
||||
}
|
||||
|
||||
void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
|
||||
|
||||
}
|
||||
|
||||
void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
|
||||
|
||||
}
|
||||
|
||||
void APIENTRY glGenerateMipmapEXT(GLenum target) {
|
||||
|
||||
}
|
||||
|
||||
GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target) {
|
||||
|
||||
}
|
||||
|
||||
GLboolean APIENTRY glIsFramebufferEXT(GLuint framebuffer) {
|
||||
|
||||
}
|
182
GL/immediate.c
Normal file
182
GL/immediate.c
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* This implements immediate mode over the top of glDrawArrays
|
||||
* current problems:
|
||||
*
|
||||
* 1. Calling glNormal(); glVertex(); glVertex(); glVertex(); will break.
|
||||
* 2. Mixing with glXPointer stuff will break badly
|
||||
* 3. This is entirely untested.
|
||||
*/
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "private.h"
|
||||
|
||||
static GLboolean IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
static GLenum ACTIVE_POLYGON_MODE = GL_TRIANGLES;
|
||||
|
||||
static AlignedVector VERTICES;
|
||||
static AlignedVector COLOURS;
|
||||
static AlignedVector TEXCOORDS;
|
||||
static AlignedVector NORMALS;
|
||||
|
||||
|
||||
static GLfloat NORMAL[3] = {0.0f, 0.0f, 1.0f};
|
||||
static GLfloat COLOR[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
static GLfloat TEXCOORD[2] = {0.0f, 0.0f};
|
||||
|
||||
|
||||
void initImmediateMode() {
|
||||
aligned_vector_init(&VERTICES, sizeof(GLfloat));
|
||||
aligned_vector_init(&COLOURS, sizeof(GLfloat));
|
||||
aligned_vector_init(&TEXCOORDS, sizeof(GLfloat));
|
||||
aligned_vector_init(&NORMALS, sizeof(GLfloat));
|
||||
}
|
||||
|
||||
GLubyte checkImmediateModeInactive(const char* func) {
|
||||
/* Returns 1 on error */
|
||||
if(IMMEDIATE_MODE_ACTIVE) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, func);
|
||||
_glKosPrintError();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void APIENTRY glBegin(GLenum mode) {
|
||||
if(IMMEDIATE_MODE_ACTIVE) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
IMMEDIATE_MODE_ACTIVE = GL_TRUE;
|
||||
ACTIVE_POLYGON_MODE = mode;
|
||||
}
|
||||
|
||||
void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
COLOR[0] = r;
|
||||
COLOR[1] = g;
|
||||
COLOR[2] = b;
|
||||
COLOR[3] = a;
|
||||
}
|
||||
|
||||
void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
|
||||
glColor4f(
|
||||
((GLfloat) r) / 255.0f,
|
||||
((GLfloat) g) / 255.0f,
|
||||
((GLfloat) b) / 255.0f,
|
||||
((GLfloat) a) / 255.0f
|
||||
);
|
||||
}
|
||||
|
||||
void APIENTRY glColor4fv(const GLfloat* v) {
|
||||
glColor4f(v[0], v[1], v[2], v[3]);
|
||||
}
|
||||
|
||||
void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) {
|
||||
static float a = 1.0f;
|
||||
glColor4f(r, g, b, a);
|
||||
}
|
||||
|
||||
void APIENTRY glColor3fv(const GLfloat* v) {
|
||||
glColor3f(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
aligned_vector_push_back(&VERTICES, &x, 1);
|
||||
aligned_vector_push_back(&VERTICES, &y, 1);
|
||||
aligned_vector_push_back(&VERTICES, &z, 1);
|
||||
|
||||
|
||||
/* Push back the stashed colour, normal and texcoord */
|
||||
aligned_vector_push_back(&COLOURS, COLOR, 4);
|
||||
aligned_vector_push_back(&TEXCOORDS, TEXCOORD, 2);
|
||||
aligned_vector_push_back(&NORMALS, NORMAL, 3);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3fv(const GLfloat* v) {
|
||||
glVertex3f(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex2f(GLfloat x, GLfloat y) {
|
||||
glVertex3f(x, y, 0.0f);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex2fv(const GLfloat* v) {
|
||||
glVertex2f(v[0], v[1]);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
|
||||
glVertex3f(x, y, z);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex4fv(const GLfloat* v) {
|
||||
glVertex4f(v[0], v[1], v[2], v[3]);
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoord2f(GLfloat u, GLfloat v) {
|
||||
TEXCOORD[0] = u;
|
||||
TEXCOORD[1] = v;
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoord2fv(const GLfloat* v) {
|
||||
glTexCoord2f(v[0], v[1]);
|
||||
}
|
||||
|
||||
void APIENTRY glNormal3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
NORMAL[0] = x;
|
||||
NORMAL[1] = y;
|
||||
NORMAL[2] = z;
|
||||
}
|
||||
|
||||
void APIENTRY glNormal3fv(const GLfloat* v) {
|
||||
glNormal3f(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
void APIENTRY glEnd() {
|
||||
IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
|
||||
/* FIXME: Push pointer state */
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, VERTICES.data);
|
||||
glColorPointer(4, GL_FLOAT, 0, COLOURS.data);
|
||||
glNormalPointer(GL_FLOAT, 0, NORMALS.data);
|
||||
|
||||
glClientActiveTextureARB(GL_TEXTURE0);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORDS.data);
|
||||
|
||||
glDrawArrays(ACTIVE_POLYGON_MODE, 0, VERTICES.size / 3);
|
||||
|
||||
aligned_vector_clear(&VERTICES);
|
||||
aligned_vector_clear(&COLOURS);
|
||||
aligned_vector_clear(&TEXCOORDS);
|
||||
aligned_vector_clear(&NORMALS);
|
||||
|
||||
/* FIXME: Pop pointers */
|
||||
}
|
||||
|
||||
void APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(x1, y1);
|
||||
glVertex2f(x2, y1);
|
||||
glVertex2f(x2, y2);
|
||||
glVertex2f(x1, y2);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void APIENTRY glRectfv(const GLfloat *v1, const GLfloat *v2) {
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(v1[0], v1[1]);
|
||||
glVertex2f(v2[0], v1[1]);
|
||||
glVertex2f(v2[0], v2[1]);
|
||||
glVertex2f(v1[0], v2[1]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void APIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2) {
|
||||
return glRectf((GLfloat)x1, (GLfloat)y1, (GLfloat)x2, (GLfloat)y2);
|
||||
}
|
||||
|
||||
void APIENTRY glRectiv(const GLint *v1, const GLint *v2) {
|
||||
return glRectfv((const GLfloat *)v1, (const GLfloat *)v2);
|
||||
}
|
280
GL/lighting.c
Normal file
280
GL/lighting.c
Normal file
|
@ -0,0 +1,280 @@
|
|||
#include <stdio.h>
|
||||
#include <dc/vec3f.h>
|
||||
#include "private.h"
|
||||
|
||||
static GLfloat SCENE_AMBIENT [] = {0.2, 0.2, 0.2, 1.0};
|
||||
static GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE;
|
||||
static GLenum COLOR_CONTROL = GL_SINGLE_COLOR;
|
||||
static GLboolean TWO_SIDED_LIGHTING = GL_FALSE;
|
||||
|
||||
static LightSource LIGHTS[MAX_LIGHTS];
|
||||
static Material MATERIAL;
|
||||
|
||||
void initLights() {
|
||||
static GLfloat ONE [] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
static GLfloat ZERO [] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
static GLfloat PARTIAL [] = {0.2f, 0.2f, 0.2f, 1.0f};
|
||||
static GLfloat MOSTLY [] = {0.8f, 0.8f, 0.8f, 1.0f};
|
||||
|
||||
memcpy(MATERIAL.ambient, PARTIAL, sizeof(GLfloat) * 4);
|
||||
memcpy(MATERIAL.diffuse, MOSTLY, sizeof(GLfloat) * 4);
|
||||
memcpy(MATERIAL.specular, ZERO, sizeof(GLfloat) * 4);
|
||||
memcpy(MATERIAL.emissive, ZERO, sizeof(GLfloat) * 4);
|
||||
MATERIAL.exponent = 0.0f;
|
||||
|
||||
GLubyte i;
|
||||
for(i = 0; i < MAX_LIGHTS; ++i) {
|
||||
memcpy(LIGHTS[i].ambient, ZERO, sizeof(GLfloat) * 4);
|
||||
memcpy(LIGHTS[i].diffuse, ONE, sizeof(GLfloat) * 4);
|
||||
memcpy(LIGHTS[i].specular, ONE, sizeof(GLfloat) * 4);
|
||||
|
||||
if(i > 0) {
|
||||
memcpy(LIGHTS[i].diffuse, ZERO, sizeof(GLfloat) * 4);
|
||||
memcpy(LIGHTS[i].specular, ZERO, sizeof(GLfloat) * 4);
|
||||
}
|
||||
|
||||
LIGHTS[i].position[0] = LIGHTS[i].position[1] = LIGHTS[i].position[3] = 0.0f;
|
||||
LIGHTS[i].position[2] = 1.0f;
|
||||
|
||||
LIGHTS[i].spot_direction[0] = LIGHTS[i].spot_direction[1] = 0.0f;
|
||||
LIGHTS[i].spot_direction[2] = -1.0f;
|
||||
|
||||
LIGHTS[i].spot_exponent = 0.0f;
|
||||
LIGHTS[i].spot_cutoff = 180.0f;
|
||||
|
||||
LIGHTS[i].constant_attenuation = 1.0f;
|
||||
LIGHTS[i].linear_attenuation = 0.0f;
|
||||
LIGHTS[i].quadratic_attenuation = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glLightModelf(GLenum pname, const GLfloat param) {
|
||||
glLightModelfv(pname, ¶m);
|
||||
}
|
||||
|
||||
void APIENTRY glLightModeli(GLenum pname, const GLint param) {
|
||||
glLightModeliv(pname, ¶m);
|
||||
}
|
||||
|
||||
void APIENTRY glLightModelfv(GLenum pname, const GLfloat *params) {
|
||||
switch(pname) {
|
||||
case GL_LIGHT_MODEL_AMBIENT:
|
||||
memcpy(SCENE_AMBIENT, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_LIGHT_MODEL_LOCAL_VIEWER:
|
||||
VIEWER_IN_EYE_COORDINATES = (*params) ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
case GL_LIGHT_MODEL_TWO_SIDE:
|
||||
/* Not implemented */
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glLightModeliv(GLenum pname, const GLint* params) {
|
||||
switch(pname) {
|
||||
case GL_LIGHT_MODEL_COLOR_CONTROL:
|
||||
COLOR_CONTROL = *params;
|
||||
break;
|
||||
case GL_LIGHT_MODEL_LOCAL_VIEWER:
|
||||
VIEWER_IN_EYE_COORDINATES = (*params) ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
|
||||
GLubyte idx = light & 0xF;
|
||||
|
||||
if(idx >= MAX_LIGHTS) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(pname) {
|
||||
case GL_AMBIENT:
|
||||
memcpy(LIGHTS[idx].ambient, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_DIFFUSE:
|
||||
memcpy(LIGHTS[idx].diffuse, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
memcpy(LIGHTS[idx].specular, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_POSITION:
|
||||
memcpy(LIGHTS[idx].position, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
case GL_SPOT_CUTOFF:
|
||||
case GL_SPOT_DIRECTION:
|
||||
case GL_SPOT_EXPONENT:
|
||||
glLightf(light, pname, *params);
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) {
|
||||
GLubyte idx = light & 0xF;
|
||||
|
||||
if(idx >= MAX_LIGHTS) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(pname) {
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
LIGHTS[idx].constant_attenuation = param;
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
LIGHTS[idx].linear_attenuation = param;
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
LIGHTS[idx].quadratic_attenuation = param;
|
||||
break;
|
||||
case GL_SPOT_EXPONENT:
|
||||
case GL_SPOT_CUTOFF:
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param) {
|
||||
if(face == GL_BACK || pname != GL_SHININESS) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
MATERIAL.exponent = param;
|
||||
}
|
||||
|
||||
void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param) {
|
||||
glMaterialf(face, pname, param);
|
||||
}
|
||||
|
||||
void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
|
||||
if(pname == GL_SHININESS) {
|
||||
glMaterialf(face, pname, *params);
|
||||
return;
|
||||
}
|
||||
|
||||
if(face == GL_BACK) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
switch(pname) {
|
||||
case GL_AMBIENT:
|
||||
memcpy(MATERIAL.ambient, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_DIFFUSE:
|
||||
memcpy(MATERIAL.diffuse, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_EMISSION:
|
||||
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_AMBIENT_AND_DIFFUSE: {
|
||||
glMaterialfv(face, GL_AMBIENT, params);
|
||||
glMaterialfv(face, GL_DIFFUSE, params);
|
||||
} break;
|
||||
case GL_COLOR_INDEXES:
|
||||
default: {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void initVec3(struct vec3f* v, const GLfloat* src) {
|
||||
memcpy(v, src, sizeof(GLfloat) * 3);
|
||||
}
|
||||
|
||||
/* Fast POW Implementation - Less accurate, but much faster than math.h */
|
||||
#define EXP_A 184
|
||||
#define EXP_C 16249
|
||||
|
||||
static float FEXP(float y) {
|
||||
union {
|
||||
float d;
|
||||
struct {
|
||||
short j, i;
|
||||
} n;
|
||||
} eco;
|
||||
eco.n.i = EXP_A * (y) + (EXP_C);
|
||||
eco.n.j = 0;
|
||||
return eco.d;
|
||||
}
|
||||
|
||||
static float FLOG(float y) {
|
||||
int *nTemp = (int *)&y;
|
||||
y = (*nTemp) >> 16;
|
||||
return (y - EXP_C) / EXP_A;
|
||||
}
|
||||
|
||||
static float FPOW(float b, float p) {
|
||||
return FEXP(FLOG(b) * p);
|
||||
}
|
||||
|
||||
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) __attribute__((optimize("fast-math")));
|
||||
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) {
|
||||
LightSource* l = &LIGHTS[light];
|
||||
|
||||
struct vec3f L = {
|
||||
l->position[0] - pos[0],
|
||||
l->position[1] - pos[1],
|
||||
l->position[2] - pos[2]
|
||||
};
|
||||
|
||||
struct vec3f N = {
|
||||
normal[0],
|
||||
normal[1],
|
||||
normal[2]
|
||||
};
|
||||
|
||||
struct vec3f V = {
|
||||
pos[0],
|
||||
pos[1],
|
||||
pos[2]
|
||||
};
|
||||
|
||||
GLfloat d;
|
||||
vec3f_length(V.x, V.y, V.z, d);
|
||||
|
||||
vec3f_normalize(L.x, L.y, L.z);
|
||||
vec3f_normalize(V.x, V.y, V.z);
|
||||
|
||||
GLfloat NdotL;
|
||||
vec3f_dot(N.x, N.y, N.z, L.x, L.y, L.z, NdotL);
|
||||
|
||||
GLfloat f = (NdotL < 0) ? 0 : 1;
|
||||
|
||||
GLfloat VdotN;
|
||||
vec3f_dot(V.x, V.y, V.z, N.x, N.y, N.z, VdotN);
|
||||
|
||||
GLfloat VdotR = VdotN - NdotL;
|
||||
GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent);
|
||||
|
||||
GLfloat att = (l->position[3] == 0) ? 1.0f : (
|
||||
l->constant_attenuation / (1.0f + l->linear_attenuation * d) * (1.0f + l->quadratic_attenuation * d * d)
|
||||
);
|
||||
|
||||
colour[0] = att * l->ambient[0] * MATERIAL.ambient[0] + f * (l->diffuse[0] * MATERIAL.diffuse[0] * NdotL + l->specular[0] * MATERIAL.specular[0] * specularPower);
|
||||
colour[1] = att * l->ambient[1] * MATERIAL.ambient[1] + f * (l->diffuse[1] * MATERIAL.diffuse[1] * NdotL + l->specular[1] * MATERIAL.specular[1] * specularPower);
|
||||
colour[2] = att * l->ambient[2] * MATERIAL.ambient[2] + f * (l->diffuse[2] * MATERIAL.diffuse[2] * NdotL + l->specular[2] * MATERIAL.specular[2] * specularPower);
|
||||
colour[3] = MATERIAL.diffuse[3];
|
||||
|
||||
if(colour[0] > 1.0f) colour[0] = 1.0f;
|
||||
if(colour[1] > 1.0f) colour[1] = 1.0f;
|
||||
if(colour[2] > 1.0f) colour[2] = 1.0f;
|
||||
if(colour[3] > 1.0f) colour[3] = 1.0f;
|
||||
}
|
416
GL/matrix.c
Normal file
416
GL/matrix.c
Normal file
|
@ -0,0 +1,416 @@
|
|||
#include <dc/matrix.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../containers/stack.h"
|
||||
|
||||
#define DEG2RAD (0.01745329251994329576923690768489)
|
||||
|
||||
/* Viewport mapping */
|
||||
static GLfloat gl_viewport_scale[3], gl_viewport_offset[3];
|
||||
|
||||
/* Depth range */
|
||||
static GLclampf gl_depthrange_near, gl_depthrange_far;
|
||||
|
||||
/* Viewport size */
|
||||
static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height;
|
||||
|
||||
static Stack MATRIX_STACKS[3]; // modelview, projection, texture
|
||||
static matrix_t NORMAL_MATRIX __attribute__((aligned(32)));
|
||||
static matrix_t SCREENVIEW_MATRIX __attribute__((aligned(32)));
|
||||
static matrix_t RENDER_MATRIX __attribute__((aligned(32)));
|
||||
|
||||
static GLenum MATRIX_MODE = GL_MODELVIEW;
|
||||
static GLubyte MATRIX_IDX = 0;
|
||||
|
||||
static const matrix_t IDENTITY = {
|
||||
{1.0f, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, 1.0f, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 1.0f}
|
||||
};
|
||||
|
||||
void APIENTRY glDepthRange(GLclampf n, GLclampf f);
|
||||
|
||||
void initMatrices() {
|
||||
init_stack(&MATRIX_STACKS[0], sizeof(matrix_t), 32);
|
||||
init_stack(&MATRIX_STACKS[1], sizeof(matrix_t), 32);
|
||||
init_stack(&MATRIX_STACKS[2], sizeof(matrix_t), 32);
|
||||
|
||||
stack_push(&MATRIX_STACKS[0], IDENTITY);
|
||||
stack_push(&MATRIX_STACKS[1], IDENTITY);
|
||||
stack_push(&MATRIX_STACKS[2], IDENTITY);
|
||||
|
||||
memcpy(NORMAL_MATRIX, IDENTITY, sizeof(matrix_t));
|
||||
memcpy(SCREENVIEW_MATRIX, IDENTITY, sizeof(matrix_t));
|
||||
|
||||
glDepthRange(0.0f, 1.0f);
|
||||
glViewport(0, 0, vid_mode->width, vid_mode->height);
|
||||
}
|
||||
|
||||
#define swap(a, b) { \
|
||||
GLfloat x = (a); \
|
||||
a = b; \
|
||||
b = x; \
|
||||
}
|
||||
|
||||
static void inverse(GLfloat* m) {
|
||||
GLfloat f4 = m[4];
|
||||
GLfloat f8 = m[8];
|
||||
GLfloat f1 = m[1];
|
||||
GLfloat f9 = m[9];
|
||||
GLfloat f2 = m[2];
|
||||
GLfloat f6 = m[6];
|
||||
GLfloat f12 = m[12];
|
||||
GLfloat f13 = m[13];
|
||||
GLfloat f14 = m[14];
|
||||
|
||||
m[1] = f4;
|
||||
m[2] = f8;
|
||||
m[4] = f1;
|
||||
m[6] = f9;
|
||||
m[8] = f2;
|
||||
m[9] = f6;
|
||||
m[12] = -(f12 * m[0] + f13 * m[4] + f14 * m[8]);
|
||||
m[13] = -(f12 * m[1] + f13 * m[5] + f14 * m[9]);
|
||||
m[14] = -(f12 * m[2] + f13 * m[6] + f14 * m[10]);
|
||||
}
|
||||
|
||||
static void transpose(GLfloat* m) {
|
||||
swap(m[1], m[4]);
|
||||
swap(m[2], m[8]);
|
||||
swap(m[3], m[12]);
|
||||
swap(m[6], m[9]);
|
||||
swap(m[7], m[3]);
|
||||
swap(m[11], m[14]);
|
||||
}
|
||||
|
||||
static void recalculateNormalMatrix() {
|
||||
memcpy(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(matrix_t));
|
||||
inverse((GLfloat*) NORMAL_MATRIX);
|
||||
transpose((GLfloat*) NORMAL_MATRIX);
|
||||
}
|
||||
|
||||
void APIENTRY glMatrixMode(GLenum mode) {
|
||||
MATRIX_MODE = mode;
|
||||
MATRIX_IDX = mode & 0xF;
|
||||
}
|
||||
|
||||
void APIENTRY glPushMatrix() {
|
||||
stack_push(MATRIX_STACKS + MATRIX_IDX, stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
}
|
||||
|
||||
void APIENTRY glPopMatrix() {
|
||||
stack_pop(MATRIX_STACKS + MATRIX_IDX);
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glLoadIdentity() {
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, IDENTITY);
|
||||
}
|
||||
|
||||
void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
mat_translate(x, y, z);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
mat_scale(x, y, z);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
float r = DEG2RAD * -angle;
|
||||
|
||||
vec3f_normalize(x, y, z);
|
||||
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
mat_rotate(r * x, r * y, r * z);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an arbitrary matrix */
|
||||
void APIENTRY glLoadMatrixf(const GLfloat *m) {
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, m);
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Ortho */
|
||||
void APIENTRY glOrtho(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
|
||||
/* Ortho Matrix */
|
||||
static matrix_t OrthoMatrix __attribute__((aligned(32))) = {
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
OrthoMatrix[0][0] = 2.0f / (right - left);
|
||||
OrthoMatrix[1][1] = 2.0f / (top - bottom);
|
||||
OrthoMatrix[2][2] = -2.0f / (zfar - znear);
|
||||
OrthoMatrix[3][0] = -(right + left) / (right - left);;
|
||||
OrthoMatrix[3][1] = -(top + bottom) / (top - bottom);
|
||||
OrthoMatrix[3][2] = -(zfar + znear) / (zfar - znear);
|
||||
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_MODE));
|
||||
mat_apply(&OrthoMatrix);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_MODE));
|
||||
}
|
||||
|
||||
|
||||
/* Set the GL frustum */
|
||||
void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
|
||||
/* Frustum Matrix */
|
||||
static matrix_t FrustumMatrix __attribute__((aligned(32))) = {
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, -1.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f }
|
||||
};
|
||||
|
||||
FrustumMatrix[0][0] = (2.0f * znear) / (right - left);
|
||||
FrustumMatrix[2][0] = (right + left) / (right - left);
|
||||
FrustumMatrix[1][1] = (2.0f * znear) / (top - bottom);
|
||||
FrustumMatrix[2][1] = (top + bottom) / (top - bottom);
|
||||
FrustumMatrix[2][2] = zfar / (zfar - znear);
|
||||
FrustumMatrix[3][2] = -(zfar * znear) / (zfar - znear);
|
||||
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
mat_apply(&FrustumMatrix);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
}
|
||||
|
||||
/* Set the Perspective */
|
||||
void gluPerspective(GLfloat angle, GLfloat aspect,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
GLfloat xmin, xmax, ymin, ymax;
|
||||
|
||||
ymax = znear * ftan(angle * F_PI / 360.0f);
|
||||
ymin = -ymax;
|
||||
xmin = ymin * aspect;
|
||||
xmax = ymax * aspect;
|
||||
|
||||
glFrustum(xmin, xmax, ymin, ymax, znear, zfar);
|
||||
}
|
||||
|
||||
/* Multiply the current matrix by an arbitrary matrix */
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
static matrix_t TEMP __attribute__((aligned(32))) = {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
memcpy(TEMP, m, sizeof(matrix_t));
|
||||
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
mat_apply(&TEMP);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an arbitrary transposed matrix */
|
||||
void glLoadTransposeMatrixf(const GLfloat *m) {
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, m);
|
||||
transpose(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiply the current matrix by an arbitrary transposed matrix */
|
||||
void glMultTransposeMatrixf(const GLfloat *m) {
|
||||
static matrix_t ml;
|
||||
|
||||
ml[0][0] = m[0];
|
||||
ml[0][1] = m[4];
|
||||
ml[0][2] = m[8];
|
||||
ml[0][3] = m[12];
|
||||
ml[1][0] = m[1];
|
||||
ml[1][1] = m[5];
|
||||
ml[1][2] = m[9];
|
||||
ml[1][3] = m[13];
|
||||
ml[2][0] = m[2];
|
||||
ml[2][1] = m[6];
|
||||
ml[2][2] = m[10];
|
||||
ml[2][3] = m[14];
|
||||
ml[3][0] = m[3];
|
||||
ml[3][1] = m[7];
|
||||
ml[3][2] = m[11];
|
||||
ml[3][3] = m[15];
|
||||
|
||||
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
mat_apply(&ml);
|
||||
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the GL viewport */
|
||||
void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
gl_viewport_x1 = x;
|
||||
gl_viewport_y1 = y;
|
||||
gl_viewport_width = width;
|
||||
gl_viewport_height = height;
|
||||
|
||||
/* Calculate the viewport scale and offset */
|
||||
gl_viewport_scale[0] = (GLfloat)width / 2.0f;
|
||||
gl_viewport_offset[0] = gl_viewport_scale[0] + (GLfloat)x;
|
||||
gl_viewport_scale[1] = (GLfloat)height / 2.0f;
|
||||
gl_viewport_offset[1] = gl_viewport_scale[1] + (GLfloat)y;
|
||||
gl_viewport_scale[2] = (gl_depthrange_far - gl_depthrange_near) / 2.0f;
|
||||
gl_viewport_offset[2] = (gl_depthrange_near + gl_depthrange_far) / 2.0f;
|
||||
|
||||
gl_viewport_offset[2] += 0.0001f;
|
||||
|
||||
/* Set the Screenview Matrix based on the viewport */
|
||||
SCREENVIEW_MATRIX[0][0] = gl_viewport_scale[0];
|
||||
SCREENVIEW_MATRIX[1][1] = -gl_viewport_scale[1];
|
||||
SCREENVIEW_MATRIX[2][2] = 1;
|
||||
SCREENVIEW_MATRIX[3][0] = gl_viewport_offset[0];
|
||||
SCREENVIEW_MATRIX[3][1] = vid_mode->height - gl_viewport_offset[1];
|
||||
}
|
||||
|
||||
/* Set the depth range */
|
||||
void APIENTRY glDepthRange(GLclampf n, GLclampf f) {
|
||||
/* clamp the values... */
|
||||
if(n < 0.0f) n = 0.0f;
|
||||
else if(n > 1.0f) n = 1.0f;
|
||||
|
||||
if(f < 0.0f) f = 0.0f;
|
||||
else if(f > 1.0f) f = 1.0f;
|
||||
|
||||
gl_depthrange_near = n;
|
||||
gl_depthrange_far = f;
|
||||
|
||||
/* Adjust the viewport scale and offset for Z */
|
||||
gl_viewport_scale[2] = ((f - n) / 2.0f);
|
||||
gl_viewport_offset[2] = (n + f) / 2.0f;
|
||||
}
|
||||
|
||||
/* Vector Cross Product - Used by glhLookAtf2 */
|
||||
static inline void vec3f_cross(const GLfloat* v1, const GLfloat* v2, GLfloat* result) {
|
||||
result[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
||||
result[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
||||
result[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
||||
}
|
||||
|
||||
/* glhLookAtf2 adapted from http://www.opengl.org/wiki/GluLookAt_code */
|
||||
void glhLookAtf2(const GLfloat* eyePosition3D,
|
||||
const GLfloat* center3D,
|
||||
const GLfloat* upVector3D) {
|
||||
|
||||
/* Look-At Matrix */
|
||||
static matrix_t MatrixLookAt __attribute__((aligned(32))) = {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
GLfloat forward[3];
|
||||
GLfloat side[3];
|
||||
GLfloat up[3];
|
||||
|
||||
vec3f_sub_normalize(center3D[0], center3D[1], center3D[2],
|
||||
eyePosition3D[0], eyePosition3D[1], eyePosition3D[2],
|
||||
forward[0], forward[1], forward[2]);
|
||||
|
||||
//Side = forward x up
|
||||
vec3f_cross(forward, upVector3D, side);
|
||||
vec3f_normalize(side[0], side[1], side[2]);
|
||||
|
||||
//Recompute up as: up = side x forward
|
||||
vec3f_cross(side, forward, up);
|
||||
|
||||
MatrixLookAt[0][0] = side[0];
|
||||
MatrixLookAt[1][0] = side[1];
|
||||
MatrixLookAt[2][0] = side[2];
|
||||
MatrixLookAt[3][0] = 0;
|
||||
|
||||
MatrixLookAt[0][1] = up[0];
|
||||
MatrixLookAt[1][1] = up[1];
|
||||
MatrixLookAt[2][1] = up[2];
|
||||
MatrixLookAt[3][1] = 0;
|
||||
|
||||
MatrixLookAt[0][2] = -forward[0];
|
||||
MatrixLookAt[1][2] = -forward[1];
|
||||
MatrixLookAt[2][2] = -forward[2];
|
||||
MatrixLookAt[3][2] = 0;
|
||||
|
||||
MatrixLookAt[0][3] =
|
||||
MatrixLookAt[1][3] =
|
||||
MatrixLookAt[2][3] = 0;
|
||||
MatrixLookAt[3][3] = 1;
|
||||
|
||||
// Does not modify internal Modelview matrix
|
||||
mat_load(&MatrixLookAt);
|
||||
mat_translate(-eyePosition3D[0], -eyePosition3D[1], -eyePosition3D[2]);
|
||||
|
||||
mat_apply(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
mat_store(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
|
||||
GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
|
||||
GLfloat upz) {
|
||||
GLfloat eye [] = { eyex, eyey, eyez };
|
||||
GLfloat point [] = { centerx, centery, centerz };
|
||||
GLfloat up [] = { upx, upy, upz };
|
||||
glhLookAtf2(eye, point, up);
|
||||
}
|
||||
|
||||
void _applyRenderMatrix() {
|
||||
mat_load(&SCREENVIEW_MATRIX);
|
||||
mat_apply(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
|
||||
mat_apply(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
mat_store(&RENDER_MATRIX);
|
||||
}
|
||||
|
||||
void _matrixLoadRender() {
|
||||
mat_load(&RENDER_MATRIX);
|
||||
}
|
||||
|
||||
void _matrixLoadTexture() {
|
||||
mat_load(stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF)));
|
||||
}
|
||||
|
||||
void _matrixLoadModelView() {
|
||||
mat_load(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
void _matrixLoadNormal() {
|
||||
mat_load(&NORMAL_MATRIX);
|
||||
}
|
116
GL/private.h
Normal file
116
GL/private.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
#ifndef PRIVATE_H
|
||||
#define PRIVATE_H
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../containers/aligned_vector.h"
|
||||
#include "../containers/named_array.h"
|
||||
|
||||
|
||||
#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;
|
||||
|
||||
typedef struct {
|
||||
GLfloat emissive[4];
|
||||
GLfloat ambient[4];
|
||||
GLfloat diffuse[4];
|
||||
GLfloat specular[4];
|
||||
GLfloat exponent;
|
||||
} Material;
|
||||
|
||||
typedef struct {
|
||||
GLfloat position[4];
|
||||
GLfloat spot_direction[3];
|
||||
GLfloat spot_cutoff;
|
||||
GLfloat constant_attenuation;
|
||||
GLfloat linear_attenuation;
|
||||
GLfloat quadratic_attenuation;
|
||||
GLfloat spot_exponent;
|
||||
GLfloat diffuse[4];
|
||||
GLfloat specular[4];
|
||||
GLfloat ambient[4];
|
||||
} LightSource;
|
||||
|
||||
|
||||
PolyList *activePolyList();
|
||||
|
||||
void initAttributePointers();
|
||||
void initContext();
|
||||
void initLights();
|
||||
void initImmediateMode();
|
||||
void initMatrices();
|
||||
|
||||
void _matrixLoadNormal();
|
||||
void _matrixLoadModelView();
|
||||
void _matrixLoadTexture();
|
||||
void _matrixLoadRender();
|
||||
void _applyRenderMatrix();
|
||||
|
||||
GLubyte checkImmediateModeInactive(const char* func);
|
||||
|
||||
pvr_poly_cxt_t* getPVRContext();
|
||||
GLubyte _glKosInitTextures();
|
||||
void updatePVRTextureContext(pvr_poly_cxt_t* context, TextureObject* tx1);
|
||||
TextureObject* getTexture0();
|
||||
TextureObject* getTexture1();
|
||||
TextureObject* getBoundTexture();
|
||||
GLboolean isBlendingEnabled();
|
||||
|
||||
GLboolean isLightingEnabled();
|
||||
GLboolean isLightEnabled(GLubyte light);
|
||||
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour);
|
||||
|
||||
void _glKosThrowError(GLenum error, const char *function);
|
||||
void _glKosPrintError();
|
||||
GLubyte _glKosHasError();
|
||||
|
||||
#define PVR_VERTEX_BUF_SIZE 2560 * 256
|
||||
#define MAX_TEXTURE_UNITS 2
|
||||
#define MAX_LIGHTS 8
|
||||
|
||||
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
|
||||
|
||||
#define mat_trans_fv12() { \
|
||||
__asm__ __volatile__( \
|
||||
"fldi1 fr15\n" \
|
||||
"ftrv xmtrx, fv12\n" \
|
||||
"fldi1 fr14\n" \
|
||||
"fdiv fr15, fr14\n" \
|
||||
"fmul fr14, fr12\n" \
|
||||
"fmul fr14, fr13\n" \
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z) \
|
||||
: "0" (__x), "1" (__y), "2" (__z) \
|
||||
: "fr15" ); \
|
||||
}
|
||||
|
||||
#endif // PRIVATE_H
|
449
GL/state.c
Normal file
449
GL/state.c
Normal file
|
@ -0,0 +1,449 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dc/pvr.h>
|
||||
#include <dc/vec3f.h>
|
||||
#include <dc/video.h>
|
||||
|
||||
#include "../include/gl.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. */
|
||||
static GLenum CULL_FACE = GL_BACK;
|
||||
static GLenum FRONT_FACE = GL_CCW;
|
||||
static GLboolean CULLING_ENABLED = GL_FALSE;
|
||||
|
||||
static int _calc_pvr_face_culling() {
|
||||
if(!CULLING_ENABLED) {
|
||||
return PVR_CULLING_NONE;
|
||||
} else {
|
||||
if(CULL_FACE == GL_BACK) {
|
||||
return (FRONT_FACE == GL_CW) ? PVR_CULLING_CCW : PVR_CULLING_CW;
|
||||
} else {
|
||||
return (FRONT_FACE == GL_CCW) ? PVR_CULLING_CCW : PVR_CULLING_CW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum DEPTH_FUNC = GL_LESS;
|
||||
static GLboolean DEPTH_TEST_ENABLED = GL_FALSE;
|
||||
|
||||
static int _calc_pvr_depth_test() {
|
||||
if(!DEPTH_TEST_ENABLED) {
|
||||
return PVR_DEPTHCMP_ALWAYS;
|
||||
}
|
||||
|
||||
switch(DEPTH_FUNC) {
|
||||
case GL_NEVER:
|
||||
return PVR_DEPTHCMP_NEVER;
|
||||
case GL_LESS:
|
||||
return PVR_DEPTHCMP_GEQUAL;
|
||||
case GL_EQUAL:
|
||||
return PVR_DEPTHCMP_EQUAL;
|
||||
case GL_LEQUAL:
|
||||
return PVR_DEPTHCMP_GREATER;
|
||||
case GL_GREATER:
|
||||
return PVR_DEPTHCMP_LEQUAL;
|
||||
case GL_NOTEQUAL:
|
||||
return PVR_DEPTHCMP_NOTEQUAL;
|
||||
case GL_GEQUAL:
|
||||
return PVR_DEPTHCMP_LESS;
|
||||
break;
|
||||
case GL_ALWAYS:
|
||||
default:
|
||||
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:
|
||||
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_ALPHA:
|
||||
return PVR_BLEND_INVSRCALPHA;
|
||||
case GL_ONE_MINUS_DST_ALPHA:
|
||||
return PVR_BLEND_INVDESTALPHA;
|
||||
case GL_ONE:
|
||||
return PVR_BLEND_ONE;
|
||||
default:
|
||||
fprintf(stderr, "Invalid blend mode: %d\n", factor);
|
||||
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_TXRALPHA_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;
|
||||
context->txr.alpha = PVR_TXRALPHA_ENABLE;
|
||||
} else {
|
||||
context->txr.enable = PVR_TEXTURE_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static GLboolean LIGHTING_ENABLED = GL_FALSE;
|
||||
static GLboolean LIGHT_ENABLED[MAX_LIGHTS];
|
||||
|
||||
GLboolean isLightingEnabled() {
|
||||
return LIGHTING_ENABLED;
|
||||
}
|
||||
|
||||
GLboolean isLightEnabled(unsigned char light) {
|
||||
return LIGHT_ENABLED[light & 0xF];
|
||||
}
|
||||
|
||||
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);
|
||||
glFrontFace(GL_CCW);
|
||||
glCullFace(GL_BACK);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
GLubyte i;
|
||||
for(i = 0; i < MAX_LIGHTS; ++i) {
|
||||
glDisable(GL_LIGHT0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glEnable(GLenum cap) {
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D:
|
||||
TEXTURES_ENABLED = GL_TRUE;
|
||||
break;
|
||||
case GL_CULL_FACE: {
|
||||
CULLING_ENABLED = GL_TRUE;
|
||||
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
|
||||
} break;
|
||||
case GL_DEPTH_TEST: {
|
||||
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;
|
||||
case GL_LIGHTING: {
|
||||
LIGHTING_ENABLED = GL_TRUE;
|
||||
} break;
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1:
|
||||
case GL_LIGHT2:
|
||||
case GL_LIGHT3:
|
||||
case GL_LIGHT4:
|
||||
case GL_LIGHT5:
|
||||
case GL_LIGHT6:
|
||||
case GL_LIGHT7:
|
||||
LIGHT_ENABLED[cap & 0xF] = GL_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glDisable(GLenum cap) {
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D: {
|
||||
TEXTURES_ENABLED = GL_FALSE;
|
||||
} break;
|
||||
case GL_CULL_FACE: {
|
||||
CULLING_ENABLED = GL_FALSE;
|
||||
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
|
||||
} break;
|
||||
case GL_DEPTH_TEST: {
|
||||
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;
|
||||
case GL_LIGHTING: {
|
||||
LIGHTING_ENABLED = GL_FALSE;
|
||||
} break;
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1:
|
||||
case GL_LIGHT2:
|
||||
case GL_LIGHT3:
|
||||
case GL_LIGHT4:
|
||||
case GL_LIGHT5:
|
||||
case GL_LIGHT6:
|
||||
case GL_LIGHT7:
|
||||
LIGHT_ENABLED[cap & 0xF] = GL_FALSE;
|
||||
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 */
|
||||
GLAPI void APIENTRY glClearDepthf(GLfloat depth) {
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
DEPTH_FUNC = func;
|
||||
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
|
||||
}
|
||||
|
||||
/* Hints */
|
||||
/* Currently Supported Capabilities:
|
||||
GL_PERSPECTIVE_CORRECTION_HINT - This will Enable on the PVR */
|
||||
GLAPI void APIENTRY glHint(GLenum target, GLenum mode) {
|
||||
if(target == GL_PERSPECTIVE_CORRECTION_HINT && mode == GL_NICEST) {
|
||||
// FIXME: enable supersampling
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
GLboolean APIENTRY glIsEnabled(GLenum cap) {
|
||||
switch(cap) {
|
||||
case GL_DEPTH_TEST:
|
||||
return DEPTH_TEST_ENABLED;
|
||||
case GL_SCISSOR_TEST:
|
||||
return GL_CONTEXT.gen.clip_mode == PVR_USERCLIP_INSIDE;
|
||||
case GL_CULL_FACE:
|
||||
return CULLING_ENABLED;
|
||||
case GL_LIGHTING:
|
||||
return LIGHTING_ENABLED;
|
||||
case GL_BLEND:
|
||||
return BLEND_ENABLED;
|
||||
}
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
void APIENTRY glGetIntegerv(GLenum pname, GLint *params) {
|
||||
switch(pname) {
|
||||
case GL_MAX_LIGHTS:
|
||||
*params = MAX_LIGHTS;
|
||||
break;
|
||||
case GL_TEXTURE_BINDING_2D:
|
||||
*params = getBoundTexture()->index;
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glGetIntegerv");
|
||||
_glKosPrintError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const GLbyte *glGetString(GLenum name) {
|
||||
switch(name) {
|
||||
case GL_VENDOR:
|
||||
return "KallistiOS / Kazade";
|
||||
|
||||
case GL_RENDERER:
|
||||
return "PowerVR2 CLX2 100mHz";
|
||||
|
||||
case GL_VERSION:
|
||||
return "GLdc 1.x";
|
||||
|
||||
case GL_EXTENSIONS:
|
||||
return "GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg";
|
||||
}
|
||||
|
||||
return "GL_KOS_ERROR: ENUM Unsupported\n";
|
||||
}
|
|
@ -1,101 +1,73 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-texture.c
|
||||
Copyright (C) 2014 Josh Pearson
|
||||
Copyright (C) 2016 Joe Fenton
|
||||
|
||||
Open GL Texture Submission implementation.
|
||||
*/
|
||||
|
||||
#include <malloc.h>
|
||||
#include "private.h"
|
||||
#include "../include/glext.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "glext.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-rgb.h"
|
||||
#include "containers/named_array.h"
|
||||
#define CLAMP_U (1<<1)
|
||||
#define CLAMP_V (1<<0)
|
||||
|
||||
//========================================================================================//
|
||||
//== 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 };
|
||||
static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL};
|
||||
static NamedArray TEXTURE_OBJECTS;
|
||||
|
||||
static GLubyte GL_KOS_ACTIVE_TEXTURE = GL_TEXTURE0_ARB & 0xF;
|
||||
|
||||
//========================================================================================//
|
||||
static GLubyte ACTIVE_TEXTURE = 0;
|
||||
|
||||
static GLuint _determinePVRFormat(GLint internalFormat, GLenum type);
|
||||
|
||||
GLubyte _glKosInitTextures() {
|
||||
named_array_init(&TEXTURE_OBJECTS, sizeof(GL_TEXTURE_OBJECT), 256);
|
||||
named_array_init(&TEXTURE_OBJECTS, sizeof(TextureObject), 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);
|
||||
TextureObject* getTexture0() {
|
||||
return TEXTURE_UNITS[0];
|
||||
}
|
||||
|
||||
static void _glKosUnbindTexture() {
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = NULL;
|
||||
TextureObject* getTexture1() {
|
||||
return TEXTURE_UNITS[1];
|
||||
}
|
||||
|
||||
GLuint _glKosTextureWidth(GLuint index) {
|
||||
GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index);
|
||||
return tex->width;
|
||||
TextureObject* getBoundTexture() {
|
||||
return TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||
}
|
||||
|
||||
GLuint _glKosTextureHeight(GLuint index) {
|
||||
GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index);
|
||||
return tex->height;
|
||||
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;
|
||||
}
|
||||
|
||||
GLvoid *_glKosTextureData(GLuint index) {
|
||||
GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index);
|
||||
return tex->data;
|
||||
}
|
||||
|
||||
void _glKosCompileHdrTx() {
|
||||
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF] ?
|
||||
_glKosCompileHdrT(GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF]) : _glKosCompileHdr();
|
||||
}
|
||||
void APIENTRY glActiveTextureARB(GLenum texture) {
|
||||
TRACE();
|
||||
|
||||
GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject() {
|
||||
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE1_ARB & 0xF];
|
||||
}
|
||||
if(texture < GL_TEXTURE0_ARB || texture > GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glActiveTextureARB");
|
||||
|
||||
GLuint _glKosBoundMultiTexID() {
|
||||
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE1_ARB & 0xF] ?
|
||||
GL_KOS_TEXTURE_UNIT[GL_TEXTURE1_ARB & 0xF]->index : 0;
|
||||
}
|
||||
if(_glKosHasError()) {
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint _glKosBoundTexID() {
|
||||
return GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF] ?
|
||||
GL_KOS_TEXTURE_UNIT[GL_TEXTURE0_ARB & 0xF]->index : 0;
|
||||
ACTIVE_TEXTURE = texture & 0xF;
|
||||
}
|
||||
|
||||
GLuint _glKosActiveTextureBoundTexID() {
|
||||
return (GL_KOS_ACTIVE_TEXTURE) ? _glKosBoundMultiTexID() : _glKosBoundTexID();
|
||||
}
|
||||
|
||||
GLubyte _glKosMaxTextureUnits() {
|
||||
return GL_KOS_MAX_TEXTURE_UNITS;
|
||||
}
|
||||
|
||||
//========================================================================================//
|
||||
//== Public KOS Open GL API Texture Unit Functionality ==//
|
||||
|
||||
void APIENTRY glGenTextures(GLsizei n, GLuint *textures) {
|
||||
TRACE();
|
||||
|
||||
while(n--) {
|
||||
GLuint id = 0;
|
||||
GL_TEXTURE_OBJECT* txr = (GL_TEXTURE_OBJECT*) named_array_alloc(&TEXTURE_OBJECTS, &id);
|
||||
TextureObject* txr = (TextureObject*) named_array_alloc(&TEXTURE_OBJECTS, &id);
|
||||
txr->index = id;
|
||||
txr->width = txr->height = 0;
|
||||
txr->mip_map = 0;
|
||||
|
@ -111,11 +83,13 @@ void APIENTRY glGenTextures(GLsizei n, GLuint *textures) {
|
|||
}
|
||||
|
||||
void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) {
|
||||
while(n--) {
|
||||
GL_TEXTURE_OBJECT* txr = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, *textures);
|
||||
TRACE();
|
||||
|
||||
if(txr == GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]) {
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = NULL;
|
||||
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) {
|
||||
|
@ -127,13 +101,61 @@ void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) {
|
|||
}
|
||||
|
||||
void APIENTRY glBindTexture(GLenum target, GLuint texture) {
|
||||
if(target != GL_TEXTURE_2D) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glBindTexture");
|
||||
_glKosPrintError();
|
||||
TRACE();
|
||||
|
||||
GLenum target_values [] = {GL_TEXTURE_2D, 0};
|
||||
|
||||
if(check_valid_enum(target, target_values, __func__) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
texture ? _glKosBindTexture(texture) : _glKosUnbindTexture();
|
||||
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,
|
||||
|
@ -144,6 +166,8 @@ void APIENTRY glCompressedTexImage2D(GLenum target,
|
|||
GLint border,
|
||||
GLsizei imageSize,
|
||||
const GLvoid *data) {
|
||||
TRACE();
|
||||
|
||||
if(target != GL_TEXTURE_2D)
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glCompressedTexImage2D");
|
||||
|
||||
|
@ -161,7 +185,7 @@ void APIENTRY glCompressedTexImage2D(GLenum target,
|
|||
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)
|
||||
if(TEXTURE_UNITS[ACTIVE_TEXTURE] == NULL)
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glCompressedTexImage2D");
|
||||
|
||||
if(_glKosHasError()) {
|
||||
|
@ -169,22 +193,24 @@ void APIENTRY glCompressedTexImage2D(GLenum target,
|
|||
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(
|
||||
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(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data)
|
||||
pvr_mem_free(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data);
|
||||
if(active->data)
|
||||
pvr_mem_free(active->data);
|
||||
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data = pvr_mem_malloc(imageSize);
|
||||
active->data = pvr_mem_malloc(imageSize);
|
||||
|
||||
if(data)
|
||||
sq_cpy(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data, data, imageSize);
|
||||
sq_cpy(active->data, data, imageSize);
|
||||
}
|
||||
|
||||
static GLint _cleanInternalFormat(GLint internalFormat) {
|
||||
|
@ -352,6 +378,7 @@ static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum f
|
|||
}
|
||||
} break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported conversion: %d -> %d, %d", internalFormat, format, type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -395,6 +422,8 @@ 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");
|
||||
}
|
||||
|
@ -425,7 +454,8 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
}
|
||||
|
||||
if(level < 0) {
|
||||
/* FIXME: Mipmaps! */
|
||||
if(level < 0 || level > 0) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
}
|
||||
|
||||
|
@ -433,7 +463,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
}
|
||||
|
||||
if(!GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]) {
|
||||
if(!TEXTURE_UNITS[ACTIVE_TEXTURE]) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D");
|
||||
}
|
||||
|
||||
|
@ -445,28 +475,29 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
/* 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) {
|
||||
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||
|
||||
if(active->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) {
|
||||
if(active->width != width ||
|
||||
active->height != height ||
|
||||
active->mip_map != level ||
|
||||
active->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;
|
||||
pvr_mem_free(active->data);
|
||||
active->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLuint bytes = level ? glKosMipMapTexSize(width, height) : (width * height * 2);
|
||||
GLuint bytes = (width * height * sizeof(GLushort));
|
||||
|
||||
if(!GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data) {
|
||||
if(!active->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);
|
||||
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 */
|
||||
|
@ -495,7 +526,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
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);
|
||||
sq_cpy(active->data, data, bytes);
|
||||
return;
|
||||
} else {
|
||||
TextureConversionFunc convert = _determineConversion(
|
||||
|
@ -509,7 +540,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
return;
|
||||
}
|
||||
|
||||
GLushort* dest = GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->data;
|
||||
GLushort* dest = active->data;
|
||||
const GLubyte* source = data;
|
||||
GLint stride = _determineStride(format, type);
|
||||
|
||||
|
@ -519,7 +550,8 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
}
|
||||
|
||||
/* Perform the conversion */
|
||||
for(GLuint i = 0; i < bytes; i += 2) {
|
||||
GLuint i;
|
||||
for(i = 0; i < bytes; i += 2) {
|
||||
convert(source, dest);
|
||||
|
||||
dest++;
|
||||
|
@ -529,25 +561,29 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
}
|
||||
|
||||
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:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_BILINEAR;
|
||||
active->filter = PVR_FILTER_BILINEAR;
|
||||
break;
|
||||
|
||||
case GL_NEAREST:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_NEAREST;
|
||||
active->filter = PVR_FILTER_NEAREST;
|
||||
break;
|
||||
|
||||
case GL_FILTER_NONE:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_NONE;
|
||||
active->filter = PVR_FILTER_NONE;
|
||||
break;
|
||||
|
||||
case GL_FILTER_BILINEAR:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->filter = PVR_FILTER_BILINEAR;
|
||||
active->filter = PVR_FILTER_BILINEAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -559,11 +595,11 @@ void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
|||
case GL_TEXTURE_WRAP_S:
|
||||
switch(param) {
|
||||
case GL_CLAMP:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp |= GL_KOS_CLAMP_U;
|
||||
active->uv_clamp |= CLAMP_U;
|
||||
break;
|
||||
|
||||
case GL_REPEAT:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp &= ~GL_KOS_CLAMP_U;
|
||||
active->uv_clamp &= ~CLAMP_U;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -572,11 +608,11 @@ void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
|||
case GL_TEXTURE_WRAP_T:
|
||||
switch(param) {
|
||||
case GL_CLAMP:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp |= GL_KOS_CLAMP_V;
|
||||
active->uv_clamp |= CLAMP_V;
|
||||
break;
|
||||
|
||||
case GL_REPEAT:
|
||||
GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->uv_clamp &= ~GL_KOS_CLAMP_V;
|
||||
active->uv_clamp &= ~CLAMP_V;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -584,36 +620,3 @@ void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
8
Makefile
8
Makefile
|
@ -3,11 +3,11 @@
|
|||
# kos-ports/libgl Makefile
|
||||
# Copyright (C) 2013, 2014 Josh Pearson
|
||||
# Copyright (C) 2014 Lawrence Sebald
|
||||
# Copyright (C) 2018 Luke Benstead
|
||||
|
||||
TARGET = libGL.a
|
||||
OBJS = gl-rgb.o gl-fog.o gl-sh4-light.o gl-light.o gl-clip.o gl-clip-arrays.o
|
||||
OBJS += gl-arrays.o gl-pvr.o gl-matrix.o gl-api.o gl-texture.o glu-texture.o
|
||||
OBJS += gl-framebuffer.o gl-cap.o gl-error.o
|
||||
OBJS = GL/draw.o GL/flush.o GL/framebuffer.o GL/immediate.o GL/lighting.o GL/state.o GL/texture.o
|
||||
OBJS += GL/matrix.o GL/fog.o GL/error.o
|
||||
|
||||
SUBDIRS =
|
||||
|
||||
|
@ -19,7 +19,7 @@ link:
|
|||
build: $(OBJS) link
|
||||
|
||||
|
||||
defaultall: create_kos_link build subdirs linklib
|
||||
defaultall: build subdirs linklib create_kos_link
|
||||
|
||||
include $(KOS_BASE)/addons/Makefile.prefab
|
||||
|
||||
|
|
31
README.md
Normal file
31
README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
# GLdc
|
||||
|
||||
This is a partial implementation of OpenGL 1.2 for the SEGA Dreamcast for use
|
||||
with the KallistiOS SDK.
|
||||
|
||||
It began as a fork of libGL by Josh Pearson but has undergone a large refactor
|
||||
which is essentially a rewrite.
|
||||
|
||||
The aim is to implement as much of OpenGL 1.2 as possible, and to add additional
|
||||
features via extensions.
|
||||
|
||||
Things left to (re)implement:
|
||||
|
||||
- Fog (Trivial)
|
||||
- Near-Z clipping (Tricky)
|
||||
- Spotlights (Trivial)
|
||||
- Framebuffer extension (Trivial)
|
||||
- Multitexturing (Trivial)
|
||||
- Texture Matrix (Trivial)
|
||||
- Mipmapping (Trivial)
|
||||
|
||||
Things I'd like to do:
|
||||
|
||||
- Use a clean "gl.h"
|
||||
- Define an extension for modifier volumes
|
||||
- Support `GL_ALPHA_TEST` using punch-thru polys
|
||||
- Add support for point sprites
|
||||
- Optimise, add unit tests for correctness
|
||||
|
||||
|
115
containers/aligned_vector.h
Normal file
115
containers/aligned_vector.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
#ifndef ALIGNED_VECTOR_H
|
||||
#define ALIGNED_VECTOR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define ALIGNED_VECTOR_INITIAL_CAPACITY 256u
|
||||
|
||||
typedef struct {
|
||||
unsigned int size;
|
||||
unsigned int capacity;
|
||||
unsigned char* data;
|
||||
unsigned int element_size;
|
||||
} AlignedVector;
|
||||
|
||||
|
||||
inline void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count);
|
||||
inline void aligned_vector_resize(AlignedVector* vector, const unsigned int element_count);
|
||||
|
||||
inline void aligned_vector_init(AlignedVector* vector, unsigned int element_size) {
|
||||
vector->size = vector->capacity = 0;
|
||||
vector->element_size = element_size;
|
||||
vector->data = NULL;
|
||||
|
||||
/* Reserve some initial capacity */
|
||||
aligned_vector_reserve(vector, ALIGNED_VECTOR_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
inline void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count) {
|
||||
if(element_count <= vector->capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int original_byte_size = vector->size * vector->element_size;
|
||||
unsigned int new_byte_size = element_count * vector->element_size;
|
||||
unsigned char* original_data = vector->data;
|
||||
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
|
||||
|
||||
if(original_data) {
|
||||
memcpy(vector->data, original_data, original_byte_size);
|
||||
free(original_data);
|
||||
}
|
||||
|
||||
vector->capacity = element_count;
|
||||
}
|
||||
|
||||
inline void aligned_vector_push_back(AlignedVector* vector, const void* objs, unsigned int count) {
|
||||
/* Resize enough room */
|
||||
|
||||
unsigned int initial_size = vector->size;
|
||||
aligned_vector_resize(vector, vector->size + count);
|
||||
|
||||
unsigned char* dest = vector->data + (vector->element_size * initial_size);
|
||||
|
||||
/* Copy the objects in */
|
||||
memcpy(dest, objs, vector->element_size * count);
|
||||
}
|
||||
|
||||
inline void aligned_vector_resize(AlignedVector* vector, const unsigned int element_count) {
|
||||
/* Don't change memory when resizing downwards, just change the size */
|
||||
if(element_count <= vector->size) {
|
||||
vector->size = element_count;
|
||||
return;
|
||||
}
|
||||
|
||||
if(vector->capacity < element_count) {
|
||||
/* Reserve more than we need so that a subsequent push_back doesn't trigger yet another
|
||||
* resize */
|
||||
aligned_vector_reserve(vector, (int) ceil(((float)element_count) * 1.5f));
|
||||
}
|
||||
|
||||
vector->size = element_count;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
inline void aligned_vector_shrink_to_fit(AlignedVector* vector) {
|
||||
if(vector->size == 0) {
|
||||
free(vector->data);
|
||||
vector->data = NULL;
|
||||
vector->capacity = 0;
|
||||
} else {
|
||||
unsigned int new_byte_size = vector->size * vector->element_size;
|
||||
unsigned char* original_data = vector->data;
|
||||
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
|
||||
|
||||
if(original_data) {
|
||||
memcpy(vector->data, original_data, new_byte_size);
|
||||
free(original_data);
|
||||
}
|
||||
|
||||
vector->capacity = vector->size;
|
||||
}
|
||||
}
|
||||
|
||||
inline void aligned_vector_cleanup(AlignedVector* vector) {
|
||||
aligned_vector_clear(vector);
|
||||
aligned_vector_shrink_to_fit(vector);
|
||||
}
|
||||
|
||||
#endif // ALIGNED_VECTOR_H
|
|
@ -43,8 +43,9 @@ inline char named_array_used(NamedArray* array, unsigned int id) {
|
|||
}
|
||||
|
||||
inline void* named_array_alloc(NamedArray* array, unsigned int* new_id) {
|
||||
for(unsigned int i = 0; i < array->marker_count; ++i) {
|
||||
for(unsigned int j = 0; j < 8; ++j) {
|
||||
unsigned int i = 0, j = 0;
|
||||
for(i = 0; i < array->marker_count; ++i) {
|
||||
for(j = 0; j < 8; ++j) {
|
||||
unsigned int id = (i * 8) + j + 1;
|
||||
if(!named_array_used(array, id)) {
|
||||
array->used_markers[i] |= (unsigned char) 1 << j;
|
||||
|
|
50
containers/stack.h
Normal file
50
containers/stack.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned char* data;
|
||||
unsigned int capacity;
|
||||
unsigned int size;
|
||||
unsigned int element_size;
|
||||
} Stack;
|
||||
|
||||
void init_stack(Stack* stack, unsigned int element_size, unsigned int capacity) {
|
||||
stack->size = 0;
|
||||
stack->capacity = capacity;
|
||||
stack->element_size = element_size;
|
||||
stack->data = (unsigned char*) memalign(0x20, element_size * capacity);
|
||||
}
|
||||
|
||||
void* stack_top(Stack* stack) {
|
||||
return &stack->data[(stack->size - 1) * stack->element_size];
|
||||
}
|
||||
|
||||
void* stack_replace(Stack* stack, const void* element) {
|
||||
memcpy(stack->data + ((stack->size - 1) * stack->element_size), element, stack->element_size);
|
||||
return stack_top(stack);
|
||||
}
|
||||
|
||||
void* stack_push(Stack* stack, const void* element) {
|
||||
if(stack->size + 1 == stack->capacity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(stack->data + (stack->size * stack->element_size), element, stack->element_size);
|
||||
stack->size++;
|
||||
|
||||
return stack_top(stack);
|
||||
}
|
||||
|
||||
void stack_pop(Stack* stack) {
|
||||
if(stack->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
stack->size--;
|
||||
}
|
||||
|
||||
|
||||
#endif // STACK_H
|
969
gl-api.c
969
gl-api.c
|
@ -1,969 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-api.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
Copyright (C) 2014 Lawrence Sebald
|
||||
|
||||
Some functionality adapted from the original KOS libgl:
|
||||
Copyright (C) 2001 Dan Potter
|
||||
Copyright (C) 2002 Benoit Miller
|
||||
|
||||
This API implements much but not all of the OpenGL 1.1 for KallistiOS.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-sh4.h"
|
||||
#include "gl-pvr.h"
|
||||
|
||||
//====================================================================================================//
|
||||
//== Local API State Macine Variables ==//
|
||||
|
||||
static GLubyte GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_GEQUAL;
|
||||
static GLubyte GL_KOS_DEPTH_WRITE = PVR_DEPTHWRITE_ENABLE;
|
||||
static GLubyte GL_KOS_BLEND_FUNC = (PVR_BLEND_ONE << 4) | (PVR_BLEND_ZERO & 0x0F);
|
||||
static GLubyte GL_KOS_SHADE_FUNC = PVR_SHADE_GOURAUD;
|
||||
static GLushort GL_KOS_CULL_FUNC = PVR_CULLING_NONE;
|
||||
static GLushort GL_KOS_FACE_FRONT = GL_CCW;
|
||||
static GLubyte GL_KOS_SUPERSAMPLE = 0;
|
||||
|
||||
static GLuint GL_KOS_VERTEX_COUNT = 0;
|
||||
static GLuint GL_KOS_VERTEX_MODE = GL_TRIANGLES;
|
||||
static GLuint GL_KOS_VERTEX_COLOR = 0xFFFFFFFF;
|
||||
static GLfloat GL_KOS_VERTEX_UV[2] = { 0, 0 };
|
||||
//static glTexCoord4f GL_KOS_VERTEX_TEX_COORD = { 0, 0, 0, 1 };
|
||||
|
||||
static GLfloat GL_KOS_COLOR_CLEAR[3] = { 0, 0, 0 };
|
||||
|
||||
static GLfloat GL_KOS_POINT_SIZE = 0.02;
|
||||
|
||||
static pvr_poly_cxt_t GL_KOS_POLY_CXT;
|
||||
|
||||
static inline void _glKosFlagsSetTriangleStrip();
|
||||
static inline void _glKosFlagsSetTriangle();
|
||||
static inline void _glKosFlagsSetQuad();
|
||||
static inline void _glKosFinishRect();
|
||||
|
||||
//====================================================================================================//
|
||||
//== API Initialization ==//
|
||||
|
||||
void APIENTRY glKosInit() {
|
||||
_glKosInitPVR();
|
||||
|
||||
_glKosInitTextures();
|
||||
|
||||
_glKosInitMatrix();
|
||||
|
||||
_glKosInitLighting();
|
||||
|
||||
_glKosInitFrameBuffers();
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Blending / Shading functions ==//
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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_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_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_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;
|
||||
}
|
||||
|
||||
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_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_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_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_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 glClearColor(float r, float g, float b, float a) {
|
||||
if(r > 1) r = 1;
|
||||
|
||||
if(g > 1) g = 1;
|
||||
|
||||
if(b > 1) b = 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;
|
||||
}
|
||||
|
||||
//== NoOp ==//
|
||||
void APIENTRY glClearDepthf(GLfloat depth) {
|
||||
;
|
||||
}
|
||||
|
||||
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_GREATER:
|
||||
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LEQUAL;
|
||||
break;
|
||||
|
||||
case GL_GEQUAL:
|
||||
GL_KOS_DEPTH_FUNC = PVR_DEPTHCMP_LESS;
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Culling functions ==//
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Vertex Attributes Submission Functions ==//
|
||||
|
||||
//== Vertex Color Submission ==//
|
||||
|
||||
void APIENTRY glColor1ui(GLuint argb) {
|
||||
GL_KOS_VERTEX_COLOR = argb;
|
||||
}
|
||||
|
||||
void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
|
||||
GL_KOS_VERTEX_COLOR = a << 24 | r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) {
|
||||
GL_KOS_VERTEX_COLOR = PVR_PACK_COLOR(1.0f, r, g, b);
|
||||
}
|
||||
|
||||
void APIENTRY glColor3fv(const GLfloat *rgb) {
|
||||
GL_KOS_VERTEX_COLOR = PVR_PACK_COLOR(1.0f, rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
GL_KOS_VERTEX_COLOR = PVR_PACK_COLOR(a, r, g, b);
|
||||
}
|
||||
|
||||
void APIENTRY glColor4fv(const GLfloat *rgba) {
|
||||
GL_KOS_VERTEX_COLOR = PVR_PACK_COLOR(rgba[3], rgba[0], rgba[1], rgba[2]);
|
||||
}
|
||||
|
||||
//== Texture Coordinate Submission ==//
|
||||
|
||||
void APIENTRY glTexCoord2f(GLfloat u, GLfloat v) {
|
||||
if(_glKosEnabledTextureMatrix()) {
|
||||
_glKosMatrixLoadTexture();
|
||||
|
||||
mat_trans_texture2_nomod(u, v, GL_KOS_VERTEX_UV[0], GL_KOS_VERTEX_UV[1]);
|
||||
|
||||
_glKosMatrixLoadRender();
|
||||
}
|
||||
else {
|
||||
GL_KOS_VERTEX_UV[0] = u;
|
||||
GL_KOS_VERTEX_UV[1] = v;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoord2fv(const GLfloat *uv) {
|
||||
if(_glKosEnabledTextureMatrix()) {
|
||||
_glKosMatrixLoadTexture();
|
||||
|
||||
mat_trans_texture2_nomod(uv[0], uv[1], GL_KOS_VERTEX_UV[0], GL_KOS_VERTEX_UV[1]);
|
||||
|
||||
_glKosMatrixLoadRender();
|
||||
}
|
||||
else {
|
||||
GL_KOS_VERTEX_UV[0] = uv[0];
|
||||
GL_KOS_VERTEX_UV[1] = uv[1];
|
||||
}
|
||||
}
|
||||
|
||||
//== Vertex Position Submission Functions ==//
|
||||
|
||||
void APIENTRY(*glVertex3f)(GLfloat, GLfloat, GLfloat);
|
||||
|
||||
void APIENTRY(*glVertex3fv)(const GLfloat *);
|
||||
|
||||
void APIENTRY glVertex2f(GLfloat x, GLfloat y) {
|
||||
return _glKosVertex3ft(x, y, 0.0f);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex2fv(const GLfloat *xy) {
|
||||
return _glKosVertex3ft(xy[0], xy[1], 0.0f);
|
||||
}
|
||||
|
||||
void APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
v[0].z = v[3].z = 0;
|
||||
|
||||
mat_trans_single3_nomod(x1, y1, v[0].z, v[0].x, v[0].y, v[0].z);
|
||||
mat_trans_single3_nomod(x2, y2, v[3].z, v[3].x, v[3].y, v[3].z);
|
||||
|
||||
_glKosFinishRect();
|
||||
}
|
||||
|
||||
void APIENTRY glRectfv(const GLfloat *v1, const GLfloat *v2) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
v[0].z = v[3].z = 0;
|
||||
|
||||
mat_trans_single3_nomod(v1[0], v1[1], v[0].z, v[0].x, v[0].y, v[0].z);
|
||||
mat_trans_single3_nomod(v2[0], v2[1], v[3].z, v[3].x, v[3].y, v[3].z);
|
||||
|
||||
_glKosFinishRect();
|
||||
}
|
||||
|
||||
void APIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2) {
|
||||
return glRectf((GLfloat)x1, (GLfloat)y1, (GLfloat)x2, (GLfloat)y2);
|
||||
}
|
||||
|
||||
void APIENTRY glRectiv(const GLint *v1, const GLint *v2) {
|
||||
return glRectfv((const GLfloat *)v1, (const GLfloat *)v2);
|
||||
}
|
||||
|
||||
void APIENTRY glKosVertex2f(GLfloat x, GLfloat y) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
v->x = x;
|
||||
v->y = y;
|
||||
v->z = 10;
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
v->argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
void APIENTRY glKosVertex2fv(const GLfloat *xy) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
v->x = xy[0];
|
||||
v->y = xy[1];
|
||||
v->z = 10;
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
v->argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== GL Begin / End ==//
|
||||
|
||||
void APIENTRY glBegin(GLenum mode) {
|
||||
_glKosMatrixApplyRender();
|
||||
|
||||
_glKosArrayBufReset();
|
||||
|
||||
_glKosEnabledTexture2D() ? _glKosCompileHdrTx() : _glKosCompileHdr();
|
||||
|
||||
GL_KOS_VERTEX_MODE = mode;
|
||||
GL_KOS_VERTEX_COUNT = 0;
|
||||
|
||||
if(mode == GL_POINTS) {
|
||||
glVertex3f = _glKosVertex3fp;
|
||||
glVertex3fv = _glKosVertex3fpv;
|
||||
}
|
||||
else if(_glKosEnabledNearZClip()
|
||||
&& _glKosEnabledLighting()) {
|
||||
glVertex3f = _glKosVertex3flc;
|
||||
glVertex3fv = _glKosVertex3flcv;
|
||||
}
|
||||
else if(_glKosEnabledLighting()) {
|
||||
glVertex3f = _glKosVertex3fl;
|
||||
glVertex3fv = _glKosVertex3flv;
|
||||
}
|
||||
else if(_glKosEnabledNearZClip()) {
|
||||
glVertex3f = _glKosVertex3fc;
|
||||
glVertex3fv = _glKosVertex3fcv;
|
||||
}
|
||||
else {
|
||||
glVertex3f = _glKosVertex3ft;
|
||||
glVertex3fv = _glKosVertex3ftv;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glEnd() {
|
||||
if(_glKosEnabledNearZClip()) { /* Z-Clipping Enabled */
|
||||
if(_glKosEnabledLighting()) {
|
||||
_glKosVertexComputeLighting(_glKosClipBufAddress(), GL_KOS_VERTEX_COUNT);
|
||||
|
||||
_glKosMatrixLoadRender();
|
||||
}
|
||||
|
||||
GLuint cverts;
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
switch(GL_KOS_VERTEX_MODE) {
|
||||
case GL_TRIANGLES:
|
||||
cverts = _glKosClipTriangles(_glKosClipBufAddress(), v, GL_KOS_VERTEX_COUNT);
|
||||
_glKosTransformClipBuf(v, cverts);
|
||||
_glKosVertexBufAdd(cverts);
|
||||
break;
|
||||
|
||||
case GL_TRIANGLE_STRIP:
|
||||
cverts = _glKosClipTriangleStrip(_glKosClipBufAddress(), v, GL_KOS_VERTEX_COUNT);
|
||||
_glKosTransformClipBuf(v, cverts);
|
||||
_glKosVertexBufAdd(cverts);
|
||||
break;
|
||||
|
||||
case GL_QUADS:
|
||||
cverts = _glKosClipQuads(_glKosClipBufAddress(), v, GL_KOS_VERTEX_COUNT);
|
||||
_glKosTransformClipBuf(v, cverts);
|
||||
_glKosVertexBufAdd(cverts);
|
||||
break;
|
||||
}
|
||||
|
||||
_glKosClipBufReset();
|
||||
}
|
||||
else { /* No Z-Clipping Enabled */
|
||||
if(_glKosEnabledLighting())
|
||||
_glKosVertexComputeLighting((pvr_vertex_t *)_glKosVertexBufPointer() - GL_KOS_VERTEX_COUNT, GL_KOS_VERTEX_COUNT);
|
||||
|
||||
switch(GL_KOS_VERTEX_MODE) {
|
||||
case GL_TRIANGLES:
|
||||
_glKosFlagsSetTriangle();
|
||||
break;
|
||||
|
||||
case GL_TRIANGLE_STRIP:
|
||||
_glKosFlagsSetTriangleStrip();
|
||||
break;
|
||||
|
||||
case GL_QUADS:
|
||||
_glKosFlagsSetQuad();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== 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.
|
||||
|
||||
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) {
|
||||
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 ==//
|
||||
|
||||
void _glKosVertex3fs(GLfloat x, GLfloat y, GLfloat z) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z);
|
||||
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
void _glKosVertex3fsv(const GLfloat *xyz) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
mat_trans_single3_nomod(xyz[0], xyz[1], xyz[2], v->x, v->y, v->z);
|
||||
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
void _glKosVertex3ft(GLfloat x, GLfloat y, GLfloat z) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z);
|
||||
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
v->argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
void _glKosVertex3ftv(const GLfloat *xyz) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
mat_trans_single3_nomod(xyz[0], xyz[1], xyz[2], v->x, v->y, v->z);
|
||||
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
v->argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
void _glKosVertex3fc(GLfloat x, GLfloat y, GLfloat z) {
|
||||
pvr_vertex_t *v = _glKosClipBufPointer();
|
||||
|
||||
v->x = x;
|
||||
v->y = y;
|
||||
v->z = z;
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
v->argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
_glKosClipBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
void _glKosVertex3fcv(const GLfloat *xyz) {
|
||||
pvr_vertex_t *v = _glKosClipBufPointer();
|
||||
|
||||
v->x = xyz[0];
|
||||
v->y = xyz[1];
|
||||
v->z = xyz[2];
|
||||
v->u = GL_KOS_VERTEX_UV[0];
|
||||
v->v = GL_KOS_VERTEX_UV[1];
|
||||
v->argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
_glKosClipBufIncrement();
|
||||
|
||||
++GL_KOS_VERTEX_COUNT;
|
||||
}
|
||||
|
||||
/* GL_POINTS */
|
||||
GLvoid _glKosVertex3fp(GLfloat x, GLfloat y, GLfloat z) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
mat_trans_single3_nomod(x - GL_KOS_POINT_SIZE, y + GL_KOS_POINT_SIZE, z,
|
||||
v[0].x, v[0].y, v[0].z);
|
||||
mat_trans_single3_nomod(x + GL_KOS_POINT_SIZE, y - GL_KOS_POINT_SIZE, z,
|
||||
v[3].x, v[3].y, v[3].z);
|
||||
|
||||
_glKosFinishRect();
|
||||
}
|
||||
|
||||
GLvoid _glKosVertex3fpv(const GLfloat *xyz) {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
mat_trans_single3_nomod(xyz[0] - GL_KOS_POINT_SIZE, xyz[1] + GL_KOS_POINT_SIZE, xyz[2],
|
||||
v[0].x, v[0].y, v[0].z);
|
||||
mat_trans_single3_nomod(xyz[0] + GL_KOS_POINT_SIZE, xyz[1] - GL_KOS_POINT_SIZE, xyz[2],
|
||||
v[3].x, v[3].y, v[3].z);
|
||||
|
||||
_glKosFinishRect();
|
||||
}
|
||||
|
||||
static inline void _glKosFinishRect() {
|
||||
pvr_vertex_t *v = _glKosVertexBufPointer();
|
||||
|
||||
v[0].argb = v[1].argb = v[2].argb = v[3].argb = GL_KOS_VERTEX_COLOR;
|
||||
|
||||
v[0].flags = v[1].flags = v[2].flags = PVR_CMD_VERTEX;
|
||||
v[3].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
v[1].x = v[0].x;
|
||||
v[1].y = v[3].y;
|
||||
v[1].z = v[3].z;
|
||||
|
||||
v[2].x = v[3].x;
|
||||
v[2].y = v[0].y;
|
||||
v[2].z = v[0].z;
|
||||
|
||||
_glKosVertexBufAdd(4);
|
||||
|
||||
GL_KOS_VERTEX_COUNT += 4;
|
||||
}
|
||||
|
||||
void _glKosTransformClipBuf(pvr_vertex_t *v, GLuint verts) {
|
||||
register float __x __asm__("fr12");
|
||||
register float __y __asm__("fr13");
|
||||
register float __z __asm__("fr14");
|
||||
|
||||
while(verts--) {
|
||||
__x = v->x;
|
||||
__y = v->y;
|
||||
__z = v->z;
|
||||
|
||||
mat_trans_fv12();
|
||||
|
||||
v->x = __x;
|
||||
v->y = __y;
|
||||
v->z = __z;
|
||||
++v;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _glKosVertexSwap(pvr_vertex_t *v1, pvr_vertex_t *v2) {
|
||||
pvr_vertex_t tmp = *v1;
|
||||
*v1 = *v2;
|
||||
*v2 = * &tmp;
|
||||
}
|
||||
|
||||
static inline void _glKosFlagsSetQuad() {
|
||||
pvr_vertex_t *v = (pvr_vertex_t *)_glKosVertexBufPointer() - GL_KOS_VERTEX_COUNT;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < GL_KOS_VERTEX_COUNT; i += 4) {
|
||||
_glKosVertexSwap(v + 2, v + 3);
|
||||
v->flags = (v + 1)->flags = (v + 2)->flags = PVR_CMD_VERTEX;
|
||||
(v + 3)->flags = PVR_CMD_VERTEX_EOL;
|
||||
v += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _glKosFlagsSetTriangle() {
|
||||
pvr_vertex_t *v = (pvr_vertex_t *)_glKosVertexBufPointer() - GL_KOS_VERTEX_COUNT;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < GL_KOS_VERTEX_COUNT; i += 3) {
|
||||
v->flags = (v + 1)->flags = PVR_CMD_VERTEX;
|
||||
(v + 2)->flags = PVR_CMD_VERTEX_EOL;
|
||||
v += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _glKosFlagsSetTriangleStrip() {
|
||||
pvr_vertex_t *v = (pvr_vertex_t *)_glKosVertexBufPointer() - GL_KOS_VERTEX_COUNT;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < GL_KOS_VERTEX_COUNT - 1; i++) {
|
||||
v->flags = PVR_CMD_VERTEX;
|
||||
v++;
|
||||
}
|
||||
|
||||
v->flags = PVR_CMD_VERTEX_EOL;
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== GL KOS PVR Header Parameter Compilation Functions ==//
|
||||
|
||||
static inline void _glKosApplyDepthFunc() {
|
||||
if(_glKosEnabledDepthTest())
|
||||
GL_KOS_POLY_CXT.depth.comparison = GL_KOS_DEPTH_FUNC;
|
||||
else
|
||||
GL_KOS_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS;
|
||||
|
||||
GL_KOS_POLY_CXT.depth.write = GL_KOS_DEPTH_WRITE;
|
||||
}
|
||||
|
||||
static inline void _glKosApplyScissorFunc() {
|
||||
if(_glKosEnabledScissorTest())
|
||||
GL_KOS_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE;
|
||||
}
|
||||
|
||||
static inline void _glKosApplyFogFunc() {
|
||||
if(_glKosEnabledFog())
|
||||
GL_KOS_POLY_CXT.gen.fog_type = PVR_FOG_TABLE;
|
||||
}
|
||||
|
||||
static inline void _glKosApplyCullingFunc() {
|
||||
if(_glKosEnabledCulling()) {
|
||||
if(GL_KOS_CULL_FUNC == GL_BACK) {
|
||||
if(GL_KOS_FACE_FRONT == GL_CW)
|
||||
GL_KOS_POLY_CXT.gen.culling = PVR_CULLING_CCW;
|
||||
else
|
||||
GL_KOS_POLY_CXT.gen.culling = PVR_CULLING_CW;
|
||||
}
|
||||
else if(GL_KOS_CULL_FUNC == GL_FRONT) {
|
||||
if(GL_KOS_FACE_FRONT == GL_CCW)
|
||||
GL_KOS_POLY_CXT.gen.culling = PVR_CULLING_CCW;
|
||||
else
|
||||
GL_KOS_POLY_CXT.gen.culling = PVR_CULLING_CW;
|
||||
}
|
||||
}
|
||||
else
|
||||
GL_KOS_POLY_CXT.gen.culling = PVR_CULLING_NONE;
|
||||
}
|
||||
|
||||
static inline void _glKosApplyBlendFunc() {
|
||||
if(_glKosEnabledBlend()) {
|
||||
GL_KOS_POLY_CXT.blend.src = (GL_KOS_BLEND_FUNC & 0xF0) >> 4;
|
||||
GL_KOS_POLY_CXT.blend.dst = (GL_KOS_BLEND_FUNC & 0x0F);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _glKosApplyTextureFunc(GL_TEXTURE_OBJECT *tex) {
|
||||
GL_KOS_POLY_CXT.txr.uv_clamp = tex->uv_clamp;
|
||||
GL_KOS_POLY_CXT.txr.mipmap = tex->mip_map ? 1 : 0;
|
||||
GL_KOS_POLY_CXT.txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
|
||||
}
|
||||
|
||||
void _glKosCompileHdr() {
|
||||
pvr_poly_hdr_t *hdr = _glKosVertexBufPointer();
|
||||
|
||||
pvr_poly_cxt_col(&GL_KOS_POLY_CXT, _glKosList() * 2);
|
||||
|
||||
GL_KOS_POLY_CXT.gen.shading = GL_KOS_SHADE_FUNC;
|
||||
|
||||
_glKosApplyDepthFunc();
|
||||
|
||||
_glKosApplyScissorFunc();
|
||||
|
||||
_glKosApplyFogFunc();
|
||||
|
||||
_glKosApplyCullingFunc();
|
||||
|
||||
_glKosApplyBlendFunc();
|
||||
|
||||
pvr_poly_compile(hdr, &GL_KOS_POLY_CXT);
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
}
|
||||
|
||||
void _glKosCompileHdrT(GL_TEXTURE_OBJECT *tex) {
|
||||
pvr_poly_hdr_t *hdr = _glKosVertexBufPointer();
|
||||
|
||||
pvr_poly_cxt_txr(&GL_KOS_POLY_CXT,
|
||||
_glKosList() * 2,
|
||||
tex->color,
|
||||
tex->width,
|
||||
tex->height,
|
||||
tex->data,
|
||||
tex->filter);
|
||||
|
||||
GL_KOS_POLY_CXT.gen.shading = GL_KOS_SHADE_FUNC;
|
||||
|
||||
_glKosApplyDepthFunc();
|
||||
|
||||
_glKosApplyScissorFunc();
|
||||
|
||||
_glKosApplyFogFunc();
|
||||
|
||||
_glKosApplyCullingFunc();
|
||||
|
||||
_glKosApplyBlendFunc();
|
||||
|
||||
_glKosApplyTextureFunc(tex);
|
||||
|
||||
if(_glKosEnabledBlend())
|
||||
GL_KOS_POLY_CXT.txr.env = tex->env;
|
||||
|
||||
pvr_poly_compile(hdr, &GL_KOS_POLY_CXT);
|
||||
|
||||
if(GL_KOS_SUPERSAMPLE)
|
||||
hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT;
|
||||
|
||||
_glKosVertexBufIncrement();
|
||||
}
|
||||
|
||||
void _glKosCompileHdrMT(pvr_poly_hdr_t *dst, GL_TEXTURE_OBJECT *tex) {
|
||||
pvr_poly_cxt_txr(&GL_KOS_POLY_CXT,
|
||||
PVR_LIST_TR_POLY,
|
||||
tex->color,
|
||||
tex->width,
|
||||
tex->height,
|
||||
tex->data,
|
||||
tex->filter);
|
||||
|
||||
GL_KOS_POLY_CXT.gen.shading = GL_KOS_SHADE_FUNC;
|
||||
|
||||
_glKosApplyDepthFunc();
|
||||
|
||||
_glKosApplyScissorFunc();
|
||||
|
||||
_glKosApplyFogFunc();
|
||||
|
||||
_glKosApplyCullingFunc();
|
||||
|
||||
_glKosApplyTextureFunc(tex);
|
||||
|
||||
GL_KOS_POLY_CXT.blend.src = (GL_KOS_BLEND_FUNC & 0xF0) >> 4;
|
||||
GL_KOS_POLY_CXT.blend.dst = (GL_KOS_BLEND_FUNC & 0x0F);
|
||||
GL_KOS_POLY_CXT.txr.env = tex->env;
|
||||
|
||||
pvr_poly_compile(dst, &GL_KOS_POLY_CXT);
|
||||
|
||||
if(GL_KOS_SUPERSAMPLE)
|
||||
dst->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT;
|
||||
}
|
||||
|
||||
//====================================================================================================//
|
||||
//== Internal GL KOS API State Functions ==//
|
||||
|
||||
GLuint _glKosBlendSrcFunc() {
|
||||
switch((GL_KOS_BLEND_FUNC & 0xF0) >> 4) {
|
||||
case PVR_BLEND_ONE:
|
||||
return GL_ONE;
|
||||
|
||||
case PVR_BLEND_ZERO:
|
||||
return GL_ZERO;
|
||||
|
||||
case PVR_BLEND_DESTCOLOR:
|
||||
return GL_DST_COLOR;
|
||||
|
||||
case PVR_BLEND_SRCALPHA:
|
||||
return GL_SRC_ALPHA;
|
||||
|
||||
case PVR_BLEND_DESTALPHA:
|
||||
return GL_DST_ALPHA;
|
||||
|
||||
case PVR_BLEND_INVSRCALPHA:
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
case PVR_BLEND_INVDESTALPHA:
|
||||
return GL_ONE_MINUS_DST_ALPHA;
|
||||
|
||||
case PVR_BLEND_INVDESTCOLOR:
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint _glKosBlendDstFunc() {
|
||||
switch(GL_KOS_BLEND_FUNC & 0xF) {
|
||||
case PVR_BLEND_ONE:
|
||||
return GL_ONE;
|
||||
|
||||
case PVR_BLEND_ZERO:
|
||||
return GL_ZERO;
|
||||
|
||||
case PVR_BLEND_DESTCOLOR:
|
||||
return GL_DST_COLOR;
|
||||
|
||||
case PVR_BLEND_SRCALPHA:
|
||||
return GL_SRC_ALPHA;
|
||||
|
||||
case PVR_BLEND_DESTALPHA:
|
||||
return GL_DST_ALPHA;
|
||||
|
||||
case PVR_BLEND_INVSRCALPHA:
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
case PVR_BLEND_INVDESTALPHA:
|
||||
return GL_ONE_MINUS_DST_ALPHA;
|
||||
|
||||
case PVR_BLEND_INVDESTCOLOR:
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLubyte _glKosCullFaceMode() {
|
||||
return GL_KOS_CULL_FUNC;
|
||||
}
|
||||
|
||||
GLubyte _glKosCullFaceFront() {
|
||||
return GL_KOS_FACE_FRONT;
|
||||
}
|
||||
|
||||
GLuint _glKosDepthFunc() {
|
||||
switch(GL_KOS_DEPTH_FUNC) {
|
||||
case PVR_DEPTHCMP_GEQUAL:
|
||||
return GL_LESS;
|
||||
|
||||
case PVR_DEPTHCMP_GREATER:
|
||||
return GL_LEQUAL;
|
||||
|
||||
case PVR_DEPTHCMP_LEQUAL:
|
||||
return GL_GREATER;
|
||||
|
||||
case PVR_DEPTHCMP_LESS:
|
||||
return GL_GEQUAL;
|
||||
|
||||
default:
|
||||
return GL_NEVER + GL_KOS_DEPTH_FUNC;
|
||||
}
|
||||
}
|
||||
|
||||
GLubyte _glKosDepthMask() {
|
||||
return (GL_KOS_DEPTH_WRITE == PVR_DEPTHWRITE_ENABLE) ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
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) {
|
||||
;
|
||||
}
|
225
gl-api.h
225
gl-api.h
|
@ -1,225 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-api.h
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
The functions defined in this header are for internal use by the API,
|
||||
and not for use externally.
|
||||
*/
|
||||
|
||||
#ifndef GL_API_H
|
||||
#define GL_API_H
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
typedef struct {
|
||||
GLfloat pos[3];
|
||||
GLfloat norm[3];
|
||||
} glVertex; /* Simple Vertex used for Dynamic Vertex Lighting */
|
||||
|
||||
typedef struct {
|
||||
GLfloat u, v;
|
||||
} glTexCoord; /* Simple Texture Coordinate used for Multi-Texturing */
|
||||
|
||||
typedef struct {
|
||||
GLfloat s, t, r, q;
|
||||
} glTexCoord4f; /* 3D Texture Coordinate */
|
||||
|
||||
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;
|
||||
} GL_TEXTURE_OBJECT; /* KOS Open GL Texture Object */
|
||||
|
||||
typedef struct {
|
||||
GLuint texID;
|
||||
GLsizei index;
|
||||
GLvoid *data;
|
||||
GLvoid *link;
|
||||
} GL_FRAMEBUFFER_OBJECT; /* KOS Open GL Frame Buffer Object */
|
||||
|
||||
typedef struct {
|
||||
pvr_poly_hdr_t hdr;
|
||||
pvr_vertex_t *src;
|
||||
GLuint count;
|
||||
} GL_MULTITEX_OBJECT;
|
||||
|
||||
typedef GLushort uint16;
|
||||
typedef GLubyte uint8;
|
||||
|
||||
/* Vertex Main Buffer Internal Functions */
|
||||
void _glKosVertexBufSwitchOP();
|
||||
void _glKosVertexBufSwitchTR();
|
||||
void *_glKosVertexBufAddress(unsigned char list);
|
||||
void *_glKosVertexBufPointer();
|
||||
void *_glKosTRVertexBufPointer();
|
||||
void _glKosVertexBufIncrement();
|
||||
void _glKosTRVertexBufIncrement();
|
||||
void _glKosVertexBufAdd(unsigned int count);
|
||||
void _glKosTRVertexBufAdd(unsigned int count);
|
||||
void _glKosVertexBufDecrement();
|
||||
void _glKosVertexBufReset();
|
||||
unsigned int _glKosVertexBufCount(unsigned char list);
|
||||
unsigned char _glKosList();
|
||||
void _glKosVertexBufCopy(void *src, void *dst, GLuint count);
|
||||
void _glKosResetEnabledTex();
|
||||
void *_glKosMultiUVBufAddress();
|
||||
void *_glKosMultiUVBufPointer();
|
||||
void _glKosMultiUVBufIncrement();
|
||||
void _glKosMultiUVBufAdd(GLuint count);
|
||||
void _glKosMultiUVBufReset();
|
||||
|
||||
/* Vertex Clip Buffer Internal Functions */
|
||||
void *_glKosClipBufAddress();
|
||||
void *_glKosClipBufPointer();
|
||||
void _glKosClipBufIncrement();
|
||||
void _glKosClipBufReset();
|
||||
|
||||
/* Vertex Array Buffer Internal Functions */
|
||||
void _glKosArrayBufIncrement();
|
||||
void _glKosArrayBufReset();
|
||||
glVertex *_glKosArrayBufAddr();
|
||||
glVertex *_glKosArrayBufPtr();
|
||||
|
||||
/* Initialize the OpenGL PVR Pipeline */
|
||||
int _glKosInitPVR();
|
||||
unsigned char _glKosInitTextures();
|
||||
|
||||
/* Compile the current Polygon Header for the PVR */
|
||||
void _glKosCompileHdr();
|
||||
void _glKosCompileHdrTx();
|
||||
void _glKosCompileHdrMTx();
|
||||
void _glKosCompileHdrT(GL_TEXTURE_OBJECT *tex);
|
||||
void _glKosCompileHdrMT(pvr_poly_hdr_t *dst, GL_TEXTURE_OBJECT *tex);
|
||||
|
||||
/* Clipping Internal Functions */
|
||||
void _glKosTransformClipBuf(pvr_vertex_t *v, GLuint verts);
|
||||
unsigned int _glKosClipTriangleStrip(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices);
|
||||
unsigned int _glKosClipTriangles(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices);
|
||||
unsigned int _glKosClipQuads(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices);
|
||||
|
||||
unsigned int _glKosClipTrianglesTransformed(pvr_vertex_t *src, float *w, pvr_vertex_t *dst, GLuint count);
|
||||
unsigned int _glKosClipQuadsTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout, unsigned int vertices);
|
||||
unsigned int _glKosClipTriangleStripTransformed(pvr_vertex_t *src, float *w, pvr_vertex_t *dst, GLuint count);
|
||||
|
||||
unsigned int _glKosClipTrianglesTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride, GLuint count);
|
||||
unsigned int _glKosClipTriangleStripTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride, GLuint count);
|
||||
unsigned int _glKosClipQuadsTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride, GLuint count);
|
||||
|
||||
|
||||
/* Lighting Internal Functions */
|
||||
void _glKosInitLighting();
|
||||
void _glKosEnableLight(const GLuint light);
|
||||
void _glKosDisableLight(const GLuint light);
|
||||
void _glKosSetEyePosition(GLfloat *position);
|
||||
void _glKosVertexComputeLighting(pvr_vertex_t *v, int verts);
|
||||
void _glKosVertexLight(glVertex *P, pvr_vertex_t *v);
|
||||
unsigned int _glKosVertexLightColor(glVertex *P);
|
||||
void _glKosVertexLights(glVertex *P, pvr_vertex_t *v, GLuint count);
|
||||
|
||||
/* Vertex Position Submission Internal Functions */
|
||||
void _glKosVertex3ft(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glKosVertex3ftv(const GLfloat *xyz);
|
||||
void _glKosVertex3fc(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glKosVertex3fcv(const GLfloat *xyz);
|
||||
void _glKosVertex3fp(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glKosVertex3fpv(const GLfloat *xyz);
|
||||
void _glKosVertex3fl(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glKosVertex3flv(const GLfloat *xyz);
|
||||
void _glKosVertex3flc(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glKosVertex3flcv(const GLfloat *xyz);
|
||||
void _glKosVertex3fs(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glKosVertex3fsv(const GLfloat *xyz);
|
||||
|
||||
/* Matrix Internal Functions */
|
||||
void _glKosInitMatrix();
|
||||
void _glKosMatrixLoadModelView();
|
||||
void _glKosMatrixLoadModelRot();
|
||||
void _glKosMatrixApplyScreenSpace();
|
||||
void _glKosMatrixApplyRender();
|
||||
void _glKosMatrixLoadRender();
|
||||
void _glKosMatrixLoadTexture();
|
||||
|
||||
/* API Enabled Capabilities Internal Functions */
|
||||
GLubyte _glKosEnabledBlend();
|
||||
GLubyte _glKosEnabledTexture2D();
|
||||
GLubyte _glKosEnabledNearZClip();
|
||||
GLubyte _glKosEnabledLighting();
|
||||
GLubyte _glKosEnabledFog();
|
||||
GLubyte _glKosEnabledCulling();
|
||||
GLubyte _glKosEnabledScissorTest();
|
||||
GLubyte _glKosEnabledDepthTest();
|
||||
|
||||
/* RGB Pixel Colorspace Internal Functions */
|
||||
uint16 __glKosAverageQuadPixelRGB565(uint16 p1, uint16 p2, uint16 p3, uint16 p4);
|
||||
uint16 __glKosAverageQuadPixelARGB1555(uint16 p1, uint16 p2, uint16 p3, uint16 p4);
|
||||
uint16 __glKosAverageQuadPixelARGB4444(uint16 p1, uint16 p2, uint16 p3, uint16 p4);
|
||||
uint16 __glKosAverageBiPixelRGB565(uint16 p1, uint16 p2);
|
||||
uint16 __glKosAverageBiPixelARGB1555(uint16 p1, uint16 p2);
|
||||
uint16 __glKosAverageBiPixelARGB4444(uint16 p1, uint16 p2);
|
||||
|
||||
/* Render-To-Texture Functions */
|
||||
void _glKosInitFrameBuffers();
|
||||
|
||||
/* Error Codes */
|
||||
void _glKosThrowError(GLenum error, char *functionName);
|
||||
void _glKosPrintError();
|
||||
GLubyte _glKosHasError();
|
||||
|
||||
GLuint _glKosTextureWidth(GLuint index);
|
||||
GLuint _glKosTextureHeight(GLuint index);
|
||||
GLvoid *_glKosTextureData(GLuint index);
|
||||
|
||||
/* Frame Buffer Object Internal Functions */
|
||||
GLsizei _glKosGetFBO();
|
||||
GLuint _glKosGetFBOWidth(GLsizei fbi);
|
||||
GLuint _glKosGetFBOHeight(GLsizei fbi);
|
||||
GLvoid *_glKosGetFBOData(GLsizei fbi);
|
||||
|
||||
/* Internal State Cap Accessors */
|
||||
GLubyte _glKosEnabledDepthTest();
|
||||
GLubyte _glKosEnabledScissorTest();
|
||||
GLubyte _glKosEnabledCulling();
|
||||
GLubyte _glKosEnabledFog();
|
||||
GLubyte _glKosEnabledLighting();
|
||||
GLubyte _glKosEnabledNearZClip();
|
||||
GLubyte _glKosEnabledTexture2D();
|
||||
GLubyte _glKosEnabledBlend();
|
||||
GLuint _glKosBlendSrcFunc();
|
||||
GLuint _glKosBlendDstFunc();
|
||||
GLubyte _glKosCullFaceMode();
|
||||
GLubyte _glKosCullFaceFront();
|
||||
GLuint _glKosDepthFunc();
|
||||
GLubyte _glKosDepthMask();
|
||||
GLubyte _glKosIsLightEnabled(GLubyte light);
|
||||
GLubyte _glKosGetMaxLights();
|
||||
GLuint _glKosBoundTexID();
|
||||
GLuint _glKosVertexColor();
|
||||
GLubyte _glKosMaxTextureUnits();
|
||||
GLubyte _glKosEnabledTextureMatrix();
|
||||
|
||||
GL_TEXTURE_OBJECT *_glKosBoundMultiTexObject();
|
||||
GLuint _glKosActiveTextureBoundTexID();
|
||||
|
||||
void _glKosPushMultiTexObject(GL_TEXTURE_OBJECT *tex,
|
||||
pvr_vertex_t *src,
|
||||
GLuint count);
|
||||
|
||||
static inline void _glKosVertexCopyPVR(const pvr_vertex_t *src, pvr_vertex_t *dst) {
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
static inline void _glKosTexCoordCopy(const glTexCoord *src, glTexCoord *dst) {
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
#endif
|
1347
gl-arrays.c
1347
gl-arrays.c
File diff suppressed because it is too large
Load Diff
30
gl-arrays.h
30
gl-arrays.h
|
@ -1,30 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-arrays.h
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Arrays Input Primitive Types Supported:
|
||||
-GL_TRIANGLES
|
||||
-GL_TRIANGLE_STRIPS
|
||||
-GL_QUADS
|
||||
|
||||
Here, it is not necessary to enable or disable client states;
|
||||
the API is aware of what arrays have been submitted, and will
|
||||
render accordingly. If you submit a normal pointer, dynamic
|
||||
vertex lighting will be applied even if you submit a color
|
||||
pointer, so only submit one or the other.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GL_ARRAYS_H
|
||||
#define GL_ARRAYS_H
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
#define GL_KOS_USE_ARRAY (1<<0)
|
||||
#define GL_KOS_USE_TEXTURE0 (1<<1)
|
||||
#define GL_KOS_USE_TEXTURE1 (1<<2)
|
||||
#define GL_KOS_USE_COLOR (1<<3)
|
||||
#define GL_KOS_USE_NORMAL (1<<4)
|
||||
|
||||
#endif
|
283
gl-cap.c
283
gl-cap.c
|
@ -1,283 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-cap.c
|
||||
Copyright (C) 2014 Josh Pearson
|
||||
|
||||
KOS Open GL Capabilty State Machine Implementation.
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
|
||||
//===============================================================================//
|
||||
//== Enable Bit Flags ==//
|
||||
|
||||
#define GL_KOS_ENABLE_DEPTH_TEST (1<<0)
|
||||
#define GL_KOS_ENABLE_SCISSOR_TEST (1<<1)
|
||||
#define GL_KOS_ENABLE_CULLING (1<<2)
|
||||
#define GL_KOS_ENABLE_FOG (1<<3)
|
||||
#define GL_KOS_ENABLE_LIGHTING (1<<4)
|
||||
#define GL_KOS_ENABLE_ZCLIPPING (1<<5)
|
||||
#define GL_KOS_ENABLE_SUPERSAMPLE (1<<6)
|
||||
#define GL_KOS_ENABLE_TEXTURE2D (1<<7)
|
||||
#define GL_KOS_ENABLE_BLENDING (1<<8)
|
||||
#define GL_KOS_ENABLE_TEXTURE_MAT (1<<9)
|
||||
|
||||
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);
|
||||
|
||||
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_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_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_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_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);
|
||||
|
||||
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_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_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_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_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);
|
||||
|
||||
switch(cap) {
|
||||
case GL_DEPTH_TEST:
|
||||
return _glKosEnabledDepthTest() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_SCISSOR_TEST:
|
||||
return _glKosEnabledScissorTest() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_CULL_FACE:
|
||||
return _glKosEnabledCulling() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_FOG:
|
||||
return _glKosEnabledFog() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_LIGHTING:
|
||||
return _glKosEnabledLighting() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_KOS_NEARZ_CLIPPING:
|
||||
return _glKosEnabledNearZClip() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_TEXTURE_2D:
|
||||
return _glKosEnabledTexture2D() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_BLEND:
|
||||
return _glKosEnabledBlend() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_KOS_TEXTURE_MATRIX:
|
||||
return _glKosEnabledTextureMatrix() ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
void APIENTRY glGetIntegerv(GLenum pname, GLint *params) {
|
||||
switch(pname) {
|
||||
case GL_ACTIVE_TEXTURE:
|
||||
*params = 0;
|
||||
break;
|
||||
|
||||
case GL_BLEND:
|
||||
*params = _glKosList();
|
||||
break;
|
||||
|
||||
case GL_BLEND_DST:
|
||||
*params = _glKosBlendSrcFunc();
|
||||
break;
|
||||
|
||||
case GL_BLEND_SRC:
|
||||
*params = _glKosBlendDstFunc();
|
||||
break;
|
||||
|
||||
case GL_CULL_FACE:
|
||||
*params = _glKosEnabledCulling();
|
||||
break;
|
||||
|
||||
case GL_CULL_FACE_MODE:
|
||||
*params = _glKosCullFaceMode();
|
||||
break;
|
||||
|
||||
case GL_DEPTH_FUNC:
|
||||
*params = _glKosDepthFunc();
|
||||
break;
|
||||
|
||||
case GL_DEPTH_TEST:
|
||||
*params = _glKosEnabledDepthTest();
|
||||
break;
|
||||
|
||||
case GL_DEPTH_WRITEMASK:
|
||||
*params = _glKosDepthMask();
|
||||
break;
|
||||
|
||||
case GL_FRONT_FACE:
|
||||
*params = _glKosCullFaceFront();
|
||||
break;
|
||||
|
||||
case GL_SCISSOR_TEST:
|
||||
*params = _glKosEnabledScissorTest();
|
||||
break;
|
||||
|
||||
case GL_MAX_LIGHTS:
|
||||
*params = _glKosGetMaxLights();
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_BINDING_2D:
|
||||
*params = _glKosActiveTextureBoundTexID();
|
||||
break;
|
||||
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glGetIntegerv");
|
||||
_glKosPrintError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glGetFloatv(GLenum pname, GLfloat *params) {
|
||||
switch(pname) {
|
||||
case GL_MODELVIEW_MATRIX:
|
||||
case GL_PROJECTION_MATRIX:
|
||||
case GL_TEXTURE_MATRIX:
|
||||
glKosGetMatrix(pname - GL_MODELVIEW_MATRIX + 1, params);
|
||||
break;
|
||||
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glGetFloatv");
|
||||
_glKosPrintError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const GLbyte *glGetString(GLenum name) {
|
||||
switch(name) {
|
||||
case GL_VENDOR:
|
||||
return "KallistiOS / Kazade";
|
||||
|
||||
case GL_RENDERER:
|
||||
return "PowerVR2 CLX2 100mHz";
|
||||
|
||||
case GL_VERSION:
|
||||
return "KGL 1.x";
|
||||
|
||||
case GL_EXTENSIONS:
|
||||
return "GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg";
|
||||
}
|
||||
|
||||
return "GL_KOS_ERROR: ENUM Unsupported\n";
|
||||
}
|
||||
|
||||
//===============================================================================//
|
||||
//== Internal API Functions ==//
|
||||
|
||||
GLubyte _glKosEnabledDepthTest() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_DEPTH_TEST;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledScissorTest() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_SCISSOR_TEST;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledCulling() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_CULLING;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledFog() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_FOG;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledLighting() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_LIGHTING;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledNearZClip() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_ZCLIPPING;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledTexture2D() {
|
||||
return GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_TEXTURE2D;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledBlend() {
|
||||
return (GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_BLENDING) >> 8;
|
||||
}
|
||||
|
||||
GLubyte _glKosEnabledTextureMatrix() {
|
||||
return (GL_KOS_ENABLE_CAP & GL_KOS_ENABLE_TEXTURE_MAT) >> 9;
|
||||
}
|
418
gl-clip-arrays.c
418
gl-clip-arrays.c
|
@ -1,418 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-clip.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Near-Z Clipping Algorithm (C) 2013-2014 Josh PH3NOM Pearson
|
||||
Input Primitive Types Supported:
|
||||
-GL_TRIANGLES
|
||||
-GL_TRIANGLE_STRIPS
|
||||
-GL_QUADS
|
||||
Outputs a mix of Triangles and Triangle Strips for use with the PVR
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-clip.h"
|
||||
|
||||
|
||||
static inline void _glKosVertexClipZNear2(pvr_vertex_t *v1, pvr_vertex_t *v2,
|
||||
GLfloat *w1, GLfloat *w2,
|
||||
glTexCoord *uva, glTexCoord *uvb) {
|
||||
GLfloat MAG = ((CLIP_NEARZ - v1->z) / (v2->z - v1->z));
|
||||
|
||||
colorui *c1 = (colorui *)&v1->argb; /* GLubyte Color Component Pointer */
|
||||
colorui *c2 = (colorui *)&v2->argb;
|
||||
|
||||
v1->x += (v2->x - v1->x) * MAG; /* Clip Vertex X, Y, Z Components */
|
||||
v1->y += (v2->y - v1->y) * MAG;
|
||||
v1->z += (v2->z - v1->z) * MAG;
|
||||
v1->u += (v2->u - v1->u) * MAG; /* Clip Vertex Texture Coordinates */
|
||||
v1->v += (v2->v - v1->v) * MAG;
|
||||
c1->a += (c2->a - c1->a) * MAG; /* Clip Vertex Color per ARGB component */
|
||||
c1->r += (c2->r - c1->r) * MAG;
|
||||
c1->g += (c2->g - c1->g) * MAG;
|
||||
c1->b += (c2->b - c1->b) * MAG;
|
||||
|
||||
*w1 += (*w2 - *w1) * MAG; /* Clip Vertex W Component */
|
||||
|
||||
uva->u += (uvb->u - uva->u) * MAG; /* Clip Vertex Multi-Texture Coordinates */
|
||||
uva->v += (uvb->v - uva->v) * MAG;
|
||||
}
|
||||
|
||||
static inline void _glKosVertexClipZNear3(pvr_vertex_t *v1, pvr_vertex_t *v2, float *w1, float *w2) {
|
||||
GLfloat MAG = ((CLIP_NEARZ - v1->z) / (v2->z - v1->z));
|
||||
|
||||
colorui *c1 = (colorui *)&v1->argb;
|
||||
colorui *c2 = (colorui *)&v2->argb;
|
||||
|
||||
v1->x += (v2->x - v1->x) * MAG;
|
||||
v1->y += (v2->y - v1->y) * MAG;
|
||||
v1->z += (v2->z - v1->z) * MAG;
|
||||
v1->u += (v2->u - v1->u) * MAG;
|
||||
v1->v += (v2->v - v1->v) * MAG;
|
||||
c1->a += (c2->a - c1->a) * MAG;
|
||||
c1->r += (c2->r - c1->r) * MAG;
|
||||
c1->g += (c2->g - c1->g) * MAG;
|
||||
c1->b += (c2->b - c1->b) * MAG;
|
||||
|
||||
*w1 += (*w2 - *w1) * MAG;
|
||||
}
|
||||
|
||||
static inline void _glKosVertexPerspectiveDivide(pvr_vertex_t *dst, GLfloat w) {
|
||||
dst->z = 1.0f / w;
|
||||
dst->x *= dst->z;
|
||||
dst->y *= dst->z;
|
||||
}
|
||||
|
||||
static inline GLubyte _glKosClipTriTransformed(pvr_vertex_t *src, GLfloat *w, pvr_vertex_t *dst) {
|
||||
GLushort clip = 0; /* Clip Code for current Triangle */
|
||||
GLubyte verts_in = 0; /* # of Vertices inside clip plane for current Triangle */
|
||||
GLfloat W[4] = { w[0], w[1], w[2] }; /* W Component for Perspective Divide */
|
||||
|
||||
(src[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in;
|
||||
(src[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in;
|
||||
(src[2].z >= CLIP_NEARZ) ? clip |= THIRD : ++verts_in;
|
||||
|
||||
switch(verts_in) { /* Start by examining # of vertices inside clip plane */
|
||||
case 0: /* All Vertices of Triangle are Outside of clip plne */
|
||||
return 0;
|
||||
|
||||
case 3: /* All Vertices of Triangle are inside of clip plne */
|
||||
_glKosVertexCopyPVR(&src[0], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[2]);
|
||||
|
||||
_glKosVertexPerspectiveDivide(&dst[0], W[0]);
|
||||
_glKosVertexPerspectiveDivide(&dst[1], W[1]);
|
||||
_glKosVertexPerspectiveDivide(&dst[2], W[2]);
|
||||
|
||||
dst[0].flags = dst[1].flags = PVR_CMD_VERTEX;
|
||||
dst[2].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 3;
|
||||
|
||||
case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */
|
||||
_glKosVertexCopyPVR(&src[0], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[2]);
|
||||
|
||||
switch(clip) {
|
||||
case FIRST_TWO_OUT:
|
||||
_glKosVertexClipZNear3(&dst[0], &dst[2], &W[0], &W[2]);
|
||||
_glKosVertexClipZNear3(&dst[1], &dst[2], &W[1], &W[2]);
|
||||
|
||||
break;
|
||||
|
||||
case FIRST_AND_LAST_OUT:
|
||||
_glKosVertexClipZNear3(&dst[0], &dst[1], &W[0], &W[1]);
|
||||
_glKosVertexClipZNear3(&dst[2], &dst[1], &W[2], &W[1]);
|
||||
|
||||
break;
|
||||
|
||||
case LAST_TWO_OUT:
|
||||
_glKosVertexClipZNear3(&dst[1], &dst[0], &W[1], &W[0]);
|
||||
_glKosVertexClipZNear3(&dst[2], &dst[0], &W[2], &W[0]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_glKosVertexPerspectiveDivide(&dst[0], W[0]);
|
||||
_glKosVertexPerspectiveDivide(&dst[1], W[1]);
|
||||
_glKosVertexPerspectiveDivide(&dst[2], W[2]);
|
||||
|
||||
dst[0].flags = dst[1].flags = PVR_CMD_VERTEX;
|
||||
dst[2].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 3;
|
||||
|
||||
case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */
|
||||
switch(clip) {
|
||||
case FIRST:
|
||||
_glKosVertexCopyPVR(&src[0], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[0], &dst[2]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[3]);
|
||||
W[3] = W[2];
|
||||
W[2] = W[0];
|
||||
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
_glKosVertexCopyPVR(&src[1], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[2]);
|
||||
_glKosVertexCopyPVR(&src[0], &dst[3]);
|
||||
W[3] = W[0];
|
||||
W[0] = W[1];
|
||||
W[1] = W[2];
|
||||
W[2] = W[0];
|
||||
|
||||
break;
|
||||
|
||||
case THIRD:
|
||||
_glKosVertexCopyPVR(&src[2], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[0], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[2]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[3]);
|
||||
W[3] = W[1];
|
||||
W[1] = W[0];
|
||||
W[0] = W[2];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_glKosVertexClipZNear3(&dst[0], &dst[1], &W[0], &W[1]);
|
||||
_glKosVertexClipZNear3(&dst[2], &dst[3], &W[2], &W[3]);
|
||||
|
||||
_glKosVertexPerspectiveDivide(&dst[0], W[0]);
|
||||
_glKosVertexPerspectiveDivide(&dst[1], W[1]);
|
||||
_glKosVertexPerspectiveDivide(&dst[2], W[2]);
|
||||
_glKosVertexPerspectiveDivide(&dst[3], W[3]);
|
||||
|
||||
dst[0].flags = dst[1].flags = dst[2].flags = PVR_CMD_VERTEX;
|
||||
dst[3].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint _glKosClipTrianglesTransformed(pvr_vertex_t *src, GLfloat *w, pvr_vertex_t *dst, GLuint count) {
|
||||
GLuint verts_out = 0;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < count; i += 3)
|
||||
verts_out += _glKosClipTriTransformed(&src[i], &w[i], &dst[verts_out]);
|
||||
|
||||
return verts_out;
|
||||
}
|
||||
|
||||
GLuint _glKosClipTriangleStripTransformed(pvr_vertex_t *src, GLfloat *w, pvr_vertex_t *dst, GLuint count) {
|
||||
GLuint verts_out = 0;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < (count - 2); i ++)
|
||||
verts_out += _glKosClipTriTransformed(&src[i], &w[i], &dst[verts_out]);
|
||||
|
||||
return verts_out;
|
||||
}
|
||||
|
||||
unsigned int _glKosClipQuadsTransformed(pvr_vertex_t *src, GLfloat *w, pvr_vertex_t *dst, GLuint count) {
|
||||
GLuint i, verts_out = 0;
|
||||
pvr_vertex_t qv[3];
|
||||
GLfloat W[3];
|
||||
|
||||
for(i = 0; i < count; i += 4) { /* Iterate all Quads, Rearranging into Triangle Strips */
|
||||
_glKosVertexCopyPVR(&src[i + 0], &qv[0]);
|
||||
_glKosVertexCopyPVR(&src[i + 2], &qv[1]);
|
||||
_glKosVertexCopyPVR(&src[i + 3], &qv[2]);
|
||||
W[0] = w[0];
|
||||
W[1] = w[2];
|
||||
W[2] = w[3];
|
||||
|
||||
verts_out += _glKosClipTriTransformed(&src[i], &w[i], &dst[verts_out]);
|
||||
verts_out += _glKosClipTriTransformed(qv, W, &dst[verts_out]);
|
||||
}
|
||||
|
||||
return verts_out;
|
||||
}
|
||||
|
||||
static inline GLubyte _glKosClipTriTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride) {
|
||||
GLushort clip = 0; /* Clip Code for current Triangle */
|
||||
GLubyte verts_in = 0; /* # of Vertices inside clip plane for current Triangle */
|
||||
GLfloat W[4] = { w[0], w[1], w[2] }; /* W Component for Perspective Divide */
|
||||
|
||||
(src[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in;
|
||||
(src[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in;
|
||||
(src[2].z >= CLIP_NEARZ) ? clip |= THIRD : ++verts_in;
|
||||
|
||||
switch(verts_in) { /* Start by examining # of vertices inside clip plane */
|
||||
case 0: /* All Vertices of Triangle are Outside of clip plane */
|
||||
return 0;
|
||||
|
||||
case 3: /* All Vertices of Triangle are Inside of clip plane */
|
||||
_glKosVertexCopyPVR(&src[0], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[2]);
|
||||
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[0], &uvdst[0]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride], &uvdst[1]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride + uv_src_stride], &uvdst[2]);
|
||||
|
||||
_glKosVertexPerspectiveDivide(&dst[0], W[0]);
|
||||
_glKosVertexPerspectiveDivide(&dst[1], W[1]);
|
||||
_glKosVertexPerspectiveDivide(&dst[2], W[2]);
|
||||
|
||||
dst[0].flags = dst[1].flags = PVR_CMD_VERTEX;
|
||||
dst[2].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 3;
|
||||
|
||||
case 1:/* 1 Vertex of Triangle is Inside of clip plane = output 1 Triangle */
|
||||
_glKosVertexCopyPVR(&src[0], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[2]);
|
||||
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[0], &uvdst[0]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride], &uvdst[1]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride + uv_src_stride], &uvdst[2]);
|
||||
|
||||
switch(clip) {
|
||||
case FIRST_TWO_OUT:
|
||||
_glKosVertexClipZNear2(&dst[0], &dst[2], &W[0], &W[2], &uvdst[0], &uvdst[2]);
|
||||
_glKosVertexClipZNear2(&dst[1], &dst[2], &W[1], &W[2], &uvdst[1], &uvdst[2]);
|
||||
|
||||
break;
|
||||
|
||||
case FIRST_AND_LAST_OUT:
|
||||
_glKosVertexClipZNear2(&dst[0], &dst[1], &W[0], &W[1], &uvdst[0], &uvdst[1]);
|
||||
_glKosVertexClipZNear2(&dst[2], &dst[1], &W[2], &W[1], &uvdst[2], &uvdst[1]);
|
||||
|
||||
break;
|
||||
|
||||
case LAST_TWO_OUT:
|
||||
_glKosVertexClipZNear2(&dst[1], &dst[0], &W[1], &W[0], &uvdst[1], &uvdst[0]);
|
||||
_glKosVertexClipZNear2(&dst[2], &dst[0], &W[2], &W[0], &uvdst[2], &uvdst[0]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_glKosVertexPerspectiveDivide(&dst[0], W[0]);
|
||||
_glKosVertexPerspectiveDivide(&dst[1], W[1]);
|
||||
_glKosVertexPerspectiveDivide(&dst[2], W[2]);
|
||||
|
||||
dst[0].flags = dst[1].flags = PVR_CMD_VERTEX;
|
||||
dst[2].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 3;
|
||||
|
||||
case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */
|
||||
switch(clip) {
|
||||
case FIRST:
|
||||
_glKosVertexCopyPVR(&src[0], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[0], &dst[2]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[3]);
|
||||
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[0], &uvdst[0]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride], &uvdst[1]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[0], &uvdst[2]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride + uv_src_stride], &uvdst[3]);
|
||||
|
||||
W[3] = W[2];
|
||||
W[2] = W[0];
|
||||
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
_glKosVertexCopyPVR(&src[1], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[2]);
|
||||
_glKosVertexCopyPVR(&src[0], &dst[3]);
|
||||
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride], &uvdst[0]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride + uv_src_stride], &uvdst[1]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride], &uvdst[2]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[0], &uvdst[3]);
|
||||
|
||||
W[3] = W[0];
|
||||
W[0] = W[1];
|
||||
W[1] = W[2];
|
||||
W[2] = W[0];
|
||||
|
||||
break;
|
||||
|
||||
case THIRD:
|
||||
_glKosVertexCopyPVR(&src[2], &dst[0]);
|
||||
_glKosVertexCopyPVR(&src[0], &dst[1]);
|
||||
_glKosVertexCopyPVR(&src[2], &dst[2]);
|
||||
_glKosVertexCopyPVR(&src[1], &dst[3]);
|
||||
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride + uv_src_stride], &uvdst[0]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[0], &uvdst[1]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride + uv_src_stride], &uvdst[2]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[uv_src_stride], &uvdst[3]);
|
||||
|
||||
W[3] = W[1];
|
||||
W[1] = W[0];
|
||||
W[0] = W[2];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_glKosVertexClipZNear2(&dst[0], &dst[1], &W[0], &W[1], &uvdst[0], &uvdst[1]);
|
||||
_glKosVertexClipZNear2(&dst[2], &dst[3], &W[2], &W[3], &uvdst[2], &uvdst[3]);
|
||||
|
||||
_glKosVertexPerspectiveDivide(&dst[0], W[0]);
|
||||
_glKosVertexPerspectiveDivide(&dst[1], W[1]);
|
||||
_glKosVertexPerspectiveDivide(&dst[2], W[2]);
|
||||
_glKosVertexPerspectiveDivide(&dst[3], W[3]);
|
||||
|
||||
dst[0].flags = dst[1].flags = dst[2].flags = PVR_CMD_VERTEX;
|
||||
dst[3].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint _glKosClipTrianglesTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride,
|
||||
GLuint count) {
|
||||
GLuint verts_out = 0;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < count; i += 3)
|
||||
verts_out += _glKosClipTriTransformedMT(&src[i], &w[i], &dst[verts_out],
|
||||
&uvsrc[i * uv_src_stride], &uvdst[verts_out], uv_src_stride);
|
||||
|
||||
return verts_out;
|
||||
}
|
||||
|
||||
GLuint _glKosClipTriangleStripTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride, GLuint count) {
|
||||
GLuint verts_out = 0;
|
||||
GLuint i;
|
||||
|
||||
for(i = 0; i < (count - 2); i ++)
|
||||
verts_out += _glKosClipTriTransformedMT(&src[i], &w[i], &dst[verts_out],
|
||||
&uvsrc[i * uv_src_stride], &uvdst[verts_out], uv_src_stride);
|
||||
|
||||
return verts_out;
|
||||
}
|
||||
|
||||
GLuint _glKosClipQuadsTransformedMT(pvr_vertex_t *src, float *w, pvr_vertex_t *dst,
|
||||
GLfloat *uvsrc, glTexCoord *uvdst, GLuint uv_src_stride, GLuint count) {
|
||||
GLuint i, verts_out = 0;
|
||||
pvr_vertex_t qv[3];
|
||||
glTexCoord uv[3];
|
||||
GLfloat W[3];
|
||||
|
||||
for(i = 0; i < count; i += 4) {
|
||||
_glKosVertexCopyPVR(&src[i + 0], &qv[0]);
|
||||
_glKosVertexCopyPVR(&src[i + 2], &qv[1]);
|
||||
_glKosVertexCopyPVR(&src[i + 3], &qv[2]);
|
||||
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[i * uv_src_stride], &uv[0]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[i * uv_src_stride + (uv_src_stride * 2)], &uv[1]);
|
||||
_glKosTexCoordCopy((glTexCoord *)&uvsrc[i * uv_src_stride + (uv_src_stride * 3)], &uv[2]);
|
||||
|
||||
W[0] = w[0];
|
||||
W[1] = w[2];
|
||||
W[2] = w[3];
|
||||
|
||||
verts_out += _glKosClipTriTransformedMT(&src[i], &w[i], &dst[verts_out],
|
||||
&uvsrc[i * uv_src_stride], &uvdst[verts_out], uv_src_stride);
|
||||
verts_out += _glKosClipTriTransformedMT(qv, W, &dst[verts_out],
|
||||
(GLfloat *)uv, &uvdst[verts_out], 2);
|
||||
}
|
||||
|
||||
return verts_out;
|
||||
}
|
310
gl-clip.c
310
gl-clip.c
|
@ -1,310 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-clip.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Near-Z Clipping Algorithm (C) 2013-2014 Josh PH3NOM Pearson
|
||||
Input Primitive Types Supported:
|
||||
-GL_TRIANGLES
|
||||
-GL_TRIANGLE_STRIPS
|
||||
-GL_QUADS
|
||||
Outputs a mix of Triangles and Triangle Strips for use with the PVR
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-clip.h"
|
||||
|
||||
static float3 CLIP_BUF[1024 * 32];
|
||||
|
||||
static inline void _glKosVertexClipZNear(pvr_vertex_t *v1, pvr_vertex_t *v2, float MAG) {
|
||||
colorui *c1 = (colorui *)&v1->argb;
|
||||
colorui *c2 = (colorui *)&v2->argb;
|
||||
|
||||
v1->x += (v2->x - v1->x) * MAG;
|
||||
v1->y += (v2->y - v1->y) * MAG;
|
||||
v1->z += (v2->z - v1->z) * MAG;
|
||||
v1->u += (v2->u - v1->u) * MAG;
|
||||
v1->v += (v2->v - v1->v) * MAG;
|
||||
c1->a += (c2->a - c1->a) * MAG;
|
||||
c1->r += (c2->r - c1->r) * MAG;
|
||||
c1->g += (c2->g - c1->g) * MAG;
|
||||
c1->b += (c2->b - c1->b) * MAG;
|
||||
}
|
||||
|
||||
static GLuint _glKosTransformClip(pvr_vertex_t *v, GLint count) {
|
||||
pvr_vertex_t *V = v;
|
||||
float3 *C = CLIP_BUF;
|
||||
GLuint in = 0;
|
||||
|
||||
while(count--) {
|
||||
mat_trans_single3_nodiv_nomod(V->x, V->y, V->z, C->x, C->y, C->z);
|
||||
|
||||
if(C->z < CLIP_NEARZ) ++in;
|
||||
|
||||
++C;
|
||||
++V;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
GLuint _glKosClipTriangleStrip(pvr_vertex_t *src, pvr_vertex_t *dst, GLuint vertices) {
|
||||
GLuint i, v = 0, in = _glKosTransformClip(src, vertices);
|
||||
float3 *C = CLIP_BUF;
|
||||
|
||||
if(in == vertices) {
|
||||
memcpy(dst, src, vertices * 0x20);
|
||||
pvr_vertex_t *v = dst;
|
||||
|
||||
while(--in) {
|
||||
v->flags = PVR_CMD_VERTEX;
|
||||
++v;
|
||||
}
|
||||
|
||||
v->flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return vertices;
|
||||
}
|
||||
else if(in == 0)
|
||||
return 0;
|
||||
|
||||
/* Iterate all Triangles of the Strip - Hence looping vertices-2 times */
|
||||
for(i = 0; i < ((vertices) - 2); i++) {
|
||||
GLushort clip = 0; /* Clip Code for current Triangle */
|
||||
GLubyte verts_in = 0; /* # of Verteices inside clip plane for current Triangle */
|
||||
|
||||
C->z >= CLIP_NEARZ ? clip |= FIRST : ++verts_in;
|
||||
(C + 1)->z >= CLIP_NEARZ ? clip |= SECOND : ++verts_in;
|
||||
(C + 2)->z >= CLIP_NEARZ ? clip |= THIRD : ++verts_in;
|
||||
|
||||
switch(verts_in) { /* Start by examining # of vertices inside clip plane */
|
||||
case 0: /* All Vertices of Triangle are outside of clip plne */
|
||||
break;
|
||||
|
||||
case 3: /* All Vertices of Triangle are inside of clip plne */
|
||||
memcpy(&dst[v], &src[i], 96);
|
||||
|
||||
dst[v].flags = dst[v + 1].flags = PVR_CMD_VERTEX;
|
||||
dst[v + 2].flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
v += 3;
|
||||
break;
|
||||
|
||||
case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */
|
||||
memcpy(&dst[v], &src[i], 96);
|
||||
|
||||
switch(clip) {
|
||||
case FIRST_TWO_OUT:
|
||||
_glKosVertexClipZNear(&dst[v], &dst[v + 2], _glKosNearZClipMag(&CLIP_BUF[i], &CLIP_BUF[i + 2]));
|
||||
_glKosVertexClipZNear(&dst[v + 1], &dst[v + 2], _glKosNearZClipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 2]));
|
||||
|
||||
break;
|
||||
|
||||
case FIRST_AND_LAST_OUT:
|
||||
_glKosVertexClipZNear(&dst[v], &dst[v + 1], _glKosNearZClipMag(&CLIP_BUF[i], &CLIP_BUF[i + 1]));
|
||||
_glKosVertexClipZNear(&dst[v + 2], &dst[v + 1], _glKosNearZClipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 1]));
|
||||
|
||||
break;
|
||||
|
||||
case LAST_TWO_OUT:
|
||||
_glKosVertexClipZNear(&dst[v + 1], &dst[v], _glKosNearZClipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 0]));
|
||||
_glKosVertexClipZNear(&dst[v + 2], &dst[v], _glKosNearZClipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 0]));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dst[v].flags = dst[v + 1].flags = PVR_CMD_VERTEX;
|
||||
dst[v + 2].flags = PVR_CMD_VERTEX_EOL;
|
||||
v += 3;
|
||||
|
||||
break;
|
||||
|
||||
case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */
|
||||
switch(clip) {
|
||||
case FIRST:
|
||||
_glKosVertexCopyPVR(&src[i + 0], &dst[v + 0]);
|
||||
_glKosVertexCopyPVR(&src[i + 1], &dst[v + 1]);
|
||||
_glKosVertexCopyPVR(&src[i + 0], &dst[v + 2]);
|
||||
_glKosVertexCopyPVR(&src[i + 2], &dst[v + 3]);
|
||||
_glKosVertexClipZNear(&dst[v + 0], &dst[v + 1], _glKosNearZClipMag(&CLIP_BUF[i], &CLIP_BUF[i + 1]));
|
||||
_glKosVertexClipZNear(&dst[v + 2], &dst[v + 3], _glKosNearZClipMag(&CLIP_BUF[i], &CLIP_BUF[i + 2]));
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
_glKosVertexCopyPVR(&src[i + 1], &dst[v + 0]);
|
||||
_glKosVertexCopyPVR(&src[i + 0], &dst[v + 1]);
|
||||
_glKosVertexCopyPVR(&src[i + 1], &dst[v + 2]);
|
||||
_glKosVertexCopyPVR(&src[i + 2], &dst[v + 3]);
|
||||
_glKosVertexClipZNear(&dst[v + 0], &dst[v + 1], _glKosNearZClipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 0]));
|
||||
_glKosVertexClipZNear(&dst[v + 2], &dst[v + 3], _glKosNearZClipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 2]));
|
||||
break;
|
||||
|
||||
case THIRD:
|
||||
_glKosVertexCopyPVR(&src[i + 2], &dst[v + 0]);
|
||||
_glKosVertexCopyPVR(&src[i + 0], &dst[v + 1]);
|
||||
_glKosVertexCopyPVR(&src[i + 2], &dst[v + 2]);
|
||||
_glKosVertexCopyPVR(&src[i + 1], &dst[v + 3]);
|
||||
_glKosVertexClipZNear(&dst[v + 0], &dst[v + 1], _glKosNearZClipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i]));
|
||||
_glKosVertexClipZNear(&dst[v + 2], &dst[v + 3], _glKosNearZClipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 1]));
|
||||
break;
|
||||
}
|
||||
|
||||
dst[v + 0].flags = dst[v + 1].flags = dst[v + 2].flags = PVR_CMD_VERTEX;
|
||||
dst[v + 3].flags = PVR_CMD_VERTEX_EOL;
|
||||
v += 4;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
C++;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline unsigned char _glKosClipTri(pvr_vertex_t *src, pvr_vertex_t *dst) {
|
||||
GLushort clip = 0; /* Clip Code for current Triangle */
|
||||
GLubyte verts_in = 0; /* # of Vertices inside clip plane for current Triangle */
|
||||
float3 clip_buf[3]; /* Store the Vertices for each Triangle Translated into Clip Space */
|
||||
|
||||
/* Transform all 3 Vertices of Triangle */
|
||||
{
|
||||
register float __x __asm__("fr12") = src->x;
|
||||
register float __y __asm__("fr13") = src->y;
|
||||
register float __z __asm__("fr14") = src->z;
|
||||
|
||||
mat_trans_fv12_nodiv();
|
||||
|
||||
clip_buf[0].x = __x;
|
||||
clip_buf[0].y = __y;
|
||||
clip_buf[0].z = __z;
|
||||
|
||||
__x = (src + 1)->x;
|
||||
__y = (src + 1)->y;
|
||||
__z = (src + 1)->z;
|
||||
|
||||
mat_trans_fv12_nodiv();
|
||||
|
||||
clip_buf[1].x = __x;
|
||||
clip_buf[1].y = __y;
|
||||
clip_buf[1].z = __z;
|
||||
|
||||
__x = (src + 2)->x;
|
||||
__y = (src + 2)->y;
|
||||
__z = (src + 2)->z;
|
||||
|
||||
mat_trans_fv12_nodiv();
|
||||
|
||||
clip_buf[2].x = __x;
|
||||
clip_buf[2].y = __y;
|
||||
clip_buf[2].z = __z;
|
||||
|
||||
/* Compute Clip Code for Triangle */
|
||||
(clip_buf[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in;
|
||||
(clip_buf[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in;
|
||||
(clip_buf[2].z >= CLIP_NEARZ) ? clip |= THIRD : ++verts_in;
|
||||
}
|
||||
|
||||
switch(verts_in) { /* Start by examining # of vertices inside clip plane */
|
||||
case 0: /* All Vertices of Triangle are Outside of clip plne */
|
||||
return 0;
|
||||
|
||||
case 3: /* All Vertices of Triangle are inside of clip plne */
|
||||
memcpy(dst, src, 96);
|
||||
|
||||
dst->flags = (dst + 1)->flags = PVR_CMD_VERTEX;
|
||||
(dst + 2)->flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 3;
|
||||
|
||||
case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */
|
||||
memcpy(dst, src, 96);
|
||||
|
||||
switch(clip) {
|
||||
case FIRST_TWO_OUT:
|
||||
_glKosVertexClipZNear(dst, dst + 2, _glKosNearZClipMag(&clip_buf[0], &clip_buf[2]));
|
||||
_glKosVertexClipZNear(dst + 1, dst + 2, _glKosNearZClipMag(&clip_buf[1], &clip_buf[2]));
|
||||
|
||||
break;
|
||||
|
||||
case FIRST_AND_LAST_OUT:
|
||||
_glKosVertexClipZNear(dst, dst + 1, _glKosNearZClipMag(&clip_buf[0], &clip_buf[1]));
|
||||
_glKosVertexClipZNear(dst + 2, dst + 1, _glKosNearZClipMag(&clip_buf[2], &clip_buf[1]));
|
||||
|
||||
break;
|
||||
|
||||
case LAST_TWO_OUT:
|
||||
_glKosVertexClipZNear(dst + 1, dst, _glKosNearZClipMag(&clip_buf[1], &clip_buf[0]));
|
||||
_glKosVertexClipZNear(dst + 2, dst, _glKosNearZClipMag(&clip_buf[2], &clip_buf[0]));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dst->flags = (dst + 1)->flags = PVR_CMD_VERTEX;
|
||||
(dst + 2)->flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 3;
|
||||
|
||||
case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */
|
||||
switch(clip) {
|
||||
case FIRST:
|
||||
memcpy(dst, src, 64);
|
||||
_glKosVertexCopyPVR(src, dst + 2);
|
||||
_glKosVertexCopyPVR(src + 2, dst + 3);
|
||||
_glKosVertexClipZNear(dst, dst + 1, _glKosNearZClipMag(&clip_buf[0], &clip_buf[1]));
|
||||
_glKosVertexClipZNear(dst + 2, dst + 3, _glKosNearZClipMag(&clip_buf[0], &clip_buf[2]));
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
_glKosVertexCopyPVR(src + 1, dst);
|
||||
_glKosVertexCopyPVR(src, dst + 1);
|
||||
memcpy(dst + 2, src + 1, 64);
|
||||
_glKosVertexClipZNear(dst, dst + 1, _glKosNearZClipMag(&clip_buf[1], &clip_buf[0]));
|
||||
_glKosVertexClipZNear(dst + 2, dst + 3, _glKosNearZClipMag(&clip_buf[1], &clip_buf[2]));
|
||||
break;
|
||||
|
||||
case THIRD:
|
||||
_glKosVertexCopyPVR(src + 2, dst);
|
||||
_glKosVertexCopyPVR(src, dst + 1);
|
||||
_glKosVertexCopyPVR(src + 2, dst + 2);
|
||||
_glKosVertexCopyPVR(src + 1, dst + 3);
|
||||
_glKosVertexClipZNear(dst, dst + 1, _glKosNearZClipMag(&clip_buf[2], &clip_buf[0]));
|
||||
_glKosVertexClipZNear(dst + 2, dst + 3, _glKosNearZClipMag(&clip_buf[2], &clip_buf[1]));
|
||||
break;
|
||||
}
|
||||
|
||||
dst->flags = (dst + 1)->flags = (dst + 2)->flags = PVR_CMD_VERTEX;
|
||||
(dst + 3)->flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint _glKosClipTriangles(pvr_vertex_t *src, pvr_vertex_t *dst, GLuint vertices) {
|
||||
GLuint i, v = 0;
|
||||
|
||||
for(i = 0; i < vertices; i += 3) /* Iterate all Triangles */
|
||||
v += _glKosClipTri(src + i, dst + v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
GLuint _glKosClipQuads(pvr_vertex_t *src, pvr_vertex_t *dst, GLuint vertices) {
|
||||
GLuint i, v = 0;
|
||||
pvr_vertex_t qv;
|
||||
|
||||
for(i = 0; i < vertices; i += 4) { /* Iterate all Quads, Rearranging into Triangle Strips */
|
||||
_glKosVertexCopyPVR(src + i + 3, &qv);
|
||||
_glKosVertexCopyPVR(src + i + 2, src + i + 3);
|
||||
_glKosVertexCopyPVR(&qv, src + i + 2);
|
||||
v += _glKosClipTriangleStrip(src + i, dst + v, 4);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
52
gl-clip.h
52
gl-clip.h
|
@ -1,52 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-clip.h
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Near-Z Clipping Algorithm (C) 2013-2014 Josh PH3NOM Pearson
|
||||
Input Primitive Types Supported:
|
||||
-GL_TRIANGLES
|
||||
-GL_TRIANGLE_STRIPS
|
||||
-GL_QUADS
|
||||
Outputs a mix of Triangles and Triangle Strips for use with the PVR
|
||||
*/
|
||||
|
||||
#ifndef GL_CLIP_H
|
||||
#define GL_CLIP_H
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-sh4.h"
|
||||
|
||||
#define NONE 0x0000 /* Clip Codes */
|
||||
#define FIRST 0x0001
|
||||
#define SECOND 0x0010
|
||||
#define THIRD 0x0100
|
||||
#define ALL 0x0111
|
||||
#define FIRST_TWO_OUT 0x0011
|
||||
#define FIRST_AND_LAST_OUT 0x0101
|
||||
#define LAST_TWO_OUT 0x0110
|
||||
|
||||
#define ALPHA 0xFF000000 /* Color Components using PVR's Packed 32bit int */
|
||||
#define RED 0x00FF0000
|
||||
#define GREEN 0x0000FF00
|
||||
#define BLUE 0x000000FF
|
||||
|
||||
#define CLIP_NEARZ -0.20f /* Clip Threshold */
|
||||
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} float3;
|
||||
|
||||
typedef struct {
|
||||
unsigned char b, g, r, a;
|
||||
} colorui;
|
||||
|
||||
static inline void _glKosVertexCopy3f(float3 *src, float3 *dst) {
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
static inline GLfloat _glKosNearZClipMag(float3 *v1, float3 *v2) {
|
||||
return ((CLIP_NEARZ - v1->z) / (v2->z - v1->z));
|
||||
}
|
||||
|
||||
#endif
|
95
gl-fog.c
95
gl-fog.c
|
@ -1,95 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-fog.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Functionality adapted from the original KOS libgl fog code:
|
||||
Copyright (C) 2002 Benoit Miller
|
||||
|
||||
OpenGL Fog - Wrapper for the PowerVR fog functions in KOS.
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
static GLuint GL_KOS_FOG_MODE = GL_EXP; /* GL_LINEAR, GL_EXP, or GL_EXP2 FOG */
|
||||
static GLfloat GL_KOS_FOG_DENSITY = 1.0f, /* Density - GL_EXP, or GL_EXP2 FOG */
|
||||
GL_KOS_FOG_START = 0.0f, /* Linear FOG */
|
||||
GL_KOS_FOG_END = 1.0f; /* Linear FOG */
|
||||
|
||||
void APIENTRY glFogi(GLenum pname, GLint param) {
|
||||
switch(pname) {
|
||||
case GL_FOG_MODE:
|
||||
switch(param) {
|
||||
case GL_LINEAR:
|
||||
pvr_fog_table_linear(GL_KOS_FOG_START, GL_KOS_FOG_END);
|
||||
break;
|
||||
|
||||
case GL_EXP:
|
||||
pvr_fog_table_exp(GL_KOS_FOG_DENSITY);
|
||||
break;
|
||||
|
||||
case GL_EXP2:
|
||||
pvr_fog_table_exp2(GL_KOS_FOG_DENSITY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogf(GLenum pname, GLfloat param) {
|
||||
switch(pname) {
|
||||
case GL_FOG_START:
|
||||
GL_KOS_FOG_START = param;
|
||||
|
||||
if(GL_KOS_FOG_MODE == GL_LINEAR)
|
||||
pvr_fog_table_linear(GL_KOS_FOG_START, GL_KOS_FOG_END);
|
||||
|
||||
break;
|
||||
|
||||
case GL_FOG_END:
|
||||
GL_KOS_FOG_END = param;
|
||||
|
||||
if(GL_KOS_FOG_MODE == GL_LINEAR)
|
||||
pvr_fog_table_linear(GL_KOS_FOG_START, GL_KOS_FOG_END);
|
||||
|
||||
break;
|
||||
|
||||
case GL_FOG_DENSITY:
|
||||
GL_KOS_FOG_DENSITY = param;
|
||||
|
||||
if(GL_KOS_FOG_MODE == GL_EXP)
|
||||
pvr_fog_table_exp(GL_KOS_FOG_DENSITY);
|
||||
|
||||
else if(GL_KOS_FOG_MODE == GL_EXP2)
|
||||
pvr_fog_table_exp2(GL_KOS_FOG_DENSITY);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogfv(GLenum pname, const GLfloat *params) {
|
||||
switch(pname) {
|
||||
case GL_FOG_MODE:
|
||||
glFogi(pname, (GLint) * params);
|
||||
break;
|
||||
|
||||
case GL_FOG_DENSITY:
|
||||
GL_KOS_FOG_DENSITY = *params;
|
||||
|
||||
if(GL_KOS_FOG_MODE == GL_EXP)
|
||||
pvr_fog_table_exp(GL_KOS_FOG_DENSITY);
|
||||
|
||||
else if(GL_KOS_FOG_MODE == GL_EXP2)
|
||||
pvr_fog_table_exp2(GL_KOS_FOG_DENSITY);
|
||||
|
||||
break;
|
||||
|
||||
case GL_FOG_START:
|
||||
case GL_FOG_END:
|
||||
glFogf(pname, *params);
|
||||
break;
|
||||
|
||||
case GL_FOG_COLOR:
|
||||
pvr_fog_table_color(params[3], params[0], params[1], params[2]);
|
||||
break;
|
||||
}
|
||||
}
|
181
gl-framebuffer.c
181
gl-framebuffer.c
|
@ -1,181 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-framebuffer.c
|
||||
Copyright (C) 2014 Josh Pearson
|
||||
|
||||
This file implements Open GL Frame Buffer Object (FBO) functionality, with what
|
||||
the DC's PVR can directly implement.
|
||||
Basically, Render-To-Texture using GL_RGB565 is the only native feature of the
|
||||
PVR, so if you are looking for a depth-buffer, bad news.
|
||||
|
||||
This implementation uses a dynamic linked list to implement the data structures needed.
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
#include "glext.h"
|
||||
#include "gl-api.h"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
//========================================================================================//
|
||||
//== Internal KOS Open GL API FBO Structures / Global Variables ==//
|
||||
|
||||
static GL_FRAMEBUFFER_OBJECT *FRAMEBUF_OBJ = NULL;
|
||||
static GLsizei FRAMEBUF_OBJECT = 0;
|
||||
|
||||
//========================================================================================//
|
||||
//== Internal KOS Open GL API FBO Functionality ==//
|
||||
|
||||
void _glKosInitFrameBuffers() {
|
||||
FRAMEBUF_OBJ = malloc(sizeof(GL_FRAMEBUFFER_OBJECT));
|
||||
|
||||
FRAMEBUF_OBJ->index = 0;
|
||||
FRAMEBUF_OBJ->texID = 0;
|
||||
FRAMEBUF_OBJ->data = NULL;
|
||||
FRAMEBUF_OBJ->link = NULL;
|
||||
}
|
||||
|
||||
static void _glKosInsertFramebufferObj(GL_FRAMEBUFFER_OBJECT *obj) {
|
||||
GL_FRAMEBUFFER_OBJECT *ptr = FRAMEBUF_OBJ;
|
||||
|
||||
while(ptr->link != NULL)
|
||||
ptr = (GL_FRAMEBUFFER_OBJECT *)ptr->link;
|
||||
|
||||
ptr->link = obj;
|
||||
}
|
||||
|
||||
static GLsizei _glKosGetLastFrameBufferIndex() {
|
||||
GL_FRAMEBUFFER_OBJECT *ptr = FRAMEBUF_OBJ;
|
||||
|
||||
while(ptr->link != NULL)
|
||||
ptr = (GL_FRAMEBUFFER_OBJECT *)ptr->link;
|
||||
|
||||
return ptr->index;
|
||||
}
|
||||
|
||||
static GL_FRAMEBUFFER_OBJECT *_glKosGetFrameBufferObj(GLuint index) {
|
||||
GL_FRAMEBUFFER_OBJECT *ptr = FRAMEBUF_OBJ;
|
||||
|
||||
while(ptr->index != index && ptr->link != NULL)
|
||||
ptr = (GL_FRAMEBUFFER_OBJECT *)ptr->link;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GLsizei _glKosGetFBO() {
|
||||
return FRAMEBUF_OBJECT;
|
||||
}
|
||||
|
||||
GLuint _glKosGetFBOWidth(GLsizei fbi) {
|
||||
GL_FRAMEBUFFER_OBJECT *fbo = _glKosGetFrameBufferObj(fbi);
|
||||
return _glKosTextureWidth(fbo->texID);
|
||||
}
|
||||
|
||||
GLuint _glKosGetFBOHeight(GLsizei fbi) {
|
||||
GL_FRAMEBUFFER_OBJECT *fbo = _glKosGetFrameBufferObj(fbi);
|
||||
return _glKosTextureHeight(fbo->texID);
|
||||
}
|
||||
|
||||
GLvoid *_glKosGetFBOData(GLsizei fbi) {
|
||||
GL_FRAMEBUFFER_OBJECT *fbo = _glKosGetFrameBufferObj(fbi);
|
||||
return fbo->data;
|
||||
}
|
||||
|
||||
//========================================================================================//
|
||||
//== Public KOS Open GL API FBO Functionality ==//
|
||||
|
||||
GLAPI void APIENTRY glGenFramebuffers(GLsizei n, GLuint *framebuffers) {
|
||||
GLsizei index = _glKosGetLastFrameBufferIndex();
|
||||
|
||||
while(n--) {
|
||||
GL_FRAMEBUFFER_OBJECT *obj = malloc(sizeof(GL_FRAMEBUFFER_OBJECT));
|
||||
obj->index = ++index;
|
||||
obj->texID = 0;
|
||||
obj->data = NULL;
|
||||
obj->link = NULL;
|
||||
|
||||
_glKosInsertFramebufferObj(obj);
|
||||
|
||||
*framebuffers++ = obj->index;
|
||||
}
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glDeleteFramebuffers(GLsizei n, GLuint *framebuffers) {
|
||||
while(n--) {
|
||||
GL_FRAMEBUFFER_OBJECT *ptr = FRAMEBUF_OBJ->link, * lptr = FRAMEBUF_OBJ;
|
||||
|
||||
while(ptr != NULL) {
|
||||
if(ptr->index == *framebuffers) {
|
||||
GL_FRAMEBUFFER_OBJECT *cur_node = ptr;
|
||||
lptr->link = ptr->link;
|
||||
ptr = (GL_FRAMEBUFFER_OBJECT *)ptr->link;
|
||||
free(cur_node);
|
||||
|
||||
if(*framebuffers == FRAMEBUF_OBJECT)
|
||||
FRAMEBUF_OBJECT = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
ptr = (GL_FRAMEBUFFER_OBJECT *)ptr->link;
|
||||
}
|
||||
|
||||
++framebuffers;
|
||||
}
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) {
|
||||
if(target != GL_FRAMEBUFFER) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glBindFramebuffer");
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
FRAMEBUF_OBJECT = framebuffer;
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level) {
|
||||
if(target != GL_FRAMEBUFFER)
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glFramebufferTexture2D");
|
||||
|
||||
if(attachment != GL_COLOR_ATTACHMENT0)
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glFramebufferTexture2D");
|
||||
|
||||
if(textarget != GL_TEXTURE_2D)
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glFramebufferTexture2D");
|
||||
|
||||
if(level)
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glFramebufferTexture2D");
|
||||
|
||||
if(!FRAMEBUF_OBJECT)
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glFramebufferTexture2D");
|
||||
|
||||
if(_glKosHasError()) {
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
GL_FRAMEBUFFER_OBJECT *fbo = _glKosGetFrameBufferObj(FRAMEBUF_OBJECT);
|
||||
|
||||
fbo->texID = texture;
|
||||
fbo->data = _glKosTextureData(texture);
|
||||
}
|
||||
|
||||
GLAPI GLenum APIENTRY glCheckFramebufferStatus(GLenum target) {
|
||||
if(target != GL_FRAMEBUFFER) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glCheckFramebufferStatus");
|
||||
_glKosPrintError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!FRAMEBUF_OBJECT)
|
||||
return GL_FRAMEBUFFER_COMPLETE;
|
||||
|
||||
GL_FRAMEBUFFER_OBJECT *fbo = _glKosGetFrameBufferObj(FRAMEBUF_OBJECT);
|
||||
|
||||
if(!fbo->texID)
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||
|
||||
return GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
561
gl-light.c
561
gl-light.c
|
@ -1,561 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-light.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Dynamic Vertex Lighting Model:
|
||||
vertexColor = emissive + ambient + ( diffuse + specular * attenuation )
|
||||
|
||||
The only difference here from real OpenGL is that only 1 ambient light
|
||||
source is used, as opposed to each light containing its own abmient value.
|
||||
Abmient light is set by the glKosLightAbmient..(..) functions below.
|
||||
|
||||
By default, the specular lighting term is enabled.
|
||||
For now, specular can be disabled by setting GL_ENABLE_SPECULAR on
|
||||
gl-light.h when you build the library.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-clip.h"
|
||||
#include "gl-light.h"
|
||||
|
||||
#define GL_KOS_MAX_LIGHTS 16 /* Number of Light Sources that may be enabled at once */
|
||||
|
||||
static GLfloat GL_GLOBAL_AMBIENT[4] = { 0, 0, 0, 0 }; /* RGBA Global Ambient Light */
|
||||
static GLfloat GL_VERTEX_NORMAL[3] = { 0, 0, 0 }; /* Current Vertex Normal */
|
||||
static GLbitfield GL_LIGHT_ENABLED = 0; /* Client State for Enabling Lighting */
|
||||
|
||||
static glLight GL_LIGHTS[GL_KOS_MAX_LIGHTS],
|
||||
GL_DEFAULT_LIGHT = { { 0.0, 0.0, 1.0, 0.0 }, /* Position */
|
||||
{ 0.0, 0.0, -1.0 }, /* Spot Direction */
|
||||
-1.0f, /* Spot Cutoff */
|
||||
1.0f, 0.0f, 0.0f, /* Attenuation Factors */
|
||||
0.0f, /* Spot Exponent */
|
||||
{ 1.0, 1.0, 1.0, 1.0 }, /* Diffuse */
|
||||
{ 1.0, 1.0, 1.0, 1.0 }, /* Specular */
|
||||
{ 0.0, 0.0, 0.0, 1.0 } /* Ambient */
|
||||
};
|
||||
|
||||
static glMaterial GL_MATERIAL,
|
||||
GL_DEFAULT_MATERIAL = { { 0.0, 0.0, 0.0, 1.0 }, /* Emissive Color */
|
||||
{ 0.2, 0.2, 0.2, 1.0 }, /* Ambient Reflectance */
|
||||
{ 0.8, 0.8, 0.8, 1.0 }, /* Diffuse Reflectance */
|
||||
{ 0.0, 0.0, 0.0, 1.0 }, /* Specular Reflectance */
|
||||
0.0 /* Shininess */
|
||||
};
|
||||
|
||||
static GLfloat GL_EYE_POSITION[3] = { 0, 0, 0 }; /* Eye Position for Specular Factor */
|
||||
|
||||
void _glKosSetEyePosition(GLfloat *position) { /* Called internally by glhLookAtf() */
|
||||
GL_EYE_POSITION[0] = position[0];
|
||||
GL_EYE_POSITION[1] = position[1];
|
||||
GL_EYE_POSITION[2] = position[2];
|
||||
}
|
||||
|
||||
void _glKosInitLighting() { /* Called internally by glInit() */
|
||||
unsigned char i;
|
||||
|
||||
for(i = 0; i < GL_KOS_MAX_LIGHTS; i++)
|
||||
memcpy(&GL_LIGHTS[i], &GL_DEFAULT_LIGHT, sizeof(glLight));
|
||||
|
||||
memcpy(&GL_MATERIAL, &GL_DEFAULT_MATERIAL, sizeof(glMaterial));
|
||||
}
|
||||
|
||||
/* Enable a light - GL_LIGHT0->GL_LIGHT7 */
|
||||
void _glKosEnableLight(const GLuint light) {
|
||||
if(light < GL_LIGHT0 || light > GL_LIGHT0 + GL_KOS_MAX_LIGHTS) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glEnable(GL_LIGHT)");
|
||||
return;
|
||||
}
|
||||
|
||||
GL_LIGHT_ENABLED |= (1 << (light & 0xF));
|
||||
}
|
||||
|
||||
/* Disable a light - GL_LIGHT0->GL_LIGHT0 + GL_KOS_MAX_LIGHTS */
|
||||
void _glKosDisableLight(const GLuint light) {
|
||||
if(light < GL_LIGHT0 || light > GL_LIGHT0 + GL_KOS_MAX_LIGHTS) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glDisable(GL_LIGHT)");
|
||||
return;
|
||||
}
|
||||
|
||||
GL_LIGHT_ENABLED &= ~(1 << (light & 0xF));
|
||||
}
|
||||
|
||||
GLubyte _glKosIsLightEnabled(GLubyte light) {
|
||||
return GL_LIGHT_ENABLED & (1 << light);
|
||||
}
|
||||
|
||||
GLubyte _glKosGetMaxLights() {
|
||||
return GL_KOS_MAX_LIGHTS;
|
||||
}
|
||||
|
||||
/* Vertex Normal Submission */
|
||||
void glNormal3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GL_VERTEX_NORMAL[0] = x;
|
||||
GL_VERTEX_NORMAL[1] = y;
|
||||
GL_VERTEX_NORMAL[2] = z;
|
||||
}
|
||||
|
||||
void glNormal3fv(const GLfloat *xyz) {
|
||||
GL_VERTEX_NORMAL[0] = xyz[0];
|
||||
GL_VERTEX_NORMAL[1] = xyz[1];
|
||||
GL_VERTEX_NORMAL[2] = xyz[2];
|
||||
}
|
||||
|
||||
void glLightModelfv(GLenum pname, const GLfloat *params) {
|
||||
if(pname != GL_LIGHT_MODEL_AMBIENT) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glLightModelfv");
|
||||
return;
|
||||
}
|
||||
|
||||
GL_GLOBAL_AMBIENT[0] = params[0];
|
||||
GL_GLOBAL_AMBIENT[1] = params[1];
|
||||
GL_GLOBAL_AMBIENT[2] = params[2];
|
||||
GL_GLOBAL_AMBIENT[3] = params[3];
|
||||
}
|
||||
|
||||
/* Misc Lighting Functions ************************************/
|
||||
static inline void glCopyRGBA(const rgba *src, rgba *dst) {
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
static inline void glCopy4f(const float *src, float *dst) {
|
||||
memcpy(dst, src, 0x10);
|
||||
}
|
||||
|
||||
static inline void glCopy3f(const float *src, float *dst) {
|
||||
memcpy(dst, src, 0xC);
|
||||
}
|
||||
|
||||
/* GL Light Parameters ******************************************************/
|
||||
|
||||
void glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
|
||||
if(light < GL_LIGHT0 || light > GL_LIGHT0 + GL_KOS_MAX_LIGHTS) return;
|
||||
|
||||
switch(pname) {
|
||||
case GL_AMBIENT:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_LIGHTS[light & 0xF].Ka);
|
||||
break;
|
||||
|
||||
case GL_DIFFUSE:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_LIGHTS[light & 0xF].Kd);
|
||||
break;
|
||||
|
||||
case GL_SPECULAR:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_LIGHTS[light & 0xF].Ks);
|
||||
break;
|
||||
|
||||
case GL_POSITION:
|
||||
glCopy4f(params, &GL_LIGHTS[light & 0xF].Pos[0]);
|
||||
break;
|
||||
|
||||
case GL_SPOT_DIRECTION:
|
||||
glCopy3f(params, &GL_LIGHTS[light & 0xF].Dir[0]);
|
||||
break;
|
||||
|
||||
case GL_SPOT_EXPONENT:
|
||||
GL_LIGHTS[light & 0xF].Exponent = *params;
|
||||
break;
|
||||
|
||||
case GL_SPOT_CUTOFF:
|
||||
if(*params >= 0.0f && *params <= 180.0f)
|
||||
GL_LIGHTS[light & 0xF].CutOff = LCOS(*params);
|
||||
|
||||
break;
|
||||
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
if(*params >= 0)
|
||||
GL_LIGHTS[light & 0xF].Kc = *params;
|
||||
else
|
||||
GL_LIGHTS[light & 0xF].Kc = 0;
|
||||
|
||||
break;
|
||||
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
if(*params >= 0)
|
||||
GL_LIGHTS[light & 0xF].Kl = *params;
|
||||
else
|
||||
GL_LIGHTS[light & 0xF].Kl = 0;
|
||||
|
||||
break;
|
||||
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
if(*params >= 0)
|
||||
GL_LIGHTS[light & 0xF].Kq = *params;
|
||||
else
|
||||
GL_LIGHTS[light & 0xF].Kq = 0;
|
||||
|
||||
break;
|
||||
|
||||
case GL_AMBIENT_AND_DIFFUSE:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_LIGHTS[light & 0xF].Ka);
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_LIGHTS[light & 0xF].Kd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void glLightf(GLenum light, GLenum pname, GLfloat param) {
|
||||
if(light < GL_LIGHT0 || light > GL_LIGHT0 + GL_KOS_MAX_LIGHTS) return;
|
||||
|
||||
switch(pname) {
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
if(param >= 0)
|
||||
GL_LIGHTS[light & 0xF].Kc = param;
|
||||
else
|
||||
GL_LIGHTS[light & 0xF].Kc = 0;
|
||||
|
||||
break;
|
||||
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
if(param >= 0)
|
||||
GL_LIGHTS[light & 0xF].Kl = param;
|
||||
else
|
||||
GL_LIGHTS[light & 0xF].Kl = 0;
|
||||
|
||||
break;
|
||||
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
if(param >= 0)
|
||||
GL_LIGHTS[light & 0xF].Kq = param;
|
||||
else
|
||||
GL_LIGHTS[light & 0xF].Kq = 0;
|
||||
|
||||
break;
|
||||
|
||||
case GL_SPOT_CUTOFF:
|
||||
if(param >= 0.0f && param <= 180.0f)
|
||||
GL_LIGHTS[light & 0xF].CutOff = LCOS(param);
|
||||
|
||||
break;
|
||||
|
||||
case GL_SPOT_EXPONENT:
|
||||
GL_LIGHTS[light & 0xF].Exponent = param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* GL Material Parameters **************************************************/
|
||||
|
||||
void glMateriali(GLenum face, GLenum pname, const GLint param) {
|
||||
//if(face!=GL_FRONT_AND_BACK) return;
|
||||
|
||||
if(pname == GL_SHININESS) {
|
||||
if(param < 0)
|
||||
GL_MATERIAL.Shine = 0;
|
||||
else if(param > 128)
|
||||
GL_MATERIAL.Shine = 128;
|
||||
else
|
||||
GL_MATERIAL.Shine = param;
|
||||
}
|
||||
}
|
||||
|
||||
void glMaterialf(GLenum face, GLenum pname, const GLfloat param) {
|
||||
//if(face!=GL_FRONT_AND_BACK) return;
|
||||
|
||||
if(pname == GL_SHININESS) {
|
||||
if(param < 0)
|
||||
GL_MATERIAL.Shine = 0;
|
||||
else if(param > 128.0)
|
||||
GL_MATERIAL.Shine = 128.0;
|
||||
else
|
||||
GL_MATERIAL.Shine = param;
|
||||
}
|
||||
}
|
||||
|
||||
void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
|
||||
//if(face!=GL_FRONT_AND_BACK) return;
|
||||
|
||||
switch(pname) {
|
||||
case GL_AMBIENT:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_MATERIAL.Ka[0]);
|
||||
break;
|
||||
|
||||
case GL_DIFFUSE:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_MATERIAL.Kd[0]);
|
||||
break;
|
||||
|
||||
case GL_SPECULAR:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_MATERIAL.Ks[0]);
|
||||
break;
|
||||
|
||||
case GL_EMISSION:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_MATERIAL.Ke[0]);
|
||||
break;
|
||||
|
||||
case GL_SHININESS:
|
||||
glMaterialf(GL_FRONT_AND_BACK, pname, *params);
|
||||
break;
|
||||
|
||||
case GL_AMBIENT_AND_DIFFUSE:
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_MATERIAL.Ka[0]);
|
||||
glCopyRGBA((rgba *)params, (rgba *)&GL_MATERIAL.Kd[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Vertex Lighting **********************************************************/
|
||||
|
||||
/* Fast POW Implementation - Less accurate, but much faster than math.h */
|
||||
#define EXP_A 184
|
||||
#define EXP_C 16249
|
||||
|
||||
float FEXP(float y) {
|
||||
union {
|
||||
float d;
|
||||
struct {
|
||||
short j, i;
|
||||
} n;
|
||||
} eco;
|
||||
eco.n.i = EXP_A * (y) + (EXP_C);
|
||||
eco.n.j = 0;
|
||||
return eco.d;
|
||||
}
|
||||
|
||||
float FLOG(float y) {
|
||||
int *nTemp = (int *)&y;
|
||||
y = (*nTemp) >> 16;
|
||||
return (y - EXP_C) / EXP_A;
|
||||
}
|
||||
|
||||
float FPOW(float b, float p) {
|
||||
return FEXP(FLOG(b) * p);
|
||||
}
|
||||
|
||||
/* End FPOW Implementation */
|
||||
|
||||
void _glKosVertex3flv(const GLfloat *xyz) {
|
||||
glVertex *v = _glKosArrayBufPtr();
|
||||
|
||||
v->pos[0] = xyz[0];
|
||||
v->pos[1] = xyz[1];
|
||||
v->pos[2] = xyz[2];
|
||||
v->norm[0] = GL_VERTEX_NORMAL[0];
|
||||
v->norm[1] = GL_VERTEX_NORMAL[1];
|
||||
v->norm[2] = GL_VERTEX_NORMAL[2];
|
||||
|
||||
_glKosArrayBufIncrement();
|
||||
|
||||
_glKosVertex3fsv(xyz);
|
||||
}
|
||||
|
||||
void _glKosVertex3fl(GLfloat x, GLfloat y, GLfloat z) {
|
||||
glVertex *v = _glKosArrayBufPtr();
|
||||
|
||||
v->pos[0] = x;
|
||||
v->pos[1] = y;
|
||||
v->pos[2] = z;
|
||||
v->norm[0] = GL_VERTEX_NORMAL[0];
|
||||
v->norm[1] = GL_VERTEX_NORMAL[1];
|
||||
v->norm[2] = GL_VERTEX_NORMAL[2];
|
||||
|
||||
_glKosArrayBufIncrement();
|
||||
|
||||
_glKosVertex3fs(x, y, z);
|
||||
}
|
||||
|
||||
void _glKosVertex3flcv(const GLfloat *xyz) {
|
||||
glVertex *v = _glKosArrayBufPtr();
|
||||
|
||||
v->pos[0] = xyz[0];
|
||||
v->pos[1] = xyz[1];
|
||||
v->pos[2] = xyz[2];
|
||||
v->norm[0] = GL_VERTEX_NORMAL[0];
|
||||
v->norm[1] = GL_VERTEX_NORMAL[1];
|
||||
v->norm[2] = GL_VERTEX_NORMAL[2];
|
||||
|
||||
_glKosArrayBufIncrement();
|
||||
|
||||
_glKosVertex3fcv(xyz);
|
||||
}
|
||||
|
||||
void _glKosVertex3flc(GLfloat x, GLfloat y, GLfloat z) {
|
||||
glVertex *v = _glKosArrayBufPtr();
|
||||
|
||||
v->pos[0] = x;
|
||||
v->pos[1] = y;
|
||||
v->pos[2] = z;
|
||||
v->norm[0] = GL_VERTEX_NORMAL[0];
|
||||
v->norm[1] = GL_VERTEX_NORMAL[1];
|
||||
v->norm[2] = GL_VERTEX_NORMAL[2];
|
||||
|
||||
_glKosArrayBufIncrement();
|
||||
|
||||
_glKosVertex3fc(x, y, z);
|
||||
}
|
||||
|
||||
/**** Compute Vertex Light Color ***/
|
||||
void _glKosVertexLights(glVertex *P, pvr_vertex_t *v, GLuint count) {
|
||||
#ifdef GL_ENABLE_SPECULAR
|
||||
float S;
|
||||
#endif
|
||||
unsigned char i;
|
||||
float L[4] __attribute__((aligned(8)));
|
||||
float C[3] = { 0, 0, 0 };
|
||||
|
||||
colorui *color = (colorui *)&v->argb;
|
||||
|
||||
/* Compute Global Ambient */
|
||||
float A[3] = { GL_MATERIAL.Ke[0] + GL_MATERIAL.Ka[0] *GL_GLOBAL_AMBIENT[0],
|
||||
GL_MATERIAL.Ke[1] + GL_MATERIAL.Ka[1] *GL_GLOBAL_AMBIENT[1],
|
||||
GL_MATERIAL.Ke[2] + GL_MATERIAL.Ka[2] *GL_GLOBAL_AMBIENT[2]
|
||||
};
|
||||
|
||||
while(count--) {
|
||||
for(i = 0; i < GL_KOS_MAX_LIGHTS; i++)
|
||||
if(GL_LIGHT_ENABLED & 1 << i)
|
||||
if(_glKosSpotlight(&GL_LIGHTS[i], P, L)) { /* Compute Spot / Diffuse */
|
||||
C[0] = A[0] + (GL_MATERIAL.Kd[0] * GL_LIGHTS[i].Kd[0] * L[3]);
|
||||
C[1] = A[1] + (GL_MATERIAL.Kd[1] * GL_LIGHTS[i].Kd[1] * L[3]);
|
||||
C[2] = A[2] + (GL_MATERIAL.Kd[2] * GL_LIGHTS[i].Kd[2] * L[3]);
|
||||
|
||||
#ifdef GL_ENABLE_SPECULAR
|
||||
S = _glKosSpecular(P, GL_EYE_POSITION, L); /* Compute Specular */
|
||||
|
||||
if(S > 0) {
|
||||
#ifdef GL_ENABLE_FAST_POW
|
||||
S = FPOW(S, GL_MATERIAL.Shine);
|
||||
#else
|
||||
S = pow(S, GL_MATERIAL.Shine);
|
||||
#endif
|
||||
C[0] += (GL_MATERIAL.Ks[0] * GL_LIGHTS[i].Ks[0] * S);
|
||||
C[1] += (GL_MATERIAL.Ks[1] * GL_LIGHTS[i].Ks[1] * S);
|
||||
C[2] += (GL_MATERIAL.Ks[2] * GL_LIGHTS[i].Ks[2] * S);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
color->a = 0xFF; /* Clamp / Pack Floating Point Colors to 32bit int */
|
||||
(C[0] > 1.0f) ? (color->r = 0xFF) : (color->r = (unsigned char)(255 * C[0]));
|
||||
(C[1] > 1.0f) ? (color->g = 0xFF) : (color->g = (unsigned char)(255 * C[1]));
|
||||
(C[2] > 1.0f) ? (color->b = 0xFF) : (color->b = (unsigned char)(255 * C[2]));
|
||||
color += 8; /* pvr_vertex_t color stride */
|
||||
++P;
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosVertexLight(glVertex *P, pvr_vertex_t *v) {
|
||||
#ifdef GL_ENABLE_SPECULAR
|
||||
float S;
|
||||
#endif
|
||||
unsigned char i;
|
||||
float L[4] __attribute__((aligned(8)));
|
||||
|
||||
/* Compute Ambient */
|
||||
float C[3] = { GL_MATERIAL.Ke[0] + GL_MATERIAL.Ka[0] *GL_GLOBAL_AMBIENT[0],
|
||||
GL_MATERIAL.Ke[1] + GL_MATERIAL.Ka[1] *GL_GLOBAL_AMBIENT[1],
|
||||
GL_MATERIAL.Ke[2] + GL_MATERIAL.Ka[2] *GL_GLOBAL_AMBIENT[2]
|
||||
};
|
||||
|
||||
for(i = 0; i < GL_KOS_MAX_LIGHTS; i++)
|
||||
if(GL_LIGHT_ENABLED & 1 << i)
|
||||
if(_glKosSpotlight(&GL_LIGHTS[i], P, L)) { /* Compute Spot / Diffuse */
|
||||
C[0] += (GL_MATERIAL.Kd[0] * GL_LIGHTS[i].Kd[0] * L[3]);
|
||||
C[1] += (GL_MATERIAL.Kd[1] * GL_LIGHTS[i].Kd[1] * L[3]);
|
||||
C[2] += (GL_MATERIAL.Kd[2] * GL_LIGHTS[i].Kd[2] * L[3]);
|
||||
|
||||
#ifdef GL_ENABLE_SPECULAR
|
||||
S = _glKosSpecular(P, GL_EYE_POSITION, L); /* Compute Specular */
|
||||
|
||||
if(S > 0) {
|
||||
#ifdef GL_ENABLE_FAST_POW
|
||||
S = FPOW(S, GL_MATERIAL.Shine);
|
||||
#else
|
||||
S = pow(S, GL_MATERIAL.Shine);
|
||||
#endif
|
||||
C[0] += (GL_MATERIAL.Ks[0] * GL_LIGHTS[i].Ks[0] * S);
|
||||
C[1] += (GL_MATERIAL.Ks[1] * GL_LIGHTS[i].Ks[1] * S);
|
||||
C[2] += (GL_MATERIAL.Ks[2] * GL_LIGHTS[i].Ks[2] * S);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
colorui *col = (colorui *)&v->argb; /* Clamp / Pack floats to a 32bit int */
|
||||
col->a = 0xFF;
|
||||
(C[0] > 1.0f) ? (col->r = 0xFF) : (col->r = (unsigned char)(255 * C[0]));
|
||||
(C[1] > 1.0f) ? (col->g = 0xFF) : (col->g = (unsigned char)(255 * C[1]));
|
||||
(C[2] > 1.0f) ? (col->b = 0xFF) : (col->b = (unsigned char)(255 * C[2]));
|
||||
}
|
||||
|
||||
GLuint _glKosVertexLightColor(glVertex *P) {
|
||||
#ifdef GL_ENABLE_SPECULAR
|
||||
float S;
|
||||
#endif
|
||||
GLuint color;
|
||||
GLubyte i;
|
||||
float L[4] __attribute__((aligned(8)));
|
||||
|
||||
/* Compute Ambient */
|
||||
float C[3] = { GL_MATERIAL.Ke[0] + GL_MATERIAL.Ka[0] *GL_GLOBAL_AMBIENT[0],
|
||||
GL_MATERIAL.Ke[1] + GL_MATERIAL.Ka[1] *GL_GLOBAL_AMBIENT[1],
|
||||
GL_MATERIAL.Ke[2] + GL_MATERIAL.Ka[2] *GL_GLOBAL_AMBIENT[2]
|
||||
};
|
||||
|
||||
for(i = 0; i < GL_KOS_MAX_LIGHTS; i++)
|
||||
if(GL_LIGHT_ENABLED & 1 << i)
|
||||
if(_glKosSpotlight(&GL_LIGHTS[i], P, L)) { /* Compute Spot / Diffuse */
|
||||
C[0] += (GL_MATERIAL.Kd[0] * GL_LIGHTS[i].Kd[0] * L[3]);
|
||||
C[1] += (GL_MATERIAL.Kd[1] * GL_LIGHTS[i].Kd[1] * L[3]);
|
||||
C[2] += (GL_MATERIAL.Kd[2] * GL_LIGHTS[i].Kd[2] * L[3]);
|
||||
|
||||
#ifdef GL_ENABLE_SPECULAR
|
||||
S = _glKosSpecular(P, GL_EYE_POSITION, L); /* Compute Specular */
|
||||
|
||||
if(S > 0) {
|
||||
#ifdef GL_ENABLE_FAST_POW
|
||||
S = FPOW(S, GL_MATERIAL.Shine);
|
||||
#else
|
||||
S = pow(S, GL_MATERIAL.Shine);
|
||||
#endif
|
||||
C[0] += (GL_MATERIAL.Ks[0] * GL_LIGHTS[i].Ks[0] * S);
|
||||
C[1] += (GL_MATERIAL.Ks[1] * GL_LIGHTS[i].Ks[1] * S);
|
||||
C[2] += (GL_MATERIAL.Ks[2] * GL_LIGHTS[i].Ks[2] * S);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
colorui *col = (colorui *)&color; /* Clamp / Pack floats to a 32bit int */
|
||||
col->a = 0xFF;
|
||||
(C[0] > 1.0f) ? (col->r = 0xFF) : (col->r = (unsigned char)(255 * C[0]));
|
||||
(C[1] > 1.0f) ? (col->g = 0xFF) : (col->g = (unsigned char)(255 * C[1]));
|
||||
(C[2] > 1.0f) ? (col->b = 0xFF) : (col->b = (unsigned char)(255 * C[2]));
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
/** Iterate vertices submitted and compute vertex lighting **/
|
||||
|
||||
void _glKosVertexComputeLighting(pvr_vertex_t *v, int verts) {
|
||||
unsigned int i;
|
||||
glVertex *s = _glKosArrayBufAddr();
|
||||
|
||||
_glKosMatrixLoadModelView();
|
||||
|
||||
for(i = 0; i < verts; i++) {
|
||||
mat_trans_single3_nodiv(s->pos[0], s->pos[1], s->pos[2]);
|
||||
++s;
|
||||
}
|
||||
|
||||
s = _glKosArrayBufAddr();
|
||||
|
||||
_glKosMatrixLoadModelRot();
|
||||
|
||||
for(i = 0; i < verts; i++) {
|
||||
mat_trans_normal3(s->norm[0], s->norm[1], s->norm[2]);
|
||||
_glKosVertexLight(s++, v++);
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosLightTransformScreenSpace(float *xyz) {
|
||||
_glKosMatrixApplyScreenSpace();
|
||||
mat_trans_single(xyz[0], xyz[1], xyz[2]);
|
||||
_glKosMatrixLoadRender();
|
||||
}
|
51
gl-light.h
51
gl-light.h
|
@ -1,51 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-light.h
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Dynamic Vertex Lighting.
|
||||
|
||||
By default, specular lighting is enabled.
|
||||
For now, specular can be disabled by setting GL_ENABLE_SPECULAR
|
||||
below when you build the library.
|
||||
By default, specular lighting uses a fast POW implementation, at
|
||||
sacrifice of accuracy. Change GL_ENABLE_FAST_POW to suit your needs.
|
||||
*/
|
||||
|
||||
#ifndef GL_LIGHT_H
|
||||
#define GL_LIGHT_H
|
||||
|
||||
#include "gl-sh4.h"
|
||||
|
||||
#define GL_ENABLE_SPECULAR 1
|
||||
#define GL_ENABLE_FAST_POW 1
|
||||
|
||||
int _glKosSpotlight(void *glLight, void *vertex6f, void *Lvectorout);
|
||||
float _glKosSpecular(void *vertex6f, void *eyepos, void *Lvectorin);
|
||||
|
||||
typedef struct {
|
||||
float r, g, b, a;
|
||||
} rgba;
|
||||
|
||||
typedef struct {
|
||||
float Ke[4]; /* RGBA material emissive color # 0.0, 0.0, 0.0, 1.0 */
|
||||
float Ka[4]; /* RGBA material ambient reflectance # 0.2, 0.2, 0.2, 1.0 */
|
||||
float Kd[4]; /* RGBA material diffuse reflectance # 0.8, 0.8, 0.8, 1.0 */
|
||||
float Ks[4]; /* RGBA material diffuse reflectance # 0.0, 0.0, 0.0, 1.0 */
|
||||
float Shine; /* Material Specular Shine # 0.0f */
|
||||
} glMaterial;
|
||||
|
||||
typedef struct {
|
||||
float Pos[4]; /* XYZW Position of Light # 0.0, 0.0, 1.0, 0.0 */
|
||||
float Dir[3]; /* Spot Light Direction # 0.0, 0.0, -1.0 */
|
||||
float CutOff; /* Spot Light CutOff #-1.0f */
|
||||
float Kc, /* Constant Attenuation # 1.0f */
|
||||
Kl, /* Linear Attenuation # 0.0f */
|
||||
Kq; /* Quadratic Attenuation # 0.0f */
|
||||
float Exponent; /* Spot Light Exponent # 0.0f */
|
||||
float Kd[4]; /* RGBA Diffuse Light Contribution # 1.0, 1.0, 1.0, 1.0 */
|
||||
float Ks[4]; /* RGBA Specular Light Contribution # 1.0, 1.0, 1.0, 1.0 */
|
||||
float Ka[4]; /* RGBA Ambient Light Contribution # 0.0, 0.0, 0.0, 1.0 */
|
||||
} glLight;
|
||||
|
||||
#endif
|
413
gl-matrix.c
413
gl-matrix.c
|
@ -1,413 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-matrix.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
Copyright (C) 2014 Lawrence Sebald
|
||||
|
||||
Some functionality adapted from the original KOS libgl:
|
||||
Copyright (C) 2001 Dan Potter
|
||||
|
||||
The GL matrix operations use the KOS SH4 matrix operations.
|
||||
Basically, we keep two seperate matrix stacks:
|
||||
1.) Internal GL API Matrix Stack ( screenview, modelview, etc. ) ( fixed stack size )
|
||||
2.) External Matrix Stack for client to push / pop ( size of each stack is determined by MAX_MATRICES )
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-sh4.h"
|
||||
|
||||
/* This Matrix contains the GL Base Stack */
|
||||
static matrix4f Matrix[GL_MATRIX_COUNT] __attribute__((aligned(32)));
|
||||
static GLsizei MatrixMode = 0;
|
||||
|
||||
/* This Matrix contains the GL Push/Pop Stack ( fixed size per mode, 32 matrices )*/
|
||||
static const GLsizei MAX_MATRICES = 32;
|
||||
static matrix4f MatrixStack[GL_MATRIX_COUNT][32] __attribute__((aligned(32)));
|
||||
static GLsizei MatrixStackPos[GL_MATRIX_COUNT];
|
||||
|
||||
/* Viewport mapping */
|
||||
static GLfloat gl_viewport_scale[3], gl_viewport_offset[3];
|
||||
|
||||
/* Depth range */
|
||||
static GLclampf gl_depthrange_near, gl_depthrange_far;
|
||||
|
||||
/* Viewport size */
|
||||
static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height;
|
||||
|
||||
/* Frustum attributes */
|
||||
typedef struct {
|
||||
float left, right, bottom, top, znear, zfar;
|
||||
} gl_frustum_t;
|
||||
|
||||
static gl_frustum_t gl_frustum;
|
||||
|
||||
/* Frustum Matrix */
|
||||
static matrix4f FrustumMatrix __attribute__((aligned(32))) = {
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, -1.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f }
|
||||
};
|
||||
|
||||
/* Ortho Matrix */
|
||||
static matrix4f OrthoMatrix __attribute__((aligned(32))) = {
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
/* Matrix for user to submit externally, ensure 32byte allignment */
|
||||
static matrix4f ml __attribute__((aligned(32)));
|
||||
|
||||
/* Look-At Matrix */
|
||||
static matrix4f MatrixLookAt __attribute__((aligned(32))) = {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
/* Modelview Rotation Matrix - Applied to Vertex Normal when Lighting is Enabled */
|
||||
static matrix4f MatrixMdlRot __attribute__((aligned(32))) = {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
void glMatrixMode(GLenum mode) {
|
||||
if(mode >= GL_SCREENVIEW && mode <= GL_IDENTITY)
|
||||
MatrixMode = mode;
|
||||
}
|
||||
|
||||
void glPushMatrix() {
|
||||
if(MatrixStackPos[MatrixMode] < MAX_MATRICES - 1) {
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_store(&MatrixStack[MatrixMode][MatrixStackPos[MatrixMode]]);
|
||||
++MatrixStackPos[MatrixMode];
|
||||
}
|
||||
}
|
||||
|
||||
void glPopMatrix() {
|
||||
if(MatrixStackPos[MatrixMode]) {
|
||||
--MatrixStackPos[MatrixMode];
|
||||
mat_load(&MatrixStack[MatrixMode][MatrixStackPos[MatrixMode]]);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
}
|
||||
|
||||
void glLoadIdentity() {
|
||||
mat_load(Matrix + GL_IDENTITY);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
|
||||
if(MatrixMode == GL_MODELVIEW) {
|
||||
mat_store(&MatrixMdlRot);
|
||||
mat_store(&MatrixLookAt);
|
||||
}
|
||||
}
|
||||
|
||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_translate(x, y, z);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_scale(x, y, z);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
float r = DEG2RAD * -angle;
|
||||
|
||||
vec3f_normalize(x, y, z);
|
||||
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_rotate(r * x, r * y, r * z);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
|
||||
if(MatrixMode == GL_MODELVIEW) {
|
||||
mat_load(&MatrixMdlRot);
|
||||
mat_rotate(r * x, r * y, r * z);
|
||||
mat_store(&MatrixMdlRot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an arbitrary matrix */
|
||||
void glLoadMatrixf(const GLfloat *m) {
|
||||
memcpy(ml, m, sizeof(matrix4f));
|
||||
mat_load(&ml);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
/* Load an arbitrary transposed matrix */
|
||||
void glLoadTransposeMatrixf(const GLfloat *m) {
|
||||
ml[0][0] = m[0];
|
||||
ml[0][1] = m[4];
|
||||
ml[0][2] = m[8];
|
||||
ml[0][3] = m[12];
|
||||
ml[1][0] = m[1];
|
||||
ml[1][1] = m[5];
|
||||
ml[1][2] = m[9];
|
||||
ml[1][3] = m[13];
|
||||
ml[2][0] = m[2];
|
||||
ml[2][1] = m[6];
|
||||
ml[2][2] = m[10];
|
||||
ml[2][3] = m[14];
|
||||
ml[3][0] = m[3];
|
||||
ml[3][1] = m[7];
|
||||
ml[3][2] = m[11];
|
||||
ml[3][3] = m[15];
|
||||
|
||||
mat_load(&ml);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
/* Multiply the current matrix by an arbitrary matrix */
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
memcpy(ml, m, sizeof(matrix4f));
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_apply(&ml);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
/* Multiply the current matrix by an arbitrary transposed matrix */
|
||||
void glMultTransposeMatrixf(const GLfloat *m) {
|
||||
ml[0][0] = m[0];
|
||||
ml[0][1] = m[4];
|
||||
ml[0][2] = m[8];
|
||||
ml[0][3] = m[12];
|
||||
ml[1][0] = m[1];
|
||||
ml[1][1] = m[5];
|
||||
ml[1][2] = m[9];
|
||||
ml[1][3] = m[13];
|
||||
ml[2][0] = m[2];
|
||||
ml[2][1] = m[6];
|
||||
ml[2][2] = m[10];
|
||||
ml[2][3] = m[14];
|
||||
ml[3][0] = m[3];
|
||||
ml[3][1] = m[7];
|
||||
ml[3][2] = m[11];
|
||||
ml[3][3] = m[15];
|
||||
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_apply(&ml);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
/* Set the depth range */
|
||||
void glDepthRange(GLclampf n, GLclampf f) {
|
||||
/* clamp the values... */
|
||||
if(n < 0.0f) n = 0.0f;
|
||||
else if(n > 1.0f) n = 1.0f;
|
||||
|
||||
if(f < 0.0f) f = 0.0f;
|
||||
else if(f > 1.0f) f = 1.0f;
|
||||
|
||||
gl_depthrange_near = n;
|
||||
gl_depthrange_far = f;
|
||||
|
||||
/* Adjust the viewport scale and offset for Z */
|
||||
gl_viewport_scale[2] = ((f - n) / 2.0f);
|
||||
gl_viewport_offset[2] = (n + f) / 2.0f;
|
||||
}
|
||||
|
||||
/* Set the GL viewport */
|
||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
gl_viewport_x1 = x;
|
||||
gl_viewport_y1 = y;
|
||||
gl_viewport_width = width;
|
||||
gl_viewport_height = height;
|
||||
|
||||
/* Calculate the viewport scale and offset */
|
||||
gl_viewport_scale[0] = (GLfloat)width / 2.0f;
|
||||
gl_viewport_offset[0] = gl_viewport_scale[0] + (GLfloat)x;
|
||||
gl_viewport_scale[1] = (GLfloat)height / 2.0f;
|
||||
gl_viewport_offset[1] = gl_viewport_scale[1] + (GLfloat)y;
|
||||
gl_viewport_scale[2] = (gl_depthrange_far - gl_depthrange_near) / 2.0f;
|
||||
gl_viewport_offset[2] = (gl_depthrange_near + gl_depthrange_far) / 2.0f;
|
||||
|
||||
gl_viewport_offset[2] += 0.0001f;
|
||||
|
||||
/* Set the Screenview Matrix based on the viewport */
|
||||
Matrix[GL_SCREENVIEW][0][0] = gl_viewport_scale[0];
|
||||
Matrix[GL_SCREENVIEW][1][1] = -gl_viewport_scale[1];
|
||||
Matrix[GL_SCREENVIEW][2][2] = 1;
|
||||
Matrix[GL_SCREENVIEW][3][0] = gl_viewport_offset[0];
|
||||
Matrix[GL_SCREENVIEW][3][1] = vid_mode->height - gl_viewport_offset[1];
|
||||
}
|
||||
|
||||
/* Set the GL frustum */
|
||||
void glFrustum(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
gl_frustum.left = left;
|
||||
gl_frustum.right = right;
|
||||
gl_frustum.bottom = bottom;
|
||||
gl_frustum.top = top;
|
||||
gl_frustum.znear = znear;
|
||||
gl_frustum.zfar = zfar;
|
||||
|
||||
FrustumMatrix[0][0] = (2.0f * znear) / (right - left);
|
||||
FrustumMatrix[2][0] = (right + left) / (right - left);
|
||||
FrustumMatrix[1][1] = (2.0f * znear) / (top - bottom);
|
||||
FrustumMatrix[2][1] = (top + bottom) / (top - bottom);
|
||||
FrustumMatrix[2][2] = zfar / (zfar - znear);
|
||||
FrustumMatrix[3][2] = -(zfar * znear) / (zfar - znear);
|
||||
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_apply(&FrustumMatrix);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
/* Ortho */
|
||||
void glOrtho(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
OrthoMatrix[0][0] = 2.0f / (right - left);
|
||||
OrthoMatrix[1][1] = 2.0f / (top - bottom);
|
||||
OrthoMatrix[2][2] = -2.0f / (zfar - znear);
|
||||
OrthoMatrix[3][0] = -(right + left) / (right - left);;
|
||||
OrthoMatrix[3][1] = -(top + bottom) / (top - bottom);
|
||||
OrthoMatrix[3][2] = -(zfar + znear) / (zfar - znear);
|
||||
|
||||
mat_load(Matrix + MatrixMode);
|
||||
mat_apply(&OrthoMatrix);
|
||||
mat_store(Matrix + MatrixMode);
|
||||
}
|
||||
|
||||
/* Set the Perspective */
|
||||
void gluPerspective(GLfloat angle, GLfloat aspect,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
GLfloat xmin, xmax, ymin, ymax;
|
||||
|
||||
ymax = znear * ftan(angle * F_PI / 360.0f);
|
||||
ymin = -ymax;
|
||||
xmin = ymin * aspect;
|
||||
xmax = ymax * aspect;
|
||||
|
||||
glFrustum(xmin, xmax, ymin, ymax, znear, zfar);
|
||||
}
|
||||
|
||||
/* Vector Cross Product - Used by glhLookAtf2 */
|
||||
void vec3f_cross(vector3f v1, vector3f v2, vector3f result) {
|
||||
result[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
||||
result[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
||||
result[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
||||
}
|
||||
|
||||
/* glhLookAtf2 adapted from http://www.opengl.org/wiki/GluLookAt_code */
|
||||
void glhLookAtf2(vector3f eyePosition3D,
|
||||
vector3f center3D,
|
||||
vector3f upVector3D) {
|
||||
vector3f forward, side, up;
|
||||
|
||||
_glKosSetEyePosition(eyePosition3D);
|
||||
|
||||
vec3f_sub_normalize(center3D[0], center3D[1], center3D[2],
|
||||
eyePosition3D[0], eyePosition3D[1], eyePosition3D[2],
|
||||
forward[0], forward[1], forward[2]);
|
||||
|
||||
//Side = forward x up
|
||||
vec3f_cross(forward, upVector3D, side);
|
||||
vec3f_normalize(side[0], side[1], side[2]);
|
||||
|
||||
//Recompute up as: up = side x forward
|
||||
vec3f_cross(side, forward, up);
|
||||
|
||||
MatrixLookAt[0][0] = side[0];
|
||||
MatrixLookAt[1][0] = side[1];
|
||||
MatrixLookAt[2][0] = side[2];
|
||||
MatrixLookAt[3][0] = 0;
|
||||
|
||||
MatrixLookAt[0][1] = up[0];
|
||||
MatrixLookAt[1][1] = up[1];
|
||||
MatrixLookAt[2][1] = up[2];
|
||||
MatrixLookAt[3][1] = 0;
|
||||
|
||||
MatrixLookAt[0][2] = -forward[0];
|
||||
MatrixLookAt[1][2] = -forward[1];
|
||||
MatrixLookAt[2][2] = -forward[2];
|
||||
MatrixLookAt[3][2] = 0;
|
||||
|
||||
MatrixLookAt[0][3] =
|
||||
MatrixLookAt[1][3] =
|
||||
MatrixLookAt[2][3] = 0;
|
||||
MatrixLookAt[3][3] = 1;
|
||||
|
||||
// Does not modify internal Modelview matrix
|
||||
mat_load(&MatrixLookAt);
|
||||
mat_translate(-eyePosition3D[0], -eyePosition3D[1], -eyePosition3D[2]);
|
||||
|
||||
mat_apply(Matrix + GL_MODELVIEW);
|
||||
mat_store(Matrix + GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
|
||||
GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
|
||||
GLfloat upz) {
|
||||
vector3f eye = { eyex, eyey, eyez };
|
||||
vector3f point = { centerx, centery, centerz };
|
||||
vector3f up = { upx, upy, upz };
|
||||
glhLookAtf2(eye, point, up);
|
||||
}
|
||||
|
||||
void _glKosMatrixApplyRender() {
|
||||
mat_load(Matrix + GL_SCREENVIEW);
|
||||
mat_apply(Matrix + GL_PROJECTION);
|
||||
mat_apply(Matrix + GL_MODELVIEW);
|
||||
mat_store(Matrix + GL_RENDER);
|
||||
}
|
||||
|
||||
void _glKosMatrixLoadRender() {
|
||||
mat_load(Matrix + GL_RENDER);
|
||||
}
|
||||
|
||||
void _glKosMatrixLoadTexture() {
|
||||
mat_load(Matrix + GL_TEXTURE);
|
||||
}
|
||||
|
||||
void _glKosMatrixLoadModelView() {
|
||||
mat_load(Matrix + GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void _glKosMatrixLoadModelRot() {
|
||||
mat_load(&MatrixMdlRot);
|
||||
}
|
||||
|
||||
void _glKosMatrixApplyScreenSpace() {
|
||||
mat_load(Matrix + GL_SCREENVIEW);
|
||||
mat_apply(Matrix + GL_PROJECTION);
|
||||
mat_apply(&MatrixLookAt);
|
||||
}
|
||||
|
||||
void _glKosInitMatrix() {
|
||||
mat_identity();
|
||||
mat_store(Matrix + GL_SCREENVIEW);
|
||||
mat_store(Matrix + GL_PROJECTION);
|
||||
mat_store(Matrix + GL_MODELVIEW);
|
||||
mat_store(Matrix + GL_TEXTURE);
|
||||
mat_store(Matrix + GL_IDENTITY);
|
||||
mat_store(Matrix + GL_RENDER);
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; i < GL_MATRIX_COUNT; i++)
|
||||
MatrixStackPos[i] = 0;
|
||||
|
||||
glDepthRange(0.0f, 1.0f);
|
||||
glViewport(0, 0, vid_mode->width, vid_mode->height);
|
||||
}
|
||||
|
||||
void glKosGetMatrix(GLenum mode, GLfloat *params) {
|
||||
if(mode < GL_SCREENVIEW || mode > GL_RENDER)
|
||||
*params = (GLfloat)GL_INVALID_ENUM;
|
||||
|
||||
memcpy(params, Matrix + mode, sizeof(GLfloat) * 16);
|
||||
}
|
336
gl-pvr.c
336
gl-pvr.c
|
@ -1,336 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-pvr.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
Copyright (C) 2016 Lawrence Sebald
|
||||
|
||||
Vertex Buffer Routines for interfacing the Dreamcast's SH4 CPU and PowerVR GPU.
|
||||
|
||||
What we are doing here is using a Vertex Buffer in main RAM to store the
|
||||
submitted data, untill the user finishes the scene by either calling
|
||||
glSwapBuffer() to submit the buffer to the PVR for render to the screen OR
|
||||
glSwapBufferToTexture() to submit the buffer to the PVR for render to texture.
|
||||
|
||||
This solution means the client can switch between transparent and opaque polygon
|
||||
sumbission at any time, in no particular order, with no penalty in speed.
|
||||
|
||||
The size of the Vertex Buffer can be controlled by setting some params on gl-pvr.h:
|
||||
GL_PVR_VERTEX_BUF_SIZE controls size of Vertex Buffer in the PVR VRAM
|
||||
GL_KOS_MAX_VERTS conrols the number of vertices per list in the Vertex Buffer in SH4 RAM
|
||||
*/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dc/sq.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-sh4.h"
|
||||
#include "gl-pvr.h"
|
||||
|
||||
/* Vertex Buffer Functions *************************************************************************/
|
||||
|
||||
#define COMMANDS_PER_ALLOC ((64 * 1024) / 32) /* 64k memory chunks */
|
||||
|
||||
static pvr_cmd_t *GL_VBUF[2] __attribute__((aligned(32))); /* Dynamic Vertex Buffer */
|
||||
static pvr_cmd_t *GL_CBUF; /* Dynamic Clip Buffer */
|
||||
static glTexCoord *GL_UVBUF; /* Dynamic Multi-Texture UV */
|
||||
|
||||
static GLuint GL_VERTS[2] = {0, 0};
|
||||
static GLuint GL_VERTS_ALLOCATED[2] = {0, 0};
|
||||
static GLuint GL_CVERTS = 0;
|
||||
static GLuint GL_UVVERTS = 0;
|
||||
static GLuint GL_LIST = GL_KOS_LIST_OP;
|
||||
|
||||
#define GL_KOS_MAX_MULTITEXTURE_OBJECTS 512
|
||||
|
||||
static GL_MULTITEX_OBJECT GL_MTOBJS[GL_KOS_MAX_MULTITEXTURE_OBJECTS];
|
||||
static GLuint GL_MTOBJECTS = 0;
|
||||
|
||||
/* Custom version of sq_cpy from KOS for copying vertex data to the PVR */
|
||||
static void pvr_list_submit(void *src, int n) {
|
||||
GLuint *d = TA_SQ_ADDR;
|
||||
GLuint *s = src;
|
||||
|
||||
/* fill/write queues as many times necessary */
|
||||
while(n--) {
|
||||
__asm__("pref @%0" : : "r"(s + 8)); /* prefetch 32 bytes for next loop */
|
||||
d[0] = *(s++);
|
||||
d[1] = *(s++);
|
||||
d[2] = *(s++);
|
||||
d[3] = *(s++);
|
||||
d[4] = *(s++);
|
||||
d[5] = *(s++);
|
||||
d[6] = *(s++);
|
||||
d[7] = *(s++);
|
||||
__asm__("pref @%0" : : "r"(d));
|
||||
d += 8;
|
||||
}
|
||||
|
||||
/* Wait for both store queues to complete */
|
||||
d = (GLuint *)0xe0000000;
|
||||
d[0] = d[8] = 0;
|
||||
}
|
||||
|
||||
#ifdef GL_KOS_USE_DMA
|
||||
/* Custom version of sq_cpy from KOS for copying 32bytes of vertex data to the PVR */
|
||||
static void pvr_hdr_submit(const GLuint *src) {
|
||||
GLuint *d = TA_SQ_ADDR;
|
||||
|
||||
d[0] = *(src++);
|
||||
d[1] = *(src++);
|
||||
d[2] = *(src++);
|
||||
d[3] = *(src++);
|
||||
d[4] = *(src++);
|
||||
d[5] = *(src++);
|
||||
d[6] = *(src++);
|
||||
d[7] = *(src++);
|
||||
|
||||
__asm__("pref @%0" : : "r"(d));
|
||||
}
|
||||
#endif
|
||||
|
||||
void _glKosPushMultiTexObject(GL_TEXTURE_OBJECT *tex,
|
||||
pvr_vertex_t *src,
|
||||
GLuint count) {
|
||||
_glKosCompileHdrMT(&GL_MTOBJS[GL_MTOBJECTS].hdr, tex);
|
||||
|
||||
GL_MTOBJS[GL_MTOBJECTS].src = src;
|
||||
GL_MTOBJS[GL_MTOBJECTS++].count = count;
|
||||
}
|
||||
|
||||
void _glKosResetMultiTexObject() {
|
||||
GL_MTOBJECTS = 0;
|
||||
}
|
||||
|
||||
void *_glKosMultiUVBufAddress() {
|
||||
return &GL_UVBUF[0];
|
||||
}
|
||||
|
||||
void *_glKosMultiUVBufPointer() {
|
||||
return &GL_UVBUF[GL_UVVERTS];
|
||||
}
|
||||
|
||||
void _glKosMultiUVBufIncrement() {
|
||||
++GL_UVVERTS;
|
||||
}
|
||||
|
||||
void _glKosMultiUVBufAdd(GLuint count) {
|
||||
GL_UVVERTS += count;
|
||||
}
|
||||
|
||||
void _glKosMultiUVBufReset() {
|
||||
GL_UVVERTS = 0;
|
||||
}
|
||||
|
||||
void *_glKosClipBufAddress() {
|
||||
return &GL_CBUF[0];
|
||||
}
|
||||
|
||||
void *_glKosClipBufPointer() {
|
||||
return &GL_CBUF[GL_CVERTS];
|
||||
}
|
||||
|
||||
void _glKosClipBufIncrement() {
|
||||
++GL_CVERTS;
|
||||
}
|
||||
|
||||
void _glKosClipBufAdd(GLuint count) {
|
||||
GL_CVERTS += count;
|
||||
}
|
||||
|
||||
void _glKosClipBufReset() {
|
||||
GL_CVERTS = 0;
|
||||
}
|
||||
|
||||
void _glKosVertexBufSwitchOP() {
|
||||
GL_LIST = GL_KOS_LIST_OP;
|
||||
}
|
||||
|
||||
void _glKosVertexBufSwitchTR() {
|
||||
GL_LIST = GL_KOS_LIST_TR;
|
||||
}
|
||||
|
||||
void *_glKosVertexBufAddress(GLubyte list) {
|
||||
return &GL_VBUF[list][0];
|
||||
}
|
||||
|
||||
void *_glKosVertexBufPointer() {
|
||||
return &GL_VBUF[GL_LIST][GL_VERTS[GL_LIST]];
|
||||
}
|
||||
|
||||
static void _glKosVertexBufIncrementList(GLubyte list, GLuint count) {
|
||||
GL_VERTS[list] += count;
|
||||
|
||||
if(GL_VERTS[list] > GL_VERTS_ALLOCATED[list]) {
|
||||
/* Grow the list buffer. We can't use realloc with memalign so we have to memcpy */
|
||||
pvr_cmd_t* orig = GL_VBUF[list];
|
||||
|
||||
/* Increase the allocated counter */
|
||||
GL_VERTS_ALLOCATED[list] += COMMANDS_PER_ALLOC;
|
||||
|
||||
/* Create a new memory buffer with the new size */
|
||||
GL_VBUF[list] = memalign(
|
||||
0x20,
|
||||
GL_VERTS_ALLOCATED[list] * sizeof(pvr_cmd_t)
|
||||
);
|
||||
|
||||
/* Copy across the original data */
|
||||
memcpy(GL_VBUF[list], orig, (GL_VERTS[list] - count) * sizeof(pvr_cmd_t));
|
||||
|
||||
/* Free previously allocated memory */
|
||||
free(orig);
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosVertexBufIncrement() {
|
||||
_glKosVertexBufIncrementList(GL_LIST, 1);
|
||||
}
|
||||
|
||||
void *_glKosTRVertexBufPointer() {
|
||||
return &GL_VBUF[GL_KOS_LIST_TR][GL_VERTS[GL_KOS_LIST_TR]];
|
||||
}
|
||||
|
||||
void _glKosTRVertexBufIncrement() {
|
||||
_glKosVertexBufIncrementList(GL_KOS_LIST_TR, 1);
|
||||
}
|
||||
|
||||
void _glKosVertexBufAdd(GLuint count) {
|
||||
_glKosVertexBufIncrementList(GL_LIST, count);
|
||||
}
|
||||
|
||||
void _glKosTRVertexBufAdd(GLuint count) {
|
||||
_glKosVertexBufIncrementList(GL_KOS_LIST_TR, count);
|
||||
}
|
||||
|
||||
void _glKosVertexBufDecrement() {
|
||||
/* Intentionally don't free data here, we only ever grow */
|
||||
--GL_VERTS[GL_LIST];
|
||||
}
|
||||
|
||||
void _glKosVertexBufReset() {
|
||||
GL_VERTS[0] = GL_VERTS[1] = 0;
|
||||
}
|
||||
|
||||
GLuint _glKosVertexBufCount(GLubyte list) {
|
||||
return GL_VERTS[list];
|
||||
}
|
||||
|
||||
GLubyte _glKosList() {
|
||||
return GL_LIST;
|
||||
}
|
||||
|
||||
void _glKosVertexBufCopy(void *dst, void *src, GLuint count) {
|
||||
memcpy(dst, src, count * 0x20);
|
||||
}
|
||||
|
||||
static void glutSwapBuffer() {
|
||||
#ifndef GL_KOS_USE_DMA
|
||||
QACR0 = QACRTA;
|
||||
QACR1 = QACRTA;
|
||||
#endif
|
||||
|
||||
pvr_list_begin(PVR_LIST_OP_POLY);
|
||||
#ifdef GL_KOS_USE_DMA
|
||||
pvr_dma_transfer(_glKosVertexBufAddress(GL_KOS_LIST_OP), 0,
|
||||
_glKosVertexBufCount(GL_KOS_LIST_OP) * 32,
|
||||
PVR_DMA_TA, 1, NULL, 0);
|
||||
#else
|
||||
pvr_list_submit(_glKosVertexBufAddress(GL_KOS_LIST_OP), _glKosVertexBufCount(GL_KOS_LIST_OP));
|
||||
#endif
|
||||
pvr_list_finish();
|
||||
|
||||
pvr_list_begin(PVR_LIST_TR_POLY);
|
||||
#ifdef GL_KOS_USE_DMA
|
||||
pvr_dma_transfer(_glKosVertexBufAddress(GL_KOS_LIST_TR), 0,
|
||||
_glKosVertexBufCount(GL_KOS_LIST_TR) * 32,
|
||||
PVR_DMA_TA, 1, NULL, 0);
|
||||
#else
|
||||
pvr_list_submit(_glKosVertexBufAddress(GL_KOS_LIST_TR), _glKosVertexBufCount(GL_KOS_LIST_TR));
|
||||
#endif
|
||||
/* Multi-Texture Pass - Modify U/V coords of submitted vertices */
|
||||
GLuint i, v;
|
||||
glTexCoord *mt = _glKosMultiUVBufAddress();
|
||||
|
||||
for(i = 0; i < GL_MTOBJECTS; i++) {
|
||||
//copy vertex uv
|
||||
for(v = 0; v < GL_MTOBJS[i].count; v ++) {
|
||||
GL_MTOBJS[i].src[v].u = mt->u;
|
||||
GL_MTOBJS[i].src[v].v = mt->v;
|
||||
++mt;
|
||||
}
|
||||
|
||||
// submit vertex data to PVR
|
||||
#ifdef GL_KOS_USE_DMA
|
||||
pvr_hdr_submit((GLuint *)&GL_MTOBJS[i].hdr);
|
||||
pvr_dma_transfer(GL_MTOBJS[i].src, 0,
|
||||
GL_MTOBJS[i].count * 32, PVR_DMA_TA, 1, NULL, 0);
|
||||
#else
|
||||
pvr_list_submit((pvr_poly_hdr_t *)&GL_MTOBJS[i].hdr, 1);
|
||||
pvr_list_submit((pvr_vertex_t *)GL_MTOBJS[i].src, GL_MTOBJS[i].count);
|
||||
#endif
|
||||
}
|
||||
|
||||
_glKosResetMultiTexObject(); /* End Multi-Texture Pass */
|
||||
|
||||
pvr_list_finish();
|
||||
|
||||
pvr_scene_finish();
|
||||
}
|
||||
|
||||
void glutSwapBuffers() {
|
||||
pvr_wait_ready();
|
||||
|
||||
if(_glKosGetFBO()) {
|
||||
GLsizei w = _glKosGetFBOWidth(_glKosGetFBO());
|
||||
GLsizei h = _glKosGetFBOHeight(_glKosGetFBO());
|
||||
pvr_scene_begin_txr(_glKosGetFBOData(_glKosGetFBO()), &w, &h);
|
||||
}
|
||||
else
|
||||
pvr_scene_begin();
|
||||
|
||||
glutSwapBuffer();
|
||||
|
||||
_glKosVertexBufReset();
|
||||
|
||||
_glKosMultiUVBufReset();
|
||||
|
||||
}
|
||||
|
||||
void glutCopyBufferToTexture(void *dst, GLsizei *x, GLsizei *y) {
|
||||
if(_glKosGetFBO()) {
|
||||
pvr_wait_ready();
|
||||
|
||||
pvr_scene_begin_txr(dst, x, y);
|
||||
|
||||
glutSwapBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
int _glKosInitPVR() {
|
||||
GLubyte i;
|
||||
|
||||
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_0 },
|
||||
GL_PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
|
||||
0, /* No DMA */
|
||||
0, /* No FSAA */
|
||||
1 /* Disable translucent auto-sorting to match traditional GL */
|
||||
};
|
||||
|
||||
pvr_init(¶ms);
|
||||
|
||||
for(i = 0; i < 2; ++i) {
|
||||
GL_VBUF[i] = memalign(0x20, COMMANDS_PER_ALLOC * sizeof(pvr_cmd_t));
|
||||
GL_VERTS_ALLOCATED[i] = COMMANDS_PER_ALLOC;
|
||||
}
|
||||
|
||||
GL_CBUF = malloc((GL_KOS_MAX_VERTS / 2) * sizeof(pvr_cmd_t));
|
||||
GL_UVBUF = malloc(GL_KOS_MAX_VERTS * sizeof(glTexCoord));
|
||||
|
||||
return 1;
|
||||
}
|
53
gl-pvr.h
53
gl-pvr.h
|
@ -1,53 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-pvr.h
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Vertex Buffer Routines for interfacing the Dreamcast's SH4 CPU and PowerVR GPU.
|
||||
*/
|
||||
|
||||
#ifndef GL_PVR_H
|
||||
#define GL_PVR_H
|
||||
|
||||
/* GL->PVR Commands */
|
||||
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 */
|
||||
|
||||
#define GL_KOS_LIST_OP 0
|
||||
#define GL_KOS_LIST_TR 1
|
||||
|
||||
//#define GL_KOS_USE_DMA 1 /* Use PVR DMA for vertex data transfer instead of store queues */
|
||||
//#define GL_USE_FLOAT 0 /* Use PVR's floating-point color Vertex Type (64bit) *NoOp* */
|
||||
|
||||
/* Misc SH4->PVR Commands */
|
||||
#define TA_SQ_ADDR (unsigned int *)(void *) \
|
||||
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
|
||||
|
||||
#define QACRTA ((((unsigned int)0x10000000)>>26)<<2)&0x1c
|
||||
|
||||
#define PVR_TA_TXR_FILTER_SHIFT 14
|
||||
|
||||
#define GL_PVR_FILTER_POINT 0x00
|
||||
#define GL_PVR_FILTER_BILINEAR 0x01
|
||||
#define GL_PVR_FILTER_TRILINEAR_A 0x10
|
||||
#define GL_PVR_FILTER_TRILINEAR_B 0x11
|
||||
|
||||
#define PVR_TA_SUPER_SAMPLE_SHIFT 12
|
||||
|
||||
#define GL_PVR_SAMPLE_POINT 0x0
|
||||
#define GL_PVR_SAMPLE_SUPER 0x1
|
||||
|
||||
#endif
|
310
gl-rgb.c
310
gl-rgb.c
|
@ -1,310 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-rgb.c
|
||||
Copyright (C) 2013-2015 Josh Pearson
|
||||
|
||||
A set of functions for working with ARGB pixel data, used by gluBuild2DMipmaps(...).
|
||||
The pixel conversion functions are for submitting textures not supported by the PVR.
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-rgb.h"
|
||||
|
||||
//===================================================================================================//
|
||||
//== ARGB Bit Masks ==//
|
||||
|
||||
static unsigned char ARGB1555_ALPHA(unsigned short c) {
|
||||
return (c & ARGB1555_ALPHA_MASK) >> ARGB1555_ALPHA_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB1555_RED(unsigned short c) {
|
||||
return (c & ARGB1555_RED_MASK) >> ARGB1555_RED_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB1555_GREEN(unsigned short c) {
|
||||
return (c & ARGB1555_GREEN_MASK) >> ARGB1555_GREEN_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB1555_BLUE(unsigned short c) {
|
||||
return (c & ARGB1555_BLUE_MASK) >> ARGB1555_BLUE_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB4444_ALPHA(unsigned short c) {
|
||||
return (c & ARGB4444_ALPHA_MASK) >> ARGB4444_ALPHA_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB4444_RED(unsigned short c) {
|
||||
return (c & ARGB4444_RED_MASK) >> ARGB4444_RED_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB4444_GREEN(unsigned short c) {
|
||||
return (c & ARGB4444_GREEN_MASK) >> ARGB4444_GREEN_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char ARGB4444_BLUE(unsigned short c) {
|
||||
return (c & ARGB4444_BLUE_MASK) >> ARGB4444_BLUE_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char RGB565_RED(unsigned short c) {
|
||||
return (c & RGB565_RED_MASK) >> RGB565_RED_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char RGB565_GREEN(unsigned short c) {
|
||||
return (c & RGB565_GREEN_MASK) >> RGB565_GREEN_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned char RGB565_BLUE(unsigned short c) {
|
||||
return c & RGB565_BLUE_MASK;
|
||||
}
|
||||
|
||||
//===================================================================================================//
|
||||
//== Block Compression ==//
|
||||
|
||||
uint16 __glKosAverageQuadPixelRGB565(uint16 p1, uint16 p2, uint16 p3, uint16 p4) {
|
||||
uint8 R = (RGB565_RED(p1) + RGB565_RED(p2) + RGB565_RED(p3) + RGB565_RED(p4)) / 4;
|
||||
uint8 G = (RGB565_GREEN(p1) + RGB565_GREEN(p2) + RGB565_GREEN(p3) + RGB565_GREEN(p4)) / 4;
|
||||
uint8 B = (RGB565_BLUE(p1) + RGB565_BLUE(p2) + RGB565_BLUE(p3) + RGB565_BLUE(p4)) / 4;
|
||||
|
||||
return R << RGB565_RED_SHIFT | G << RGB565_GREEN_SHIFT | B;
|
||||
}
|
||||
|
||||
uint16 __glKosAverageQuadPixelARGB1555(uint16 p1, uint16 p2, uint16 p3, uint16 p4) {
|
||||
uint8 A = (ARGB1555_ALPHA(p1) + ARGB1555_ALPHA(p2) + ARGB1555_ALPHA(p3) + ARGB1555_ALPHA(p4)) / 4;
|
||||
uint8 R = (ARGB1555_RED(p1) + ARGB1555_RED(p2) + ARGB1555_RED(p3) + ARGB1555_RED(p4)) / 4;
|
||||
uint8 G = (ARGB1555_GREEN(p1) + ARGB1555_GREEN(p2) + ARGB1555_GREEN(p3) + ARGB1555_GREEN(p4)) / 4;
|
||||
uint8 B = (ARGB1555_BLUE(p1) + ARGB1555_BLUE(p2) + ARGB1555_BLUE(p3) + ARGB1555_BLUE(p4)) / 4;
|
||||
|
||||
return ((A & RGB1_MAX) << ARGB1555_ALPHA_SHIFT) | ((R & RGB5_MAX) << ARGB1555_RED_SHIFT)
|
||||
| ((G & RGB5_MAX) << ARGB1555_GREEN_SHIFT) | (B & RGB5_MAX);
|
||||
}
|
||||
|
||||
uint16 __glKosAverageQuadPixelARGB4444(uint16 p1, uint16 p2, uint16 p3, uint16 p4) {
|
||||
uint8 A = (ARGB4444_ALPHA(p1) + ARGB4444_ALPHA(p2) + ARGB4444_ALPHA(p3) + ARGB4444_ALPHA(p4)) / 4;
|
||||
uint8 R = (ARGB4444_RED(p1) + ARGB4444_RED(p2) + ARGB4444_RED(p3) + ARGB4444_RED(p4)) / 4;
|
||||
uint8 G = (ARGB4444_GREEN(p1) + ARGB4444_GREEN(p2) + ARGB4444_GREEN(p3) + ARGB4444_GREEN(p4)) / 4;
|
||||
uint8 B = (ARGB4444_BLUE(p1) + ARGB4444_BLUE(p2) + ARGB4444_BLUE(p3) + ARGB4444_BLUE(p4)) / 4;
|
||||
|
||||
return ((A & RGB4_MAX) << ARGB4444_ALPHA_SHIFT) | ((R & RGB4_MAX) << ARGB4444_RED_SHIFT)
|
||||
| ((G & RGB4_MAX) << ARGB4444_GREEN_SHIFT) | (B & RGB4_MAX);
|
||||
}
|
||||
|
||||
uint16 __glKosAverageBiPixelRGB565(uint16 p1, uint16 p2) {
|
||||
uint8 R = (RGB565_RED(p1) + RGB565_RED(p2)) / 2;
|
||||
uint8 G = (RGB565_GREEN(p1) + RGB565_GREEN(p2)) / 2;
|
||||
uint8 B = (RGB565_BLUE(p1) + RGB565_BLUE(p2)) / 2;
|
||||
|
||||
return R << RGB565_RED_SHIFT | G << RGB565_GREEN_SHIFT | B;
|
||||
}
|
||||
|
||||
uint16 __glKosAverageBiPixelARGB1555(uint16 p1, uint16 p2) {
|
||||
uint8 A = (ARGB1555_ALPHA(p1) + ARGB1555_ALPHA(p2)) / 2;
|
||||
uint8 R = (ARGB1555_RED(p1) + ARGB1555_RED(p2)) / 2;
|
||||
uint8 G = (ARGB1555_GREEN(p1) + ARGB1555_GREEN(p2)) / 2;
|
||||
uint8 B = (ARGB1555_BLUE(p1) + ARGB1555_BLUE(p2)) / 2;
|
||||
|
||||
return ((A & RGB1_MAX) << ARGB1555_ALPHA_SHIFT) | ((R & RGB5_MAX) << ARGB1555_RED_SHIFT)
|
||||
| ((G & RGB5_MAX) << ARGB1555_GREEN_SHIFT) | (B & RGB5_MAX);
|
||||
}
|
||||
|
||||
uint16 __glKosAverageBiPixelARGB4444(uint16 p1, uint16 p2) {
|
||||
uint8 A = (ARGB4444_ALPHA(p1) + ARGB4444_ALPHA(p2)) / 2;
|
||||
uint8 R = (ARGB4444_RED(p1) + ARGB4444_RED(p2)) / 2;
|
||||
uint8 G = (ARGB4444_GREEN(p1) + ARGB4444_GREEN(p2)) / 2;
|
||||
uint8 B = (ARGB4444_BLUE(p1) + ARGB4444_BLUE(p2)) / 2;
|
||||
|
||||
return ((A & RGB4_MAX) << ARGB4444_ALPHA_SHIFT) | ((R & RGB4_MAX) << ARGB4444_RED_SHIFT)
|
||||
| ((G & RGB4_MAX) << ARGB4444_GREEN_SHIFT) | (B & RGB4_MAX);
|
||||
}
|
||||
|
||||
//===================================================================================================//
|
||||
//== Colorspace Conversion ==//
|
||||
|
||||
static uint16 _glKosConvPixelRGBAU32(uint8 r, uint8 g, uint8 b, uint8 a) {
|
||||
return (uint16)((a & RGB4_MAX) << ARGB4444_ALPHA_SHIFT) |
|
||||
((r & RGB4_MAX) << ARGB4444_RED_SHIFT) |
|
||||
((g & RGB4_MAX) << ARGB4444_GREEN_SHIFT) |
|
||||
((b & RGB4_MAX));
|
||||
}
|
||||
|
||||
static uint16 _glKosConvPixelRGBU24(uint8 r, uint8 g, uint8 b) {
|
||||
return (uint16)((r & RGB5_MAX) << RGB565_RED_SHIFT) |
|
||||
((g & RGB6_MAX) << RGB565_GREEN_SHIFT) |
|
||||
((b & RGB5_MAX));
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBF(int w, int h, float *src, uint16 *dst) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
dst[i] = _glKosConvPixelRGBU24((uint8)(src[i * 3 + 0] * RGB5_MAX),
|
||||
(uint8)(src[i * 3 + 1] * RGB6_MAX),
|
||||
(uint8)(src[i * 3 + 2] * RGB5_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBAF(int w, int h, float *src, uint16 *dst) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
dst[i] = _glKosConvPixelRGBAU32((uint8)(src[i * 4 + 0] * RGB4_MAX),
|
||||
(uint8)(src[i * 4 + 1] * RGB4_MAX),
|
||||
(uint8)(src[i * 4 + 2] * RGB4_MAX),
|
||||
(uint8)(src[i * 4 + 3] * RGB4_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBU24(int w, int h, uint8 *src, uint16 *dst) {
|
||||
unsigned char r, g, b;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = (src[i * 3 + 0] * RGB5_MAX) / RGB8_MAX;
|
||||
g = (src[i * 3 + 1] * RGB6_MAX) / RGB8_MAX;
|
||||
b = (src[i * 3 + 2] * RGB5_MAX) / RGB8_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBU24(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBAU32(int w, int h, uint8 *src, uint16 *dst) {
|
||||
unsigned char r, g, b, a;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = (src[i * 4 + 0] * RGB4_MAX) / RGB8_MAX;
|
||||
g = (src[i * 4 + 1] * RGB4_MAX) / RGB8_MAX;
|
||||
b = (src[i * 4 + 2] * RGB4_MAX) / RGB8_MAX;
|
||||
a = (src[i * 4 + 3] * RGB4_MAX) / RGB8_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBAU32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBS24(int w, int h, int8 *src, uint16 *dst) {
|
||||
unsigned char r, g, b;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = ((src[i * 3 + 0] + S8_NEG_OFT) * RGB5_MAX) / RGB8_MAX;
|
||||
g = ((src[i * 3 + 1] + S8_NEG_OFT) * RGB6_MAX) / RGB8_MAX;
|
||||
b = ((src[i * 3 + 2] + S8_NEG_OFT) * RGB5_MAX) / RGB8_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBU24(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBAS32(int w, int h, int8 *src, uint16 *dst) {
|
||||
unsigned char r, g, b, a;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = ((src[i * 4 + 0] + S8_NEG_OFT) * RGB4_MAX) / RGB8_MAX;
|
||||
g = ((src[i * 4 + 1] + S8_NEG_OFT) * RGB4_MAX) / RGB8_MAX;
|
||||
b = ((src[i * 4 + 2] + S8_NEG_OFT) * RGB4_MAX) / RGB8_MAX;
|
||||
a = ((src[i * 4 + 3] + S8_NEG_OFT) * RGB4_MAX) / RGB8_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBAU32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBS48(int w, int h, int16 *src, uint16 *dst) {
|
||||
unsigned char r, g, b;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = ((src[i * 3 + 0] + S16_NEG_OFT) * RGB5_MAX) / RGB16_MAX;
|
||||
g = ((src[i * 3 + 1] + S16_NEG_OFT) * RGB6_MAX) / RGB16_MAX;
|
||||
b = ((src[i * 3 + 2] + S16_NEG_OFT) * RGB5_MAX) / RGB16_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBU24(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBAS64(int w, int h, int16 *src, uint16 *dst) {
|
||||
unsigned char r, g, b, a;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = ((src[i * 4 + 0] + S16_NEG_OFT) * RGB4_MAX) / RGB16_MAX;
|
||||
g = ((src[i * 4 + 1] + S16_NEG_OFT) * RGB4_MAX) / RGB16_MAX;
|
||||
b = ((src[i * 4 + 2] + S16_NEG_OFT) * RGB4_MAX) / RGB16_MAX;
|
||||
a = ((src[i * 4 + 3] + S16_NEG_OFT) * RGB4_MAX) / RGB16_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBAU32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBU48(int w, int h, uint16 *src, uint16 *dst) {
|
||||
unsigned char r, g, b;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = ((src[i * 3 + 0]) * RGB5_MAX) / RGB16_MAX;
|
||||
g = ((src[i * 3 + 1]) * RGB6_MAX) / RGB16_MAX;
|
||||
b = ((src[i * 3 + 2]) * RGB5_MAX) / RGB16_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBU24(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void _glKosConvPixelsRGBAU64(int w, int h, uint16 *src, uint16 *dst) {
|
||||
unsigned char r, g, b, a;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < w * h; i++) {
|
||||
r = (src[i * 4 + 0] * RGB4_MAX) / RGB16_MAX;
|
||||
g = (src[i * 4 + 1] * RGB4_MAX) / RGB16_MAX;
|
||||
b = (src[i * 4 + 2] * RGB4_MAX) / RGB16_MAX;
|
||||
a = (src[i * 4 + 3] * RGB4_MAX) / RGB16_MAX;
|
||||
|
||||
dst[i] = _glKosConvPixelRGBAU32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosPixelConvertRGB(int format, int w, int h, void *src, uint16 *dst) {
|
||||
switch(format) {
|
||||
case GL_BYTE:
|
||||
_glKosConvPixelsRGBS24(w, h, (int8 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosConvPixelsRGBU24(w, h, (uint8 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_SHORT:
|
||||
_glKosConvPixelsRGBS48(w, h, (int16 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosConvPixelsRGBU48(w, h, (uint16 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_FLOAT:
|
||||
_glKosConvPixelsRGBF(w, h, (float *)src, dst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosPixelConvertRGBA(int format, int w, int h, void *src, uint16 *dst) {
|
||||
switch(format) {
|
||||
case GL_BYTE:
|
||||
_glKosConvPixelsRGBAS32(w, h, (int8 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_glKosConvPixelsRGBAU32(w, h, (uint8 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_SHORT:
|
||||
_glKosConvPixelsRGBAS64(w, h, (int16 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_glKosConvPixelsRGBAU64(w, h, (uint16 *)src, dst);
|
||||
break;
|
||||
|
||||
case GL_FLOAT:
|
||||
_glKosConvPixelsRGBAF(w, h, (float *)src, dst);
|
||||
break;
|
||||
}
|
||||
}
|
70
gl-rgb.h
70
gl-rgb.h
|
@ -1,70 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-rgb.h
|
||||
Copyright (C) 2013-2015 Josh Pearson
|
||||
|
||||
A set of functions for working with ARGB pixel data.
|
||||
*/
|
||||
|
||||
#ifndef GL_RGB_H
|
||||
#define GL_RGB_H
|
||||
|
||||
typedef GLubyte GLrgb3ub[3];
|
||||
typedef GLubyte GLrgba4ub[3];
|
||||
typedef GLfloat GLrgb3f[3];
|
||||
typedef GLfloat GLrgba4f[4];
|
||||
|
||||
#define RGB565_RED_MASK 0xF800
|
||||
#define RGB565_GREEN_MASK 0x7E0
|
||||
#define RGB565_BLUE_MASK 0x1F
|
||||
|
||||
#define RGB565_RED_SHIFT 0xB
|
||||
#define RGB565_GREEN_SHIFT 0x5
|
||||
#define RGB565_BLUE_SHIFT 0x0
|
||||
|
||||
#define ARGB4444_ALPHA_MASK 0xF000
|
||||
#define ARGB4444_RED_MASK 0x0F00
|
||||
#define ARGB4444_GREEN_MASK 0x00F0
|
||||
#define ARGB4444_BLUE_MASK 0x000F
|
||||
|
||||
#define ARGB4444_ALPHA_SHIFT 0xC
|
||||
#define ARGB4444_RED_SHIFT 0x8
|
||||
#define ARGB4444_GREEN_SHIFT 0x4
|
||||
#define ARGB4444_BLUE_SHIFT 0x0
|
||||
|
||||
#define ARGB1555_ALPHA_MASK 0x8000
|
||||
#define ARGB1555_RED_MASK 0x7C00
|
||||
#define ARGB1555_GREEN_MASK 0x3E0
|
||||
#define ARGB1555_BLUE_MASK 0x1F
|
||||
|
||||
#define ARGB1555_ALPHA_SHIFT 0xF
|
||||
#define ARGB1555_RED_SHIFT 0xA
|
||||
#define ARGB1555_GREEN_SHIFT 0x5
|
||||
#define ARGB1555_BLUE_SHIFT 0x0
|
||||
|
||||
#define ARGB32_ALPHA_MASK 0xFF000000
|
||||
#define ARGB32_RGB_MASK 0xFFFFFF
|
||||
#define ARGB32_RED_SHIFT 0x8
|
||||
|
||||
#define RGBA32_APLHA_MASK 0xFF
|
||||
#define RGBA32_RGB_MASK 0xFFFFFF00
|
||||
|
||||
#define RGB1_MAX 0x1
|
||||
#define RGB4_MAX 0xF
|
||||
#define RGB5_MAX 0x1F
|
||||
#define RGB6_MAX 0x3F
|
||||
#define RGB8_MAX 0xFF
|
||||
#define RGB16_MAX 0xFFFF
|
||||
|
||||
#define RGBA32_2_ARGB32(n) (((n & ARGB32_RGB_MASK) << ARGB32_RED_SHIFT) | (n & ARGB32_ALPHA_MASK))
|
||||
|
||||
#define ARGB_PACK_RGBF(r,g,b) (0xFF000000 | ((r*0xFF) << 16) | ((g*0xFF)<<8) | (b*0xFF))
|
||||
#define ARGB_PACK_ARGBF(a,r,g,b) (((a*0xFF) << 24) | ((r*0xFF) << 16) | ((g*0xFF)<<8) | (b*0xFF))
|
||||
|
||||
#define S8_NEG_OFT 128 // Absolute Value of Minimum 8bit Signed Range //
|
||||
#define S16_NEG_OFT 32768 // Absolute Value of Minimum 16bit Signed Range //
|
||||
|
||||
void _glKosPixelConvertRGB(int format, int w, int h, void *src, uint16 *dst);
|
||||
void _glKosPixelConvertRGBA(int format, int w, int h, void *src, uint16 *dst);
|
||||
|
||||
#endif
|
209
gl-sh4-light.S
209
gl-sh4-light.S
|
@ -1,209 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-sh4-light.S
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Dynamic Vertex Lighting
|
||||
|
||||
This Assembly file contains 2 functions:
|
||||
_glKosSpotLight - This function computes diffuse / spotlight / attenuation
|
||||
_glKosSpecular - This functions computes the Specular Term
|
||||
*/
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
!float _glKosSpecular( void * vertex6f, void * eyepos, void * Lvectorin );
|
||||
.globl __glKosSpecular
|
||||
|
||||
!r4 = [arg][void*] = vertex
|
||||
!r5 = [arg][void*] = eyepos
|
||||
!r6 = [arg][void*] = L vector
|
||||
|
||||
!fr0 = return value
|
||||
!fv0 = vertex position (P)(N)
|
||||
!fv4 = eye position (E)
|
||||
!fv8 = L vector (L)
|
||||
|
||||
__glKosSpecular:
|
||||
|
||||
fmov @r4+, fr0 ! load vertex x to fv0
|
||||
fmov @r4+, fr1 ! load vertex y to fv0
|
||||
fmov @r4+, fr2 ! load vertex z to fv0
|
||||
|
||||
fmov @r5+, fr4 ! load eye pos x to fv4
|
||||
fmov @r5+, fr5 ! load eye pos y to fv4
|
||||
fmov @r5+, fr6 ! load eye pos z to fv4
|
||||
|
||||
fmov @r6+, fr8 ! load L vector x to fv8
|
||||
fmov @r6+, fr9 ! load L vector y to fv8
|
||||
fmov @r6+, fr10 ! load L vector z to fv8
|
||||
|
||||
fsub fr0, fr4 ! fv4 = V = normalize ( E - P )
|
||||
fsub fr1, fr5
|
||||
fsub fr2, fr6
|
||||
fldi0 fr3 ! load 0 for P w
|
||||
fldi0 fr7 ! load 0 for E w
|
||||
|
||||
fipr fv4, fv4 ! Normalize V vector
|
||||
fsrra fr7
|
||||
fmul fr7, fr4
|
||||
fmul fr7, fr5
|
||||
fmul fr7, fr6
|
||||
|
||||
fadd fr4, fr8 ! fv8 = H = normalize( L + V )
|
||||
fadd fr5, fr9
|
||||
fadd fr6, fr10
|
||||
fldi0 fr11 ! load 0 for H w
|
||||
|
||||
fipr fv8, fv8 ! Normalize H vector
|
||||
fsrra fr11
|
||||
fmul fr11, fr8
|
||||
fmul fr11, fr9
|
||||
fmul fr11, fr10
|
||||
|
||||
fmov @r4+, fr0 ! load N to fv0
|
||||
fmov @r4+, fr1
|
||||
fmov @r4+, fr2
|
||||
|
||||
fipr fv0, fv8 ! N dot H for specular term
|
||||
|
||||
rts
|
||||
fmov fr11, fr0 ! move N dot H to fr0 for return
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
!int _glKosSpotlight( void * glLight, void * vertex6f, void * Lvectorout );
|
||||
.globl __glKosSpotlight
|
||||
|
||||
!r0 = return value | true or false
|
||||
!r1 = boolean flag
|
||||
!r2 = boolean false
|
||||
!r4 = [arg] = light
|
||||
!r5 = [arg] = vertex
|
||||
!r6 = [arg] = output
|
||||
|
||||
!fv0 = vertex position
|
||||
!fv4 = light position | L vector | normalize(light pos - vertex pos) | w = attenuation distance
|
||||
!fv8 = light direction | N vector = Vertex Normal
|
||||
!fv12 = Spot vector | normalize(vertex pos - light pos)
|
||||
|
||||
__glKosSpotlight:
|
||||
|
||||
mov #0, r1 ! load 0 for boolean flag
|
||||
mov #0, r2 ! load 0 for boolean false
|
||||
|
||||
fmov @r4+, fr4 ! load light position x to fv4
|
||||
fmov @r4+, fr5 ! load light position y to fv4
|
||||
fmov @r4+, fr6 ! load light position z to fv4
|
||||
fmov @r4+, fr7 ! load light position w to fv4
|
||||
|
||||
fmov @r4+, fr8 ! load light direction x to fv8
|
||||
fmov @r4+, fr9 ! load light direction y to fv8
|
||||
fmov @r4+, fr10 ! load light direction z to fv8
|
||||
|
||||
fmov @r5+, fr0 ! load vertex position x to fv0
|
||||
fmov @r5+, fr1 ! load vertex position y to fv0
|
||||
fmov @r5+, fr2 ! load vertex position z to fv0
|
||||
|
||||
fldi0 fr11 ! load 0 for light dir w
|
||||
fcmp/gt fr11, fr7 ! light pos w component set = spot light
|
||||
bf .VERTEXLIGHT0 ! light not a spot light - branch to vertex lighting
|
||||
|
||||
fschg
|
||||
fmov dr0, dr12 ! copy vertex x,y to fv12
|
||||
fschg
|
||||
fmov fr2, fr14 ! copy vertex z to fv12
|
||||
|
||||
fsub fr4, fr12 ! fv12 = ( vertex position - light position)
|
||||
fsub fr5, fr13
|
||||
fsub fr6, fr14
|
||||
fldi0 fr15 ! set fv12 w component to 0
|
||||
|
||||
fipr fv12, fv12 ! Normalize vector
|
||||
fsrra fr15
|
||||
fmul fr15, fr12
|
||||
fmul fr15, fr13
|
||||
fmul fr15, fr14
|
||||
|
||||
fldi0 fr15 ! set fv12 w component to 0
|
||||
fipr fv12, fv8 ! fr11 now holds light cosDir
|
||||
|
||||
fmov @r4+, fr15 ! load light cutOff to fr15
|
||||
mov #1, r1 ! load 1 for boolean flag = indicate light cutOff was read
|
||||
|
||||
fcmp/gt fr15, fr11 ! cosDir > cutOff ? 0 : 1
|
||||
bt .RET0spot ! vertex outside of spotlight = return 0
|
||||
|
||||
.VERTEXLIGHT0:
|
||||
|
||||
fsub fr0, fr4 ! fv4 = L vector = ( light position - vertex position)
|
||||
fsub fr1, fr5
|
||||
fsub fr2, fr6
|
||||
fldi0 fr7 ! load 0 for L w
|
||||
fldi0 fr11 ! load 0 for N w
|
||||
|
||||
fipr fv4, fv4 ! Normalize L vector
|
||||
fsrra fr7
|
||||
fmul fr7, fr4
|
||||
fmul fr7, fr5
|
||||
fmul fr7, fr6 ! fv4 = Normalized L Vector
|
||||
|
||||
fmov fr7, fr3 ! copy L w to fr3
|
||||
|
||||
fldi0 fr7 ! load 0 for L w
|
||||
|
||||
fcmp/gt fr7, fr3
|
||||
bf .RET0spot ! if L w < 0, return 0 now to avoid pointless computations
|
||||
|
||||
fmov @r5+, fr8 ! load normal to fv8
|
||||
fmov @r5+, fr9 ! load normal to fv8
|
||||
fmov @r5+, fr10 ! load normal to fv8
|
||||
|
||||
fipr fv8, fv4 ! N dot L
|
||||
|
||||
fcmp/gt fr11, fr7 ! L w < = 0 ? L w = 0
|
||||
bf .RET0spot: ! if L w < 0, return 0 now to avoid pointless computations
|
||||
|
||||
.WRITEDi:
|
||||
|
||||
fschg
|
||||
fmov dr4, @r6 ! write L vector x to output
|
||||
fschg
|
||||
add #8, r6
|
||||
fmov fr6, @r6 ! write L vector z to output
|
||||
add #4, r6
|
||||
|
||||
cmp/gt r2, r1
|
||||
bt .READattenf
|
||||
|
||||
add #4, r4
|
||||
|
||||
.READattenf:
|
||||
|
||||
fmov @r4+, fr8 ! vertex normal gets overwritten by atten factors
|
||||
fmov @r4+, fr9
|
||||
fmov @r4+, fr10
|
||||
fldi1 fr11
|
||||
|
||||
fmul fr3, fr9 ! calculate attenuation
|
||||
fmul fr3, fr10
|
||||
fmul fr3, fr10
|
||||
fadd fr9, fr8
|
||||
fadd fr10, fr8
|
||||
fdiv fr8, fr11 ! fr11 = A
|
||||
|
||||
fmul fr7, fr11 ! D * A
|
||||
|
||||
fmov fr11, @r6 ! write D*A to output
|
||||
|
||||
.RET1spot:
|
||||
|
||||
rts
|
||||
mov #1, r0
|
||||
|
||||
.RET0spot:
|
||||
|
||||
rts
|
||||
mov #0, r0
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
86
gl-sh4.h
86
gl-sh4.h
|
@ -1,86 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/gl-sh4.h
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
Macros for utilizing the Dreamcast's SH4 CPU vector / matrix math functions.
|
||||
*/
|
||||
|
||||
#ifndef GL_SH4_H
|
||||
#define GL_SH4_H
|
||||
|
||||
typedef float vector3f[3]; /* 3 float vector */
|
||||
typedef float matrix4f[4][4]; /* 4x4 float matrix */
|
||||
|
||||
/* DEG2RAD - convert Degrees to Radians = PI / 180.0f */
|
||||
#define DEG2RAD (0.01745329251994329576923690768489)
|
||||
|
||||
/* Calculate Spot Light Angle Cosine = (PI / 180.0f) * (n / 2) */
|
||||
#define LCOS(n) fcos(n*0.00872664625997164788461845384244)
|
||||
|
||||
/* Internal GL API macro */
|
||||
#define mat_trans_fv12() { \
|
||||
__asm__ __volatile__( \
|
||||
"fldi1 fr15\n" \
|
||||
"ftrv xmtrx, fv12\n" \
|
||||
"fldi1 fr14\n" \
|
||||
"fdiv fr15, fr14\n" \
|
||||
"fmul fr14, fr12\n" \
|
||||
"fmul fr14, fr13\n" \
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z) \
|
||||
: "0" (__x), "1" (__y), "2" (__z) \
|
||||
: "fr15" ); \
|
||||
}
|
||||
|
||||
/* Internal GL API macro */
|
||||
#define mat_trans_fv12_nodiv() { \
|
||||
__asm__ __volatile__( \
|
||||
"fldi1 fr15\n" \
|
||||
"ftrv xmtrx, fv12\n" \
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z) \
|
||||
: "0" (__x), "1" (__y), "2" (__z) ); \
|
||||
}
|
||||
|
||||
#define mat_trans_fv12_nodivw() { \
|
||||
__asm__ __volatile__( \
|
||||
"fldi1 fr15\n" \
|
||||
"ftrv xmtrx, fv12\n" \
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w) \
|
||||
: "0" (__x), "1" (__y), "2" (__z), "3" (__w) ); \
|
||||
}
|
||||
|
||||
#define mat_trans_texture4(s, t, r, q) { \
|
||||
register float __s __asm__("fr4") = (s); \
|
||||
register float __t __asm__("fr5") = (t); \
|
||||
register float __r __asm__("fr6") = (r); \
|
||||
register float __q __asm__("fr7") = (q); \
|
||||
__asm__ __volatile__( \
|
||||
"ftrv xmtrx,fv4\n" \
|
||||
"fldi1 fr6\n" \
|
||||
"fdiv fr7,fr6\n" \
|
||||
"fmul fr6,fr4\n" \
|
||||
"fmul fr6,fr5\n" \
|
||||
: "=f" (__s), "=f" (__t), "=f" (__r) \
|
||||
: "0" (__s), "1" (__t), "2" (__r) \
|
||||
: "fr7" ); \
|
||||
s = __s; t = __t; r = __r; \
|
||||
}
|
||||
|
||||
#define mat_trans_texture2_nomod(s, t, so, to) { \
|
||||
register float __s __asm__("fr4") = (s); \
|
||||
register float __t __asm__("fr5") = (t); \
|
||||
__asm__ __volatile__( \
|
||||
"fldi0 fr6\n" \
|
||||
"fldi1 fr7\n" \
|
||||
"ftrv xmtrx,fv4\n" \
|
||||
"fldi1 fr6\n" \
|
||||
"fdiv fr7,fr6\n" \
|
||||
"fmul fr6,fr4\n" \
|
||||
"fmul fr6,fr5\n" \
|
||||
: "=f" (__s), "=f" (__t) \
|
||||
: "0" (__s), "1" (__t) \
|
||||
: "fr7" ); \
|
||||
so = __s; to = __t; \
|
||||
}
|
||||
|
||||
#endif
|
115
glu-texture.c
115
glu-texture.c
|
@ -1,115 +0,0 @@
|
|||
/* KallistiGL for KallistiOS ##version##
|
||||
|
||||
libgl/glu-texture.c
|
||||
Copyright (C) 2013-2014 Josh Pearson
|
||||
|
||||
A set of functions for working with ARGB pixel data.
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl-api.h"
|
||||
#include "gl-rgb.h"
|
||||
#include "glu.h"
|
||||
|
||||
GLAPI GLuint APIENTRY glKosMipMapTexSize(GLuint width, GLuint height) {
|
||||
GLuint b = 0;
|
||||
|
||||
while(width >= 1 && height >= 1) {
|
||||
b += width * height * 2;
|
||||
|
||||
if(width >= 1)
|
||||
width /= 2;
|
||||
|
||||
if(height >= 1)
|
||||
height /= 2;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static GLint gluBuild2DBiMipmaps(GLenum target, GLint internalFormat, GLsizei width,
|
||||
GLsizei height, GLenum format, GLenum type, const void *data) {
|
||||
if(target != GL_TEXTURE_2D)
|
||||
return -1;
|
||||
|
||||
if(width < 1 || height < 1)
|
||||
return 0;
|
||||
|
||||
uint32 i = 0;
|
||||
uint16 x , y;
|
||||
|
||||
uint16 *src = (uint16 *)data;
|
||||
uint16 *dst = (uint16 *)data + (width * height);
|
||||
|
||||
for(y = 0; y < height; y += 2) {
|
||||
for(x = 0; x < width; x += 2) {
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
dst[i++] = __glKosAverageBiPixelRGB565(*src, *(src + 1));
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
dst[i++] = __glKosAverageBiPixelARGB4444(*src, *(src + 1));
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
||||
dst[i++] = __glKosAverageBiPixelARGB1555(*src, *(src + 1));
|
||||
break;
|
||||
}
|
||||
|
||||
src += 2;
|
||||
}
|
||||
|
||||
src += width;
|
||||
}
|
||||
|
||||
return gluBuild2DBiMipmaps(target, internalFormat, width / 2, height / 2,
|
||||
format, type, (uint16 *)data + (width * height));
|
||||
}
|
||||
|
||||
GLint APIENTRY gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
|
||||
GLsizei height, GLenum format, GLenum type, const void *data) {
|
||||
if(target != GL_TEXTURE_2D)
|
||||
return -1;
|
||||
|
||||
if(type != GL_UNSIGNED_SHORT_5_6_5 && type != GL_UNSIGNED_SHORT_4_4_4_4
|
||||
&& type != GL_UNSIGNED_SHORT_1_5_5_5_REV)
|
||||
return -1;
|
||||
|
||||
if(width < 1 || height < 1)
|
||||
return 0;
|
||||
|
||||
if(width == 1 || height == 1)
|
||||
return gluBuild2DBiMipmaps(target, internalFormat, width, height, format, type, data);
|
||||
|
||||
uint32 i = 0;
|
||||
uint16 x, y;
|
||||
|
||||
uint16 *src = (uint16 *)data;
|
||||
uint16 *dst = (uint16 *)data + (width * height);
|
||||
|
||||
for(y = 0; y < height; y += 2) {
|
||||
for(x = 0; x < width; x += 2) {
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
dst[i++] = __glKosAverageQuadPixelRGB565(*src, *(src + 1), *(src + width), *(src + width + 1));
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
dst[i++] = __glKosAverageQuadPixelARGB4444(*src, *(src + 1), *(src + width), *(src + width + 1));
|
||||
break;
|
||||
|
||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
||||
dst[i++] = __glKosAverageQuadPixelARGB1555(*src, *(src + 1), *(src + width), *(src + width + 1));
|
||||
break;
|
||||
}
|
||||
|
||||
src += 2;
|
||||
}
|
||||
|
||||
src += width;
|
||||
}
|
||||
|
||||
return gluBuild2DMipmaps(target, internalFormat, width / 2, height / 2,
|
||||
format, type, (uint16 *)data + (width * height));
|
||||
}
|
38
include/gl.h
38
include/gl.h
|
@ -56,13 +56,9 @@ __BEGIN_DECLS
|
|||
|
||||
/* Matrix modes */
|
||||
#define GL_MATRIX_MODE 0x0BA0
|
||||
#define GL_SCREENVIEW 0x00
|
||||
#define GL_MODELVIEW 0x01
|
||||
#define GL_PROJECTION 0x02
|
||||
#define GL_TEXTURE 0x03
|
||||
#define GL_IDENTITY 0x04
|
||||
#define GL_RENDER 0x05
|
||||
#define GL_MATRIX_COUNT 0x06
|
||||
#define GL_MODELVIEW 0x1700
|
||||
#define GL_PROJECTION 0x1701
|
||||
#define GL_TEXTURE 0x1702
|
||||
|
||||
#define GL_MODELVIEW_MATRIX 0x0BA6
|
||||
#define GL_PROJECTION_MATRIX 0x0BA7
|
||||
|
@ -235,6 +231,11 @@ __BEGIN_DECLS
|
|||
#define GL_LIGHT14 0x400E
|
||||
#define GL_LIGHT15 0x400F
|
||||
|
||||
/* EXT_separate_specular_color.txt */
|
||||
#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
|
||||
#define GL_SINGLE_COLOR 0x81F9
|
||||
#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
|
||||
|
||||
/* Client state caps */
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#define GL_NORMAL_ARRAY 0x8075
|
||||
|
@ -435,13 +436,9 @@ GLAPI void APIENTRY glVertex2f(GLfloat x, GLfloat y);
|
|||
GLAPI void APIENTRY glVertex2fv(const GLfloat *xy);
|
||||
#define glVertex2iv glVertex2fv
|
||||
|
||||
/* Non-Standard KOS Primitive 2D Submission. This will perform no tranformations on the vertices. */
|
||||
GLAPI void APIENTRY glKosVertex2f(GLfloat x, GLfloat y);
|
||||
GLAPI void APIENTRY glKosVertex2fv(const GLfloat *xy);
|
||||
|
||||
/* Primitive 3D Position Submission */
|
||||
GLAPI void APIENTRY(*glVertex3f)(GLfloat, GLfloat, GLfloat);
|
||||
GLAPI void APIENTRY(*glVertex3fv)(const GLfloat *);
|
||||
GLAPI void APIENTRY glVertex3f(GLfloat, GLfloat, GLfloat);
|
||||
GLAPI void APIENTRY glVertex3fv(const GLfloat *);
|
||||
|
||||
/* 2D Non-Textured Rectangle Submission */
|
||||
GLAPI GLvoid APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
|
||||
|
@ -473,8 +470,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);
|
||||
|
||||
|
@ -620,7 +617,12 @@ GLAPI void APIENTRY glFogfv(GLenum pname, const GLfloat *params);
|
|||
/* Set Individual Light Parameters */
|
||||
GLAPI void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params);
|
||||
GLAPI void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param);
|
||||
|
||||
GLAPI void APIENTRY glLightModelf(GLenum pname, const GLfloat param);
|
||||
GLAPI void APIENTRY glLightModeli(GLenum pname, const GLint param);
|
||||
GLAPI void APIENTRY glLightModelfv(GLenum pname, const GLfloat *params);
|
||||
GLAPI void APIENTRY glLightModeliv(GLenum pname, const GLint *params);
|
||||
|
||||
|
||||
/* Set Global Material Parameters */
|
||||
GLAPI void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param);
|
||||
|
@ -640,14 +642,6 @@ GLAPI const GLbyte* APIENTRY glGetString(GLenum name);
|
|||
GLAPI void APIENTRY glActiveTextureARB(GLenum texture);
|
||||
GLAPI void APIENTRY glClientActiveTextureARB(GLenum texture);
|
||||
|
||||
/* Frame Buffer Objects / Render-To-Texture Functions */
|
||||
GLAPI void APIENTRY glGenFramebuffers(GLsizei n, GLuint *framebuffers);
|
||||
GLAPI void APIENTRY glDeleteFramebuffers(GLsizei n, GLuint *framebuffers);
|
||||
GLAPI void APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer);
|
||||
GLAPI void APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level);
|
||||
GLAPI GLenum APIENTRY glCheckFramebufferStatus(GLenum target);
|
||||
|
||||
/* Error handling */
|
||||
GLAPI GLenum APIENTRY glGetError(void);
|
||||
|
||||
|
|
20
include/glkos.h
Normal file
20
include/glkos.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef GLKOS_H
|
||||
#define GLKOS_H
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
GLAPI void APIENTRY glKosSwapBuffers();
|
||||
|
||||
GLAPI void APIENTRY glGenFramebuffersEXT(GLsizei n, GLuint* framebuffers);
|
||||
GLAPI void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers);
|
||||
GLAPI void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer);
|
||||
GLAPI void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GLAPI void APIENTRY glGenerateMipmapEXT(GLenum target);
|
||||
GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target);
|
||||
GLAPI GLboolean APIENTRY glIsFramebufferEXT(GLuint framebuffer);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // GLKOS_H
|
Loading…
Reference in New Issue
Block a user