Merge pull request #7 from Kazade/experimental

Complete rewrite of libGL, now called GLdc
This commit is contained in:
Luke Benstead 2018-05-20 16:24:31 +01:00 committed by GitHub
commit dd75ae3caf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 2476 additions and 6293 deletions

429
GL/draw.c Normal file
View 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;
}

View File

@ -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
View 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(&params);
}
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
View 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
View 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
View 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
View 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, &param);
}
void APIENTRY glLightModeli(GLenum pname, const GLint param) {
glLightModeliv(pname, &param);
}
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
View 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
View 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
View 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";
}

View File

@ -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;
}

View File

@ -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
View 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
View 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

View File

@ -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
View 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
View File

@ -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
View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -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;
}

View File

@ -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
View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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

View File

@ -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
View File

@ -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(&params);
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;
}

View File

@ -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
View File

@ -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;
}
}

View File

@ -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

View File

@ -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
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

View File

@ -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

View File

@ -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));
}

View File

@ -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
View 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