diff --git a/gl-api.c b/gl-api.c index c1f3313..a53aacd 100755 --- a/gl-api.c +++ b/gl-api.c @@ -1,1382 +1,1382 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-api.c - Copyright (C) 2013-2014 Josh "PH3NOM" 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 -#include -#include - -#include "gl.h" -#include "glu.h" -#include "gl-api.h" -#include "gl-sh4.h" -#include "gl-pvr.h" - -/* Texture Submission Functions ************************************************************************/ -/* The texutre sumbission uses a fixed-size buffer, that defaults to 1024 textures. - That means that you must manage your texture submission by calling glDelTextures(...) - when you are done using a texture that was created by glGenTextures(...). - The size of the texture buffer can be controlled by setting GL_MAX_TEXTURES on gl-pvr.h. - - glTexImage2D(..) is used for loading texture data to OpenGL that is located in Main RAM: - OpenGL will allocate VRAM for the texture, and copy the texture data from Main RAM to VRAM. - - glKosTexImage2D(...) is used for loading texture data to OpenGL that is already in VRAM: - This mode must be used for a render-to-texture if you are using glutSwapBuffersToTexture(). -*/ - -typedef struct { - GLenum target; - GLint level; - GLint border; - GLenum format; - GLenum type; - GLint filter, env; - GLuint width, height; - GLuint internalFormat; - GLvoid *data; -} glTexCxt; - -static glTexCxt GL_TEX_LIST[GL_MAX_TEXTURES]; -static GLint GL_BOUND_TEX = -1, GL_LAST_BOUND_TEX = -1, - GL_BOUND_TEX1 = -1, GL_LAST_BOUND_TEX1 = -1; - -static GLubyte BLEND_SRC = PVR_BLEND_ONE; -static GLubyte BLEND_DST = PVR_BLEND_ZERO; - -static GLubyte GL_SHADE_FUNC = PVR_SHADE_GOURAUD; - -static GLubyte GL_CULL_FUNC = PVR_CULLING_NONE; - -static GLubyte GL_DEPTH_CMP = PVR_DEPTHCMP_GEQUAL; -static GLubyte GL_DEPTH_ENABLE = PVR_DEPTHWRITE_ENABLE; - -static GLubyte GL_TEX_ENV = PVR_TXRENV_MODULATEALPHA; - -static GLubyte GL_ENABLE_CLIPZ = 0; -static GLubyte GL_ENABLE_LIGHTING = 0; -static GLubyte GL_ENABLE_SCISSOR = 0; -static GLubyte GL_ENABLE_FOG = 0; -static GLubyte GL_ENABLE_CULLING = 0; -static GLubyte GL_ENABLE_DEPTH_TEST = 0; -static GLubyte GL_ENABLE_SUPERSAMP = 0; - -static GLubyte GL_FACE_FRONT = 0; -static GLubyte GL_CLAMP_ST = 0; - -/* Primitive 3D Position Submission */ -void (*glVertex3f)(float, float, float); -void (*glVertex3fv)(float *); - -#define GL_CLAMP_U 0x0F -#define GL_CLAMP_V 0xF0 -#define GL_CLAMP_UV 0xFF - -#define GL_TEXTURE_0 1<<0 -#define GL_TEXTURE_1 1<<1 - -static GLuint GL_TEXTURE_ENABLED = 0; -static GLuint GL_CUR_ACTIVE_TEX = 0; - -void glActiveTexture(GLenum texture) { - if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + GL_MAX_TEXTURE_UNITS) - return; - - GL_CUR_ACTIVE_TEX = ((texture & 0xFF) - (GL_TEXTURE0 & 0xFF)); -} - -void glBindTexture(GLenum target, GLuint texture) { - if(target == GL_TEXTURE_2D) { - switch(GL_CUR_ACTIVE_TEX) { - case 0: - GL_BOUND_TEX = texture; - GL_LAST_BOUND_TEX = GL_BOUND_TEX; - break; - - case 1: - GL_BOUND_TEX1 = texture; - GL_LAST_BOUND_TEX1 = GL_BOUND_TEX1; - break; - } - } -} - -void glGetIntegerv(GLenum pname, GLint *params) { - switch(pname) { - case GL_ACTIVE_TEXTURE: - *params = GL_CUR_ACTIVE_TEX; - break; - - case GL_BLEND: - *params = _glKosList(); - break; - - case GL_BLEND_DST: - *params = BLEND_SRC; - break; - - case GL_BLEND_SRC: - *params = BLEND_DST; - break; - - case GL_CULL_FACE: - *params = GL_ENABLE_CULLING; - break; - - case GL_CULL_FACE_MODE: - *params = GL_CULL_FUNC; - break; - - case GL_DEPTH_FUNC: - *params = GL_DEPTH_CMP; - break; - - case GL_DEPTH_TEST: - *params = GL_ENABLE_DEPTH_TEST; - break; - - case GL_DEPTH_WRITEMASK: - *params = GL_DEPTH_ENABLE; - break; - - case GL_FRONT_FACE: - *params = GL_FACE_FRONT; - break; - - case GL_SCISSOR_TEST: - *params = GL_ENABLE_SCISSOR; - break; - - default: - *params = -1; // Indicate invalid parameter // - break; - } -} - -void 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: - *params = (GLfloat)GL_INVALID_ENUM; - break; - } -} - -static void _glKosInitTextures() { - GLuint i; - - for(i = 0; i < GL_MAX_TEXTURES; i++) - GL_TEX_LIST[i].data = NULL; -} - -static GLuint _glKosNextTexture() { - GLint i; - - for(i = 0; i < GL_MAX_TEXTURES; i++) - if(GL_TEX_LIST[i].data == NULL) - return i; - - return 0; /* Invalid Texture! */ -} - -GLuint 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; -} - -void glGenTextures(GLsizei n, GLuint *textures) { - while(n--) - *textures++ = _glKosNextTexture(); -} - -void glDelTextures(GLsizei n, GLuint *textures) { - while(n--) { - if(GL_TEX_LIST[*textures].data != NULL) { - pvr_mem_free(GL_TEX_LIST[*textures].data); - GL_TEX_LIST[*textures].data = NULL; - } - - textures++; - } -} - -void glTexImage2D(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, GLvoid *data) { - if(target != GL_TEXTURE_2D) return; - - GL_TEX_LIST[GL_BOUND_TEX].target = target; - GL_TEX_LIST[GL_BOUND_TEX].level = level; - GL_TEX_LIST[GL_BOUND_TEX].border = border; - GL_TEX_LIST[GL_BOUND_TEX].format = format; - GL_TEX_LIST[GL_BOUND_TEX].type = type; - - GLuint bytes; - - if(!level) - bytes = width * height * 2; - else - bytes = glKosMipMapTexSize(width, height); - - if(format == PVR_TXRFMT_VQ_ENABLE) - bytes /= 4; - - GL_TEX_LIST[GL_BOUND_TEX].data = pvr_mem_malloc(bytes); - - GL_TEX_LIST[GL_BOUND_TEX].width = width; - GL_TEX_LIST[GL_BOUND_TEX].height = height; - GL_TEX_LIST[GL_BOUND_TEX].internalFormat = internalFormat; - - GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NONE; - - sq_cpy(GL_TEX_LIST[GL_BOUND_TEX].data, data, bytes); -} - -void glKosTexImage2D(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, GLvoid *data) { - if(target != GL_TEXTURE_2D) return; - - GL_TEX_LIST[GL_BOUND_TEX].target = target; - GL_TEX_LIST[GL_BOUND_TEX].level = level; - GL_TEX_LIST[GL_BOUND_TEX].border = border; - GL_TEX_LIST[GL_BOUND_TEX].format = format; - GL_TEX_LIST[GL_BOUND_TEX].type = type; - - GL_TEX_LIST[GL_BOUND_TEX].data = data; - - GL_TEX_LIST[GL_BOUND_TEX].width = width; - GL_TEX_LIST[GL_BOUND_TEX].height = height; - GL_TEX_LIST[GL_BOUND_TEX].internalFormat = internalFormat; - - GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NONE; -} - -void glTexParameteri(GLenum target, GLenum pname, GLint param) { - if(target == GL_TEXTURE_2D) { - switch(pname) { - case GL_TEXTURE_MAG_FILTER: - case GL_TEXTURE_MIN_FILTER: - switch(param) { - case GL_LINEAR: - GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_BILINEAR; - break; - - case GL_NEAREST: - GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NEAREST; - break; - - case GL_FILTER_NONE: /* Compatabile with deprecated kgl */ - GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NONE; - break; - - case GL_FILTER_BILINEAR: /* Compatabile with deprecated kgl */ - GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_BILINEAR; - break; - - case GL_NEAREST_MIPMAP_NEAREST: - GL_TEX_LIST[GL_BOUND_TEX].level = PVR_MIPMAP_ENABLE; - break; - - default: - break; - } - - break; - - case GL_TEXTURE_WRAP_S: - switch(param) { - case GL_CLAMP: - GL_CLAMP_ST |= GL_CLAMP_U; - break; - - case GL_REPEAT: - GL_CLAMP_ST ^= GL_CLAMP_U; - break; - } - - break; - - case GL_TEXTURE_WRAP_T: - switch(param) { - case GL_CLAMP: - GL_CLAMP_ST |= GL_CLAMP_V; - break; - - case GL_REPEAT: - GL_CLAMP_ST ^= GL_CLAMP_V; - break; - } - - break; - } - } -} - -void glTexEnvi(GLenum target, GLenum pname, GLint param) { - if(target == GL_TEXTURE_ENV) - if(pname == GL_TEXTURE_ENV_MODE) - if(param >= PVR_TXRENV_REPLACE && param <= PVR_TXRENV_MODULATEALPHA) - GL_TEX_ENV = param; -} - -void glTexEnvf(GLenum target, GLenum pname, GLfloat param) { - /* GL_TEXTURE_LOD_BIAS Not Implemented */ - glTexEnvi(target, pname, param); -} - -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: - 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 gluBuild2DMipmaps(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; - - 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: - 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)); -} - -/* Blending / Shading functions ********************************************************/ - -void glShadeModel(GLenum mode) { - switch(mode) { - case GL_FLAT: - GL_SHADE_FUNC = PVR_SHADE_FLAT; - break; - - case GL_SMOOTH: - GL_SHADE_FUNC = PVR_SHADE_GOURAUD; - break; - } -} - -void glBlendFunc(GLenum sfactor, GLenum dfactor) { - switch(sfactor) { - case GL_ONE: - BLEND_SRC = PVR_BLEND_ONE; - break; - - case GL_ZERO: - BLEND_SRC = PVR_BLEND_ZERO; - break; - - case GL_SRC_COLOR: - BLEND_SRC = PVR_BLEND_SRCALPHA; - break; - - case GL_DST_COLOR: - BLEND_SRC = PVR_BLEND_DESTCOLOR; - break; - - case GL_SRC_ALPHA: - BLEND_SRC = PVR_BLEND_SRCALPHA; - break; - - case GL_DST_ALPHA: - BLEND_SRC = PVR_BLEND_DESTALPHA; - break; - - case GL_ONE_MINUS_SRC_ALPHA: - BLEND_SRC = PVR_BLEND_INVSRCALPHA; - break; - - case GL_ONE_MINUS_DST_ALPHA: - BLEND_SRC = PVR_BLEND_INVDESTALPHA; - break; - - case GL_ONE_MINUS_DST_COLOR: - BLEND_SRC = PVR_BLEND_INVDESTCOLOR; - break; - } - - switch(dfactor) { - case GL_ONE: - BLEND_DST = PVR_BLEND_ONE; - break; - - case GL_ZERO: - BLEND_DST = PVR_BLEND_ZERO; - break; - - case GL_SRC_COLOR: - BLEND_DST = PVR_BLEND_SRCALPHA; - break; - - case GL_DST_COLOR: - BLEND_DST = PVR_BLEND_DESTCOLOR; - break; - - case GL_SRC_ALPHA: - BLEND_DST = PVR_BLEND_SRCALPHA; - break; - - case GL_DST_ALPHA: - BLEND_DST = PVR_BLEND_DESTALPHA; - break; - - case GL_ONE_MINUS_SRC_ALPHA: - BLEND_DST = PVR_BLEND_INVSRCALPHA; - break; - - case GL_ONE_MINUS_DST_ALPHA: - BLEND_DST = PVR_BLEND_INVDESTALPHA; - break; - - case GL_ONE_MINUS_DST_COLOR: - BLEND_DST = PVR_BLEND_INVDESTCOLOR; - break; - } -} - -/* Depth / Clear functions */ -static GLfloat GL_DEPTH_CLEAR = 1.0f, - GL_COLOR_CLEAR[3] = { 0, 0, 0 }; - -void glClear(GLuint mode) { - if(mode & GL_COLOR_BUFFER_BIT) - pvr_set_bg_color(GL_COLOR_CLEAR[0], GL_COLOR_CLEAR[1], GL_COLOR_CLEAR[2]); -} - -void 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_COLOR_CLEAR[0] = r * a; - GL_COLOR_CLEAR[1] = g * a; - GL_COLOR_CLEAR[2] = b * a; -} - -void glClearDepthf(GLfloat depth) { - GL_DEPTH_CLEAR = depth; -} - -void glDepthFunc(GLenum func) { - switch(func) { - case GL_LESS: - GL_DEPTH_CMP = PVR_DEPTHCMP_GEQUAL; - break; - - case GL_LEQUAL: - GL_DEPTH_CMP = PVR_DEPTHCMP_GREATER; - break; - - case GL_GREATER: - GL_DEPTH_CMP = PVR_DEPTHCMP_LEQUAL; - break; - - case GL_GEQUAL: - GL_DEPTH_CMP = PVR_DEPTHCMP_LESS; - break; - - default: - GL_DEPTH_CMP = func & 0xF; - } -} - -void glDepthMask(GLboolean flag) { - flag ? (GL_DEPTH_ENABLE = PVR_DEPTHWRITE_ENABLE) : - (GL_DEPTH_ENABLE = PVR_DEPTHWRITE_DISABLE); -} - -void glFrontFace(GLenum mode) { - switch(mode) { - case GL_CW: - case GL_CCW: - GL_FACE_FRONT = mode; - break; - } -} - -void glCullFace(GLenum mode) { - switch(mode) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - GL_CULL_FUNC = mode; - break; - } -} - -/* glEnable / glDisable ****************************************************************/ - -void glEnable(GLenum cap) { - if(cap >= GL_LIGHT0 && cap <= GL_LIGHT7) return _glKosEnableLight(cap); - - switch(cap) { - case GL_TEXTURE_2D: - GL_TEXTURE_ENABLED |= (1 << GL_CUR_ACTIVE_TEX); - break; - - case GL_BLEND: - _glKosVertexBufSwitchTR(); - break; - - case GL_DEPTH_TEST: - GL_ENABLE_DEPTH_TEST = 1; - break; - - case GL_LIGHTING: - GL_ENABLE_LIGHTING = 1; - break; - - case GL_KOS_NEARZ_CLIPPING: - GL_ENABLE_CLIPZ = 1; - break; - - case GL_SCISSOR_TEST: - GL_ENABLE_SCISSOR = 1; - break; - - case GL_FOG: - GL_ENABLE_FOG = 1; - break; - - case GL_CULL_FACE: - GL_ENABLE_CULLING = 1; - break; - } -} - -void glDisable(GLenum cap) { - if(cap >= GL_LIGHT0 && cap <= GL_LIGHT7) return _glKosDisableLight(cap); - - switch(cap) { - case GL_TEXTURE_2D: - GL_TEXTURE_ENABLED &= ~(1 << GL_CUR_ACTIVE_TEX); - break; - - case GL_BLEND: - _glKosVertexBufSwitchOP(); - break; - - case GL_DEPTH_TEST: - GL_ENABLE_DEPTH_TEST = 0; - break; - - case GL_LIGHTING: - GL_ENABLE_LIGHTING = 0; - break; - - case GL_KOS_NEARZ_CLIPPING: - GL_ENABLE_CLIPZ = 0; - break; - - case GL_SCISSOR_TEST: - GL_ENABLE_SCISSOR = 0; - break; - - case GL_FOG: - GL_ENABLE_FOG = 0; - break; - - case GL_CULL_FACE: - GL_ENABLE_CULLING = 0; - break; - } -} - -/* Vertex Submission Functions *************************************************************************/ -static GLuint GL_VERTICES = 0, - GL_VERTEX_MODE = GL_TRIANGLES; -static GLuint GL_VERTEX_COLOR = 0xFFFFFFFF; -//static GLuint GL_VERTEX_SPECULAR = 0xFF000000; -static GLfloat GL_VERTEX_UV[2] = {0, 0}; - -typedef struct { - GLfloat u; - GLfloat v; -} TexCoord; - -static TexCoord GL_MULTI_UV[GL_MAX_VERTS]; - -static pvr_poly_cxt_t GL_POLY_CXT; - -void glKosInit() { - _glKosInitPVR(); - - _glKosInitTextures(); - - _glKosInitMatrix(); - - _glKosInitLighting(); -} - -void _glKosCompileHdr() { - pvr_poly_hdr_t *hdr = _glKosVertexBufPointer(); - - /* Non-textured pvr poly header */ - pvr_poly_cxt_col(&GL_POLY_CXT, _glKosList() * 2); - - GL_POLY_CXT.gen.shading = GL_SHADE_FUNC; - - if(GL_ENABLE_DEPTH_TEST) - GL_POLY_CXT.depth.comparison = GL_DEPTH_CMP; - else - GL_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS; - - GL_POLY_CXT.depth.write = GL_DEPTH_ENABLE; - - if(GL_ENABLE_SCISSOR) - GL_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE; - - if(GL_ENABLE_FOG) - GL_POLY_CXT.gen.fog_type = PVR_FOG_TABLE; - - if(GL_ENABLE_CULLING) { - if(GL_CULL_FUNC == GL_BACK) { - if(GL_FACE_FRONT == GL_CW) - GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; - else - GL_POLY_CXT.gen.culling = PVR_CULLING_CW; - } - else if(GL_CULL_FUNC == GL_FRONT) { - if(GL_FACE_FRONT == GL_CCW) - GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; - else - GL_POLY_CXT.gen.culling = PVR_CULLING_CW; - } - } - else - GL_POLY_CXT.gen.culling = PVR_CULLING_NONE; - - pvr_poly_compile(hdr, &GL_POLY_CXT); - - if(GL_ENABLE_SUPERSAMP) - hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT; - - _glKosVertexBufIncrement(); -} - -void _glKosCompileHdrTx() { - pvr_poly_hdr_t *hdr = _glKosVertexBufPointer(); - - pvr_poly_cxt_txr(&GL_POLY_CXT, _glKosList() * 2, - GL_TEX_LIST[GL_BOUND_TEX].format | - GL_TEX_LIST[GL_BOUND_TEX].type, - GL_TEX_LIST[GL_BOUND_TEX].width, - GL_TEX_LIST[GL_BOUND_TEX].height, - GL_TEX_LIST[GL_BOUND_TEX].data, - GL_TEX_LIST[GL_BOUND_TEX].filter); - - GL_POLY_CXT.gen.shading = GL_SHADE_FUNC; - - if(GL_ENABLE_DEPTH_TEST) - GL_POLY_CXT.depth.comparison = GL_DEPTH_CMP; - else - GL_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS; - - GL_POLY_CXT.depth.write = GL_DEPTH_ENABLE; - - if(GL_ENABLE_SCISSOR) - GL_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE; - - if(GL_ENABLE_FOG) - GL_POLY_CXT.gen.fog_type = PVR_FOG_TABLE; - - if(GL_ENABLE_CULLING) { - if(GL_CULL_FUNC == GL_BACK) { - if(GL_FACE_FRONT == GL_CW) - GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; - else - GL_POLY_CXT.gen.culling = PVR_CULLING_CW; - } - else if(GL_CULL_FUNC == GL_FRONT) { - if(GL_FACE_FRONT == GL_CCW) - GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; - else - GL_POLY_CXT.gen.culling = PVR_CULLING_CW; - } - } - else - GL_POLY_CXT.gen.culling = PVR_CULLING_NONE; - - if(GL_CLAMP_ST == GL_CLAMP_UV) - GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_UV; - else if(GL_CLAMP_ST & GL_CLAMP_U) - GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_U; - else if(GL_CLAMP_ST & GL_CLAMP_V) - GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_V; - - GL_POLY_CXT.txr.mipmap = GL_TEX_LIST[GL_BOUND_TEX].level; - GL_POLY_CXT.txr.mipmap_bias = PVR_MIPBIAS_NORMAL; - - if(_glKosList()) { - GL_POLY_CXT.txr.env = GL_TEX_ENV; - GL_POLY_CXT.blend.src = BLEND_SRC; - GL_POLY_CXT.blend.dst = BLEND_DST; - } - - pvr_poly_compile(hdr, &GL_POLY_CXT); - - if(GL_ENABLE_SUPERSAMP) - hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT; - - _glKosVertexBufIncrement(); -} - - -void _glKosCompileHdrTx2() { - pvr_poly_hdr_t *hdr = _glKosTRVertexBufPointer(); - - pvr_poly_cxt_txr(&GL_POLY_CXT, 2, - GL_TEX_LIST[GL_BOUND_TEX1].format | - GL_TEX_LIST[GL_BOUND_TEX1].type, - GL_TEX_LIST[GL_BOUND_TEX1].width, - GL_TEX_LIST[GL_BOUND_TEX1].height, - GL_TEX_LIST[GL_BOUND_TEX1].data, - GL_TEX_LIST[GL_BOUND_TEX1].filter); - - GL_POLY_CXT.gen.shading = GL_SHADE_FUNC; - - if(GL_ENABLE_DEPTH_TEST) - GL_POLY_CXT.depth.comparison = GL_DEPTH_CMP; - else - GL_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS; - - GL_POLY_CXT.depth.write = GL_DEPTH_ENABLE; - - if(GL_ENABLE_SCISSOR) - GL_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE; - - if(GL_ENABLE_FOG) - GL_POLY_CXT.gen.fog_type = PVR_FOG_TABLE; - - if(GL_ENABLE_CULLING) { - if(GL_CULL_FUNC == GL_BACK) { - if(GL_FACE_FRONT == GL_CW) - GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; - else - GL_POLY_CXT.gen.culling = PVR_CULLING_CW; - } - else if(GL_CULL_FUNC == GL_FRONT) { - if(GL_FACE_FRONT == GL_CCW) - GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; - else - GL_POLY_CXT.gen.culling = PVR_CULLING_CW; - } - } - else - GL_POLY_CXT.gen.culling = PVR_CULLING_NONE; - - if(GL_CLAMP_ST == GL_CLAMP_UV) - GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_UV; - else if(GL_CLAMP_ST & GL_CLAMP_U) - GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_U; - else if(GL_CLAMP_ST & GL_CLAMP_V) - GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_V; - - GL_POLY_CXT.txr.mipmap = GL_TEX_LIST[GL_BOUND_TEX1].level; - GL_POLY_CXT.txr.mipmap_bias = PVR_MIPBIAS_NORMAL; - - GL_POLY_CXT.txr.env = GL_TEX_ENV; - GL_POLY_CXT.blend.src = BLEND_SRC; - GL_POLY_CXT.blend.dst = BLEND_DST; - - pvr_poly_compile(hdr, &GL_POLY_CXT); - - if(GL_ENABLE_SUPERSAMP) - hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT; - - _glKosTRVertexBufIncrement(); -} - -/* Vertex Color Submission */ - -void glColor1ui(GLuint argb) { - GL_VERTEX_COLOR = argb; -} - -void glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { - GL_VERTEX_COLOR = a << 24 | r << 16 | g << 8 | b; -} - -void glColor3f(float r, float g, float b) { - GL_VERTEX_COLOR = PVR_PACK_COLOR(1.0f, r, g, b); -} - -void glColor3fv(float *rgb) { - GL_VERTEX_COLOR = PVR_PACK_COLOR(1.0f, rgb[0], rgb[1], rgb[2]); -} - -void glColor4f(float r, float g, float b, float a) { - GL_VERTEX_COLOR = PVR_PACK_COLOR(a, r, g, b); -} - -void glColor4fv(float *rgba) { - GL_VERTEX_COLOR = PVR_PACK_COLOR(rgba[3], rgba[0], rgba[1], rgba[2]); -} - -/* Texture Coordinate Submission */ - -void glTexCoord2f(GLfloat u, GLfloat v) { - GL_VERTEX_UV[0] = u; - GL_VERTEX_UV[1] = v; -} - -void glTexCoord2fv(GLfloat *uv) { - GL_VERTEX_UV[0] = uv[0]; - GL_VERTEX_UV[1] = uv[1]; -} - -void glMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) { - switch(target) { - case GL_TEXTURE0: - GL_VERTEX_UV[0] = s; - GL_VERTEX_UV[1] = t; - break; - - case GL_TEXTURE1: - GL_MULTI_UV[GL_VERTICES].u = s; - GL_MULTI_UV[GL_VERTICES].v = t; - break; - } -} - -void glMultiTexCoord2fv(GLenum target, const GLfloat *v) { - switch(target) { - case GL_TEXTURE0: - GL_VERTEX_UV[0] = v[0]; - GL_VERTEX_UV[1] = v[1]; - break; - - case GL_TEXTURE1: - GL_MULTI_UV[GL_VERTICES].u = v[0]; - GL_MULTI_UV[GL_VERTICES].v = v[1]; - break; - } -} - -static inline void _glKosMultiTexCoord(pvr_vertex_t *v, GLuint count) { - GLuint i; - - for(i = 0; i < count; i++) { - v[i].u = GL_MULTI_UV[i].u; - v[i].v = GL_MULTI_UV[i].v; - } -} - -static inline void _glKosMultiTexCoordQuads(pvr_vertex_t *v, GLuint count) { - GLuint i; - - for(i = 0; i < count / 4; i += 4) { - v[i + 0].u = GL_MULTI_UV[i + 0].u; - v[i + 0].v = GL_MULTI_UV[i + 0].v; - v[i + 1].u = GL_MULTI_UV[i + 1].u; - v[i + 1].v = GL_MULTI_UV[i + 1].v; - v[i + 2].u = GL_MULTI_UV[i + 3].u; - v[i + 2].v = GL_MULTI_UV[i + 3].v; - v[i + 3].u = GL_MULTI_UV[i + 2].u; - v[i + 3].v = GL_MULTI_UV[i + 2].v; - } -} - -/* Vertex Submission */ - -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_VERTICES; - GLuint i; - - for(i = 0; i < GL_VERTICES; 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_VERTICES; - GLuint i; - - for(i = 0; i < GL_VERTICES; 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_VERTICES; - GLuint i; - - for(i = 0; i < GL_VERTICES - 1; i++) { - v->flags = PVR_CMD_VERTEX; - v++; - } - - v->flags = PVR_CMD_VERTEX_EOL; -} - -void glBegin(unsigned int mode) { - _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ - - _glKosArrayBufReset(); /* Make sure arrays buffer is reset */ - - GL_VERTEX_MODE = mode; - - GL_BOUND_TEX < 0 ? _glKosCompileHdr() : _glKosCompileHdrTx(); - - if(GL_TEXTURE_ENABLED & GL_TEXTURE_1) - _glKosCompileHdrTx2(); - - GL_VERTICES = 0; - - if(mode == GL_POINTS) { - glVertex3f = _glKosVertex3fp; - glVertex3fv = _glKosVertex3fpv; - } - else if(GL_ENABLE_CLIPZ && GL_ENABLE_LIGHTING) { - glVertex3f = _glKosVertex3flc; - glVertex3fv = _glKosVertex3flcv; - } - else if(GL_ENABLE_LIGHTING) { - glVertex3f = _glKosVertex3fl; - glVertex3fv = _glKosVertex3flv; - } - else if(GL_ENABLE_CLIPZ) { - glVertex3f = _glKosVertex3fc; - glVertex3fv = _glKosVertex3fcv; - } - else { - glVertex3f = _glKosVertex3ft; - glVertex3fv = _glKosVertex3ftv; - } -} - -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 _glKosCopyMultiTexture(pvr_vertex_t *v, GLuint count) { - if(GL_TEXTURE_ENABLED & GL_TEXTURE_1) { - _glKosVertexBufCopy(_glKosTRVertexBufPointer(), v, count); - - if(GL_VERTEX_MODE == GL_QUADS) - _glKosMultiTexCoordQuads(_glKosTRVertexBufPointer(), count); - else - _glKosMultiTexCoord(_glKosTRVertexBufPointer(), count); - - _glKosTRVertexBufAdd(count); - } -} - -void glEnd() { - if(GL_ENABLE_CLIPZ) { /* Z-Clipping Enabled */ - if(GL_ENABLE_LIGHTING) { - _glKosVertexComputeLighting(_glKosClipBufAddress(), GL_VERTICES); - - _glKosMatrixLoadRender(); - } - - GLuint cverts; - pvr_vertex_t *v = _glKosVertexBufPointer(); - - switch(GL_VERTEX_MODE) { - case GL_TRIANGLES: - cverts = _glKosClipTriangles(_glKosClipBufAddress(), v, GL_VERTICES); - _glKosTransformClipBuf(v, cverts); - _glKosCopyMultiTexture(v, cverts); - _glKosVertexBufAdd(cverts); - break; - - case GL_TRIANGLE_STRIP: - cverts = _glKosClipTriangleStrip(_glKosClipBufAddress(), v, GL_VERTICES); - _glKosTransformClipBuf(v, cverts); - _glKosCopyMultiTexture(v, cverts); - _glKosVertexBufAdd(cverts); - break; - - case GL_QUADS: - cverts = _glKosClipQuads(_glKosClipBufAddress(), v, GL_VERTICES); - _glKosTransformClipBuf(v, cverts); - _glKosCopyMultiTexture(v, cverts); - _glKosVertexBufAdd(cverts); - break; - } - - _glKosClipBufReset(); - } - else { /* No Z-Clipping Enabled */ - if(GL_ENABLE_LIGHTING) - _glKosVertexComputeLighting((pvr_vertex_t *)_glKosVertexBufPointer() - GL_VERTICES, GL_VERTICES); - - switch(GL_VERTEX_MODE) { - case GL_TRIANGLES: - _glKosFlagsSetTriangle(); - break; - - case GL_TRIANGLE_STRIP: - _glKosFlagsSetTriangleStrip(); - break; - - case GL_QUADS: - _glKosFlagsSetQuad(); - break; - } - - _glKosCopyMultiTexture((pvr_vertex_t *)_glKosVertexBufPointer() - GL_VERTICES, GL_VERTICES); - } -} - -void glVertex2f(GLfloat x, GLfloat y) { - return _glKosVertex3ft(x, y, 0.0f); -} - -void glVertex2fv(GLfloat *xy) { - return _glKosVertex3ft(xy[0], xy[1], 0.0f); -} - -void glKosVertex2f(GLfloat x, GLfloat y) { - pvr_vertex_t *v = _glKosVertexBufPointer(); - - v->x = x; - v->y = y; - v->z = 10; - v->u = GL_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosVertexBufIncrement(); - - ++GL_VERTICES; -} - -void glKosVertex2fv(GLfloat *xy) { - pvr_vertex_t *v = _glKosVertexBufPointer(); - - v->x = xy[0]; - v->y = xy[1]; - v->z = 10; - v->u = GL_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosVertexBufIncrement(); - - ++GL_VERTICES; -} - -void _glKosVertex3fs(float x, float y, float z) { - pvr_vertex_t *v = _glKosVertexBufPointer(); - - mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); - - v->u = GL_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosVertexBufIncrement(); - - ++GL_VERTICES; -} - -void _glKosVertex3fsv(float *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_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosVertexBufIncrement(); - - ++GL_VERTICES; -} - -void _glKosVertex3ft(float x, float y, float z) { - pvr_vertex_t *v = _glKosVertexBufPointer(); - - mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); - - v->u = GL_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosVertexBufIncrement(); - - ++GL_VERTICES; -} - -void _glKosVertex3ftv(float *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_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosVertexBufIncrement(); - - ++GL_VERTICES; -} - -void _glKosVertex3fc(float x, float y, float z) { - pvr_vertex_t *v = _glKosClipBufPointer(); - - v->x = x; - v->y = y; - v->z = z; - v->u = GL_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosClipBufIncrement(); - - ++GL_VERTICES; -} - -void _glKosVertex3fcv(float *xyz) { - pvr_vertex_t *v = _glKosClipBufPointer(); - - v->x = xyz[0]; - v->y = xyz[1]; - v->z = xyz[2]; - v->u = GL_VERTEX_UV[0]; - v->v = GL_VERTEX_UV[1]; - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - - _glKosClipBufIncrement(); - - ++GL_VERTICES; -} - -/* GL_POINTS */ -static float GL_POINT_SIZE = 0.02; - -inline void _glKosVertex3fpa(float x, float y, float z) { - pvr_vertex_t *v = _glKosVertexBufPointer(); - - mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); - - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - v->flags = PVR_CMD_VERTEX; - - _glKosVertexBufIncrement(); -} - -inline void _glKosVertex3fpb(float x, float y, float z) { - pvr_vertex_t *v = _glKosVertexBufPointer(); - - mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); - - v->argb = GL_VERTEX_COLOR; - //v->oargb = GL_VERTEX_SPECULAR; - v->flags = PVR_CMD_VERTEX_EOL; - - _glKosVertexBufIncrement(); -} - -void _glKosVertex3fp(float x, float y, float z) { - _glKosVertex3fpa(x - GL_POINT_SIZE, y - GL_POINT_SIZE, z); - _glKosVertex3fpa(x + GL_POINT_SIZE, y - GL_POINT_SIZE, z); - _glKosVertex3fpa(x - GL_POINT_SIZE, y + GL_POINT_SIZE, z); - _glKosVertex3fpb(x + GL_POINT_SIZE, y + GL_POINT_SIZE, z); -} - -void _glKosVertex3fpv(float *xyz) { - _glKosVertex3fpa(xyz[0] - GL_POINT_SIZE, xyz[1] - GL_POINT_SIZE, xyz[2]); - _glKosVertex3fpa(xyz[0] + GL_POINT_SIZE, xyz[1] - GL_POINT_SIZE, xyz[2]); - _glKosVertex3fpa(xyz[0] - GL_POINT_SIZE, xyz[1] + GL_POINT_SIZE, xyz[2]); - _glKosVertex3fpb(xyz[0] + GL_POINT_SIZE, xyz[1] + GL_POINT_SIZE, xyz[2]); -} - -/* 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 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 glHint(GLenum target, GLenum mode) { - switch(target) { - case GL_PERSPECTIVE_CORRECTION_HINT: - if(mode == GL_NICEST) - GL_ENABLE_SUPERSAMP = 1; - else - GL_ENABLE_SUPERSAMP = 0; - - break; - } -} - -GLint _glKosEnabledTexture2D() { - return GL_TEXTURE_ENABLED; -} - -GLubyte _glKosEnabledNearZClip() { - return GL_ENABLE_CLIPZ; -} - -GLubyte _glKosEnabledLighting() { - return GL_ENABLE_LIGHTING; -} - -inline void _glKosResetEnabledTex() { - GL_TEXTURE_ENABLED = GL_CUR_ACTIVE_TEX = 0; -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-api.c + Copyright (C) 2013-2014 Josh "PH3NOM" 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 +#include +#include + +#include "gl.h" +#include "glu.h" +#include "gl-api.h" +#include "gl-sh4.h" +#include "gl-pvr.h" + +/* Texture Submission Functions ************************************************************************/ +/* The texutre sumbission uses a fixed-size buffer, that defaults to 1024 textures. + That means that you must manage your texture submission by calling glDelTextures(...) + when you are done using a texture that was created by glGenTextures(...). + The size of the texture buffer can be controlled by setting GL_MAX_TEXTURES on gl-pvr.h. + + glTexImage2D(..) is used for loading texture data to OpenGL that is located in Main RAM: + OpenGL will allocate VRAM for the texture, and copy the texture data from Main RAM to VRAM. + + glKosTexImage2D(...) is used for loading texture data to OpenGL that is already in VRAM: + This mode must be used for a render-to-texture if you are using glutSwapBuffersToTexture(). +*/ + +typedef struct { + GLenum target; + GLint level; + GLint border; + GLenum format; + GLenum type; + GLint filter, env; + GLuint width, height; + GLuint internalFormat; + GLvoid *data; +} glTexCxt; + +static glTexCxt GL_TEX_LIST[GL_MAX_TEXTURES]; +static GLint GL_BOUND_TEX = -1, GL_LAST_BOUND_TEX = -1, + GL_BOUND_TEX1 = -1, GL_LAST_BOUND_TEX1 = -1; + +static GLubyte BLEND_SRC = PVR_BLEND_ONE; +static GLubyte BLEND_DST = PVR_BLEND_ZERO; + +static GLubyte GL_SHADE_FUNC = PVR_SHADE_GOURAUD; + +static GLubyte GL_CULL_FUNC = PVR_CULLING_NONE; + +static GLubyte GL_DEPTH_CMP = PVR_DEPTHCMP_GEQUAL; +static GLubyte GL_DEPTH_ENABLE = PVR_DEPTHWRITE_ENABLE; + +static GLubyte GL_TEX_ENV = PVR_TXRENV_MODULATEALPHA; + +static GLubyte GL_ENABLE_CLIPZ = 0; +static GLubyte GL_ENABLE_LIGHTING = 0; +static GLubyte GL_ENABLE_SCISSOR = 0; +static GLubyte GL_ENABLE_FOG = 0; +static GLubyte GL_ENABLE_CULLING = 0; +static GLubyte GL_ENABLE_DEPTH_TEST = 0; +static GLubyte GL_ENABLE_SUPERSAMP = 0; + +static GLubyte GL_FACE_FRONT = 0; +static GLubyte GL_CLAMP_ST = 0; + +/* Primitive 3D Position Submission */ +void (*glVertex3f)(float, float, float); +void (*glVertex3fv)(float *); + +#define GL_CLAMP_U 0x0F +#define GL_CLAMP_V 0xF0 +#define GL_CLAMP_UV 0xFF + +#define GL_TEXTURE_0 1<<0 +#define GL_TEXTURE_1 1<<1 + +static GLuint GL_TEXTURE_ENABLED = 0; +static GLuint GL_CUR_ACTIVE_TEX = 0; + +void glActiveTexture(GLenum texture) { + if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + GL_MAX_TEXTURE_UNITS) + return; + + GL_CUR_ACTIVE_TEX = ((texture & 0xFF) - (GL_TEXTURE0 & 0xFF)); +} + +void glBindTexture(GLenum target, GLuint texture) { + if(target == GL_TEXTURE_2D) { + switch(GL_CUR_ACTIVE_TEX) { + case 0: + GL_BOUND_TEX = texture; + GL_LAST_BOUND_TEX = GL_BOUND_TEX; + break; + + case 1: + GL_BOUND_TEX1 = texture; + GL_LAST_BOUND_TEX1 = GL_BOUND_TEX1; + break; + } + } +} + +void glGetIntegerv(GLenum pname, GLint *params) { + switch(pname) { + case GL_ACTIVE_TEXTURE: + *params = GL_CUR_ACTIVE_TEX; + break; + + case GL_BLEND: + *params = _glKosList(); + break; + + case GL_BLEND_DST: + *params = BLEND_SRC; + break; + + case GL_BLEND_SRC: + *params = BLEND_DST; + break; + + case GL_CULL_FACE: + *params = GL_ENABLE_CULLING; + break; + + case GL_CULL_FACE_MODE: + *params = GL_CULL_FUNC; + break; + + case GL_DEPTH_FUNC: + *params = GL_DEPTH_CMP; + break; + + case GL_DEPTH_TEST: + *params = GL_ENABLE_DEPTH_TEST; + break; + + case GL_DEPTH_WRITEMASK: + *params = GL_DEPTH_ENABLE; + break; + + case GL_FRONT_FACE: + *params = GL_FACE_FRONT; + break; + + case GL_SCISSOR_TEST: + *params = GL_ENABLE_SCISSOR; + break; + + default: + *params = -1; // Indicate invalid parameter // + break; + } +} + +void 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: + *params = (GLfloat)GL_INVALID_ENUM; + break; + } +} + +static void _glKosInitTextures() { + GLuint i; + + for(i = 0; i < GL_MAX_TEXTURES; i++) + GL_TEX_LIST[i].data = NULL; +} + +static GLuint _glKosNextTexture() { + GLint i; + + for(i = 0; i < GL_MAX_TEXTURES; i++) + if(GL_TEX_LIST[i].data == NULL) + return i; + + return 0; /* Invalid Texture! */ +} + +GLuint 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; +} + +void glGenTextures(GLsizei n, GLuint *textures) { + while(n--) + *textures++ = _glKosNextTexture(); +} + +void glDelTextures(GLsizei n, GLuint *textures) { + while(n--) { + if(GL_TEX_LIST[*textures].data != NULL) { + pvr_mem_free(GL_TEX_LIST[*textures].data); + GL_TEX_LIST[*textures].data = NULL; + } + + textures++; + } +} + +void glTexImage2D(GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, GLvoid *data) { + if(target != GL_TEXTURE_2D) return; + + GL_TEX_LIST[GL_BOUND_TEX].target = target; + GL_TEX_LIST[GL_BOUND_TEX].level = level; + GL_TEX_LIST[GL_BOUND_TEX].border = border; + GL_TEX_LIST[GL_BOUND_TEX].format = format; + GL_TEX_LIST[GL_BOUND_TEX].type = type; + + GLuint bytes; + + if(!level) + bytes = width * height * 2; + else + bytes = glKosMipMapTexSize(width, height); + + if(format == PVR_TXRFMT_VQ_ENABLE) + bytes /= 4; + + GL_TEX_LIST[GL_BOUND_TEX].data = pvr_mem_malloc(bytes); + + GL_TEX_LIST[GL_BOUND_TEX].width = width; + GL_TEX_LIST[GL_BOUND_TEX].height = height; + GL_TEX_LIST[GL_BOUND_TEX].internalFormat = internalFormat; + + GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NONE; + + sq_cpy(GL_TEX_LIST[GL_BOUND_TEX].data, data, bytes); +} + +void glKosTexImage2D(GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, GLvoid *data) { + if(target != GL_TEXTURE_2D) return; + + GL_TEX_LIST[GL_BOUND_TEX].target = target; + GL_TEX_LIST[GL_BOUND_TEX].level = level; + GL_TEX_LIST[GL_BOUND_TEX].border = border; + GL_TEX_LIST[GL_BOUND_TEX].format = format; + GL_TEX_LIST[GL_BOUND_TEX].type = type; + + GL_TEX_LIST[GL_BOUND_TEX].data = data; + + GL_TEX_LIST[GL_BOUND_TEX].width = width; + GL_TEX_LIST[GL_BOUND_TEX].height = height; + GL_TEX_LIST[GL_BOUND_TEX].internalFormat = internalFormat; + + GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NONE; +} + +void glTexParameteri(GLenum target, GLenum pname, GLint param) { + if(target == GL_TEXTURE_2D) { + switch(pname) { + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_MIN_FILTER: + switch(param) { + case GL_LINEAR: + GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_BILINEAR; + break; + + case GL_NEAREST: + GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NEAREST; + break; + + case GL_FILTER_NONE: /* Compatabile with deprecated kgl */ + GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_NONE; + break; + + case GL_FILTER_BILINEAR: /* Compatabile with deprecated kgl */ + GL_TEX_LIST[GL_BOUND_TEX].filter = PVR_FILTER_BILINEAR; + break; + + case GL_NEAREST_MIPMAP_NEAREST: + GL_TEX_LIST[GL_BOUND_TEX].level = PVR_MIPMAP_ENABLE; + break; + + default: + break; + } + + break; + + case GL_TEXTURE_WRAP_S: + switch(param) { + case GL_CLAMP: + GL_CLAMP_ST |= GL_CLAMP_U; + break; + + case GL_REPEAT: + GL_CLAMP_ST ^= GL_CLAMP_U; + break; + } + + break; + + case GL_TEXTURE_WRAP_T: + switch(param) { + case GL_CLAMP: + GL_CLAMP_ST |= GL_CLAMP_V; + break; + + case GL_REPEAT: + GL_CLAMP_ST ^= GL_CLAMP_V; + break; + } + + break; + } + } +} + +void glTexEnvi(GLenum target, GLenum pname, GLint param) { + if(target == GL_TEXTURE_ENV) + if(pname == GL_TEXTURE_ENV_MODE) + if(param >= PVR_TXRENV_REPLACE && param <= PVR_TXRENV_MODULATEALPHA) + GL_TEX_ENV = param; +} + +void glTexEnvf(GLenum target, GLenum pname, GLfloat param) { + /* GL_TEXTURE_LOD_BIAS Not Implemented */ + glTexEnvi(target, pname, param); +} + +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: + 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 gluBuild2DMipmaps(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; + + 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: + 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)); +} + +/* Blending / Shading functions ********************************************************/ + +void glShadeModel(GLenum mode) { + switch(mode) { + case GL_FLAT: + GL_SHADE_FUNC = PVR_SHADE_FLAT; + break; + + case GL_SMOOTH: + GL_SHADE_FUNC = PVR_SHADE_GOURAUD; + break; + } +} + +void glBlendFunc(GLenum sfactor, GLenum dfactor) { + switch(sfactor) { + case GL_ONE: + BLEND_SRC = PVR_BLEND_ONE; + break; + + case GL_ZERO: + BLEND_SRC = PVR_BLEND_ZERO; + break; + + case GL_SRC_COLOR: + BLEND_SRC = PVR_BLEND_SRCALPHA; + break; + + case GL_DST_COLOR: + BLEND_SRC = PVR_BLEND_DESTCOLOR; + break; + + case GL_SRC_ALPHA: + BLEND_SRC = PVR_BLEND_SRCALPHA; + break; + + case GL_DST_ALPHA: + BLEND_SRC = PVR_BLEND_DESTALPHA; + break; + + case GL_ONE_MINUS_SRC_ALPHA: + BLEND_SRC = PVR_BLEND_INVSRCALPHA; + break; + + case GL_ONE_MINUS_DST_ALPHA: + BLEND_SRC = PVR_BLEND_INVDESTALPHA; + break; + + case GL_ONE_MINUS_DST_COLOR: + BLEND_SRC = PVR_BLEND_INVDESTCOLOR; + break; + } + + switch(dfactor) { + case GL_ONE: + BLEND_DST = PVR_BLEND_ONE; + break; + + case GL_ZERO: + BLEND_DST = PVR_BLEND_ZERO; + break; + + case GL_SRC_COLOR: + BLEND_DST = PVR_BLEND_SRCALPHA; + break; + + case GL_DST_COLOR: + BLEND_DST = PVR_BLEND_DESTCOLOR; + break; + + case GL_SRC_ALPHA: + BLEND_DST = PVR_BLEND_SRCALPHA; + break; + + case GL_DST_ALPHA: + BLEND_DST = PVR_BLEND_DESTALPHA; + break; + + case GL_ONE_MINUS_SRC_ALPHA: + BLEND_DST = PVR_BLEND_INVSRCALPHA; + break; + + case GL_ONE_MINUS_DST_ALPHA: + BLEND_DST = PVR_BLEND_INVDESTALPHA; + break; + + case GL_ONE_MINUS_DST_COLOR: + BLEND_DST = PVR_BLEND_INVDESTCOLOR; + break; + } +} + +/* Depth / Clear functions */ +static GLfloat GL_DEPTH_CLEAR = 1.0f, + GL_COLOR_CLEAR[3] = { 0, 0, 0 }; + +void glClear(GLuint mode) { + if(mode & GL_COLOR_BUFFER_BIT) + pvr_set_bg_color(GL_COLOR_CLEAR[0], GL_COLOR_CLEAR[1], GL_COLOR_CLEAR[2]); +} + +void 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_COLOR_CLEAR[0] = r * a; + GL_COLOR_CLEAR[1] = g * a; + GL_COLOR_CLEAR[2] = b * a; +} + +void glClearDepthf(GLfloat depth) { + GL_DEPTH_CLEAR = depth; +} + +void glDepthFunc(GLenum func) { + switch(func) { + case GL_LESS: + GL_DEPTH_CMP = PVR_DEPTHCMP_GEQUAL; + break; + + case GL_LEQUAL: + GL_DEPTH_CMP = PVR_DEPTHCMP_GREATER; + break; + + case GL_GREATER: + GL_DEPTH_CMP = PVR_DEPTHCMP_LEQUAL; + break; + + case GL_GEQUAL: + GL_DEPTH_CMP = PVR_DEPTHCMP_LESS; + break; + + default: + GL_DEPTH_CMP = func & 0xF; + } +} + +void glDepthMask(GLboolean flag) { + flag ? (GL_DEPTH_ENABLE = PVR_DEPTHWRITE_ENABLE) : + (GL_DEPTH_ENABLE = PVR_DEPTHWRITE_DISABLE); +} + +void glFrontFace(GLenum mode) { + switch(mode) { + case GL_CW: + case GL_CCW: + GL_FACE_FRONT = mode; + break; + } +} + +void glCullFace(GLenum mode) { + switch(mode) { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + GL_CULL_FUNC = mode; + break; + } +} + +/* glEnable / glDisable ****************************************************************/ + +void glEnable(GLenum cap) { + if(cap >= GL_LIGHT0 && cap <= GL_LIGHT7) return _glKosEnableLight(cap); + + switch(cap) { + case GL_TEXTURE_2D: + GL_TEXTURE_ENABLED |= (1 << GL_CUR_ACTIVE_TEX); + break; + + case GL_BLEND: + _glKosVertexBufSwitchTR(); + break; + + case GL_DEPTH_TEST: + GL_ENABLE_DEPTH_TEST = 1; + break; + + case GL_LIGHTING: + GL_ENABLE_LIGHTING = 1; + break; + + case GL_KOS_NEARZ_CLIPPING: + GL_ENABLE_CLIPZ = 1; + break; + + case GL_SCISSOR_TEST: + GL_ENABLE_SCISSOR = 1; + break; + + case GL_FOG: + GL_ENABLE_FOG = 1; + break; + + case GL_CULL_FACE: + GL_ENABLE_CULLING = 1; + break; + } +} + +void glDisable(GLenum cap) { + if(cap >= GL_LIGHT0 && cap <= GL_LIGHT7) return _glKosDisableLight(cap); + + switch(cap) { + case GL_TEXTURE_2D: + GL_TEXTURE_ENABLED &= ~(1 << GL_CUR_ACTIVE_TEX); + break; + + case GL_BLEND: + _glKosVertexBufSwitchOP(); + break; + + case GL_DEPTH_TEST: + GL_ENABLE_DEPTH_TEST = 0; + break; + + case GL_LIGHTING: + GL_ENABLE_LIGHTING = 0; + break; + + case GL_KOS_NEARZ_CLIPPING: + GL_ENABLE_CLIPZ = 0; + break; + + case GL_SCISSOR_TEST: + GL_ENABLE_SCISSOR = 0; + break; + + case GL_FOG: + GL_ENABLE_FOG = 0; + break; + + case GL_CULL_FACE: + GL_ENABLE_CULLING = 0; + break; + } +} + +/* Vertex Submission Functions *************************************************************************/ +static GLuint GL_VERTICES = 0, + GL_VERTEX_MODE = GL_TRIANGLES; +static GLuint GL_VERTEX_COLOR = 0xFFFFFFFF; +//static GLuint GL_VERTEX_SPECULAR = 0xFF000000; +static GLfloat GL_VERTEX_UV[2] = {0, 0}; + +typedef struct { + GLfloat u; + GLfloat v; +} TexCoord; + +static TexCoord GL_MULTI_UV[GL_MAX_VERTS]; + +static pvr_poly_cxt_t GL_POLY_CXT; + +void glKosInit() { + _glKosInitPVR(); + + _glKosInitTextures(); + + _glKosInitMatrix(); + + _glKosInitLighting(); +} + +void _glKosCompileHdr() { + pvr_poly_hdr_t *hdr = _glKosVertexBufPointer(); + + /* Non-textured pvr poly header */ + pvr_poly_cxt_col(&GL_POLY_CXT, _glKosList() * 2); + + GL_POLY_CXT.gen.shading = GL_SHADE_FUNC; + + if(GL_ENABLE_DEPTH_TEST) + GL_POLY_CXT.depth.comparison = GL_DEPTH_CMP; + else + GL_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS; + + GL_POLY_CXT.depth.write = GL_DEPTH_ENABLE; + + if(GL_ENABLE_SCISSOR) + GL_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE; + + if(GL_ENABLE_FOG) + GL_POLY_CXT.gen.fog_type = PVR_FOG_TABLE; + + if(GL_ENABLE_CULLING) { + if(GL_CULL_FUNC == GL_BACK) { + if(GL_FACE_FRONT == GL_CW) + GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; + else + GL_POLY_CXT.gen.culling = PVR_CULLING_CW; + } + else if(GL_CULL_FUNC == GL_FRONT) { + if(GL_FACE_FRONT == GL_CCW) + GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; + else + GL_POLY_CXT.gen.culling = PVR_CULLING_CW; + } + } + else + GL_POLY_CXT.gen.culling = PVR_CULLING_NONE; + + pvr_poly_compile(hdr, &GL_POLY_CXT); + + if(GL_ENABLE_SUPERSAMP) + hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT; + + _glKosVertexBufIncrement(); +} + +void _glKosCompileHdrTx() { + pvr_poly_hdr_t *hdr = _glKosVertexBufPointer(); + + pvr_poly_cxt_txr(&GL_POLY_CXT, _glKosList() * 2, + GL_TEX_LIST[GL_BOUND_TEX].format | + GL_TEX_LIST[GL_BOUND_TEX].type, + GL_TEX_LIST[GL_BOUND_TEX].width, + GL_TEX_LIST[GL_BOUND_TEX].height, + GL_TEX_LIST[GL_BOUND_TEX].data, + GL_TEX_LIST[GL_BOUND_TEX].filter); + + GL_POLY_CXT.gen.shading = GL_SHADE_FUNC; + + if(GL_ENABLE_DEPTH_TEST) + GL_POLY_CXT.depth.comparison = GL_DEPTH_CMP; + else + GL_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS; + + GL_POLY_CXT.depth.write = GL_DEPTH_ENABLE; + + if(GL_ENABLE_SCISSOR) + GL_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE; + + if(GL_ENABLE_FOG) + GL_POLY_CXT.gen.fog_type = PVR_FOG_TABLE; + + if(GL_ENABLE_CULLING) { + if(GL_CULL_FUNC == GL_BACK) { + if(GL_FACE_FRONT == GL_CW) + GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; + else + GL_POLY_CXT.gen.culling = PVR_CULLING_CW; + } + else if(GL_CULL_FUNC == GL_FRONT) { + if(GL_FACE_FRONT == GL_CCW) + GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; + else + GL_POLY_CXT.gen.culling = PVR_CULLING_CW; + } + } + else + GL_POLY_CXT.gen.culling = PVR_CULLING_NONE; + + if(GL_CLAMP_ST == GL_CLAMP_UV) + GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_UV; + else if(GL_CLAMP_ST & GL_CLAMP_U) + GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_U; + else if(GL_CLAMP_ST & GL_CLAMP_V) + GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_V; + + GL_POLY_CXT.txr.mipmap = GL_TEX_LIST[GL_BOUND_TEX].level; + GL_POLY_CXT.txr.mipmap_bias = PVR_MIPBIAS_NORMAL; + + if(_glKosList()) { + GL_POLY_CXT.txr.env = GL_TEX_ENV; + GL_POLY_CXT.blend.src = BLEND_SRC; + GL_POLY_CXT.blend.dst = BLEND_DST; + } + + pvr_poly_compile(hdr, &GL_POLY_CXT); + + if(GL_ENABLE_SUPERSAMP) + hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT; + + _glKosVertexBufIncrement(); +} + + +void _glKosCompileHdrTx2() { + pvr_poly_hdr_t *hdr = _glKosTRVertexBufPointer(); + + pvr_poly_cxt_txr(&GL_POLY_CXT, 2, + GL_TEX_LIST[GL_BOUND_TEX1].format | + GL_TEX_LIST[GL_BOUND_TEX1].type, + GL_TEX_LIST[GL_BOUND_TEX1].width, + GL_TEX_LIST[GL_BOUND_TEX1].height, + GL_TEX_LIST[GL_BOUND_TEX1].data, + GL_TEX_LIST[GL_BOUND_TEX1].filter); + + GL_POLY_CXT.gen.shading = GL_SHADE_FUNC; + + if(GL_ENABLE_DEPTH_TEST) + GL_POLY_CXT.depth.comparison = GL_DEPTH_CMP; + else + GL_POLY_CXT.depth.comparison = PVR_DEPTHCMP_ALWAYS; + + GL_POLY_CXT.depth.write = GL_DEPTH_ENABLE; + + if(GL_ENABLE_SCISSOR) + GL_POLY_CXT.gen.clip_mode = PVR_USERCLIP_INSIDE; + + if(GL_ENABLE_FOG) + GL_POLY_CXT.gen.fog_type = PVR_FOG_TABLE; + + if(GL_ENABLE_CULLING) { + if(GL_CULL_FUNC == GL_BACK) { + if(GL_FACE_FRONT == GL_CW) + GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; + else + GL_POLY_CXT.gen.culling = PVR_CULLING_CW; + } + else if(GL_CULL_FUNC == GL_FRONT) { + if(GL_FACE_FRONT == GL_CCW) + GL_POLY_CXT.gen.culling = PVR_CULLING_CCW; + else + GL_POLY_CXT.gen.culling = PVR_CULLING_CW; + } + } + else + GL_POLY_CXT.gen.culling = PVR_CULLING_NONE; + + if(GL_CLAMP_ST == GL_CLAMP_UV) + GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_UV; + else if(GL_CLAMP_ST & GL_CLAMP_U) + GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_U; + else if(GL_CLAMP_ST & GL_CLAMP_V) + GL_POLY_CXT.txr.uv_clamp = PVR_UVCLAMP_V; + + GL_POLY_CXT.txr.mipmap = GL_TEX_LIST[GL_BOUND_TEX1].level; + GL_POLY_CXT.txr.mipmap_bias = PVR_MIPBIAS_NORMAL; + + GL_POLY_CXT.txr.env = GL_TEX_ENV; + GL_POLY_CXT.blend.src = BLEND_SRC; + GL_POLY_CXT.blend.dst = BLEND_DST; + + pvr_poly_compile(hdr, &GL_POLY_CXT); + + if(GL_ENABLE_SUPERSAMP) + hdr->mode2 |= GL_PVR_SAMPLE_SUPER << PVR_TA_SUPER_SAMPLE_SHIFT; + + _glKosTRVertexBufIncrement(); +} + +/* Vertex Color Submission */ + +void glColor1ui(GLuint argb) { + GL_VERTEX_COLOR = argb; +} + +void glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { + GL_VERTEX_COLOR = a << 24 | r << 16 | g << 8 | b; +} + +void glColor3f(float r, float g, float b) { + GL_VERTEX_COLOR = PVR_PACK_COLOR(1.0f, r, g, b); +} + +void glColor3fv(float *rgb) { + GL_VERTEX_COLOR = PVR_PACK_COLOR(1.0f, rgb[0], rgb[1], rgb[2]); +} + +void glColor4f(float r, float g, float b, float a) { + GL_VERTEX_COLOR = PVR_PACK_COLOR(a, r, g, b); +} + +void glColor4fv(float *rgba) { + GL_VERTEX_COLOR = PVR_PACK_COLOR(rgba[3], rgba[0], rgba[1], rgba[2]); +} + +/* Texture Coordinate Submission */ + +void glTexCoord2f(GLfloat u, GLfloat v) { + GL_VERTEX_UV[0] = u; + GL_VERTEX_UV[1] = v; +} + +void glTexCoord2fv(GLfloat *uv) { + GL_VERTEX_UV[0] = uv[0]; + GL_VERTEX_UV[1] = uv[1]; +} + +void glMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) { + switch(target) { + case GL_TEXTURE0: + GL_VERTEX_UV[0] = s; + GL_VERTEX_UV[1] = t; + break; + + case GL_TEXTURE1: + GL_MULTI_UV[GL_VERTICES].u = s; + GL_MULTI_UV[GL_VERTICES].v = t; + break; + } +} + +void glMultiTexCoord2fv(GLenum target, const GLfloat *v) { + switch(target) { + case GL_TEXTURE0: + GL_VERTEX_UV[0] = v[0]; + GL_VERTEX_UV[1] = v[1]; + break; + + case GL_TEXTURE1: + GL_MULTI_UV[GL_VERTICES].u = v[0]; + GL_MULTI_UV[GL_VERTICES].v = v[1]; + break; + } +} + +static inline void _glKosMultiTexCoord(pvr_vertex_t *v, GLuint count) { + GLuint i; + + for(i = 0; i < count; i++) { + v[i].u = GL_MULTI_UV[i].u; + v[i].v = GL_MULTI_UV[i].v; + } +} + +static inline void _glKosMultiTexCoordQuads(pvr_vertex_t *v, GLuint count) { + GLuint i; + + for(i = 0; i < count / 4; i += 4) { + v[i + 0].u = GL_MULTI_UV[i + 0].u; + v[i + 0].v = GL_MULTI_UV[i + 0].v; + v[i + 1].u = GL_MULTI_UV[i + 1].u; + v[i + 1].v = GL_MULTI_UV[i + 1].v; + v[i + 2].u = GL_MULTI_UV[i + 3].u; + v[i + 2].v = GL_MULTI_UV[i + 3].v; + v[i + 3].u = GL_MULTI_UV[i + 2].u; + v[i + 3].v = GL_MULTI_UV[i + 2].v; + } +} + +/* Vertex Submission */ + +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_VERTICES; + GLuint i; + + for(i = 0; i < GL_VERTICES; 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_VERTICES; + GLuint i; + + for(i = 0; i < GL_VERTICES; 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_VERTICES; + GLuint i; + + for(i = 0; i < GL_VERTICES - 1; i++) { + v->flags = PVR_CMD_VERTEX; + v++; + } + + v->flags = PVR_CMD_VERTEX_EOL; +} + +void glBegin(unsigned int mode) { + _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ + + _glKosArrayBufReset(); /* Make sure arrays buffer is reset */ + + GL_VERTEX_MODE = mode; + + GL_BOUND_TEX < 0 ? _glKosCompileHdr() : _glKosCompileHdrTx(); + + if(GL_TEXTURE_ENABLED & GL_TEXTURE_1) + _glKosCompileHdrTx2(); + + GL_VERTICES = 0; + + if(mode == GL_POINTS) { + glVertex3f = _glKosVertex3fp; + glVertex3fv = _glKosVertex3fpv; + } + else if(GL_ENABLE_CLIPZ && GL_ENABLE_LIGHTING) { + glVertex3f = _glKosVertex3flc; + glVertex3fv = _glKosVertex3flcv; + } + else if(GL_ENABLE_LIGHTING) { + glVertex3f = _glKosVertex3fl; + glVertex3fv = _glKosVertex3flv; + } + else if(GL_ENABLE_CLIPZ) { + glVertex3f = _glKosVertex3fc; + glVertex3fv = _glKosVertex3fcv; + } + else { + glVertex3f = _glKosVertex3ft; + glVertex3fv = _glKosVertex3ftv; + } +} + +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 _glKosCopyMultiTexture(pvr_vertex_t *v, GLuint count) { + if(GL_TEXTURE_ENABLED & GL_TEXTURE_1) { + _glKosVertexBufCopy(_glKosTRVertexBufPointer(), v, count); + + if(GL_VERTEX_MODE == GL_QUADS) + _glKosMultiTexCoordQuads(_glKosTRVertexBufPointer(), count); + else + _glKosMultiTexCoord(_glKosTRVertexBufPointer(), count); + + _glKosTRVertexBufAdd(count); + } +} + +void glEnd() { + if(GL_ENABLE_CLIPZ) { /* Z-Clipping Enabled */ + if(GL_ENABLE_LIGHTING) { + _glKosVertexComputeLighting(_glKosClipBufAddress(), GL_VERTICES); + + _glKosMatrixLoadRender(); + } + + GLuint cverts; + pvr_vertex_t *v = _glKosVertexBufPointer(); + + switch(GL_VERTEX_MODE) { + case GL_TRIANGLES: + cverts = _glKosClipTriangles(_glKosClipBufAddress(), v, GL_VERTICES); + _glKosTransformClipBuf(v, cverts); + _glKosCopyMultiTexture(v, cverts); + _glKosVertexBufAdd(cverts); + break; + + case GL_TRIANGLE_STRIP: + cverts = _glKosClipTriangleStrip(_glKosClipBufAddress(), v, GL_VERTICES); + _glKosTransformClipBuf(v, cverts); + _glKosCopyMultiTexture(v, cverts); + _glKosVertexBufAdd(cverts); + break; + + case GL_QUADS: + cverts = _glKosClipQuads(_glKosClipBufAddress(), v, GL_VERTICES); + _glKosTransformClipBuf(v, cverts); + _glKosCopyMultiTexture(v, cverts); + _glKosVertexBufAdd(cverts); + break; + } + + _glKosClipBufReset(); + } + else { /* No Z-Clipping Enabled */ + if(GL_ENABLE_LIGHTING) + _glKosVertexComputeLighting((pvr_vertex_t *)_glKosVertexBufPointer() - GL_VERTICES, GL_VERTICES); + + switch(GL_VERTEX_MODE) { + case GL_TRIANGLES: + _glKosFlagsSetTriangle(); + break; + + case GL_TRIANGLE_STRIP: + _glKosFlagsSetTriangleStrip(); + break; + + case GL_QUADS: + _glKosFlagsSetQuad(); + break; + } + + _glKosCopyMultiTexture((pvr_vertex_t *)_glKosVertexBufPointer() - GL_VERTICES, GL_VERTICES); + } +} + +void glVertex2f(GLfloat x, GLfloat y) { + return _glKosVertex3ft(x, y, 0.0f); +} + +void glVertex2fv(GLfloat *xy) { + return _glKosVertex3ft(xy[0], xy[1], 0.0f); +} + +void glKosVertex2f(GLfloat x, GLfloat y) { + pvr_vertex_t *v = _glKosVertexBufPointer(); + + v->x = x; + v->y = y; + v->z = 10; + v->u = GL_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosVertexBufIncrement(); + + ++GL_VERTICES; +} + +void glKosVertex2fv(GLfloat *xy) { + pvr_vertex_t *v = _glKosVertexBufPointer(); + + v->x = xy[0]; + v->y = xy[1]; + v->z = 10; + v->u = GL_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosVertexBufIncrement(); + + ++GL_VERTICES; +} + +void _glKosVertex3fs(float x, float y, float z) { + pvr_vertex_t *v = _glKosVertexBufPointer(); + + mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); + + v->u = GL_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosVertexBufIncrement(); + + ++GL_VERTICES; +} + +void _glKosVertex3fsv(float *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_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosVertexBufIncrement(); + + ++GL_VERTICES; +} + +void _glKosVertex3ft(float x, float y, float z) { + pvr_vertex_t *v = _glKosVertexBufPointer(); + + mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); + + v->u = GL_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosVertexBufIncrement(); + + ++GL_VERTICES; +} + +void _glKosVertex3ftv(float *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_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosVertexBufIncrement(); + + ++GL_VERTICES; +} + +void _glKosVertex3fc(float x, float y, float z) { + pvr_vertex_t *v = _glKosClipBufPointer(); + + v->x = x; + v->y = y; + v->z = z; + v->u = GL_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosClipBufIncrement(); + + ++GL_VERTICES; +} + +void _glKosVertex3fcv(float *xyz) { + pvr_vertex_t *v = _glKosClipBufPointer(); + + v->x = xyz[0]; + v->y = xyz[1]; + v->z = xyz[2]; + v->u = GL_VERTEX_UV[0]; + v->v = GL_VERTEX_UV[1]; + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + + _glKosClipBufIncrement(); + + ++GL_VERTICES; +} + +/* GL_POINTS */ +static float GL_POINT_SIZE = 0.02; + +inline void _glKosVertex3fpa(float x, float y, float z) { + pvr_vertex_t *v = _glKosVertexBufPointer(); + + mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); + + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + v->flags = PVR_CMD_VERTEX; + + _glKosVertexBufIncrement(); +} + +inline void _glKosVertex3fpb(float x, float y, float z) { + pvr_vertex_t *v = _glKosVertexBufPointer(); + + mat_trans_single3_nomod(x, y, z, v->x, v->y, v->z); + + v->argb = GL_VERTEX_COLOR; + //v->oargb = GL_VERTEX_SPECULAR; + v->flags = PVR_CMD_VERTEX_EOL; + + _glKosVertexBufIncrement(); +} + +void _glKosVertex3fp(float x, float y, float z) { + _glKosVertex3fpa(x - GL_POINT_SIZE, y - GL_POINT_SIZE, z); + _glKosVertex3fpa(x + GL_POINT_SIZE, y - GL_POINT_SIZE, z); + _glKosVertex3fpa(x - GL_POINT_SIZE, y + GL_POINT_SIZE, z); + _glKosVertex3fpb(x + GL_POINT_SIZE, y + GL_POINT_SIZE, z); +} + +void _glKosVertex3fpv(float *xyz) { + _glKosVertex3fpa(xyz[0] - GL_POINT_SIZE, xyz[1] - GL_POINT_SIZE, xyz[2]); + _glKosVertex3fpa(xyz[0] + GL_POINT_SIZE, xyz[1] - GL_POINT_SIZE, xyz[2]); + _glKosVertex3fpa(xyz[0] - GL_POINT_SIZE, xyz[1] + GL_POINT_SIZE, xyz[2]); + _glKosVertex3fpb(xyz[0] + GL_POINT_SIZE, xyz[1] + GL_POINT_SIZE, xyz[2]); +} + +/* 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 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 glHint(GLenum target, GLenum mode) { + switch(target) { + case GL_PERSPECTIVE_CORRECTION_HINT: + if(mode == GL_NICEST) + GL_ENABLE_SUPERSAMP = 1; + else + GL_ENABLE_SUPERSAMP = 0; + + break; + } +} + +GLint _glKosEnabledTexture2D() { + return GL_TEXTURE_ENABLED; +} + +GLubyte _glKosEnabledNearZClip() { + return GL_ENABLE_CLIPZ; +} + +GLubyte _glKosEnabledLighting() { + return GL_ENABLE_LIGHTING; +} + +inline void _glKosResetEnabledTex() { + GL_TEXTURE_ENABLED = GL_CUR_ACTIVE_TEX = 0; +} diff --git a/gl-api.h b/gl-api.h index e6d83f6..585ecd9 100755 --- a/gl-api.h +++ b/gl-api.h @@ -1,116 +1,116 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-api.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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 - -typedef struct { - float pos[3]; - float norm[3]; -} glVertex; /* Simple Vertex used for Dynamic Vertex Lighting */ - -typedef unsigned short uint16; -typedef unsigned char uint8; - -/* Vertex Main Buffer Internal Functions */ -inline void _glKosVertexBufSwitchOP(); -inline void _glKosVertexBufSwitchTR(); -inline void *_glKosVertexBufAddress(unsigned char list); -inline void *_glKosVertexBufPointer(); -inline void *_glKosTRVertexBufPointer(); -inline void _glKosVertexBufIncrement(); -inline void _glKosTRVertexBufIncrement(); -inline void _glKosVertexBufAdd(unsigned int count); -inline void _glKosTRVertexBufAdd(unsigned int count); -inline void _glKosVertexBufDecrement(); -inline void _glKosVertexBufReset(); -inline unsigned int _glKosVertexBufCount(unsigned char list); -unsigned char _glKosList(); -inline void _glKosVertexBufCopy(void *src, void *dst, GLuint count); -inline void _glKosResetEnabledTex(); - -/* Vertex Clip Buffer Internal Functions */ -inline void *_glKosClipBufAddress(); -inline void *_glKosClipBufPointer(); -inline void _glKosClipBufIncrement(); -inline void _glKosClipBufReset(); - -/* Vertex Array Buffer Internal Functions */ -inline void _glKosArrayBufIncrement(); -inline void _glKosArrayBufReset(); -inline glVertex *_glKosArrayBufAddr(); -inline glVertex *_glKosArrayBufPtr(); - -/* Initialize the OpenGL PVR Pipeline */ -int _glKosInitPVR(); - -/* Compile the current Polygon Header for the PVR */ -void _glKosCompileHdr(); -void _glKosCompileHdrTx(); -void _glKosCompileHdrTx2(); - -/* 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 char _glKosClipTriTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout); -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); - -/* 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 _glKosVertex2ft(GLfloat x, GLfloat y); -void _glKosVertex2ftv(GLfloat *xy); -void _glKosVertex3ft(GLfloat x, GLfloat y, GLfloat z); -void _glKosVertex3ftv(GLfloat *xyz); -void _glKosVertex3fc(GLfloat x, GLfloat y, GLfloat z); -void _glKosVertex3fcv(GLfloat *xyz); -void _glKosVertex3fp(GLfloat x, GLfloat y, GLfloat z); -void _glKosVertex3fpv(GLfloat *xyz); -void _glKosVertex3fl(GLfloat x, GLfloat y, GLfloat z); -void _glKosVertex3flv(GLfloat *xyz); -void _glKosVertex3flc(GLfloat x, GLfloat y, GLfloat z); -void _glKosVertex3flcv(GLfloat *xyz); -void _glKosVertex3fs(GLfloat x, GLfloat y, GLfloat z); -void _glKosVertex3fsv(GLfloat *xyz); - -/* Matrix Internal Functions */ -void _glKosInitMatrix(); -void _glKosMatrixLoadModelView(); -void _glKosMatrixLoadModelRot(); -void _glKosMatrixApplyScreenSpace(); -void _glKosMatrixApplyRender(); -void _glKosMatrixLoadRender(); - -/* API Enabled Capabilities Internal Functions */ -GLint _glKosEnabledTexture2D(); -GLubyte _glKosEnabledNearZClip(); -GLubyte _glKosEnabledLighting(); - -/* 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); - -#endif +/* KallistiGL for KallistiOS ##version## + + libgl/gl-api.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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 + +typedef struct { + float pos[3]; + float norm[3]; +} glVertex; /* Simple Vertex used for Dynamic Vertex Lighting */ + +typedef unsigned short uint16; +typedef unsigned char uint8; + +/* Vertex Main Buffer Internal Functions */ +inline void _glKosVertexBufSwitchOP(); +inline void _glKosVertexBufSwitchTR(); +inline void *_glKosVertexBufAddress(unsigned char list); +inline void *_glKosVertexBufPointer(); +inline void *_glKosTRVertexBufPointer(); +inline void _glKosVertexBufIncrement(); +inline void _glKosTRVertexBufIncrement(); +inline void _glKosVertexBufAdd(unsigned int count); +inline void _glKosTRVertexBufAdd(unsigned int count); +inline void _glKosVertexBufDecrement(); +inline void _glKosVertexBufReset(); +inline unsigned int _glKosVertexBufCount(unsigned char list); +unsigned char _glKosList(); +inline void _glKosVertexBufCopy(void *src, void *dst, GLuint count); +inline void _glKosResetEnabledTex(); + +/* Vertex Clip Buffer Internal Functions */ +inline void *_glKosClipBufAddress(); +inline void *_glKosClipBufPointer(); +inline void _glKosClipBufIncrement(); +inline void _glKosClipBufReset(); + +/* Vertex Array Buffer Internal Functions */ +inline void _glKosArrayBufIncrement(); +inline void _glKosArrayBufReset(); +inline glVertex *_glKosArrayBufAddr(); +inline glVertex *_glKosArrayBufPtr(); + +/* Initialize the OpenGL PVR Pipeline */ +int _glKosInitPVR(); + +/* Compile the current Polygon Header for the PVR */ +void _glKosCompileHdr(); +void _glKosCompileHdrTx(); +void _glKosCompileHdrTx2(); + +/* 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 char _glKosClipTriTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout); +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); + +/* 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 _glKosVertex2ft(GLfloat x, GLfloat y); +void _glKosVertex2ftv(GLfloat *xy); +void _glKosVertex3ft(GLfloat x, GLfloat y, GLfloat z); +void _glKosVertex3ftv(GLfloat *xyz); +void _glKosVertex3fc(GLfloat x, GLfloat y, GLfloat z); +void _glKosVertex3fcv(GLfloat *xyz); +void _glKosVertex3fp(GLfloat x, GLfloat y, GLfloat z); +void _glKosVertex3fpv(GLfloat *xyz); +void _glKosVertex3fl(GLfloat x, GLfloat y, GLfloat z); +void _glKosVertex3flv(GLfloat *xyz); +void _glKosVertex3flc(GLfloat x, GLfloat y, GLfloat z); +void _glKosVertex3flcv(GLfloat *xyz); +void _glKosVertex3fs(GLfloat x, GLfloat y, GLfloat z); +void _glKosVertex3fsv(GLfloat *xyz); + +/* Matrix Internal Functions */ +void _glKosInitMatrix(); +void _glKosMatrixLoadModelView(); +void _glKosMatrixLoadModelRot(); +void _glKosMatrixApplyScreenSpace(); +void _glKosMatrixApplyRender(); +void _glKosMatrixLoadRender(); + +/* API Enabled Capabilities Internal Functions */ +GLint _glKosEnabledTexture2D(); +GLubyte _glKosEnabledNearZClip(); +GLubyte _glKosEnabledLighting(); + +/* 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); + +#endif diff --git a/gl-arrays.c b/gl-arrays.c index c7d2158..a4f61ab 100755 --- a/gl-arrays.c +++ b/gl-arrays.c @@ -1,1039 +1,1039 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-arrays.c - Copyright (C) 2013-2014 Josh "PH3NOM" 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 pointers 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. -*/ - -#include -#include - -#include "gl.h" -#include "gl-api.h" -#include "gl-arrays.h" -#include "gl-rgb.h" -#include "gl-sh4.h" - -//========================================================================================// -//== Local Variables ==// - -#define GL_MAX_ARRAY_VERTICES 1024*32 /* Maximum Number of Vertices in the Array Buffer */ -static glVertex GL_ARRAY_BUF[GL_MAX_ARRAY_VERTICES]; -static GLfloat GL_ARRAY_BUFW[GL_MAX_ARRAY_VERTICES]; -static GLfloat GL_ARRAY_DSTW[GL_MAX_ARRAY_VERTICES]; -static glVertex *GL_ARRAY_BUF_PTR; -static GLuint GL_VERTEX_PTR_MODE = 0; - -//========================================================================================// -//== Multi-Texture Extensions ==// - -#define GL_TEXTURE_0 1<<0 -#define GL_TEXTURE_1 1<<1 - -static GLuint GL_ARRAY_TEXTURE_ENABLED = 0; -static GLuint GL_ARRAY_ACTIVE_TEXTURE = 0; - -void glClientActiveTexture(GLenum texture) { - if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + GL_MAX_TEXTURE_UNITS) - return; - - GL_ARRAY_ACTIVE_TEXTURE = ((texture & 0xFF) - (GL_TEXTURE0 & 0xFF)); - - return glActiveTexture(texture); -} - -static inline void _glKosArrayCopyMultiTexture(GLuint count) { - if(GL_ARRAY_TEXTURE_ENABLED == 3) { - pvr_vertex_t *dst = _glKosTRVertexBufPointer(); - pvr_vertex_t *src = _glKosVertexBufPointer(); - GLuint i; - - for(i = 0; i < count; i++) { - dst[i].x = src[i].x; - dst[i].y = src[i].y; - dst[i].z = src[i].z; - dst[i].argb = src[i].argb; - dst[i].flags = src[i].flags; - - dst[i].u = GL_TEXCOORD2_POINTER[0]; - dst[i].v = GL_TEXCOORD2_POINTER[1]; - GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; - } - - _glKosTRVertexBufAdd(count); - } -} - -static inline void _glKosArrayCopyMultiTextureQuads(GLuint count) { - if(GL_ARRAY_TEXTURE_ENABLED == 3) { - pvr_vertex_t *dst = _glKosTRVertexBufPointer(); - pvr_vertex_t *src = _glKosVertexBufPointer(); - GLuint i; - - for(i = 0; i < count; i += 4) { - /* 1st Vertex */ - dst[i].x = src[i].x; - dst[i].y = src[i].y; - dst[i].z = src[i].z; - dst[i].argb = src[i].argb; - dst[i].flags = src[i].flags; - - dst[i].u = GL_TEXCOORD2_POINTER[0]; - dst[i].v = GL_TEXCOORD2_POINTER[1]; - GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; - - /* 2nd Vertex */ - dst[i + 1].x = src[i + 1].x; - dst[i + 1].y = src[i + 1].y; - dst[i + 1].z = src[i + 1].z; - dst[i + 1].argb = src[i + 1].argb; - dst[i + 1].flags = src[i + 1].flags; - - dst[i + 1].u = GL_TEXCOORD2_POINTER[0]; - dst[i + 1].v = GL_TEXCOORD2_POINTER[1]; - GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; - - /* 3rd Vertex */ - dst[i + 2].x = src[i + 2].x; - dst[i + 2].y = src[i + 2].y; - dst[i + 2].z = src[i + 2].z; - dst[i + 2].argb = src[i + 2].argb; - dst[i + 2].flags = src[i + 2].flags; - - dst[i + 3].u = GL_TEXCOORD2_POINTER[0]; - dst[i + 3].v = GL_TEXCOORD2_POINTER[1]; - GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; - - /* 4th Vertex */ - dst[i + 3].x = src[i + 3].x; - dst[i + 3].y = src[i + 3].y; - dst[i + 3].z = src[i + 3].z; - dst[i + 3].argb = src[i + 3].argb; - dst[i + 3].flags = src[i + 3].flags; - - dst[i + 2].u = GL_TEXCOORD2_POINTER[0]; - dst[i + 2].v = GL_TEXCOORD2_POINTER[1]; - GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; - } - - _glKosTRVertexBufAdd(count); - } -} - -//========================================================================================// -//== Local Function Definitions ==// - -static inline void _glKosArraysTransformNormals(GLfloat *normal, GLuint count); -static inline void _glKosArraysTransformPositions(GLfloat *position, GLuint count); - -//========================================================================================// -//== Open GL API Public Functions ==// - -/* Submit a Vertex Position Pointer */ -void glVertexPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - if(size != 3) return; /* Expect 3D X,Y,Z vertex... could do 2d X,Y later */ - - if(type != GL_FLOAT) return; /* Expect Floating point vertices */ - - (stride) ? (GL_VERTEX_STRIDE = stride / 4) : (GL_VERTEX_STRIDE = 3); - - GL_VERTEX_POINTER = (float *)pointer; - - GL_VERTEX_PTR_MODE |= GL_USE_ARRAY; -} - -/* Submit a Vertex Normal Pointer */ -void glNormalPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - if(size != 3) return; - - if(type != GL_FLOAT) return; /* Expect Floating point vertices */ - - (stride) ? (GL_NORMAL_STRIDE = stride / 4) : (GL_NORMAL_STRIDE = 3); - - GL_NORMAL_POINTER = (float *)pointer; - - GL_VERTEX_PTR_MODE |= GL_USE_NORMAL; -} - -/* Submit a Texture Coordinate Pointer */ -void glTexCoordPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - if(size != 2) return; /* Expect u and v */ - - if(type != GL_FLOAT) return; /* Expect Floating point vertices */ - - if(GL_ARRAY_ACTIVE_TEXTURE == 0) { - (stride) ? (GL_TEXCOORD_STRIDE = stride / 4) : (GL_TEXCOORD_STRIDE = 2); - - GL_TEXCOORD_POINTER = (float *)pointer; - - GL_VERTEX_PTR_MODE |= GL_USE_TEXTURE; - - GL_ARRAY_TEXTURE_ENABLED |= GL_TEXTURE_0; - } - else if(GL_ARRAY_ACTIVE_TEXTURE == 1) { - (stride) ? (GL_TEXCOORD2_STRIDE = stride / 4) : (GL_TEXCOORD2_STRIDE = 2); - - GL_TEXCOORD2_POINTER = (float *)pointer; - - GL_ARRAY_TEXTURE_ENABLED |= GL_TEXTURE_1; - } -} - -/* Submit a Color Pointer */ -void glColorPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - if((type == GL_UNSIGNED_INT) && (size == 1)) { - GL_COLOR_COMPONENTS = 1; - GL_COLOR_POINTER = (GLvoid *)pointer; - GL_COLOR_TYPE = type; - } - else if((type == GL_UNSIGNED_BYTE) && (size == 4)) { - GL_COLOR_COMPONENTS = 4; - GL_COLOR_POINTER = (GLvoid *)pointer; - GL_COLOR_TYPE = type; - } - else if((type == GL_FLOAT) && (size == 3)) { - GL_COLOR_COMPONENTS = 3; - GL_COLOR_POINTER = (GLfloat *)pointer; - GL_COLOR_TYPE = type; - } - else if((type == GL_FLOAT) && (size == 4)) { - GL_COLOR_COMPONENTS = 4; - GL_COLOR_POINTER = (GLfloat *)pointer; - GL_COLOR_TYPE = type; - } - else - return; - - (stride) ? (GL_COLOR_STRIDE = stride / 4) : (GL_COLOR_STRIDE = size); - - GL_VERTEX_PTR_MODE |= GL_USE_COLOR; -} -//========================================================================================// -//== Vertex Pointer Internal API ==// - -inline void _glKosArrayBufIncrement() { - ++GL_ARRAY_BUF_PTR; -} - -inline void _glKosArrayBufReset() { - GL_ARRAY_BUF_PTR = &GL_ARRAY_BUF[0]; -} - -inline glVertex *_glKosArrayBufAddr() { - return &GL_ARRAY_BUF[0]; -} - -inline glVertex *_glKosArrayBufPtr() { - return GL_ARRAY_BUF_PTR; -} - -static inline void _glKosArraysTransformNormals(GLfloat *normal, GLuint count) { - glVertex *v = &GL_ARRAY_BUF[0]; - GLfloat *N = normal; - - _glKosMatrixLoadModelRot(); - - while(count--) { - mat_trans_normal3_nomod(N[0], N[1], N[2], v->norm[0], v->norm[1], v->norm[2]); - N += 3; - ++v; - } -} - -static inline void _glKosArraysTransformPositions(GLfloat *position, GLuint count) { - glVertex *v = &GL_ARRAY_BUF[0]; - GLfloat *P = position; - - _glKosMatrixLoadModelView(); - - while(count--) { - mat_trans_single3_nodiv_nomod(P[0], P[1], P[2], v->pos[0], v->pos[1], v->pos[2]); - P += 3; - ++v; - } -} - -//========================================================================================// -//== Arrays Vertex Transform ==/ - -static void _glKosArraysTransform(GLuint count) { - GLfloat *src = GL_VERTEX_POINTER; - pvr_vertex_t *dst = _glKosVertexBufPointer(); - - register float __x __asm__("fr12"); - register float __y __asm__("fr13"); - register float __z __asm__("fr14"); - - while(count--) { - __x = *src++; - __y = *src++; - __z = *src++; - - mat_trans_fv12() - - dst->x = __x; - dst->y = __y; - dst->z = __z; - - ++dst; - } -} - -static void _glKosArraysTransformClip(GLuint count) { - GLfloat *src = GL_VERTEX_POINTER; - GLfloat *W = GL_ARRAY_DSTW; - pvr_vertex_t *dst = _glKosClipBufAddress(); - - register float __x __asm__("fr12"); - register float __y __asm__("fr13"); - register float __z __asm__("fr14"); - register float __w __asm__("fr15"); - - while(count--) { - __x = *src++; - __y = *src++; - __z = *src++; - - mat_trans_fv12_nodivw() - - dst->x = __x; - dst->y = __y; - dst->z = __z; - *W++ = __w; - ++dst; - } -} - -static void _glKosArraysTransformElements(GLuint count) { - GLfloat *src = GL_VERTEX_POINTER; - GLuint i = 0; - - register float __x __asm__("fr12"); - register float __y __asm__("fr13"); - register float __z __asm__("fr14"); - - printf("Transform Elements()\n"); - - for(i = 0; i < count; i++) { - __x = src[0]; - __y = src[1]; - __z = src[2]; - - mat_trans_fv12() - - GL_ARRAY_BUF[i].pos[0] = __x; - GL_ARRAY_BUF[i].pos[1] = __y; - GL_ARRAY_BUF[i].pos[2] = __z; - - src += GL_VERTEX_STRIDE; - } -} - -static void _glKosArraysTransformClipElements(GLuint count) { - GLfloat *src = GL_VERTEX_POINTER; - GLuint i; - - register float __x __asm__("fr12"); - register float __y __asm__("fr13"); - register float __z __asm__("fr14"); - register float __w __asm__("fr15"); - - for(i = 0; i < count; i++) { - __x = src[0]; - __y = src[1]; - __z = src[2]; - - mat_trans_fv12_nodivw() - - GL_ARRAY_BUF[i].pos[0] = __x; - GL_ARRAY_BUF[i].pos[1] = __y; - GL_ARRAY_BUF[i].pos[2] = __z; - GL_ARRAY_BUFW[i] = __w; - - src += GL_VERTEX_STRIDE; - } -} - -//========================================================================================// -//== Element Attribute Functions ==// - -//== Color ==// - -static inline void _glKosElementColor0(pvr_vertex_t *dst, GLuint count) { - GLuint i; - - for(i = 0; i < count; i++) - dst[i].argb = 0xFFFFFFFF; -} - -static inline void _glKosElementColor1uiU8(pvr_vertex_t *dst, GLuint count) { - GLuint i; - GLuint *src = (GLuint *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) - dst[i].argb = src[GL_INDEX_POINTER_U8[i] * GL_COLOR_STRIDE]; -} - -static inline void _glKosElementColor1uiU16(pvr_vertex_t *dst, GLuint count) { - GLuint i; - GLuint *color = (GLuint *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) - dst[i].argb = color[GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE]; -} - -static inline void _glKosElementColor4ubU8(pvr_vertex_t *dst, GLuint count) { - GLuint i, *color = (GLuint *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) - dst[i].argb = RGBA32_2_ARGB32(color[GL_INDEX_POINTER_U8[i]] * GL_COLOR_STRIDE); -} - -static inline void _glKosElementColor4ubU16(pvr_vertex_t *dst, GLuint count) { - GLuint i, *color = (GLuint *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) - dst[i].argb = RGBA32_2_ARGB32(color[GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE]); -} - -static inline void _glKosElementColor3fU8(pvr_vertex_t *dst, GLuint count) { - GLuint i, index; - GLrgb3f *color = (GLrgb3f *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - index = GL_INDEX_POINTER_U8[i] * GL_COLOR_STRIDE; - dst[i].argb = (0xFF000000 | ((GLubyte)color[index][0] * 0xFF) << 16 - | ((GLubyte)color[index][1] * 0xFF) << 8 - | ((GLubyte)color[index][2] * 0xFF)); - } -} - -static inline void _glKosElementColor3fU16(pvr_vertex_t *dst, GLuint count) { - GLuint i, index; - GLrgb3f *color = (GLrgb3f *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - index = GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE; - dst[i].argb = (0xFF000000 | ((GLubyte)color[index][0] * 0xFF) << 16 - | ((GLubyte)color[index][1] * 0xFF) << 8 - | ((GLubyte)color[index][2] * 0xFF)); - } -} - -static inline void _glKosElementColor4fU8(pvr_vertex_t *dst, GLuint count) { - GLuint i, index; - GLrgba4f *color = (GLrgba4f *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - index = GL_INDEX_POINTER_U8[i] * GL_COLOR_STRIDE; - dst[i].argb = (((GLubyte)color[index][3] * 0xFF) << 24 - | ((GLubyte)color[index][0] * 0xFF) << 16 - | ((GLubyte)color[index][1] * 0xFF) << 8 - | ((GLubyte)color[index][2] * 0xFF)); - } -} - -static inline void _glKosElementColor4fU16(pvr_vertex_t *dst, GLuint count) { - GLuint i, index; - GLrgba4f *color = (GLrgba4f *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - index = GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE; - dst[i].argb = (((GLubyte)color[index][3] * 0xFF) << 24 - | ((GLubyte)color[index][0] * 0xFF) << 16 - | ((GLubyte)color[index][1] * 0xFF) << 8 - | ((GLubyte)color[index][2] * 0xFF)); - } -} - -//== Texture Coordinates ==// - -static inline void _glKosElementTexCoord2fU16(pvr_vertex_t *dst, GLuint count) { - GLuint i, index; - GLfloat *t = GL_TEXCOORD_POINTER; - - for(i = 0; i < count; i++) { - index = GL_INDEX_POINTER_U16[i] * GL_TEXCOORD_STRIDE; - dst[i].u = t[index]; - dst[i].v = t[index + 1]; - } -} - -static inline void _glKosElementTexCoord2fU8(pvr_vertex_t *dst, GLuint count) { - GLuint i, index; - GLfloat *t = GL_TEXCOORD_POINTER; - - for(i = 0; i < count; i++) { - index = GL_INDEX_POINTER_U8[i] * GL_TEXCOORD_STRIDE; - dst[i].u = t[index]; - dst[i].v = t[index + 1]; - } -} - -//========================================================================================// -//== Element Unpacking ==// - -static inline void _glKosArraysUnpackElementsS16(pvr_vertex_t *dst, GLuint count) { - glVertex *vert = GL_ARRAY_BUF; - GLuint i; - - for(i = 0; i < count; i++) { - dst[i].x = vert[GL_INDEX_POINTER_U16[i]].pos[0]; - dst[i].y = vert[GL_INDEX_POINTER_U16[i]].pos[1]; - dst[i].z = vert[GL_INDEX_POINTER_U16[i]].pos[2]; - } -} - -static inline void _glKosArraysUnpackElementsS8(pvr_vertex_t *dst, GLuint count) { - glVertex *vert = GL_ARRAY_BUF; - GLuint i; - - for(i = 0; i < count; i++) { - dst[i].x = vert[GL_INDEX_POINTER_U8[i]].pos[0]; - dst[i].y = vert[GL_INDEX_POINTER_U8[i]].pos[1]; - dst[i].z = vert[GL_INDEX_POINTER_U8[i]].pos[2]; - } -} - -static inline void _glKosArraysUnpackClipElementsS16(pvr_vertex_t *dst, GLuint count) { - glVertex *vert = GL_ARRAY_BUF; - GLuint i; - - for(i = 0; i < count; i++) { - dst[i].x = vert[GL_INDEX_POINTER_U16[i]].pos[0]; - dst[i].y = vert[GL_INDEX_POINTER_U16[i]].pos[1]; - dst[i].z = vert[GL_INDEX_POINTER_U16[i]].pos[2]; - GL_ARRAY_DSTW[i] = GL_ARRAY_BUFW[GL_INDEX_POINTER_U16[i]]; - } -} - -static inline void _glKosArraysUnpackClipElementsS8(pvr_vertex_t *dst, GLuint count) { - glVertex *vert = GL_ARRAY_BUF; - GLuint i; - - for(i = 0; i < count; i++) { - dst[i].x = vert[GL_INDEX_POINTER_U8[i]].pos[0]; - dst[i].y = vert[GL_INDEX_POINTER_U8[i]].pos[1]; - dst[i].z = vert[GL_INDEX_POINTER_U8[i]].pos[2]; - GL_ARRAY_DSTW[i] = GL_ARRAY_BUFW[GL_INDEX_POINTER_U8[i]]; - } -} - -//========================================================================================// -//== Misc Utils ==// - -static inline void _glKosVertexSwizzle(pvr_vertex_t *v1, pvr_vertex_t *v2) { - pvr_vertex_t tmp = *v1; - *v1 = *v2; - *v2 = * &tmp; -} - -static inline void _glKosArraysResetState() { - GL_VERTEX_PTR_MODE = 0; - - if(GL_ARRAY_TEXTURE_ENABLED == 3) - _glKosResetEnabledTex(); - - GL_ARRAY_TEXTURE_ENABLED = GL_ARRAY_ACTIVE_TEXTURE = 0; -} - -//========================================================================================// -//== Vertex Flag Settings for the PVR2DC hardware ==// - -static inline void _glKosArrayFlagsSetQuad(pvr_vertex_t *dst, GLuint count) { - GLuint i; - - for(i = 0; i < count; i += 4) { - _glKosVertexSwizzle(&dst[2], &dst[3]); - dst[i + 0].flags = dst[i + 1].flags = dst[i + 2].flags = PVR_CMD_VERTEX; - dst[i + 3].flags = PVR_CMD_VERTEX_EOL; - } -} - -static inline void _glKosArrayFlagsSetTriangle(pvr_vertex_t *dst, GLuint count) { - GLuint i; - - for(i = 0; i < count; i += 3) { - dst[i + 0].flags = dst[i + 1].flags = PVR_CMD_VERTEX; - dst[i + 2].flags = PVR_CMD_VERTEX_EOL; - } -} - -static inline void _glKosArrayFlagsSetTriangleStrip(pvr_vertex_t *dst, GLuint count) { - GLuint i; - - for(i = 0; i < count - 1; i++) - dst[i].flags = PVR_CMD_VERTEX; - - dst[i].flags = PVR_CMD_VERTEX_EOL; -} - -//========================================================================================// -//== OpenGL Error Code Genration ==// - -static GLuint _glKosArraysVerifyParameter(GLenum mode, GLsizei count, GLenum type, GLubyte element) { - GLuint GL_ERROR_CODE = 0; - - if(mode != GL_QUADS) - if(mode != GL_TRIANGLES) - if(mode != GL_TRIANGLE_STRIP) - GL_ERROR_CODE |= GL_INVALID_ENUM; - - if(count < 0) - GL_ERROR_CODE |= GL_INVALID_VALUE; - - if(!(GL_VERTEX_PTR_MODE & GL_USE_ARRAY)) - GL_ERROR_CODE |= GL_INVALID_OPERATION; - - if(count > GL_MAX_ARRAY_VERTICES) - GL_ERROR_CODE |= GL_OUT_OF_MEMORY; - - if(element) { - switch(type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - - default: - GL_ERROR_CODE |= GL_INVALID_ENUM; - } - } - else if(type > count) - GL_ERROR_CODE |= GL_INVALID_VALUE; - - return GL_ERROR_CODE; -} - -void _glKosPrintErrorString(GLuint error) { - if(error) { - printf("GL_ERROR_CODE GENERATED:\n"); - - if(error & GL_INVALID_ENUM) - printf("\tGL_INVALID_ENUM\n"); - - if(error & GL_INVALID_VALUE) - printf("\tGL_INVALID_VALUE\n"); - - if(error & GL_INVALID_OPERATION) - printf("\tGL_INVALID__OPERATION\n"); - - if(error & GL_OUT_OF_MEMORY) - printf("\tGL_OUT_OF_MEMORY\n"); - } -} - -//========================================================================================// -//== OpenGL Elemental Array Submission ==// - -void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { - /* Before we process the vertex data, ensure all parameters are valid */ - GLuint error = _glKosArraysVerifyParameter(mode, count, type, 1); - - if(error) { - _glKosPrintErrorString(error); - - _glKosArraysResetState(); - - return; - } - - switch(type) { - case GL_UNSIGNED_BYTE: - GL_INDEX_POINTER_U8 = (GLubyte *)indices; - break; - - case GL_UNSIGNED_SHORT: - GL_INDEX_POINTER_U16 = (GLushort *)indices; - break; - } - - /* Compile the PVR polygon context with the currently enabled flags */ - if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE)) - _glKosCompileHdrTx(); - else - _glKosCompileHdr(); - - if(GL_ARRAY_TEXTURE_ENABLED == 3) /* Multi-Texture! */ - _glKosCompileHdrTx2(); - - pvr_vertex_t *dst; /* Destination of Output Vertex Array */ - - if(_glKosEnabledNearZClip()) - dst = _glKosClipBufAddress(); - else - dst = _glKosVertexBufPointer(); - - /* Check if Vertex Lighting is enabled. Else, check for Color Submission */ - if((GL_VERTEX_PTR_MODE & GL_USE_NORMAL) && _glKosEnabledLighting()) { - _glKosArraysTransformNormals(GL_NORMAL_POINTER, count); - _glKosArraysTransformPositions(GL_VERTEX_POINTER, count); - _glKosVertexLights(GL_ARRAY_BUF, dst, count); - } - else if(GL_VERTEX_PTR_MODE & GL_USE_COLOR) { - switch(GL_COLOR_TYPE) { - case GL_FLOAT: - switch(GL_COLOR_COMPONENTS) { - case 3: - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosElementColor3fU8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosElementColor3fU16(dst, count); - break; - } - - break; - - case 4: - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosElementColor4fU8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosElementColor4fU16(dst, count); - break; - } - - break; - } - - break; - - case GL_UNSIGNED_INT: - if(GL_COLOR_COMPONENTS == 1) - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosElementColor1uiU8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosElementColor1uiU16(dst, count); - break; - } - - break; - - case GL_UNSIGNED_BYTE: - if(GL_COLOR_COMPONENTS == 4) - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosElementColor4ubU8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosElementColor4ubU16(dst, count); - break; - } - - break; - } - } - else - _glKosElementColor0(dst, count); /* No colors bound, color white */ - - /* Check if Texture Coordinates are enabled */ - if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE) && (_glKosEnabledTexture2D() >= 0)) - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosElementTexCoord2fU8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosElementTexCoord2fU16(dst, count); - break; - } - - _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ - - if(!(_glKosEnabledNearZClip())) {/* Transform the element vertices */ - /* Transform vertices with perspective divde */ - _glKosArraysTransformElements(count); - - /* Unpack the indexed positions into primitives for rasterization */ - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosArraysUnpackElementsS8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosArraysUnpackElementsS16(dst, count); - break; - } - - /* Set the vertex flags for use with the PVR */ - switch(mode) { - case GL_QUADS: - _glKosArrayFlagsSetQuad(dst, count); - break; - - case GL_TRIANGLES: - _glKosArrayFlagsSetTriangle(dst, count); - break; - - case GL_TRIANGLE_STRIP: - _glKosArrayFlagsSetTriangleStrip(dst, count); - break; - } - - if(mode == GL_QUADS) - _glKosArrayCopyMultiTextureQuads(count); - else - _glKosArrayCopyMultiTexture(count); - } - else { - /* Transform vertices with no perspective divde, store w component */ - _glKosArraysTransformClipElements(count); - - /* Unpack the indexed positions into primitives for rasterization */ - switch(type) { - case GL_UNSIGNED_BYTE: - _glKosArraysUnpackClipElementsS8(dst, count); - break; - - case GL_UNSIGNED_SHORT: - _glKosArraysUnpackClipElementsS16(dst, count); - break; - } - - /* Finally, clip the input vertex data into the output vertex buffer */ - switch(mode) { - case GL_TRIANGLES: - count = _glKosClipTrianglesTransformed(dst, GL_ARRAY_DSTW, - (pvr_vertex_t *)_glKosVertexBufPointer(), count); - break; - - case GL_QUADS: - count = _glKosClipQuadsTransformed(dst, GL_ARRAY_DSTW, - (pvr_vertex_t *)_glKosVertexBufPointer(), count); - - break; - - case GL_TRIANGLE_STRIP: - count = _glKosClipTriangleStripTransformed(dst, GL_ARRAY_DSTW, - (pvr_vertex_t *)_glKosVertexBufPointer(), count); - break; - } - } - - _glKosVertexBufAdd(count); - - _glKosArraysResetState(); -} - - - -//========================================================================================// -//== Array Attribute Functions ==// - -//== Color ==// - -static inline void _glKosArrayColor0(pvr_vertex_t *dst, GLuint count) { - GLuint i; - - for(i = 0; i < count; i++) - dst[i].argb = 0xFFFFFFFF; -} - -static inline void _glKosArrayColor1ui(pvr_vertex_t *dst, GLuint count) { - GLuint i; - GLuint *color = (GLuint *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - dst[i].argb = *color; - color += GL_COLOR_STRIDE; - } -} - -static inline void _glKosArrayColor4ub(pvr_vertex_t *dst, GLuint count) { - GLuint i, *color = (GLuint *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - dst[i].argb = RGBA32_2_ARGB32(*color); - color += GL_COLOR_STRIDE; - } -} - -static inline void _glKosArrayColor3f(pvr_vertex_t *dst, GLuint count) { - GLuint i; - GLfloat *color = (GLfloat *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - dst[i].argb = (0xFF000000 | ((GLubyte)(color[0] * 0xFF)) << 16 - | ((GLubyte)(color[1] * 0xFF)) << 8 - | ((GLubyte)(color[2] * 0xFF))); - color += GL_COLOR_STRIDE; - } -} - -static inline void _glKosArrayColor4f(pvr_vertex_t *dst, GLuint count) { - GLuint i; - GLfloat *color = (GLfloat *)GL_COLOR_POINTER; - - for(i = 0; i < count; i++) { - dst[i].argb = (((GLubyte)(color[3] * 0xFF)) << 24 - | ((GLubyte)(color[0] * 0xFF)) << 16 - | ((GLubyte)(color[1] * 0xFF)) << 8 - | ((GLubyte)(color[2] * 0xFF))); - color += GL_COLOR_STRIDE; - } -} - -//== Texture Coordinates ==// - -static inline void _glKosArrayTexCoord2f(pvr_vertex_t *dst, GLuint count) { - GLuint i; - GLfloat *uv = GL_TEXCOORD_POINTER; - - for(i = 0; i < count; i++) { - dst[i].u = uv[0]; - dst[i].v = uv[1]; - uv += GL_TEXCOORD_STRIDE; - } -} - -//========================================================================================// -//== Openg GL Draw Arrays ==// - -void glDrawArrays(GLenum mode, GLint first, GLsizei count) { - /* Before we process the vertex data, ensure all parameters are valid */ - GLuint error = _glKosArraysVerifyParameter(mode, count, first, 0); - - if(error) { - _glKosPrintErrorString(error); - - return _glKosArraysResetState(); - } - - GL_VERTEX_POINTER += first; /* Add Pointer Offset */ - GL_TEXCOORD_POINTER += first; - GL_COLOR_POINTER += first; - GL_NORMAL_POINTER += first; - - /* Compile the PVR polygon context with the currently enabled flags */ - if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE)) - _glKosCompileHdrTx(); - else - _glKosCompileHdr(); - - if(GL_ARRAY_TEXTURE_ENABLED == 3) /* Multi-Texture! */ - _glKosCompileHdrTx2(); - - pvr_vertex_t *dst; /* Destination of Output Vertex Array */ - - if(_glKosEnabledNearZClip()) - dst = _glKosClipBufAddress(); - else - dst = _glKosVertexBufPointer(); - - /* Check if Vertex Lighting is enabled. Else, check for Color Submission */ - if((GL_VERTEX_PTR_MODE & GL_USE_NORMAL) && _glKosEnabledLighting()) { - _glKosArraysTransformNormals(GL_NORMAL_POINTER, count); - _glKosArraysTransformPositions(GL_VERTEX_POINTER, count); - _glKosVertexLights(GL_ARRAY_BUF, dst, count); - } - else if(GL_VERTEX_PTR_MODE & GL_USE_COLOR) { - switch(GL_COLOR_TYPE) { - case GL_FLOAT: - switch(GL_COLOR_COMPONENTS) { - case 3: - _glKosArrayColor3f(dst, count); - break; - - case 4: - _glKosArrayColor4f(dst, count); - break; - } - - break; - - case GL_UNSIGNED_INT: - if(GL_COLOR_COMPONENTS == 1) - _glKosArrayColor1ui(dst, count); - - break; - - case GL_UNSIGNED_BYTE: - if(GL_COLOR_COMPONENTS == 4) - _glKosArrayColor4ub(dst, count); - - break; - } - } - else - _glKosArrayColor0(dst, count); /* No colors bound, color white */ - - /* Check if Texture Coordinates are enabled */ - if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE) && (_glKosEnabledTexture2D() >= 0)) - _glKosArrayTexCoord2f(dst, count); - - _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ - - if(!_glKosEnabledNearZClip()) { - /* Transform Vertex Positions */ - _glKosArraysTransform(count); - - /* Set the vertex flags for use with the PVR */ - switch(mode) { - case GL_QUADS: - _glKosArrayFlagsSetQuad(dst, count); - break; - - case GL_TRIANGLES: - _glKosArrayFlagsSetTriangle(dst, count); - break; - - case GL_TRIANGLE_STRIP: - _glKosArrayFlagsSetTriangleStrip(dst, count); - break; - } - - if(mode == GL_QUADS) - _glKosArrayCopyMultiTextureQuads(count); - else - _glKosArrayCopyMultiTexture(count); - } - else { - /* Transform vertices with no perspective divde, store w component */ - _glKosArraysTransformClip(count); - - /* Finally, clip the input vertex data into the output vertex buffer */ - switch(mode) { - case GL_TRIANGLES: - count = _glKosClipTrianglesTransformed(dst, GL_ARRAY_DSTW, - (pvr_vertex_t *)_glKosVertexBufPointer(), count); - break; - - case GL_QUADS: - count = _glKosClipQuadsTransformed(dst, GL_ARRAY_DSTW, - (pvr_vertex_t *)_glKosVertexBufPointer(), count); - - break; - - case GL_TRIANGLE_STRIP: - count = _glKosClipTriangleStripTransformed(dst, GL_ARRAY_DSTW, - (pvr_vertex_t *)_glKosVertexBufPointer(), count); - break; - } - } - - _glKosVertexBufAdd(count); - - _glKosArraysResetState(); +/* KallistiGL for KallistiOS ##version## + + libgl/gl-arrays.c + Copyright (C) 2013-2014 Josh "PH3NOM" 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 pointers 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. +*/ + +#include +#include + +#include "gl.h" +#include "gl-api.h" +#include "gl-arrays.h" +#include "gl-rgb.h" +#include "gl-sh4.h" + +//========================================================================================// +//== Local Variables ==// + +#define GL_MAX_ARRAY_VERTICES 1024*32 /* Maximum Number of Vertices in the Array Buffer */ +static glVertex GL_ARRAY_BUF[GL_MAX_ARRAY_VERTICES]; +static GLfloat GL_ARRAY_BUFW[GL_MAX_ARRAY_VERTICES]; +static GLfloat GL_ARRAY_DSTW[GL_MAX_ARRAY_VERTICES]; +static glVertex *GL_ARRAY_BUF_PTR; +static GLuint GL_VERTEX_PTR_MODE = 0; + +//========================================================================================// +//== Multi-Texture Extensions ==// + +#define GL_TEXTURE_0 1<<0 +#define GL_TEXTURE_1 1<<1 + +static GLuint GL_ARRAY_TEXTURE_ENABLED = 0; +static GLuint GL_ARRAY_ACTIVE_TEXTURE = 0; + +void glClientActiveTexture(GLenum texture) { + if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + GL_MAX_TEXTURE_UNITS) + return; + + GL_ARRAY_ACTIVE_TEXTURE = ((texture & 0xFF) - (GL_TEXTURE0 & 0xFF)); + + return glActiveTexture(texture); +} + +static inline void _glKosArrayCopyMultiTexture(GLuint count) { + if(GL_ARRAY_TEXTURE_ENABLED == 3) { + pvr_vertex_t *dst = _glKosTRVertexBufPointer(); + pvr_vertex_t *src = _glKosVertexBufPointer(); + GLuint i; + + for(i = 0; i < count; i++) { + dst[i].x = src[i].x; + dst[i].y = src[i].y; + dst[i].z = src[i].z; + dst[i].argb = src[i].argb; + dst[i].flags = src[i].flags; + + dst[i].u = GL_TEXCOORD2_POINTER[0]; + dst[i].v = GL_TEXCOORD2_POINTER[1]; + GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; + } + + _glKosTRVertexBufAdd(count); + } +} + +static inline void _glKosArrayCopyMultiTextureQuads(GLuint count) { + if(GL_ARRAY_TEXTURE_ENABLED == 3) { + pvr_vertex_t *dst = _glKosTRVertexBufPointer(); + pvr_vertex_t *src = _glKosVertexBufPointer(); + GLuint i; + + for(i = 0; i < count; i += 4) { + /* 1st Vertex */ + dst[i].x = src[i].x; + dst[i].y = src[i].y; + dst[i].z = src[i].z; + dst[i].argb = src[i].argb; + dst[i].flags = src[i].flags; + + dst[i].u = GL_TEXCOORD2_POINTER[0]; + dst[i].v = GL_TEXCOORD2_POINTER[1]; + GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; + + /* 2nd Vertex */ + dst[i + 1].x = src[i + 1].x; + dst[i + 1].y = src[i + 1].y; + dst[i + 1].z = src[i + 1].z; + dst[i + 1].argb = src[i + 1].argb; + dst[i + 1].flags = src[i + 1].flags; + + dst[i + 1].u = GL_TEXCOORD2_POINTER[0]; + dst[i + 1].v = GL_TEXCOORD2_POINTER[1]; + GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; + + /* 3rd Vertex */ + dst[i + 2].x = src[i + 2].x; + dst[i + 2].y = src[i + 2].y; + dst[i + 2].z = src[i + 2].z; + dst[i + 2].argb = src[i + 2].argb; + dst[i + 2].flags = src[i + 2].flags; + + dst[i + 3].u = GL_TEXCOORD2_POINTER[0]; + dst[i + 3].v = GL_TEXCOORD2_POINTER[1]; + GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; + + /* 4th Vertex */ + dst[i + 3].x = src[i + 3].x; + dst[i + 3].y = src[i + 3].y; + dst[i + 3].z = src[i + 3].z; + dst[i + 3].argb = src[i + 3].argb; + dst[i + 3].flags = src[i + 3].flags; + + dst[i + 2].u = GL_TEXCOORD2_POINTER[0]; + dst[i + 2].v = GL_TEXCOORD2_POINTER[1]; + GL_TEXCOORD2_POINTER += GL_TEXCOORD2_STRIDE; + } + + _glKosTRVertexBufAdd(count); + } +} + +//========================================================================================// +//== Local Function Definitions ==// + +static inline void _glKosArraysTransformNormals(GLfloat *normal, GLuint count); +static inline void _glKosArraysTransformPositions(GLfloat *position, GLuint count); + +//========================================================================================// +//== Open GL API Public Functions ==// + +/* Submit a Vertex Position Pointer */ +void glVertexPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + if(size != 3) return; /* Expect 3D X,Y,Z vertex... could do 2d X,Y later */ + + if(type != GL_FLOAT) return; /* Expect Floating point vertices */ + + (stride) ? (GL_VERTEX_STRIDE = stride / 4) : (GL_VERTEX_STRIDE = 3); + + GL_VERTEX_POINTER = (float *)pointer; + + GL_VERTEX_PTR_MODE |= GL_USE_ARRAY; +} + +/* Submit a Vertex Normal Pointer */ +void glNormalPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + if(size != 3) return; + + if(type != GL_FLOAT) return; /* Expect Floating point vertices */ + + (stride) ? (GL_NORMAL_STRIDE = stride / 4) : (GL_NORMAL_STRIDE = 3); + + GL_NORMAL_POINTER = (float *)pointer; + + GL_VERTEX_PTR_MODE |= GL_USE_NORMAL; +} + +/* Submit a Texture Coordinate Pointer */ +void glTexCoordPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + if(size != 2) return; /* Expect u and v */ + + if(type != GL_FLOAT) return; /* Expect Floating point vertices */ + + if(GL_ARRAY_ACTIVE_TEXTURE == 0) { + (stride) ? (GL_TEXCOORD_STRIDE = stride / 4) : (GL_TEXCOORD_STRIDE = 2); + + GL_TEXCOORD_POINTER = (float *)pointer; + + GL_VERTEX_PTR_MODE |= GL_USE_TEXTURE; + + GL_ARRAY_TEXTURE_ENABLED |= GL_TEXTURE_0; + } + else if(GL_ARRAY_ACTIVE_TEXTURE == 1) { + (stride) ? (GL_TEXCOORD2_STRIDE = stride / 4) : (GL_TEXCOORD2_STRIDE = 2); + + GL_TEXCOORD2_POINTER = (float *)pointer; + + GL_ARRAY_TEXTURE_ENABLED |= GL_TEXTURE_1; + } +} + +/* Submit a Color Pointer */ +void glColorPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + if((type == GL_UNSIGNED_INT) && (size == 1)) { + GL_COLOR_COMPONENTS = 1; + GL_COLOR_POINTER = (GLvoid *)pointer; + GL_COLOR_TYPE = type; + } + else if((type == GL_UNSIGNED_BYTE) && (size == 4)) { + GL_COLOR_COMPONENTS = 4; + GL_COLOR_POINTER = (GLvoid *)pointer; + GL_COLOR_TYPE = type; + } + else if((type == GL_FLOAT) && (size == 3)) { + GL_COLOR_COMPONENTS = 3; + GL_COLOR_POINTER = (GLfloat *)pointer; + GL_COLOR_TYPE = type; + } + else if((type == GL_FLOAT) && (size == 4)) { + GL_COLOR_COMPONENTS = 4; + GL_COLOR_POINTER = (GLfloat *)pointer; + GL_COLOR_TYPE = type; + } + else + return; + + (stride) ? (GL_COLOR_STRIDE = stride / 4) : (GL_COLOR_STRIDE = size); + + GL_VERTEX_PTR_MODE |= GL_USE_COLOR; +} +//========================================================================================// +//== Vertex Pointer Internal API ==// + +inline void _glKosArrayBufIncrement() { + ++GL_ARRAY_BUF_PTR; +} + +inline void _glKosArrayBufReset() { + GL_ARRAY_BUF_PTR = &GL_ARRAY_BUF[0]; +} + +inline glVertex *_glKosArrayBufAddr() { + return &GL_ARRAY_BUF[0]; +} + +inline glVertex *_glKosArrayBufPtr() { + return GL_ARRAY_BUF_PTR; +} + +static inline void _glKosArraysTransformNormals(GLfloat *normal, GLuint count) { + glVertex *v = &GL_ARRAY_BUF[0]; + GLfloat *N = normal; + + _glKosMatrixLoadModelRot(); + + while(count--) { + mat_trans_normal3_nomod(N[0], N[1], N[2], v->norm[0], v->norm[1], v->norm[2]); + N += 3; + ++v; + } +} + +static inline void _glKosArraysTransformPositions(GLfloat *position, GLuint count) { + glVertex *v = &GL_ARRAY_BUF[0]; + GLfloat *P = position; + + _glKosMatrixLoadModelView(); + + while(count--) { + mat_trans_single3_nodiv_nomod(P[0], P[1], P[2], v->pos[0], v->pos[1], v->pos[2]); + P += 3; + ++v; + } +} + +//========================================================================================// +//== Arrays Vertex Transform ==/ + +static void _glKosArraysTransform(GLuint count) { + GLfloat *src = GL_VERTEX_POINTER; + pvr_vertex_t *dst = _glKosVertexBufPointer(); + + register float __x __asm__("fr12"); + register float __y __asm__("fr13"); + register float __z __asm__("fr14"); + + while(count--) { + __x = *src++; + __y = *src++; + __z = *src++; + + mat_trans_fv12() + + dst->x = __x; + dst->y = __y; + dst->z = __z; + + ++dst; + } +} + +static void _glKosArraysTransformClip(GLuint count) { + GLfloat *src = GL_VERTEX_POINTER; + GLfloat *W = GL_ARRAY_DSTW; + pvr_vertex_t *dst = _glKosClipBufAddress(); + + register float __x __asm__("fr12"); + register float __y __asm__("fr13"); + register float __z __asm__("fr14"); + register float __w __asm__("fr15"); + + while(count--) { + __x = *src++; + __y = *src++; + __z = *src++; + + mat_trans_fv12_nodivw() + + dst->x = __x; + dst->y = __y; + dst->z = __z; + *W++ = __w; + ++dst; + } +} + +static void _glKosArraysTransformElements(GLuint count) { + GLfloat *src = GL_VERTEX_POINTER; + GLuint i = 0; + + register float __x __asm__("fr12"); + register float __y __asm__("fr13"); + register float __z __asm__("fr14"); + + printf("Transform Elements()\n"); + + for(i = 0; i < count; i++) { + __x = src[0]; + __y = src[1]; + __z = src[2]; + + mat_trans_fv12() + + GL_ARRAY_BUF[i].pos[0] = __x; + GL_ARRAY_BUF[i].pos[1] = __y; + GL_ARRAY_BUF[i].pos[2] = __z; + + src += GL_VERTEX_STRIDE; + } +} + +static void _glKosArraysTransformClipElements(GLuint count) { + GLfloat *src = GL_VERTEX_POINTER; + GLuint i; + + register float __x __asm__("fr12"); + register float __y __asm__("fr13"); + register float __z __asm__("fr14"); + register float __w __asm__("fr15"); + + for(i = 0; i < count; i++) { + __x = src[0]; + __y = src[1]; + __z = src[2]; + + mat_trans_fv12_nodivw() + + GL_ARRAY_BUF[i].pos[0] = __x; + GL_ARRAY_BUF[i].pos[1] = __y; + GL_ARRAY_BUF[i].pos[2] = __z; + GL_ARRAY_BUFW[i] = __w; + + src += GL_VERTEX_STRIDE; + } +} + +//========================================================================================// +//== Element Attribute Functions ==// + +//== Color ==// + +static inline void _glKosElementColor0(pvr_vertex_t *dst, GLuint count) { + GLuint i; + + for(i = 0; i < count; i++) + dst[i].argb = 0xFFFFFFFF; +} + +static inline void _glKosElementColor1uiU8(pvr_vertex_t *dst, GLuint count) { + GLuint i; + GLuint *src = (GLuint *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) + dst[i].argb = src[GL_INDEX_POINTER_U8[i] * GL_COLOR_STRIDE]; +} + +static inline void _glKosElementColor1uiU16(pvr_vertex_t *dst, GLuint count) { + GLuint i; + GLuint *color = (GLuint *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) + dst[i].argb = color[GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE]; +} + +static inline void _glKosElementColor4ubU8(pvr_vertex_t *dst, GLuint count) { + GLuint i, *color = (GLuint *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) + dst[i].argb = RGBA32_2_ARGB32(color[GL_INDEX_POINTER_U8[i]] * GL_COLOR_STRIDE); +} + +static inline void _glKosElementColor4ubU16(pvr_vertex_t *dst, GLuint count) { + GLuint i, *color = (GLuint *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) + dst[i].argb = RGBA32_2_ARGB32(color[GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE]); +} + +static inline void _glKosElementColor3fU8(pvr_vertex_t *dst, GLuint count) { + GLuint i, index; + GLrgb3f *color = (GLrgb3f *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + index = GL_INDEX_POINTER_U8[i] * GL_COLOR_STRIDE; + dst[i].argb = (0xFF000000 | ((GLubyte)color[index][0] * 0xFF) << 16 + | ((GLubyte)color[index][1] * 0xFF) << 8 + | ((GLubyte)color[index][2] * 0xFF)); + } +} + +static inline void _glKosElementColor3fU16(pvr_vertex_t *dst, GLuint count) { + GLuint i, index; + GLrgb3f *color = (GLrgb3f *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + index = GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE; + dst[i].argb = (0xFF000000 | ((GLubyte)color[index][0] * 0xFF) << 16 + | ((GLubyte)color[index][1] * 0xFF) << 8 + | ((GLubyte)color[index][2] * 0xFF)); + } +} + +static inline void _glKosElementColor4fU8(pvr_vertex_t *dst, GLuint count) { + GLuint i, index; + GLrgba4f *color = (GLrgba4f *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + index = GL_INDEX_POINTER_U8[i] * GL_COLOR_STRIDE; + dst[i].argb = (((GLubyte)color[index][3] * 0xFF) << 24 + | ((GLubyte)color[index][0] * 0xFF) << 16 + | ((GLubyte)color[index][1] * 0xFF) << 8 + | ((GLubyte)color[index][2] * 0xFF)); + } +} + +static inline void _glKosElementColor4fU16(pvr_vertex_t *dst, GLuint count) { + GLuint i, index; + GLrgba4f *color = (GLrgba4f *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + index = GL_INDEX_POINTER_U16[i] * GL_COLOR_STRIDE; + dst[i].argb = (((GLubyte)color[index][3] * 0xFF) << 24 + | ((GLubyte)color[index][0] * 0xFF) << 16 + | ((GLubyte)color[index][1] * 0xFF) << 8 + | ((GLubyte)color[index][2] * 0xFF)); + } +} + +//== Texture Coordinates ==// + +static inline void _glKosElementTexCoord2fU16(pvr_vertex_t *dst, GLuint count) { + GLuint i, index; + GLfloat *t = GL_TEXCOORD_POINTER; + + for(i = 0; i < count; i++) { + index = GL_INDEX_POINTER_U16[i] * GL_TEXCOORD_STRIDE; + dst[i].u = t[index]; + dst[i].v = t[index + 1]; + } +} + +static inline void _glKosElementTexCoord2fU8(pvr_vertex_t *dst, GLuint count) { + GLuint i, index; + GLfloat *t = GL_TEXCOORD_POINTER; + + for(i = 0; i < count; i++) { + index = GL_INDEX_POINTER_U8[i] * GL_TEXCOORD_STRIDE; + dst[i].u = t[index]; + dst[i].v = t[index + 1]; + } +} + +//========================================================================================// +//== Element Unpacking ==// + +static inline void _glKosArraysUnpackElementsS16(pvr_vertex_t *dst, GLuint count) { + glVertex *vert = GL_ARRAY_BUF; + GLuint i; + + for(i = 0; i < count; i++) { + dst[i].x = vert[GL_INDEX_POINTER_U16[i]].pos[0]; + dst[i].y = vert[GL_INDEX_POINTER_U16[i]].pos[1]; + dst[i].z = vert[GL_INDEX_POINTER_U16[i]].pos[2]; + } +} + +static inline void _glKosArraysUnpackElementsS8(pvr_vertex_t *dst, GLuint count) { + glVertex *vert = GL_ARRAY_BUF; + GLuint i; + + for(i = 0; i < count; i++) { + dst[i].x = vert[GL_INDEX_POINTER_U8[i]].pos[0]; + dst[i].y = vert[GL_INDEX_POINTER_U8[i]].pos[1]; + dst[i].z = vert[GL_INDEX_POINTER_U8[i]].pos[2]; + } +} + +static inline void _glKosArraysUnpackClipElementsS16(pvr_vertex_t *dst, GLuint count) { + glVertex *vert = GL_ARRAY_BUF; + GLuint i; + + for(i = 0; i < count; i++) { + dst[i].x = vert[GL_INDEX_POINTER_U16[i]].pos[0]; + dst[i].y = vert[GL_INDEX_POINTER_U16[i]].pos[1]; + dst[i].z = vert[GL_INDEX_POINTER_U16[i]].pos[2]; + GL_ARRAY_DSTW[i] = GL_ARRAY_BUFW[GL_INDEX_POINTER_U16[i]]; + } +} + +static inline void _glKosArraysUnpackClipElementsS8(pvr_vertex_t *dst, GLuint count) { + glVertex *vert = GL_ARRAY_BUF; + GLuint i; + + for(i = 0; i < count; i++) { + dst[i].x = vert[GL_INDEX_POINTER_U8[i]].pos[0]; + dst[i].y = vert[GL_INDEX_POINTER_U8[i]].pos[1]; + dst[i].z = vert[GL_INDEX_POINTER_U8[i]].pos[2]; + GL_ARRAY_DSTW[i] = GL_ARRAY_BUFW[GL_INDEX_POINTER_U8[i]]; + } +} + +//========================================================================================// +//== Misc Utils ==// + +static inline void _glKosVertexSwizzle(pvr_vertex_t *v1, pvr_vertex_t *v2) { + pvr_vertex_t tmp = *v1; + *v1 = *v2; + *v2 = * &tmp; +} + +static inline void _glKosArraysResetState() { + GL_VERTEX_PTR_MODE = 0; + + if(GL_ARRAY_TEXTURE_ENABLED == 3) + _glKosResetEnabledTex(); + + GL_ARRAY_TEXTURE_ENABLED = GL_ARRAY_ACTIVE_TEXTURE = 0; +} + +//========================================================================================// +//== Vertex Flag Settings for the PVR2DC hardware ==// + +static inline void _glKosArrayFlagsSetQuad(pvr_vertex_t *dst, GLuint count) { + GLuint i; + + for(i = 0; i < count; i += 4) { + _glKosVertexSwizzle(&dst[2], &dst[3]); + dst[i + 0].flags = dst[i + 1].flags = dst[i + 2].flags = PVR_CMD_VERTEX; + dst[i + 3].flags = PVR_CMD_VERTEX_EOL; + } +} + +static inline void _glKosArrayFlagsSetTriangle(pvr_vertex_t *dst, GLuint count) { + GLuint i; + + for(i = 0; i < count; i += 3) { + dst[i + 0].flags = dst[i + 1].flags = PVR_CMD_VERTEX; + dst[i + 2].flags = PVR_CMD_VERTEX_EOL; + } +} + +static inline void _glKosArrayFlagsSetTriangleStrip(pvr_vertex_t *dst, GLuint count) { + GLuint i; + + for(i = 0; i < count - 1; i++) + dst[i].flags = PVR_CMD_VERTEX; + + dst[i].flags = PVR_CMD_VERTEX_EOL; +} + +//========================================================================================// +//== OpenGL Error Code Genration ==// + +static GLuint _glKosArraysVerifyParameter(GLenum mode, GLsizei count, GLenum type, GLubyte element) { + GLuint GL_ERROR_CODE = 0; + + if(mode != GL_QUADS) + if(mode != GL_TRIANGLES) + if(mode != GL_TRIANGLE_STRIP) + GL_ERROR_CODE |= GL_INVALID_ENUM; + + if(count < 0) + GL_ERROR_CODE |= GL_INVALID_VALUE; + + if(!(GL_VERTEX_PTR_MODE & GL_USE_ARRAY)) + GL_ERROR_CODE |= GL_INVALID_OPERATION; + + if(count > GL_MAX_ARRAY_VERTICES) + GL_ERROR_CODE |= GL_OUT_OF_MEMORY; + + if(element) { + switch(type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + + default: + GL_ERROR_CODE |= GL_INVALID_ENUM; + } + } + else if(type > count) + GL_ERROR_CODE |= GL_INVALID_VALUE; + + return GL_ERROR_CODE; +} + +void _glKosPrintErrorString(GLuint error) { + if(error) { + printf("GL_ERROR_CODE GENERATED:\n"); + + if(error & GL_INVALID_ENUM) + printf("\tGL_INVALID_ENUM\n"); + + if(error & GL_INVALID_VALUE) + printf("\tGL_INVALID_VALUE\n"); + + if(error & GL_INVALID_OPERATION) + printf("\tGL_INVALID__OPERATION\n"); + + if(error & GL_OUT_OF_MEMORY) + printf("\tGL_OUT_OF_MEMORY\n"); + } +} + +//========================================================================================// +//== OpenGL Elemental Array Submission ==// + +void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { + /* Before we process the vertex data, ensure all parameters are valid */ + GLuint error = _glKosArraysVerifyParameter(mode, count, type, 1); + + if(error) { + _glKosPrintErrorString(error); + + _glKosArraysResetState(); + + return; + } + + switch(type) { + case GL_UNSIGNED_BYTE: + GL_INDEX_POINTER_U8 = (GLubyte *)indices; + break; + + case GL_UNSIGNED_SHORT: + GL_INDEX_POINTER_U16 = (GLushort *)indices; + break; + } + + /* Compile the PVR polygon context with the currently enabled flags */ + if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE)) + _glKosCompileHdrTx(); + else + _glKosCompileHdr(); + + if(GL_ARRAY_TEXTURE_ENABLED == 3) /* Multi-Texture! */ + _glKosCompileHdrTx2(); + + pvr_vertex_t *dst; /* Destination of Output Vertex Array */ + + if(_glKosEnabledNearZClip()) + dst = _glKosClipBufAddress(); + else + dst = _glKosVertexBufPointer(); + + /* Check if Vertex Lighting is enabled. Else, check for Color Submission */ + if((GL_VERTEX_PTR_MODE & GL_USE_NORMAL) && _glKosEnabledLighting()) { + _glKosArraysTransformNormals(GL_NORMAL_POINTER, count); + _glKosArraysTransformPositions(GL_VERTEX_POINTER, count); + _glKosVertexLights(GL_ARRAY_BUF, dst, count); + } + else if(GL_VERTEX_PTR_MODE & GL_USE_COLOR) { + switch(GL_COLOR_TYPE) { + case GL_FLOAT: + switch(GL_COLOR_COMPONENTS) { + case 3: + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosElementColor3fU8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosElementColor3fU16(dst, count); + break; + } + + break; + + case 4: + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosElementColor4fU8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosElementColor4fU16(dst, count); + break; + } + + break; + } + + break; + + case GL_UNSIGNED_INT: + if(GL_COLOR_COMPONENTS == 1) + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosElementColor1uiU8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosElementColor1uiU16(dst, count); + break; + } + + break; + + case GL_UNSIGNED_BYTE: + if(GL_COLOR_COMPONENTS == 4) + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosElementColor4ubU8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosElementColor4ubU16(dst, count); + break; + } + + break; + } + } + else + _glKosElementColor0(dst, count); /* No colors bound, color white */ + + /* Check if Texture Coordinates are enabled */ + if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE) && (_glKosEnabledTexture2D() >= 0)) + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosElementTexCoord2fU8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosElementTexCoord2fU16(dst, count); + break; + } + + _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ + + if(!(_glKosEnabledNearZClip())) {/* Transform the element vertices */ + /* Transform vertices with perspective divde */ + _glKosArraysTransformElements(count); + + /* Unpack the indexed positions into primitives for rasterization */ + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosArraysUnpackElementsS8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosArraysUnpackElementsS16(dst, count); + break; + } + + /* Set the vertex flags for use with the PVR */ + switch(mode) { + case GL_QUADS: + _glKosArrayFlagsSetQuad(dst, count); + break; + + case GL_TRIANGLES: + _glKosArrayFlagsSetTriangle(dst, count); + break; + + case GL_TRIANGLE_STRIP: + _glKosArrayFlagsSetTriangleStrip(dst, count); + break; + } + + if(mode == GL_QUADS) + _glKosArrayCopyMultiTextureQuads(count); + else + _glKosArrayCopyMultiTexture(count); + } + else { + /* Transform vertices with no perspective divde, store w component */ + _glKosArraysTransformClipElements(count); + + /* Unpack the indexed positions into primitives for rasterization */ + switch(type) { + case GL_UNSIGNED_BYTE: + _glKosArraysUnpackClipElementsS8(dst, count); + break; + + case GL_UNSIGNED_SHORT: + _glKosArraysUnpackClipElementsS16(dst, count); + break; + } + + /* Finally, clip the input vertex data into the output vertex buffer */ + switch(mode) { + case GL_TRIANGLES: + count = _glKosClipTrianglesTransformed(dst, GL_ARRAY_DSTW, + (pvr_vertex_t *)_glKosVertexBufPointer(), count); + break; + + case GL_QUADS: + count = _glKosClipQuadsTransformed(dst, GL_ARRAY_DSTW, + (pvr_vertex_t *)_glKosVertexBufPointer(), count); + + break; + + case GL_TRIANGLE_STRIP: + count = _glKosClipTriangleStripTransformed(dst, GL_ARRAY_DSTW, + (pvr_vertex_t *)_glKosVertexBufPointer(), count); + break; + } + } + + _glKosVertexBufAdd(count); + + _glKosArraysResetState(); +} + + + +//========================================================================================// +//== Array Attribute Functions ==// + +//== Color ==// + +static inline void _glKosArrayColor0(pvr_vertex_t *dst, GLuint count) { + GLuint i; + + for(i = 0; i < count; i++) + dst[i].argb = 0xFFFFFFFF; +} + +static inline void _glKosArrayColor1ui(pvr_vertex_t *dst, GLuint count) { + GLuint i; + GLuint *color = (GLuint *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + dst[i].argb = *color; + color += GL_COLOR_STRIDE; + } +} + +static inline void _glKosArrayColor4ub(pvr_vertex_t *dst, GLuint count) { + GLuint i, *color = (GLuint *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + dst[i].argb = RGBA32_2_ARGB32(*color); + color += GL_COLOR_STRIDE; + } +} + +static inline void _glKosArrayColor3f(pvr_vertex_t *dst, GLuint count) { + GLuint i; + GLfloat *color = (GLfloat *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + dst[i].argb = (0xFF000000 | ((GLubyte)(color[0] * 0xFF)) << 16 + | ((GLubyte)(color[1] * 0xFF)) << 8 + | ((GLubyte)(color[2] * 0xFF))); + color += GL_COLOR_STRIDE; + } +} + +static inline void _glKosArrayColor4f(pvr_vertex_t *dst, GLuint count) { + GLuint i; + GLfloat *color = (GLfloat *)GL_COLOR_POINTER; + + for(i = 0; i < count; i++) { + dst[i].argb = (((GLubyte)(color[3] * 0xFF)) << 24 + | ((GLubyte)(color[0] * 0xFF)) << 16 + | ((GLubyte)(color[1] * 0xFF)) << 8 + | ((GLubyte)(color[2] * 0xFF))); + color += GL_COLOR_STRIDE; + } +} + +//== Texture Coordinates ==// + +static inline void _glKosArrayTexCoord2f(pvr_vertex_t *dst, GLuint count) { + GLuint i; + GLfloat *uv = GL_TEXCOORD_POINTER; + + for(i = 0; i < count; i++) { + dst[i].u = uv[0]; + dst[i].v = uv[1]; + uv += GL_TEXCOORD_STRIDE; + } +} + +//========================================================================================// +//== Openg GL Draw Arrays ==// + +void glDrawArrays(GLenum mode, GLint first, GLsizei count) { + /* Before we process the vertex data, ensure all parameters are valid */ + GLuint error = _glKosArraysVerifyParameter(mode, count, first, 0); + + if(error) { + _glKosPrintErrorString(error); + + return _glKosArraysResetState(); + } + + GL_VERTEX_POINTER += first; /* Add Pointer Offset */ + GL_TEXCOORD_POINTER += first; + GL_COLOR_POINTER += first; + GL_NORMAL_POINTER += first; + + /* Compile the PVR polygon context with the currently enabled flags */ + if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE)) + _glKosCompileHdrTx(); + else + _glKosCompileHdr(); + + if(GL_ARRAY_TEXTURE_ENABLED == 3) /* Multi-Texture! */ + _glKosCompileHdrTx2(); + + pvr_vertex_t *dst; /* Destination of Output Vertex Array */ + + if(_glKosEnabledNearZClip()) + dst = _glKosClipBufAddress(); + else + dst = _glKosVertexBufPointer(); + + /* Check if Vertex Lighting is enabled. Else, check for Color Submission */ + if((GL_VERTEX_PTR_MODE & GL_USE_NORMAL) && _glKosEnabledLighting()) { + _glKosArraysTransformNormals(GL_NORMAL_POINTER, count); + _glKosArraysTransformPositions(GL_VERTEX_POINTER, count); + _glKosVertexLights(GL_ARRAY_BUF, dst, count); + } + else if(GL_VERTEX_PTR_MODE & GL_USE_COLOR) { + switch(GL_COLOR_TYPE) { + case GL_FLOAT: + switch(GL_COLOR_COMPONENTS) { + case 3: + _glKosArrayColor3f(dst, count); + break; + + case 4: + _glKosArrayColor4f(dst, count); + break; + } + + break; + + case GL_UNSIGNED_INT: + if(GL_COLOR_COMPONENTS == 1) + _glKosArrayColor1ui(dst, count); + + break; + + case GL_UNSIGNED_BYTE: + if(GL_COLOR_COMPONENTS == 4) + _glKosArrayColor4ub(dst, count); + + break; + } + } + else + _glKosArrayColor0(dst, count); /* No colors bound, color white */ + + /* Check if Texture Coordinates are enabled */ + if((GL_VERTEX_PTR_MODE & GL_USE_TEXTURE) && (_glKosEnabledTexture2D() >= 0)) + _glKosArrayTexCoord2f(dst, count); + + _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ + + if(!_glKosEnabledNearZClip()) { + /* Transform Vertex Positions */ + _glKosArraysTransform(count); + + /* Set the vertex flags for use with the PVR */ + switch(mode) { + case GL_QUADS: + _glKosArrayFlagsSetQuad(dst, count); + break; + + case GL_TRIANGLES: + _glKosArrayFlagsSetTriangle(dst, count); + break; + + case GL_TRIANGLE_STRIP: + _glKosArrayFlagsSetTriangleStrip(dst, count); + break; + } + + if(mode == GL_QUADS) + _glKosArrayCopyMultiTextureQuads(count); + else + _glKosArrayCopyMultiTexture(count); + } + else { + /* Transform vertices with no perspective divde, store w component */ + _glKosArraysTransformClip(count); + + /* Finally, clip the input vertex data into the output vertex buffer */ + switch(mode) { + case GL_TRIANGLES: + count = _glKosClipTrianglesTransformed(dst, GL_ARRAY_DSTW, + (pvr_vertex_t *)_glKosVertexBufPointer(), count); + break; + + case GL_QUADS: + count = _glKosClipQuadsTransformed(dst, GL_ARRAY_DSTW, + (pvr_vertex_t *)_glKosVertexBufPointer(), count); + + break; + + case GL_TRIANGLE_STRIP: + count = _glKosClipTriangleStripTransformed(dst, GL_ARRAY_DSTW, + (pvr_vertex_t *)_glKosVertexBufPointer(), count); + break; + } + } + + _glKosVertexBufAdd(count); + + _glKosArraysResetState(); } \ No newline at end of file diff --git a/gl-arrays.h b/gl-arrays.h index d514169..16e5fa2 100755 --- a/gl-arrays.h +++ b/gl-arrays.h @@ -1,58 +1,58 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-arrays.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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. - - ToDo: glDrawElements() is not yet implemented. -*/ - -#ifndef GL_ARRAYS_H -#define GL_ARRAYS_H - -#include "gl.h" - -#define GL_USE_ARRAY 0x0001 -#define GL_USE_TEXTURE 0x0010 -#define GL_USE_COLOR 0x0100 -#define GL_USE_NORMAL 0x1000 -#define GL_USE_TEXTURE_COLOR 0x0111 -#define GL_USE_TEXTURE_LIT 0x1011 - -void (*_glKosArrayTexCoordFunc)(pvr_vertex_t *); -void (*_glKosArrayColorFunc)(pvr_vertex_t *); - -void (*_glKosElementTexCoordFunc)(pvr_vertex_t *, GLuint); -void (*_glKosElementColorFunc)(pvr_vertex_t *, GLuint); - -static GLfloat *GL_VERTEX_POINTER = NULL; -static GLushort GL_VERTEX_STRIDE = 0; - -static GLfloat *GL_NORMAL_POINTER = NULL; -static GLushort GL_NORMAL_STRIDE = 0; - -static GLfloat *GL_TEXCOORD_POINTER = NULL; -static GLushort GL_TEXCOORD_STRIDE = 0; - -static GLfloat *GL_TEXCOORD2_POINTER = NULL; -static GLushort GL_TEXCOORD2_STRIDE = 0; - -static GLfloat *GL_COLOR_POINTER = NULL; -static GLushort GL_COLOR_STRIDE = 0; -static GLubyte GL_COLOR_COMPONENTS = 0; -static GLenum GL_COLOR_TYPE = 0; - -static GLubyte *GL_INDEX_POINTER_U8 = NULL; -static GLushort *GL_INDEX_POINTER_U16 = NULL; - -#endif +/* KallistiGL for KallistiOS ##version## + + libgl/gl-arrays.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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. + + ToDo: glDrawElements() is not yet implemented. +*/ + +#ifndef GL_ARRAYS_H +#define GL_ARRAYS_H + +#include "gl.h" + +#define GL_USE_ARRAY 0x0001 +#define GL_USE_TEXTURE 0x0010 +#define GL_USE_COLOR 0x0100 +#define GL_USE_NORMAL 0x1000 +#define GL_USE_TEXTURE_COLOR 0x0111 +#define GL_USE_TEXTURE_LIT 0x1011 + +void (*_glKosArrayTexCoordFunc)(pvr_vertex_t *); +void (*_glKosArrayColorFunc)(pvr_vertex_t *); + +void (*_glKosElementTexCoordFunc)(pvr_vertex_t *, GLuint); +void (*_glKosElementColorFunc)(pvr_vertex_t *, GLuint); + +static GLfloat *GL_VERTEX_POINTER = NULL; +static GLushort GL_VERTEX_STRIDE = 0; + +static GLfloat *GL_NORMAL_POINTER = NULL; +static GLushort GL_NORMAL_STRIDE = 0; + +static GLfloat *GL_TEXCOORD_POINTER = NULL; +static GLushort GL_TEXCOORD_STRIDE = 0; + +static GLfloat *GL_TEXCOORD2_POINTER = NULL; +static GLushort GL_TEXCOORD2_STRIDE = 0; + +static GLfloat *GL_COLOR_POINTER = NULL; +static GLushort GL_COLOR_STRIDE = 0; +static GLubyte GL_COLOR_COMPONENTS = 0; +static GLenum GL_COLOR_TYPE = 0; + +static GLubyte *GL_INDEX_POINTER_U8 = NULL; +static GLushort *GL_INDEX_POINTER_U16 = NULL; + +#endif diff --git a/gl-clip.c b/gl-clip.c index b1a704a..86943f4 100755 --- a/gl-clip.c +++ b/gl-clip.c @@ -1,745 +1,745 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-clip.c - Copyright (C) 2013-2014 Josh "PH3NOM" 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 -#include - -#include "gl-clip.h" - -static float3 CLIP_BUF[1024 * 32]; - -static inline void glVertexCopy3f(float3 *src, float3 *dst) { - *dst = *src; -} - -static inline void glVertexCopyPVR(pvr_vertex_t *src, pvr_vertex_t *dst) { - *dst = *src; -} - -static inline void _glKosVertexCopyPVR(pvr_vertex_t *src, pvr_vertex_t *dst) { - *dst = *src; -} - -static inline float ZclipMag(float3 *v1, float3 *v2) { - return ((CLIP_NEARZ - v1->z) / (v2->z - v1->z)); -} - -static inline void glVertexClipZNear(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 inline void _glKosVertexClipZNear3(pvr_vertex_t *v1, pvr_vertex_t *v2, float *w1, float *w2) { - float 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 GLuint glTransformClip(pvr_vertex_t *v, int 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 *vin, pvr_vertex_t *vout, unsigned int vertices) { - GLuint i, v = 0, in = glTransformClip(vin, vertices); - float3 *C = CLIP_BUF; - - if(in == vertices) { - memcpy(vout, vin, vertices * 0x20); - pvr_vertex_t *v = vout; - - 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++) { - unsigned short int clip = 0; /* Clip Code for current Triangle */ - unsigned char 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(&vout[v], &vin[i], 96); - - vout[v].flags = vout[v + 1].flags = PVR_CMD_VERTEX; - vout[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(&vout[v], &vin[i], 96); - - switch(clip) { - case FIRST_TWO_OUT: - glVertexClipZNear(&vout[v], &vout[v + 2], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 2])); - glVertexClipZNear(&vout[v + 1], &vout[v + 2], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 2])); - - break; - - case FIRST_AND_LAST_OUT: - glVertexClipZNear(&vout[v], &vout[v + 1], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 1])); - glVertexClipZNear(&vout[v + 2], &vout[v + 1], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 1])); - - break; - - case LAST_TWO_OUT: - glVertexClipZNear(&vout[v + 1], &vout[v], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 0])); - glVertexClipZNear(&vout[v + 2], &vout[v], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 0])); - - break; - } - - vout[v].flags = vout[v + 1].flags = PVR_CMD_VERTEX; - vout[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: - glVertexCopyPVR(&vin[i + 0], &vout[v + 0]); - glVertexCopyPVR(&vin[i + 1], &vout[v + 1]); - glVertexCopyPVR(&vin[i + 0], &vout[v + 2]); - glVertexCopyPVR(&vin[i + 2], &vout[v + 3]); - glVertexClipZNear(&vout[v + 0], &vout[v + 1], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 1])); - glVertexClipZNear(&vout[v + 2], &vout[v + 3], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 2])); - break; - - case SECOND: - glVertexCopyPVR(&vin[i + 1], &vout[v + 0]); - glVertexCopyPVR(&vin[i + 0], &vout[v + 1]); - glVertexCopyPVR(&vin[i + 1], &vout[v + 2]); - glVertexCopyPVR(&vin[i + 2], &vout[v + 3]); - glVertexClipZNear(&vout[v + 0], &vout[v + 1], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 0])); - glVertexClipZNear(&vout[v + 2], &vout[v + 3], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 2])); - break; - - case THIRD: - glVertexCopyPVR(&vin[i + 2], &vout[v + 0]); - glVertexCopyPVR(&vin[i + 0], &vout[v + 1]); - glVertexCopyPVR(&vin[i + 2], &vout[v + 2]); - glVertexCopyPVR(&vin[i + 1], &vout[v + 3]); - glVertexClipZNear(&vout[v + 0], &vout[v + 1], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i])); - glVertexClipZNear(&vout[v + 2], &vout[v + 3], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 1])); - break; - } - - vout[v + 0].flags = vout[v + 1].flags = vout[v + 2].flags = PVR_CMD_VERTEX; - vout[v + 3].flags = PVR_CMD_VERTEX_EOL; - v += 4; - - break; - } - - C++; - } - - return v; -} - -static inline unsigned char _glKosClipTri(pvr_vertex_t *vin, pvr_vertex_t *vout) { - unsigned short int clip = 0; /* Clip Code for current Triangle */ - unsigned char 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") = vin->x; - register float __y __asm__("fr13") = vin->y; - register float __z __asm__("fr14") = vin->z; - - mat_trans_fv12_nodiv(); - - clip_buf[0].x = __x; - clip_buf[0].y = __y; - clip_buf[0].z = __z; - - __x = (vin + 1)->x; - __y = (vin + 1)->y; - __z = (vin + 1)->z; - - mat_trans_fv12_nodiv(); - - clip_buf[1].x = __x; - clip_buf[1].y = __y; - clip_buf[1].z = __z; - - __x = (vin + 2)->x; - __y = (vin + 2)->y; - __z = (vin + 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(vout, vin, 96); - - vout->flags = (vout + 1)->flags = PVR_CMD_VERTEX; - (vout + 2)->flags = PVR_CMD_VERTEX_EOL; - - return 3; - - case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ - memcpy(vout, vin, 96); - - switch(clip) { - case FIRST_TWO_OUT: - glVertexClipZNear(vout, vout + 2, ZclipMag(&clip_buf[0], &clip_buf[2])); - glVertexClipZNear(vout + 1, vout + 2, ZclipMag(&clip_buf[1], &clip_buf[2])); - - break; - - case FIRST_AND_LAST_OUT: - glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[0], &clip_buf[1])); - glVertexClipZNear(vout + 2, vout + 1, ZclipMag(&clip_buf[2], &clip_buf[1])); - - break; - - case LAST_TWO_OUT: - glVertexClipZNear(vout + 1, vout, ZclipMag(&clip_buf[1], &clip_buf[0])); - glVertexClipZNear(vout + 2, vout, ZclipMag(&clip_buf[2], &clip_buf[0])); - - break; - } - - vout->flags = (vout + 1)->flags = PVR_CMD_VERTEX; - (vout + 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(vout, vin, 64); - glVertexCopyPVR(vin, vout + 2); - glVertexCopyPVR(vin + 2, vout + 3); - glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[0], &clip_buf[1])); - glVertexClipZNear(vout + 2, vout + 3, ZclipMag(&clip_buf[0], &clip_buf[2])); - break; - - case SECOND: - glVertexCopyPVR(vin + 1, vout); - glVertexCopyPVR(vin, vout + 1); - memcpy(vout + 2, vin + 1, 64); - glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[1], &clip_buf[0])); - glVertexClipZNear(vout + 2, vout + 3, ZclipMag(&clip_buf[1], &clip_buf[2])); - break; - - case THIRD: - glVertexCopyPVR(vin + 2, vout); - glVertexCopyPVR(vin, vout + 1); - glVertexCopyPVR(vin + 2, vout + 2); - glVertexCopyPVR(vin + 1, vout + 3); - glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[2], &clip_buf[0])); - glVertexClipZNear(vout + 2, vout + 3, ZclipMag(&clip_buf[2], &clip_buf[1])); - break; - } - - vout->flags = (vout + 1)->flags = (vout + 2)->flags = PVR_CMD_VERTEX; - (vout + 3)->flags = PVR_CMD_VERTEX_EOL; - - return 4; - } - - return 0; -} - -unsigned int _glKosClipTriangles(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices) { - unsigned int i, v = 0; - - for(i = 0; i < vertices; i += 3) /* Iterate all Triangles */ - v += _glKosClipTri(vin + i, vout + v); - - return v; -} - -unsigned int _glKosClipQuads(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices) { - unsigned int i, v = 0; - pvr_vertex_t qv; - - for(i = 0; i < vertices; i += 4) { /* Iterate all Quads, Rearranging into Triangle Strips */ - glVertexCopyPVR(vin + i + 3, &qv); - glVertexCopyPVR(vin + i + 2, vin + i + 3); - glVertexCopyPVR(&qv, vin + i + 2); - v += _glKosClipTriangleStrip(vin + i, vout + v, 4); - } - - return v; -} - -static inline void _glKosVertexPerspectiveDivide(pvr_vertex_t *dst, float w) { - dst->z = 1.0f / w; - dst->x *= dst->z; - dst->y *= dst->z; -} - -GLuint _glKosClipTrianglesTransformed(pvr_vertex_t *src, float *w, pvr_vertex_t *dst, GLuint count) { - pvr_vertex_t *vin = src; - pvr_vertex_t *vout = dst; - unsigned short int clip; - unsigned char verts_in = 0; - GLuint verts_out = 0; - GLuint i; - - for(i = 0; i < count; i += 3) { - clip = 0; /* Clip Code for current Triangle */ - verts_in = 0; /* # of Vertices inside clip plane for current Triangle */ - float W[4] = { w[i], w[i + 1], w[i + 2] }; /* W Component for Perspective Divide */ - - (vin[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in; - (vin[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in; - (vin[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 */ - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - - vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; - vout[2].flags = PVR_CMD_VERTEX_EOL; - - vout += 3; - verts_out += 3; - break; - - case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - - switch(clip) { - case FIRST_TWO_OUT: - _glKosVertexClipZNear3(&vout[0], &vout[2], &W[0], &W[2]); - _glKosVertexClipZNear3(&vout[1], &vout[2], &W[1], &W[2]); - - break; - - case FIRST_AND_LAST_OUT: - _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); - _glKosVertexClipZNear3(&vout[2], &vout[1], &W[2], &W[1]); - - break; - - case LAST_TWO_OUT: - _glKosVertexClipZNear3(&vout[1], &vout[0], &W[1], &W[0]); - _glKosVertexClipZNear3(&vout[2], &vout[0], &W[2], &W[0]); - - break; - } - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - - vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; - vout[2].flags = PVR_CMD_VERTEX_EOL; - - vout += 3; - verts_out += 3; - break; - - case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */ - switch(clip) { - case FIRST: - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[0], &vout[2]); - _glKosVertexCopyPVR(&vin[2], &vout[3]); - W[3] = W[2]; - W[2] = W[0]; - - break; - - case SECOND: - _glKosVertexCopyPVR(&vin[1], &vout[0]); - _glKosVertexCopyPVR(&vin[2], &vout[1]); - _glKosVertexCopyPVR(&vin[1], &vout[2]); - _glKosVertexCopyPVR(&vin[0], &vout[3]); - W[3] = W[0]; - W[0] = W[1]; - W[1] = W[2]; - W[2] = W[0]; - - break; - - case THIRD: - _glKosVertexCopyPVR(&vin[2], &vout[0]); - _glKosVertexCopyPVR(&vin[0], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - _glKosVertexCopyPVR(&vin[1], &vout[3]); - W[3] = W[1]; - W[1] = W[0]; - W[0] = W[2]; - - break; - } - - _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); - _glKosVertexClipZNear3(&vout[2], &vout[3], &W[2], &W[3]); - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - _glKosVertexPerspectiveDivide(&vout[3], W[3]); - - vout[0].flags = vout[1].flags = vout[2].flags = PVR_CMD_VERTEX; - vout[3].flags = PVR_CMD_VERTEX_EOL; - - vout += 4; - verts_out += 4; - break; - } - - vin += 3; - } - - return verts_out; -} - -GLuint _glKosClipTriangleStripTransformed(pvr_vertex_t *src, float *w, pvr_vertex_t *dst, GLuint count) { - pvr_vertex_t *vin = src; - pvr_vertex_t *vout = dst; - unsigned short int clip; - unsigned char verts_in = 0; - GLuint verts_out = 0; - GLuint i; - - for(i = 0; i < (count - 2); i ++) { - clip = 0; /* Clip Code for current Triangle */ - verts_in = 0; /* # of Vertices inside clip plane for current Triangle */ - float W[4] = { w[i], w[i + 1], w[i + 2] }; /* W Component for Perspective Divide */ - - (vin[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in; - (vin[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in; - (vin[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 */ - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - - vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; - vout[2].flags = PVR_CMD_VERTEX_EOL; - - vout += 3; - verts_out += 3; - break; - - case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - - switch(clip) { - case FIRST_TWO_OUT: - _glKosVertexClipZNear3(&vout[0], &vout[2], &W[0], &W[2]); - _glKosVertexClipZNear3(&vout[1], &vout[2], &W[1], &W[2]); - - break; - - case FIRST_AND_LAST_OUT: - _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); - _glKosVertexClipZNear3(&vout[2], &vout[1], &W[2], &W[1]); - - break; - - case LAST_TWO_OUT: - _glKosVertexClipZNear3(&vout[1], &vout[0], &W[1], &W[0]); - _glKosVertexClipZNear3(&vout[2], &vout[0], &W[2], &W[0]); - - break; - } - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - - vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; - vout[2].flags = PVR_CMD_VERTEX_EOL; - - vout += 3; - verts_out += 3; - break; - - case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */ - switch(clip) { - case FIRST: - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[0], &vout[2]); - _glKosVertexCopyPVR(&vin[2], &vout[3]); - W[3] = W[2]; - W[2] = W[0]; - - break; - - case SECOND: - _glKosVertexCopyPVR(&vin[1], &vout[0]); - _glKosVertexCopyPVR(&vin[2], &vout[1]); - _glKosVertexCopyPVR(&vin[1], &vout[2]); - _glKosVertexCopyPVR(&vin[0], &vout[3]); - W[3] = W[0]; - W[0] = W[1]; - W[1] = W[2]; - W[2] = W[0]; - - break; - - case THIRD: - _glKosVertexCopyPVR(&vin[2], &vout[0]); - _glKosVertexCopyPVR(&vin[0], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - _glKosVertexCopyPVR(&vin[1], &vout[3]); - W[3] = W[1]; - W[1] = W[0]; - W[0] = W[2]; - - break; - } - - _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); - _glKosVertexClipZNear3(&vout[2], &vout[3], &W[2], &W[3]); - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - _glKosVertexPerspectiveDivide(&vout[3], W[3]); - - vout[0].flags = vout[1].flags = vout[2].flags = PVR_CMD_VERTEX; - vout[3].flags = PVR_CMD_VERTEX_EOL; - - vout += 4; - verts_out += 4; - break; - } - - ++vin; - } - - return verts_out; -} - -GLubyte _glKosClipTriTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout) { - unsigned short int clip = 0; /* Clip Code for current Triangle */ - unsigned char verts_in = 0; /* # of Vertices inside clip plane for current Triangle */ - float W[4] = { w[0], w[1], w[2] }; /* W Component for Perspective Divide */ - - (vin[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in; - (vin[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in; - (vin[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(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - - vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; - vout[2].flags = PVR_CMD_VERTEX_EOL; - - return 3; - - case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ - _glKosVertexCopyPVR(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - - switch(clip) { - case FIRST_TWO_OUT: - _glKosVertexClipZNear3(&vout[0], &vout[2], &W[0], &W[2]); - _glKosVertexClipZNear3(&vout[1], &vout[2], &W[1], &W[2]); - - break; - - case FIRST_AND_LAST_OUT: - _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); - _glKosVertexClipZNear3(&vout[2], &vout[1], &W[2], &W[1]); - - break; - - case LAST_TWO_OUT: - _glKosVertexClipZNear3(&vout[1], &vout[0], &W[1], &W[0]); - _glKosVertexClipZNear3(&vout[2], &vout[0], &W[2], &W[0]); - - break; - } - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - - vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; - vout[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(&vin[0], &vout[0]); - _glKosVertexCopyPVR(&vin[1], &vout[1]); - _glKosVertexCopyPVR(&vin[0], &vout[2]); - _glKosVertexCopyPVR(&vin[2], &vout[3]); - W[3] = W[2]; - W[2] = W[0]; - - break; - - case SECOND: - _glKosVertexCopyPVR(&vin[1], &vout[0]); - _glKosVertexCopyPVR(&vin[2], &vout[1]); - _glKosVertexCopyPVR(&vin[1], &vout[2]); - _glKosVertexCopyPVR(&vin[0], &vout[3]); - W[3] = W[0]; - W[0] = W[1]; - W[1] = W[2]; - W[2] = W[0]; - - break; - - case THIRD: - _glKosVertexCopyPVR(&vin[2], &vout[0]); - _glKosVertexCopyPVR(&vin[0], &vout[1]); - _glKosVertexCopyPVR(&vin[2], &vout[2]); - _glKosVertexCopyPVR(&vin[1], &vout[3]); - W[3] = W[1]; - W[1] = W[0]; - W[0] = W[2]; - - break; - } - - _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); - _glKosVertexClipZNear3(&vout[2], &vout[3], &W[2], &W[3]); - - _glKosVertexPerspectiveDivide(&vout[0], W[0]); - _glKosVertexPerspectiveDivide(&vout[1], W[1]); - _glKosVertexPerspectiveDivide(&vout[2], W[2]); - _glKosVertexPerspectiveDivide(&vout[3], W[3]); - - vout[0].flags = vout[1].flags = vout[2].flags = PVR_CMD_VERTEX; - vout[3].flags = PVR_CMD_VERTEX_EOL; - - return 4; - } - - return 0; -} - -unsigned int _glKosClipQuadsTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout, unsigned int vertices) { - unsigned int i, v = 0; - pvr_vertex_t qv[3]; - float W[3]; - - for(i = 0; i < vertices; i += 4) { /* Iterate all Quads, Rearranging into Triangle Strips */ - _glKosVertexCopyPVR(&vin[i + 0], &qv[0]); - _glKosVertexCopyPVR(&vin[i + 2], &qv[1]); - _glKosVertexCopyPVR(&vin[i + 3], &qv[2]); - W[0] = w[0]; - W[1] = w[2]; - W[2] = w[3]; - - v += _glKosClipTriTransformed(&vin[i], &w[i], &vout[v]); - v += _glKosClipTriTransformed(&qv[i], &W[i], &vout[v]); - } - - return v; -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-clip.c + Copyright (C) 2013-2014 Josh "PH3NOM" 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 +#include + +#include "gl-clip.h" + +static float3 CLIP_BUF[1024 * 32]; + +static inline void glVertexCopy3f(float3 *src, float3 *dst) { + *dst = *src; +} + +static inline void glVertexCopyPVR(pvr_vertex_t *src, pvr_vertex_t *dst) { + *dst = *src; +} + +static inline void _glKosVertexCopyPVR(pvr_vertex_t *src, pvr_vertex_t *dst) { + *dst = *src; +} + +static inline float ZclipMag(float3 *v1, float3 *v2) { + return ((CLIP_NEARZ - v1->z) / (v2->z - v1->z)); +} + +static inline void glVertexClipZNear(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 inline void _glKosVertexClipZNear3(pvr_vertex_t *v1, pvr_vertex_t *v2, float *w1, float *w2) { + float 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 GLuint glTransformClip(pvr_vertex_t *v, int 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 *vin, pvr_vertex_t *vout, unsigned int vertices) { + GLuint i, v = 0, in = glTransformClip(vin, vertices); + float3 *C = CLIP_BUF; + + if(in == vertices) { + memcpy(vout, vin, vertices * 0x20); + pvr_vertex_t *v = vout; + + 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++) { + unsigned short int clip = 0; /* Clip Code for current Triangle */ + unsigned char 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(&vout[v], &vin[i], 96); + + vout[v].flags = vout[v + 1].flags = PVR_CMD_VERTEX; + vout[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(&vout[v], &vin[i], 96); + + switch(clip) { + case FIRST_TWO_OUT: + glVertexClipZNear(&vout[v], &vout[v + 2], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 2])); + glVertexClipZNear(&vout[v + 1], &vout[v + 2], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 2])); + + break; + + case FIRST_AND_LAST_OUT: + glVertexClipZNear(&vout[v], &vout[v + 1], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 1])); + glVertexClipZNear(&vout[v + 2], &vout[v + 1], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 1])); + + break; + + case LAST_TWO_OUT: + glVertexClipZNear(&vout[v + 1], &vout[v], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 0])); + glVertexClipZNear(&vout[v + 2], &vout[v], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 0])); + + break; + } + + vout[v].flags = vout[v + 1].flags = PVR_CMD_VERTEX; + vout[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: + glVertexCopyPVR(&vin[i + 0], &vout[v + 0]); + glVertexCopyPVR(&vin[i + 1], &vout[v + 1]); + glVertexCopyPVR(&vin[i + 0], &vout[v + 2]); + glVertexCopyPVR(&vin[i + 2], &vout[v + 3]); + glVertexClipZNear(&vout[v + 0], &vout[v + 1], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 1])); + glVertexClipZNear(&vout[v + 2], &vout[v + 3], ZclipMag(&CLIP_BUF[i], &CLIP_BUF[i + 2])); + break; + + case SECOND: + glVertexCopyPVR(&vin[i + 1], &vout[v + 0]); + glVertexCopyPVR(&vin[i + 0], &vout[v + 1]); + glVertexCopyPVR(&vin[i + 1], &vout[v + 2]); + glVertexCopyPVR(&vin[i + 2], &vout[v + 3]); + glVertexClipZNear(&vout[v + 0], &vout[v + 1], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 0])); + glVertexClipZNear(&vout[v + 2], &vout[v + 3], ZclipMag(&CLIP_BUF[i + 1], &CLIP_BUF[i + 2])); + break; + + case THIRD: + glVertexCopyPVR(&vin[i + 2], &vout[v + 0]); + glVertexCopyPVR(&vin[i + 0], &vout[v + 1]); + glVertexCopyPVR(&vin[i + 2], &vout[v + 2]); + glVertexCopyPVR(&vin[i + 1], &vout[v + 3]); + glVertexClipZNear(&vout[v + 0], &vout[v + 1], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i])); + glVertexClipZNear(&vout[v + 2], &vout[v + 3], ZclipMag(&CLIP_BUF[i + 2], &CLIP_BUF[i + 1])); + break; + } + + vout[v + 0].flags = vout[v + 1].flags = vout[v + 2].flags = PVR_CMD_VERTEX; + vout[v + 3].flags = PVR_CMD_VERTEX_EOL; + v += 4; + + break; + } + + C++; + } + + return v; +} + +static inline unsigned char _glKosClipTri(pvr_vertex_t *vin, pvr_vertex_t *vout) { + unsigned short int clip = 0; /* Clip Code for current Triangle */ + unsigned char 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") = vin->x; + register float __y __asm__("fr13") = vin->y; + register float __z __asm__("fr14") = vin->z; + + mat_trans_fv12_nodiv(); + + clip_buf[0].x = __x; + clip_buf[0].y = __y; + clip_buf[0].z = __z; + + __x = (vin + 1)->x; + __y = (vin + 1)->y; + __z = (vin + 1)->z; + + mat_trans_fv12_nodiv(); + + clip_buf[1].x = __x; + clip_buf[1].y = __y; + clip_buf[1].z = __z; + + __x = (vin + 2)->x; + __y = (vin + 2)->y; + __z = (vin + 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(vout, vin, 96); + + vout->flags = (vout + 1)->flags = PVR_CMD_VERTEX; + (vout + 2)->flags = PVR_CMD_VERTEX_EOL; + + return 3; + + case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ + memcpy(vout, vin, 96); + + switch(clip) { + case FIRST_TWO_OUT: + glVertexClipZNear(vout, vout + 2, ZclipMag(&clip_buf[0], &clip_buf[2])); + glVertexClipZNear(vout + 1, vout + 2, ZclipMag(&clip_buf[1], &clip_buf[2])); + + break; + + case FIRST_AND_LAST_OUT: + glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[0], &clip_buf[1])); + glVertexClipZNear(vout + 2, vout + 1, ZclipMag(&clip_buf[2], &clip_buf[1])); + + break; + + case LAST_TWO_OUT: + glVertexClipZNear(vout + 1, vout, ZclipMag(&clip_buf[1], &clip_buf[0])); + glVertexClipZNear(vout + 2, vout, ZclipMag(&clip_buf[2], &clip_buf[0])); + + break; + } + + vout->flags = (vout + 1)->flags = PVR_CMD_VERTEX; + (vout + 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(vout, vin, 64); + glVertexCopyPVR(vin, vout + 2); + glVertexCopyPVR(vin + 2, vout + 3); + glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[0], &clip_buf[1])); + glVertexClipZNear(vout + 2, vout + 3, ZclipMag(&clip_buf[0], &clip_buf[2])); + break; + + case SECOND: + glVertexCopyPVR(vin + 1, vout); + glVertexCopyPVR(vin, vout + 1); + memcpy(vout + 2, vin + 1, 64); + glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[1], &clip_buf[0])); + glVertexClipZNear(vout + 2, vout + 3, ZclipMag(&clip_buf[1], &clip_buf[2])); + break; + + case THIRD: + glVertexCopyPVR(vin + 2, vout); + glVertexCopyPVR(vin, vout + 1); + glVertexCopyPVR(vin + 2, vout + 2); + glVertexCopyPVR(vin + 1, vout + 3); + glVertexClipZNear(vout, vout + 1, ZclipMag(&clip_buf[2], &clip_buf[0])); + glVertexClipZNear(vout + 2, vout + 3, ZclipMag(&clip_buf[2], &clip_buf[1])); + break; + } + + vout->flags = (vout + 1)->flags = (vout + 2)->flags = PVR_CMD_VERTEX; + (vout + 3)->flags = PVR_CMD_VERTEX_EOL; + + return 4; + } + + return 0; +} + +unsigned int _glKosClipTriangles(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices) { + unsigned int i, v = 0; + + for(i = 0; i < vertices; i += 3) /* Iterate all Triangles */ + v += _glKosClipTri(vin + i, vout + v); + + return v; +} + +unsigned int _glKosClipQuads(pvr_vertex_t *vin, pvr_vertex_t *vout, unsigned int vertices) { + unsigned int i, v = 0; + pvr_vertex_t qv; + + for(i = 0; i < vertices; i += 4) { /* Iterate all Quads, Rearranging into Triangle Strips */ + glVertexCopyPVR(vin + i + 3, &qv); + glVertexCopyPVR(vin + i + 2, vin + i + 3); + glVertexCopyPVR(&qv, vin + i + 2); + v += _glKosClipTriangleStrip(vin + i, vout + v, 4); + } + + return v; +} + +static inline void _glKosVertexPerspectiveDivide(pvr_vertex_t *dst, float w) { + dst->z = 1.0f / w; + dst->x *= dst->z; + dst->y *= dst->z; +} + +GLuint _glKosClipTrianglesTransformed(pvr_vertex_t *src, float *w, pvr_vertex_t *dst, GLuint count) { + pvr_vertex_t *vin = src; + pvr_vertex_t *vout = dst; + unsigned short int clip; + unsigned char verts_in = 0; + GLuint verts_out = 0; + GLuint i; + + for(i = 0; i < count; i += 3) { + clip = 0; /* Clip Code for current Triangle */ + verts_in = 0; /* # of Vertices inside clip plane for current Triangle */ + float W[4] = { w[i], w[i + 1], w[i + 2] }; /* W Component for Perspective Divide */ + + (vin[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in; + (vin[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in; + (vin[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 */ + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + + vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; + vout[2].flags = PVR_CMD_VERTEX_EOL; + + vout += 3; + verts_out += 3; + break; + + case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + + switch(clip) { + case FIRST_TWO_OUT: + _glKosVertexClipZNear3(&vout[0], &vout[2], &W[0], &W[2]); + _glKosVertexClipZNear3(&vout[1], &vout[2], &W[1], &W[2]); + + break; + + case FIRST_AND_LAST_OUT: + _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); + _glKosVertexClipZNear3(&vout[2], &vout[1], &W[2], &W[1]); + + break; + + case LAST_TWO_OUT: + _glKosVertexClipZNear3(&vout[1], &vout[0], &W[1], &W[0]); + _glKosVertexClipZNear3(&vout[2], &vout[0], &W[2], &W[0]); + + break; + } + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + + vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; + vout[2].flags = PVR_CMD_VERTEX_EOL; + + vout += 3; + verts_out += 3; + break; + + case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */ + switch(clip) { + case FIRST: + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[0], &vout[2]); + _glKosVertexCopyPVR(&vin[2], &vout[3]); + W[3] = W[2]; + W[2] = W[0]; + + break; + + case SECOND: + _glKosVertexCopyPVR(&vin[1], &vout[0]); + _glKosVertexCopyPVR(&vin[2], &vout[1]); + _glKosVertexCopyPVR(&vin[1], &vout[2]); + _glKosVertexCopyPVR(&vin[0], &vout[3]); + W[3] = W[0]; + W[0] = W[1]; + W[1] = W[2]; + W[2] = W[0]; + + break; + + case THIRD: + _glKosVertexCopyPVR(&vin[2], &vout[0]); + _glKosVertexCopyPVR(&vin[0], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + _glKosVertexCopyPVR(&vin[1], &vout[3]); + W[3] = W[1]; + W[1] = W[0]; + W[0] = W[2]; + + break; + } + + _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); + _glKosVertexClipZNear3(&vout[2], &vout[3], &W[2], &W[3]); + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + _glKosVertexPerspectiveDivide(&vout[3], W[3]); + + vout[0].flags = vout[1].flags = vout[2].flags = PVR_CMD_VERTEX; + vout[3].flags = PVR_CMD_VERTEX_EOL; + + vout += 4; + verts_out += 4; + break; + } + + vin += 3; + } + + return verts_out; +} + +GLuint _glKosClipTriangleStripTransformed(pvr_vertex_t *src, float *w, pvr_vertex_t *dst, GLuint count) { + pvr_vertex_t *vin = src; + pvr_vertex_t *vout = dst; + unsigned short int clip; + unsigned char verts_in = 0; + GLuint verts_out = 0; + GLuint i; + + for(i = 0; i < (count - 2); i ++) { + clip = 0; /* Clip Code for current Triangle */ + verts_in = 0; /* # of Vertices inside clip plane for current Triangle */ + float W[4] = { w[i], w[i + 1], w[i + 2] }; /* W Component for Perspective Divide */ + + (vin[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in; + (vin[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in; + (vin[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 */ + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + + vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; + vout[2].flags = PVR_CMD_VERTEX_EOL; + + vout += 3; + verts_out += 3; + break; + + case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + + switch(clip) { + case FIRST_TWO_OUT: + _glKosVertexClipZNear3(&vout[0], &vout[2], &W[0], &W[2]); + _glKosVertexClipZNear3(&vout[1], &vout[2], &W[1], &W[2]); + + break; + + case FIRST_AND_LAST_OUT: + _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); + _glKosVertexClipZNear3(&vout[2], &vout[1], &W[2], &W[1]); + + break; + + case LAST_TWO_OUT: + _glKosVertexClipZNear3(&vout[1], &vout[0], &W[1], &W[0]); + _glKosVertexClipZNear3(&vout[2], &vout[0], &W[2], &W[0]); + + break; + } + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + + vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; + vout[2].flags = PVR_CMD_VERTEX_EOL; + + vout += 3; + verts_out += 3; + break; + + case 2:/* 2 Vertices of Triangle are inside of clip plane = output 2 Triangles */ + switch(clip) { + case FIRST: + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[0], &vout[2]); + _glKosVertexCopyPVR(&vin[2], &vout[3]); + W[3] = W[2]; + W[2] = W[0]; + + break; + + case SECOND: + _glKosVertexCopyPVR(&vin[1], &vout[0]); + _glKosVertexCopyPVR(&vin[2], &vout[1]); + _glKosVertexCopyPVR(&vin[1], &vout[2]); + _glKosVertexCopyPVR(&vin[0], &vout[3]); + W[3] = W[0]; + W[0] = W[1]; + W[1] = W[2]; + W[2] = W[0]; + + break; + + case THIRD: + _glKosVertexCopyPVR(&vin[2], &vout[0]); + _glKosVertexCopyPVR(&vin[0], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + _glKosVertexCopyPVR(&vin[1], &vout[3]); + W[3] = W[1]; + W[1] = W[0]; + W[0] = W[2]; + + break; + } + + _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); + _glKosVertexClipZNear3(&vout[2], &vout[3], &W[2], &W[3]); + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + _glKosVertexPerspectiveDivide(&vout[3], W[3]); + + vout[0].flags = vout[1].flags = vout[2].flags = PVR_CMD_VERTEX; + vout[3].flags = PVR_CMD_VERTEX_EOL; + + vout += 4; + verts_out += 4; + break; + } + + ++vin; + } + + return verts_out; +} + +GLubyte _glKosClipTriTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout) { + unsigned short int clip = 0; /* Clip Code for current Triangle */ + unsigned char verts_in = 0; /* # of Vertices inside clip plane for current Triangle */ + float W[4] = { w[0], w[1], w[2] }; /* W Component for Perspective Divide */ + + (vin[0].z >= CLIP_NEARZ) ? clip |= FIRST : ++verts_in; + (vin[1].z >= CLIP_NEARZ) ? clip |= SECOND : ++verts_in; + (vin[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(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + + vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; + vout[2].flags = PVR_CMD_VERTEX_EOL; + + return 3; + + case 1:/* 1 Vertex of Triangle is inside of clip plane = output 1 Triangle */ + _glKosVertexCopyPVR(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + + switch(clip) { + case FIRST_TWO_OUT: + _glKosVertexClipZNear3(&vout[0], &vout[2], &W[0], &W[2]); + _glKosVertexClipZNear3(&vout[1], &vout[2], &W[1], &W[2]); + + break; + + case FIRST_AND_LAST_OUT: + _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); + _glKosVertexClipZNear3(&vout[2], &vout[1], &W[2], &W[1]); + + break; + + case LAST_TWO_OUT: + _glKosVertexClipZNear3(&vout[1], &vout[0], &W[1], &W[0]); + _glKosVertexClipZNear3(&vout[2], &vout[0], &W[2], &W[0]); + + break; + } + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + + vout[0].flags = vout[1].flags = PVR_CMD_VERTEX; + vout[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(&vin[0], &vout[0]); + _glKosVertexCopyPVR(&vin[1], &vout[1]); + _glKosVertexCopyPVR(&vin[0], &vout[2]); + _glKosVertexCopyPVR(&vin[2], &vout[3]); + W[3] = W[2]; + W[2] = W[0]; + + break; + + case SECOND: + _glKosVertexCopyPVR(&vin[1], &vout[0]); + _glKosVertexCopyPVR(&vin[2], &vout[1]); + _glKosVertexCopyPVR(&vin[1], &vout[2]); + _glKosVertexCopyPVR(&vin[0], &vout[3]); + W[3] = W[0]; + W[0] = W[1]; + W[1] = W[2]; + W[2] = W[0]; + + break; + + case THIRD: + _glKosVertexCopyPVR(&vin[2], &vout[0]); + _glKosVertexCopyPVR(&vin[0], &vout[1]); + _glKosVertexCopyPVR(&vin[2], &vout[2]); + _glKosVertexCopyPVR(&vin[1], &vout[3]); + W[3] = W[1]; + W[1] = W[0]; + W[0] = W[2]; + + break; + } + + _glKosVertexClipZNear3(&vout[0], &vout[1], &W[0], &W[1]); + _glKosVertexClipZNear3(&vout[2], &vout[3], &W[2], &W[3]); + + _glKosVertexPerspectiveDivide(&vout[0], W[0]); + _glKosVertexPerspectiveDivide(&vout[1], W[1]); + _glKosVertexPerspectiveDivide(&vout[2], W[2]); + _glKosVertexPerspectiveDivide(&vout[3], W[3]); + + vout[0].flags = vout[1].flags = vout[2].flags = PVR_CMD_VERTEX; + vout[3].flags = PVR_CMD_VERTEX_EOL; + + return 4; + } + + return 0; +} + +unsigned int _glKosClipQuadsTransformed(pvr_vertex_t *vin, float *w, pvr_vertex_t *vout, unsigned int vertices) { + unsigned int i, v = 0; + pvr_vertex_t qv[3]; + float W[3]; + + for(i = 0; i < vertices; i += 4) { /* Iterate all Quads, Rearranging into Triangle Strips */ + _glKosVertexCopyPVR(&vin[i + 0], &qv[0]); + _glKosVertexCopyPVR(&vin[i + 2], &qv[1]); + _glKosVertexCopyPVR(&vin[i + 3], &qv[2]); + W[0] = w[0]; + W[1] = w[2]; + W[2] = w[3]; + + v += _glKosClipTriTransformed(&vin[i], &w[i], &vout[v]); + v += _glKosClipTriTransformed(&qv[i], &W[i], &vout[v]); + } + + return v; +} diff --git a/gl-clip.h b/gl-clip.h index 64ed34b..5db9101 100755 --- a/gl-clip.h +++ b/gl-clip.h @@ -1,44 +1,44 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-clip.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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.5f /* Clip Threshold */ - -typedef struct { - float x, y, z; -} float3; - -typedef struct { - unsigned char b, g, r, a; -} colorui; - -#endif +/* KallistiGL for KallistiOS ##version## + + libgl/gl-clip.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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.5f /* Clip Threshold */ + +typedef struct { + float x, y, z; +} float3; + +typedef struct { + unsigned char b, g, r, a; +} colorui; + +#endif diff --git a/gl-fog.c b/gl-fog.c index 99c1ecb..d4f8564 100755 --- a/gl-fog.c +++ b/gl-fog.c @@ -1,102 +1,102 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-fog.c - Copyright (C) 2013-2014 Josh "PH3NOM" 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 FOG_MODE = GL_EXP; /* GL_LINEAR, GL_EXP, or GL_EXP2 FOG */ -static GLfloat FOG_DENSITY = 1.0f, /* Density - GL_EXP, or GL_EXP2 FOG */ - FOG_START = 0.0f, /* Linear FOG */ - FOG_END = 1.0f; /* Linear FOG */ - -void glFogi(GLenum pname, GLint param) { - switch(pname) { - case GL_FOG_MODE: - switch(param) { - case GL_LINEAR: - return pvr_fog_table_linear(FOG_START, FOG_END); - - case GL_EXP: - return pvr_fog_table_exp(FOG_DENSITY); - - case GL_EXP2: - return pvr_fog_table_exp2(FOG_DENSITY); - - default: - return; - } - - default: - return; - } -} - -void glFogf(GLenum pname, GLfloat param) { - switch(pname) { - case GL_FOG_START: - FOG_START = param; - - if(FOG_MODE == GL_LINEAR) - return pvr_fog_table_linear(FOG_START, FOG_END); - - return; - - case GL_FOG_END: - FOG_END = param; - - if(FOG_MODE == GL_LINEAR) - return pvr_fog_table_linear(FOG_START, FOG_END); - - return; - - case GL_FOG_DENSITY: - FOG_DENSITY = param; - - if(FOG_MODE == GL_EXP) - return pvr_fog_table_exp(FOG_DENSITY); - - if(FOG_MODE == GL_EXP2) - return pvr_fog_table_exp2(FOG_DENSITY); - - return; - - default: - return; - } -} - -void glFogfv(GLenum pname, const GLfloat *params) { - switch(pname) { - case GL_FOG_MODE: - return glFogi(pname, (GLint) * params); - - case GL_FOG_DENSITY: - FOG_DENSITY = *params; - - if(FOG_MODE == GL_EXP) - return pvr_fog_table_exp(FOG_DENSITY); - - if(FOG_MODE == GL_EXP2) - return pvr_fog_table_exp2(FOG_DENSITY); - - return; - - case GL_FOG_START: - case GL_FOG_END: - return glFogf(pname, *params); - - case GL_FOG_COLOR: - return pvr_fog_table_color(params[3], params[0], params[1], params[2]); - - case GL_FOG_INDEX: - default: - return; - } -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-fog.c + Copyright (C) 2013-2014 Josh "PH3NOM" 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 FOG_MODE = GL_EXP; /* GL_LINEAR, GL_EXP, or GL_EXP2 FOG */ +static GLfloat FOG_DENSITY = 1.0f, /* Density - GL_EXP, or GL_EXP2 FOG */ + FOG_START = 0.0f, /* Linear FOG */ + FOG_END = 1.0f; /* Linear FOG */ + +void glFogi(GLenum pname, GLint param) { + switch(pname) { + case GL_FOG_MODE: + switch(param) { + case GL_LINEAR: + return pvr_fog_table_linear(FOG_START, FOG_END); + + case GL_EXP: + return pvr_fog_table_exp(FOG_DENSITY); + + case GL_EXP2: + return pvr_fog_table_exp2(FOG_DENSITY); + + default: + return; + } + + default: + return; + } +} + +void glFogf(GLenum pname, GLfloat param) { + switch(pname) { + case GL_FOG_START: + FOG_START = param; + + if(FOG_MODE == GL_LINEAR) + return pvr_fog_table_linear(FOG_START, FOG_END); + + return; + + case GL_FOG_END: + FOG_END = param; + + if(FOG_MODE == GL_LINEAR) + return pvr_fog_table_linear(FOG_START, FOG_END); + + return; + + case GL_FOG_DENSITY: + FOG_DENSITY = param; + + if(FOG_MODE == GL_EXP) + return pvr_fog_table_exp(FOG_DENSITY); + + if(FOG_MODE == GL_EXP2) + return pvr_fog_table_exp2(FOG_DENSITY); + + return; + + default: + return; + } +} + +void glFogfv(GLenum pname, const GLfloat *params) { + switch(pname) { + case GL_FOG_MODE: + return glFogi(pname, (GLint) * params); + + case GL_FOG_DENSITY: + FOG_DENSITY = *params; + + if(FOG_MODE == GL_EXP) + return pvr_fog_table_exp(FOG_DENSITY); + + if(FOG_MODE == GL_EXP2) + return pvr_fog_table_exp2(FOG_DENSITY); + + return; + + case GL_FOG_START: + case GL_FOG_END: + return glFogf(pname, *params); + + case GL_FOG_COLOR: + return pvr_fog_table_color(params[3], params[0], params[1], params[2]); + + case GL_FOG_INDEX: + default: + return; + } +} diff --git a/gl-light.c b/gl-light.c index 3c57991..d98970e 100755 --- a/gl-light.c +++ b/gl-light.c @@ -1,562 +1,562 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-light.c - Copyright (C) 2013-2014 Josh "PH3NOM" 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 -#include -#include - -#include "gl.h" -#include "gl-api.h" -#include "gl-clip.h" -#include "gl-light.h" - -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 GLuint GL_LIGHT_ENABLED = 0; /* Client State for Enabling Lighting */ - -static glLight GL_LIGHTS[GL_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_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_LIGHT7) return; - - GL_LIGHT_ENABLED |= (1 << (light & 0xF)); -} - -/* Disable a light - GL_LIGHT0->GL_LIGHT7 */ -void _glKosDisableLight(const GLuint light) { - if(light < GL_LIGHT0 || light > GL_LIGHT7) return; - - GL_LIGHT_ENABLED &= ~(1 << (light & 0xF)); -} - -/* Vertex Normal Submission */ -void glNormal3f(float x, float y, float z) { - GL_VERTEX_NORMAL[0] = x; - GL_VERTEX_NORMAL[1] = y; - GL_VERTEX_NORMAL[2] = z; -} - -void glNormal3fv(float *xyz) { - GL_VERTEX_NORMAL[0] = xyz[0]; - GL_VERTEX_NORMAL[1] = xyz[1]; - GL_VERTEX_NORMAL[2] = xyz[2]; -} - -/* Global Ambient Light Parameters */ -void glKosLightAmbient4fv(float *rgba) { - GL_GLOBAL_AMBIENT[0] = rgba[0]; - GL_GLOBAL_AMBIENT[1] = rgba[1]; - GL_GLOBAL_AMBIENT[2] = rgba[2]; - GL_GLOBAL_AMBIENT[3] = rgba[3]; -} - -void glKosLightAmbient4f(float r, float g, float b, float a) { - GL_GLOBAL_AMBIENT[0] = r; - GL_GLOBAL_AMBIENT[1] = g; - GL_GLOBAL_AMBIENT[2] = b; - GL_GLOBAL_AMBIENT[3] = a; -} - -void glKosLightAmbient3fv(float *rgb) { - GL_GLOBAL_AMBIENT[0] = rgb[0]; - GL_GLOBAL_AMBIENT[1] = rgb[1]; - GL_GLOBAL_AMBIENT[2] = rgb[2]; - GL_GLOBAL_AMBIENT[3] = 1.0f; -} - -void glKosLightAmbient3f(float r, float g, float b) { - GL_GLOBAL_AMBIENT[0] = r; - GL_GLOBAL_AMBIENT[1] = g; - GL_GLOBAL_AMBIENT[2] = b; - GL_GLOBAL_AMBIENT[3] = 1.0f; -} - -/* Misc Lighting Functions ************************************/ -static inline void glCopyRGBA(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_LIGHT7) 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_LIGHT7) 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(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(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]; - 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_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]; - - /* 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_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]; - - /* 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_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(); -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-light.c + Copyright (C) 2013-2014 Josh "PH3NOM" 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 +#include +#include + +#include "gl.h" +#include "gl-api.h" +#include "gl-clip.h" +#include "gl-light.h" + +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 GLuint GL_LIGHT_ENABLED = 0; /* Client State for Enabling Lighting */ + +static glLight GL_LIGHTS[GL_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_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_LIGHT7) return; + + GL_LIGHT_ENABLED |= (1 << (light & 0xF)); +} + +/* Disable a light - GL_LIGHT0->GL_LIGHT7 */ +void _glKosDisableLight(const GLuint light) { + if(light < GL_LIGHT0 || light > GL_LIGHT7) return; + + GL_LIGHT_ENABLED &= ~(1 << (light & 0xF)); +} + +/* Vertex Normal Submission */ +void glNormal3f(float x, float y, float z) { + GL_VERTEX_NORMAL[0] = x; + GL_VERTEX_NORMAL[1] = y; + GL_VERTEX_NORMAL[2] = z; +} + +void glNormal3fv(float *xyz) { + GL_VERTEX_NORMAL[0] = xyz[0]; + GL_VERTEX_NORMAL[1] = xyz[1]; + GL_VERTEX_NORMAL[2] = xyz[2]; +} + +/* Global Ambient Light Parameters */ +void glKosLightAmbient4fv(float *rgba) { + GL_GLOBAL_AMBIENT[0] = rgba[0]; + GL_GLOBAL_AMBIENT[1] = rgba[1]; + GL_GLOBAL_AMBIENT[2] = rgba[2]; + GL_GLOBAL_AMBIENT[3] = rgba[3]; +} + +void glKosLightAmbient4f(float r, float g, float b, float a) { + GL_GLOBAL_AMBIENT[0] = r; + GL_GLOBAL_AMBIENT[1] = g; + GL_GLOBAL_AMBIENT[2] = b; + GL_GLOBAL_AMBIENT[3] = a; +} + +void glKosLightAmbient3fv(float *rgb) { + GL_GLOBAL_AMBIENT[0] = rgb[0]; + GL_GLOBAL_AMBIENT[1] = rgb[1]; + GL_GLOBAL_AMBIENT[2] = rgb[2]; + GL_GLOBAL_AMBIENT[3] = 1.0f; +} + +void glKosLightAmbient3f(float r, float g, float b) { + GL_GLOBAL_AMBIENT[0] = r; + GL_GLOBAL_AMBIENT[1] = g; + GL_GLOBAL_AMBIENT[2] = b; + GL_GLOBAL_AMBIENT[3] = 1.0f; +} + +/* Misc Lighting Functions ************************************/ +static inline void glCopyRGBA(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_LIGHT7) 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_LIGHT7) 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(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(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]; + 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_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]; + + /* 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_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]; + + /* 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_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(); +} diff --git a/gl-light.h b/gl-light.h index 005f7a4..db7cf2c 100755 --- a/gl-light.h +++ b/gl-light.h @@ -1,51 +1,51 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-light.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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 +/* KallistiGL for KallistiOS ##version## + + libgl/gl-light.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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 diff --git a/gl-matrix.c b/gl-matrix.c index f49731e..a1c1550 100755 --- a/gl-matrix.c +++ b/gl-matrix.c @@ -1,403 +1,403 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-matrix.c - Copyright (C) 2013-2014 Josh "PH3NOM" 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 - -#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); -} - -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; - 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_store(&MatrixLookAt); -} - -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(&MatrixLookAt); - mat_apply(Matrix + GL_MODELVIEW); - mat_store(Matrix + GL_RENDER); -} - -void _glKosMatrixLoadRender() { - mat_load(Matrix + GL_RENDER); -} - -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); -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-matrix.c + Copyright (C) 2013-2014 Josh "PH3NOM" 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 + +#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); +} + +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; + 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_store(&MatrixLookAt); +} + +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(&MatrixLookAt); + mat_apply(Matrix + GL_MODELVIEW); + mat_store(Matrix + GL_RENDER); +} + +void _glKosMatrixLoadRender() { + mat_load(Matrix + GL_RENDER); +} + +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); +} diff --git a/gl-pvr.c b/gl-pvr.c index 7c53dd0..9414bbf 100755 --- a/gl-pvr.c +++ b/gl-pvr.c @@ -1,215 +1,215 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-pvr.c - Copyright (C) 2013-2014 Josh "PH3NOM" Pearson - - 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_MAX_VERTS conrols the number of vertices per list in the Vertex Buffer in SH4 RAM -*/ - -#include -#include -#include -#include - -#include "gl.h" -#include "gl-sh4.h" -#include "gl-pvr.h" - -/* Vertex Buffer Functions *************************************************************************/ - -#ifdef GL_USE_MALLOC -static pvr_cmd_t *GL_VBUF[2] __attribute__((aligned(32))); /* Dynamic Vertex Buffer */ -static pvr_cmd_t *GL_CBUF; /* Dynamic Clip Buffer */ -#else -static pvr_cmd_t GL_VBUF[2][GL_MAX_VERTS] __attribute__((aligned(32))); /* Static Vertex Buffer */ -static pvr_cmd_t GL_CBUF[GL_MAX_VERTS / 2]; /* Static Clip Buffer */ -#endif - -static unsigned int GL_VERTS[2] = {0, 0}, - GL_CVERTS = 0, - GL_LIST = GL_LIST_OP; - -/* Custom version of sq_cpy from KOS for copying vertex data to the PVR */ -static inline void pvr_list_submit(void *src, int n) { - unsigned int *d = TA_SQ_ADDR; - unsigned int *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 = (unsigned int *)0xe0000000; - d[0] = d[8] = 0; -} - -inline void *_glKosClipBufAddress() { - return &GL_CBUF[0]; -} - -inline void *_glKosClipBufPointer() { - return &GL_CBUF[GL_CVERTS]; -} - -inline void _glKosClipBufIncrement() { - ++GL_CVERTS; -} - -inline void _glKosClipBufAdd(unsigned int count) { - GL_CVERTS += count; -} - -inline void _glKosClipBufReset() { - GL_CVERTS = 0; -} - -inline void _glKosVertexBufSwitchOP() { - GL_LIST = GL_LIST_OP; -} - -inline void _glKosVertexBufSwitchTR() { - GL_LIST = GL_LIST_TR; -} - -inline void *_glKosVertexBufAddress(unsigned char list) { - return &GL_VBUF[list][0]; -} - -inline void *_glKosVertexBufPointer() { - return &GL_VBUF[GL_LIST][GL_VERTS[GL_LIST]]; -} - -inline void _glKosVertexBufIncrement() { - ++GL_VERTS[GL_LIST]; -} - -inline void *_glKosTRVertexBufPointer() { - return &GL_VBUF[GL_LIST_TR][GL_VERTS[GL_LIST_TR]]; -} - -inline void _glKosTRVertexBufIncrement() { - ++GL_VERTS[GL_LIST_TR]; -} - -inline void _glKosVertexBufAdd(unsigned int count) { - GL_VERTS[GL_LIST] += count; -} - -inline void _glKosTRVertexBufAdd(unsigned int count) { - GL_VERTS[GL_LIST_TR] += count; -} - -inline void _glKosVertexBufDecrement() { - --GL_VERTS[GL_LIST]; -} - -inline void _glKosVertexBufReset() { - GL_VERTS[0] = GL_VERTS[1] = 0; -} - -inline unsigned int _glKosVertexBufCount(unsigned char list) { - return GL_VERTS[list]; -} - -unsigned char _glKosList() { - return GL_LIST; -} - -inline void _glKosVertexBufCopy(void *dst, void *src, GLuint count) { - memcpy(dst, src, count * 0x20); -} - -static inline void glutSwapBuffer() { - pvr_list_begin(PVR_LIST_OP_POLY); - - pvr_list_submit(_glKosVertexBufAddress(GL_LIST_OP), _glKosVertexBufCount(GL_LIST_OP)); - - pvr_list_finish(); - - pvr_list_begin(PVR_LIST_TR_POLY); - - pvr_list_submit(_glKosVertexBufAddress(GL_LIST_TR), _glKosVertexBufCount(GL_LIST_TR)); - - pvr_list_finish(); - - pvr_scene_finish(); -} - -void glutSwapBuffers() { - pvr_wait_ready(); - - pvr_scene_begin(); - - glutSwapBuffer(); - - _glKosVertexBufReset(); -} - -void glutSwapBuffersToTexture(void *dst, GLsizei *x, GLsizei *y) { - pvr_wait_ready(); - - pvr_scene_begin_txr(dst, x, y); - - glutSwapBuffer(); - - _glKosVertexBufReset(); -} - -void glutCopyBufferToTexture(void *dst, GLsizei *x, GLsizei *y) { - pvr_wait_ready(); - - pvr_scene_begin_txr(dst, x, y); - - glutSwapBuffer(); -} - -int _glKosInitPVR() { - 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 */ - }; - - pvr_init(¶ms); -#ifdef GL_USE_DMA - pvr_dma_init(); -#endif - -#ifdef GL_USE_MALLOC - GL_VBUF[0] = memalign(0x20, GL_MAX_VERTS * sizeof(pvr_cmd_t)); - GL_VBUF[1] = memalign(0x20, GL_MAX_VERTS * sizeof(pvr_cmd_t)); - GL_CBUF = malloc((GL_MAX_VERTS / 2) * sizeof(pvr_cmd_t)); -#endif - - return 1; -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-pvr.c + Copyright (C) 2013-2014 Josh "PH3NOM" Pearson + + 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_MAX_VERTS conrols the number of vertices per list in the Vertex Buffer in SH4 RAM +*/ + +#include +#include +#include +#include + +#include "gl.h" +#include "gl-sh4.h" +#include "gl-pvr.h" + +/* Vertex Buffer Functions *************************************************************************/ + +#ifdef GL_USE_MALLOC +static pvr_cmd_t *GL_VBUF[2] __attribute__((aligned(32))); /* Dynamic Vertex Buffer */ +static pvr_cmd_t *GL_CBUF; /* Dynamic Clip Buffer */ +#else +static pvr_cmd_t GL_VBUF[2][GL_MAX_VERTS] __attribute__((aligned(32))); /* Static Vertex Buffer */ +static pvr_cmd_t GL_CBUF[GL_MAX_VERTS / 2]; /* Static Clip Buffer */ +#endif + +static unsigned int GL_VERTS[2] = {0, 0}, + GL_CVERTS = 0, + GL_LIST = GL_LIST_OP; + +/* Custom version of sq_cpy from KOS for copying vertex data to the PVR */ +static inline void pvr_list_submit(void *src, int n) { + unsigned int *d = TA_SQ_ADDR; + unsigned int *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 = (unsigned int *)0xe0000000; + d[0] = d[8] = 0; +} + +inline void *_glKosClipBufAddress() { + return &GL_CBUF[0]; +} + +inline void *_glKosClipBufPointer() { + return &GL_CBUF[GL_CVERTS]; +} + +inline void _glKosClipBufIncrement() { + ++GL_CVERTS; +} + +inline void _glKosClipBufAdd(unsigned int count) { + GL_CVERTS += count; +} + +inline void _glKosClipBufReset() { + GL_CVERTS = 0; +} + +inline void _glKosVertexBufSwitchOP() { + GL_LIST = GL_LIST_OP; +} + +inline void _glKosVertexBufSwitchTR() { + GL_LIST = GL_LIST_TR; +} + +inline void *_glKosVertexBufAddress(unsigned char list) { + return &GL_VBUF[list][0]; +} + +inline void *_glKosVertexBufPointer() { + return &GL_VBUF[GL_LIST][GL_VERTS[GL_LIST]]; +} + +inline void _glKosVertexBufIncrement() { + ++GL_VERTS[GL_LIST]; +} + +inline void *_glKosTRVertexBufPointer() { + return &GL_VBUF[GL_LIST_TR][GL_VERTS[GL_LIST_TR]]; +} + +inline void _glKosTRVertexBufIncrement() { + ++GL_VERTS[GL_LIST_TR]; +} + +inline void _glKosVertexBufAdd(unsigned int count) { + GL_VERTS[GL_LIST] += count; +} + +inline void _glKosTRVertexBufAdd(unsigned int count) { + GL_VERTS[GL_LIST_TR] += count; +} + +inline void _glKosVertexBufDecrement() { + --GL_VERTS[GL_LIST]; +} + +inline void _glKosVertexBufReset() { + GL_VERTS[0] = GL_VERTS[1] = 0; +} + +inline unsigned int _glKosVertexBufCount(unsigned char list) { + return GL_VERTS[list]; +} + +unsigned char _glKosList() { + return GL_LIST; +} + +inline void _glKosVertexBufCopy(void *dst, void *src, GLuint count) { + memcpy(dst, src, count * 0x20); +} + +static inline void glutSwapBuffer() { + pvr_list_begin(PVR_LIST_OP_POLY); + + pvr_list_submit(_glKosVertexBufAddress(GL_LIST_OP), _glKosVertexBufCount(GL_LIST_OP)); + + pvr_list_finish(); + + pvr_list_begin(PVR_LIST_TR_POLY); + + pvr_list_submit(_glKosVertexBufAddress(GL_LIST_TR), _glKosVertexBufCount(GL_LIST_TR)); + + pvr_list_finish(); + + pvr_scene_finish(); +} + +void glutSwapBuffers() { + pvr_wait_ready(); + + pvr_scene_begin(); + + glutSwapBuffer(); + + _glKosVertexBufReset(); +} + +void glutSwapBuffersToTexture(void *dst, GLsizei *x, GLsizei *y) { + pvr_wait_ready(); + + pvr_scene_begin_txr(dst, x, y); + + glutSwapBuffer(); + + _glKosVertexBufReset(); +} + +void glutCopyBufferToTexture(void *dst, GLsizei *x, GLsizei *y) { + pvr_wait_ready(); + + pvr_scene_begin_txr(dst, x, y); + + glutSwapBuffer(); +} + +int _glKosInitPVR() { + 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 */ + }; + + pvr_init(¶ms); +#ifdef GL_USE_DMA + pvr_dma_init(); +#endif + +#ifdef GL_USE_MALLOC + GL_VBUF[0] = memalign(0x20, GL_MAX_VERTS * sizeof(pvr_cmd_t)); + GL_VBUF[1] = memalign(0x20, GL_MAX_VERTS * sizeof(pvr_cmd_t)); + GL_CBUF = malloc((GL_MAX_VERTS / 2) * sizeof(pvr_cmd_t)); +#endif + + return 1; +} diff --git a/gl-pvr.h b/gl-pvr.h index f80b0c9..da1fa00 100755 --- a/gl-pvr.h +++ b/gl-pvr.h @@ -1,54 +1,54 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-pvr.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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_MAX_VERTS 1024*64 /* SH4 Vertex Count */ -#define GL_MAX_TEXTURES 1024 /* Textures in Buffer */ - -#define GL_USE_MALLOC 1 /* Use Dynamic Vertex Array */ -//#define GL_USE_FLOAT 0 /* Use PVR's floating-point color Vertex Type (64bit) *NoOp* */ -//#define GL_USE_DMA 0 /* Use PVR DMA for vertex data transfer *NoOp* */ -#define GL_LIST_OP 0 -#define GL_LIST_TR 1 - -/* 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 +/* KallistiGL for KallistiOS ##version## + + libgl/gl-pvr.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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_MAX_VERTS 1024*64 /* SH4 Vertex Count */ +#define GL_MAX_TEXTURES 1024 /* Textures in Buffer */ + +#define GL_USE_MALLOC 1 /* Use Dynamic Vertex Array */ +//#define GL_USE_FLOAT 0 /* Use PVR's floating-point color Vertex Type (64bit) *NoOp* */ +//#define GL_USE_DMA 0 /* Use PVR DMA for vertex data transfer *NoOp* */ +#define GL_LIST_OP 0 +#define GL_LIST_TR 1 + +/* 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 diff --git a/gl-rgb.c b/gl-rgb.c index c8ee319..c63dd05 100755 --- a/gl-rgb.c +++ b/gl-rgb.c @@ -1,116 +1,116 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-rgb.c - Copyright (C) 2013-2014 Josh "PH3NOM" Pearson - - A set of functions for working with ARGB pixel data, used by gluBuild2DMipmaps(...). -*/ - -#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)) / 4; - uint8 R = (ARGB1555_RED(p1) + ARGB1555_RED(p2)) / 4; - uint8 G = (ARGB1555_GREEN(p1) + ARGB1555_GREEN(p2)) / 4; - uint8 B = (ARGB1555_BLUE(p1) + ARGB1555_BLUE(p2)) / 4; - - 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)) / 4; - uint8 R = (ARGB4444_RED(p1) + ARGB4444_RED(p2)) / 4; - uint8 G = (ARGB4444_GREEN(p1) + ARGB4444_GREEN(p2)) / 4; - uint8 B = (ARGB4444_BLUE(p1) + ARGB4444_BLUE(p2)) / 4; - - return ((A & RGB4_MAX) << ARGB4444_ALPHA_SHIFT) | ((R & RGB4_MAX) << ARGB4444_RED_SHIFT) - | ((G & RGB4_MAX) << ARGB4444_GREEN_SHIFT) | (B & RGB4_MAX); -} +/* KallistiGL for KallistiOS ##version## + + libgl/gl-rgb.c + Copyright (C) 2013-2014 Josh "PH3NOM" Pearson + + A set of functions for working with ARGB pixel data, used by gluBuild2DMipmaps(...). +*/ + +#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)) / 4; + uint8 R = (ARGB1555_RED(p1) + ARGB1555_RED(p2)) / 4; + uint8 G = (ARGB1555_GREEN(p1) + ARGB1555_GREEN(p2)) / 4; + uint8 B = (ARGB1555_BLUE(p1) + ARGB1555_BLUE(p2)) / 4; + + 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)) / 4; + uint8 R = (ARGB4444_RED(p1) + ARGB4444_RED(p2)) / 4; + uint8 G = (ARGB4444_GREEN(p1) + ARGB4444_GREEN(p2)) / 4; + uint8 B = (ARGB4444_BLUE(p1) + ARGB4444_BLUE(p2)) / 4; + + return ((A & RGB4_MAX) << ARGB4444_ALPHA_SHIFT) | ((R & RGB4_MAX) << ARGB4444_RED_SHIFT) + | ((G & RGB4_MAX) << ARGB4444_GREEN_SHIFT) | (B & RGB4_MAX); +} diff --git a/gl-rgb.h b/gl-rgb.h index f212cf5..3615b30 100755 --- a/gl-rgb.h +++ b/gl-rgb.h @@ -1,63 +1,63 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-rgb.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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 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)) - -#endif +/* KallistiGL for KallistiOS ##version## + + libgl/gl-rgb.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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 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)) + +#endif diff --git a/gl-sh4-light.S b/gl-sh4-light.S index 67e6a86..733e375 100755 --- a/gl-sh4-light.S +++ b/gl-sh4-light.S @@ -1,232 +1,232 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-sh4-light.S - Copyright (C) 2013-2014 Josh "PH3NOM" 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 - fsqrt fr7 - - fcmp/gt fr3, fr7 ! V w <=0 = skip ndiv - bf .SKIPVndiv - - fdiv fr7, fr4 - fdiv fr7, fr5 - fdiv fr7, fr6 - -.SKIPVndiv: - - 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 - fsqrt fr11 - - fcmp/gt fr3, fr11 ! H w <=0 = skip ndiv - bf .SKIPHndiv - - fdiv fr11, fr8 - fdiv fr11, fr9 - fdiv fr11, fr10 - -.SKIPHndiv: - 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 - fsqrt fr15 - - fcmp/gt fr11, fr15 ! Check for Normalization division - bf .SPOTcosdir ! If w < 0, skip division - - fdiv fr12, fr15 - fdiv fr13, fr15 - fdiv fr14, fr15 - -.SPOTcosdir: - - 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 - fsqrt fr7 - - fcmp/gt fr11, fr7 ! Normalization division if w component > 0 - bf .SDIVlv - - fdiv fr7, fr4 - fdiv fr7, fr5 - fdiv fr7, fr6 ! fv4 = Normalized L Vector - -.SDIVlv: - - 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 - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +/* KallistiGL for KallistiOS ##version## + + libgl/gl-sh4-light.S + Copyright (C) 2013-2014 Josh "PH3NOM" 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 + fsqrt fr7 + + fcmp/gt fr3, fr7 ! V w <=0 = skip ndiv + bf .SKIPVndiv + + fdiv fr7, fr4 + fdiv fr7, fr5 + fdiv fr7, fr6 + +.SKIPVndiv: + + 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 + fsqrt fr11 + + fcmp/gt fr3, fr11 ! H w <=0 = skip ndiv + bf .SKIPHndiv + + fdiv fr11, fr8 + fdiv fr11, fr9 + fdiv fr11, fr10 + +.SKIPHndiv: + 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 + fsqrt fr15 + + fcmp/gt fr11, fr15 ! Check for Normalization division + bf .SPOTcosdir ! If w < 0, skip division + + fdiv fr12, fr15 + fdiv fr13, fr15 + fdiv fr14, fr15 + +.SPOTcosdir: + + 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 + fsqrt fr7 + + fcmp/gt fr11, fr7 ! Normalization division if w component > 0 + bf .SDIVlv + + fdiv fr7, fr4 + fdiv fr7, fr5 + fdiv fr7, fr6 ! fv4 = Normalized L Vector + +.SDIVlv: + + 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 + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/gl-sh4.h b/gl-sh4.h index 4aad810..1ead9bb 100755 --- a/gl-sh4.h +++ b/gl-sh4.h @@ -1,52 +1,52 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-sh4.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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) ); \ - } - -#endif +/* KallistiGL for KallistiOS ##version## + + libgl/gl-sh4.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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) ); \ + } + +#endif diff --git a/include/gl.h b/include/gl.h index f6737a1..3e92d33 100755 --- a/include/gl.h +++ b/include/gl.h @@ -1,527 +1,527 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl.h - Copyright (C) 2013-2014 Josh "PH3NOM" 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. -*/ - -#ifndef __GL_GL_H -#define __GL_GL_H - -#include -__BEGIN_DECLS - -#include - -#include -#include -#include -#include -#include -#include - -/* Primitive Types taken from GL for compatability */ -/* Not all types are implemented in Open GL DC V.1.0 */ -#define GL_POINTS 0x01 -#define GL_LINES 0x02 -#define GL_LINE_LOOP 0x03 -#define GL_LINE_STRIP 0x04 -#define GL_TRIANGLES 0x05 -#define GL_TRIANGLE_STRIP 0x06 -#define GL_TRIANGLE_FAN 0x07 -#define GL_QUADS 0x08 -#define GL_QUAD_STRIP 0x09 -#define GL_POLYGON 0x0A - -/* FrontFaceDirection */ -#define GL_CW 0x0900 -#define GL_CCW 0x0901 - -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_CULL_FACE 0x0B44 -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 - -/* Scissor box */ -#define GL_SCISSOR_TEST 0x0008 /* capability bit */ -#define GL_SCISSOR_BOX 0x0C10 - -/* 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_MATRIX 0x0BA6 -#define GL_PROJECTION_MATRIX 0x0BA7 -#define GL_TEXTURE_MATRIX 0x0BA8 - -/* Depth buffer */ -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_DEPTH_TEST 0x0B71 -#define GL_DEPTH_BITS 0x0D56 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_COMPONENT 0x1902 - -/* Blending: Simply Need to Map GL constants to PVR constants */ -#define GL_BLEND 0x0BE2 /* capability bit */ -#define GL_BLEND_DST 0x0BE0 -#define GL_BLEND_SRC 0x0BE1 - -#define GL_ZERO 0x0 -#define GL_ONE 0x1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 - -/* Misc texture constants */ -#define GL_TEXTURE_2D 0x0001 /* capability bit */ -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_FILTER GL_TEXTURE_MIN_FILTER -#define GL_FILTER_NONE 0x0 -#define GL_FILTER_BILINEAR 0x1 -#define GL_REPEAT 0x2901 -#define GL_CLAMP 0x2900 - -/* Texture Environment */ -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_REPLACE 0x0 -#define GL_MODULATE 0x1 -#define GL_DECAL 0x2 -#define GL_MODULATEALPHA 0x3 - -/* TextureMagFilter */ -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 - -/* Texture mapping */ -#define GL_TEXTURE_ENV 0x2300 -#define GL_TEXTURE_ENV_COLOR 0x2201 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 - -#define GL_MAX_TEXTURE_UNITS 0x2 /* 0 = Opaque, 1 = Translucent / Blended */ - -#define GL_TEXTURE_BINDING_2D 0x8069 - -/* TextureUnit */ -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 - -#define GL_CURRENT_BIT 0x00000001 -#define GL_POINT_BIT 0x00000002 -#define GL_LINE_BIT 0x00000004 -#define GL_POLYGON_BIT 0x00000008 -#define GL_POLYGON_STIPPLE_BIT 0x00000010 -#define GL_PIXEL_MODE_BIT 0x00000020 -#define GL_LIGHTING_BIT 0x00000040 -#define GL_FOG_BIT 0x00000080 -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_ACCUM_BUFFER_BIT 0x00000200 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_VIEWPORT_BIT 0x00000800 -#define GL_TRANSFORM_BIT 0x00001000 -#define GL_ENABLE_BIT 0x00002000 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_HINT_BIT 0x00008000 -#define GL_EVAL_BIT 0x00010000 -#define GL_LIST_BIT 0x00020000 -#define GL_TEXTURE_BIT 0x00040000 -#define GL_SCISSOR_BIT 0x00080000 -#define GL_ALL_ATTRIB_BITS 0x000FFFFF - -/* Fog */ -#define GL_FOG 0x0004 /* capability bit */ -#define GL_FOG_MODE 0x0B65 -#define GL_FOG_DENSITY 0x0B62 -#define GL_FOG_COLOR 0x0B66 -#define GL_FOG_INDEX 0x0B61 -#define GL_FOG_START 0x0B63 -#define GL_FOG_END 0x0B64 -#define GL_LINEAR 0x2601 -#define GL_EXP 0x0800 -#define GL_EXP2 0x0801 - -/* Hints - Not used by the API, only here for compatibility */ -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 -#define GL_POINT_SMOOTH_HINT 0x0C51 -#define GL_LINE_SMOOTH_HINT 0x0C52 -#define GL_POLYGON_SMOOTH_HINT 0x0C53 -#define GL_FOG_HINT 0x0C54 - -/* Lighting constants */ -#define GL_MAX_LIGHTS 0x0008 - -#define GL_LIGHTING 0x0b50 - -#define GL_LIGHT0 0x4000 -#define GL_LIGHT1 0x4001 -#define GL_LIGHT2 0x4002 -#define GL_LIGHT3 0x4003 -#define GL_LIGHT4 0x4004 -#define GL_LIGHT5 0x4005 -#define GL_LIGHT6 0x4006 -#define GL_LIGHT7 0x4007 - -/* LightParameter */ -#define GL_AMBIENT 0x1200 -#define GL_DIFFUSE 0x1201 -#define GL_SPECULAR 0x1202 -#define GL_POSITION 0x1203 -#define GL_SPOT_DIRECTION 0x1204 -#define GL_SPOT_EXPONENT 0x1205 -#define GL_SPOT_CUTOFF 0x1206 -#define GL_CONSTANT_ATTENUATION 0x1207 -#define GL_LINEAR_ATTENUATION 0x1208 -#define GL_QUADRATIC_ATTENUATION 0x1209 - -/* MaterialParameter */ -#define GL_EMISSION 0x1600 -#define GL_SHININESS 0x1601 -#define GL_AMBIENT_AND_DIFFUSE 0x1602 -#define GL_COLOR_INDEXES 0x1603 -#define GL_COLOR_MATERIAL 0x0B57 -#define GL_COLOR_MATERIAL_FACE 0x0B55 -#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 -#define GL_NORMALIZE 0x0BA1 -#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 -#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 -#define GL_LIGHT_MODEL_AMBIENT 0x0B53 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 - -#define GL_SHADE_MODEL 0x0b54 -#define GL_FLAT 0x1d00 -#define GL_SMOOTH 0x1d01 - -/* Data types */ -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_DOUBLE 0x140A -#define GL_2_BYTES 0x1407 -#define GL_3_BYTES 0x1408 -#define GL_4_BYTES 0x1409 - -/* ErrorCode */ -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 - -/* KOS near Z-CLIPPING */ -#define GL_KOS_NEARZ_CLIPPING 0x0020 /* capability bit */ - -#define GL_UNSIGNED_SHORT_5_6_5 PVR_TXRFMT_RGB565 -#define GL_UNSIGNED_SHORT_5_6_5_REV PVR_TXRFMT_RGB565 -#define GL_UNSIGNED_SHORT_1_5_5_5 PVR_TXRFMT_ARGB1555 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV PVR_TXRFMT_ARGB1555 -#define GL_UNSIGNED_SHORT_4_4_4_4 PVR_TXRFMT_ARGB4444 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV PVR_TXRFMT_ARGB4444 - -#define GL_RGB565_TWID PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED -#define GL_ARGB4444_TWID PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED - -#define GL_RED 0x00 -#define GL_RG 0x01 -#define GL_RGB 0x02 -#define GL_BGR 0x03 -#define GL_RGBA 0x04 -#define GL_BGRA 0x05 - -#define GLbyte char -#define GLshort short -#define GLint int -#define GLfloat float -#define GLdouble float -#define GLvoid void -#define GLushort unsigned short -#define GLuint unsigned int -#define GLenum unsigned int -#define GLsizei unsigned long -#define GLfixed const unsigned int -#define GLclampf float -#define GLubyte unsigned char -#define GLboolean int -#define GL_FALSE 0 -#define GL_TRUE 1 - -#define GLAPI extern -#define APIENTRY - -/* Initialize the GL pipeline. GL will initialize the PVR. */ -GLAPI void APIENTRY glKosInit(); - -/* Start Submission of Primitive Data */ -/* Currently Supported Primitive Types: - -GL_POINTS ( does NOT work with glDrawArrays )( ZClipping NOT supported ) - -GL_TRIANGLES ( works with glDrawArrays )( ZClipping supported ) - -GL_TRIANLGLE_STRIP ( works with glDrawArrays )( ZClipping supported ) - -GL_QUADS ( works with glDrawArrays )( ZClipping supported ) -**/ -GLAPI void APIENTRY glBegin(GLenum mode); - -/* Finish Submission of Primitive Data */ -GLAPI void APIENTRY glEnd(); - -/* Primitive Texture Coordinate Submission */ -GLAPI void APIENTRY glTexCoord2f(GLfloat u, GLfloat v); -GLAPI void APIENTRY glTexCoord2fv(GLfloat *uv); - -/* Primitive Color Submission */ -GLAPI void APIENTRY glColor1ui(GLuint argb); -GLAPI void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a); -GLAPI void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b); -GLAPI void APIENTRY glColor3fv(GLfloat *rgb); -GLAPI void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); -GLAPI void APIENTRY glColor4fv(GLfloat *rgba); - -/* Primitive Normal Submission */ -GLAPI void APIENTRY glNormal3f(float x, float y, float z); -GLAPI void APIENTRY glNormal3fv(float *xyz); - -/* Primitive 2D Position Submission */ -GLAPI void APIENTRY glVertex2f(GLfloat x, GLfloat y); -GLAPI void APIENTRY glVertex2fv(GLfloat *xy); - -/* 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(GLfloat *xy); - -/* Primitive 3D Position Submission */ -GLAPI void APIENTRY(*glVertex3f)(float, float, float); -GLAPI void APIENTRY(*glVertex3fv)(float *); - -/* Enable / Disable Capability */ -/* Currently Supported Capabilities: - GL_TEXTURE_2D - GL_BLEND - GL_DEPTH_TEST - GL_LIGHTING - GL_SCISSOR_TEST - GL_FOG - GL_CULL_FACE - GL_KOS_NEARZ_CLIPPING -*/ -GLAPI void APIENTRY glEnable(GLenum cap); -GLAPI void APIENTRY glDisable(GLenum cap); - -/* Clear Caps */ -GLAPI void APIENTRY glClear(GLuint mode); -GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); - -/* Depth Testing */ -GLAPI void APIENTRY glClearDepthf(GLfloat depth); -#define glClearDepth glClearDepthf -GLAPI void APIENTRY glDepthMask(GLboolean flag); -GLAPI void APIENTRY glDepthFunc(GLenum func); - -/* Hints */ -/* Currently Supported Capabilities: - GL_PERSPECTIVE_CORRECTION_HINT - This will Enable Texture Super-Sampling on the PVR */ -GLAPI void APIENTRY glHint(GLenum target, GLenum mode); - -/* Culling */ -GLAPI void APIENTRY glFrontFace(GLenum mode); -GLAPI void APIENTRY glCullFace(GLenum mode); - -/* Shading - Flat or Goraud */ -GLAPI void APIENTRY glShadeModel(GLenum mode); - -/* Blending */ -GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor); - -/* Texturing */ -GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param); - -GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures); -GLAPI void APIENTRY glDelTextures(GLsizei n, GLuint *textures); -GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture); - -/* Loads texture from SH4 RAM into PVR VRAM */ -GLAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, GLvoid *data); - -/* Bind a Texture that is already in PVR VRAM */ -GLAPI void APIENTRY glKosTexImage2D(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, GLvoid *data); - -/* GL Array API - Only GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_QUADS are supported */ -GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer); - -GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer); - -/* If a Normal Pointer is set and GL Lighting has been enabled, - Vertex Lighting will be used instead of glColorPointer */ -GLAPI void APIENTRY glNormalPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer); - -/* Use either this OR glNormalPointer to color vertices, NOT both */ -GLAPI void APIENTRY glColorPointer(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer); - -GLAPI void APIENTRY glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer); - -/* Array Data Submission */ -GLAPI void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count); -GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); - -/* No need to Enable Array Client State... */ -#define glEnableClientState(cap) {;} -#define glDisableClientState(cap) {;} - -/* Transformation / Matrix Functions */ - -GLAPI void APIENTRY glMatrixMode(GLenum mode); - -GLAPI void APIENTRY glLoadIdentity(); - -GLAPI void APIENTRY glLoadMatrixf(const GLfloat *m); -GLAPI void APIENTRY glLoadTransposeMatrixf(const GLfloat *m); -GLAPI void APIENTRY glMultMatrixf(const GLfloat *m); -GLAPI void APIENTRY glMultTransposeMatrixf(const GLfloat *m); - -GLAPI void APIENTRY glPushMatrix(); -GLAPI void APIENTRY glPopMatrix(); - -GLAPI void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z); -#define glTranslated glTranslatef - -GLAPI void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z); -#define glScaled glScalef - -GLAPI void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -#define glRotated glRotatef - -GLAPI void APIENTRY glOrtho(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat znear, GLfloat zfar); - -GLAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height); - -GLAPI void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height); - -GLAPI void APIENTRY glKosGetMatrix(GLenum mode, GLfloat *params); - - -/* Fog Functions - client must enable GL_FOG for this to take effect */ -GLAPI void APIENTRY glFogi(GLenum pname, GLint param); -GLAPI void APIENTRY glFogf(GLenum pname, GLfloat param); -GLAPI void APIENTRY glFogfv(GLenum pname, const GLfloat *params); - -/* Lighting Functions - client must enable GL_LIGHTING for this to take effect */ - -/* Set Global Ambient Light Color */ -GLAPI void APIENTRY glKosLightAmbient3f(GLfloat r, GLfloat g, GLfloat b); -GLAPI void APIENTRY glKosLightAmbient4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); -GLAPI void APIENTRY glKosLightAmbient3fv(GLfloat *rgb); -GLAPI void APIENTRY glKosLightAmbient4fv(GLfloat *rgba); - -/* 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); - -/* Set Global Material Parameters */ -GLAPI void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param); -GLAPI void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param); -GLAPI void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); - -/* Returns the size needed to store a mip-mapped texture generated by gluBuild2DMipmaps(...) */ -GLAPI GLuint APIENTRY glKosMipMapTexSize(GLuint width, GLuint height); - -/* glGet Functions */ -void glGetIntegerv(GLenum pname, GLint *params); -void glGetFloatv(GLenum pname, GLfloat *params); - -/* Multi-Texture Extensions */ -GLAPI void APIENTRY glActiveTexture(GLenum texture); - -GLAPI void APIENTRY glClientActiveTexture(GLenum texture); - -GLAPI void APIENTRY glMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t); -GLAPI void APIENTRY glMultiTexCoord2fv(GLenum target, const GLfloat *v); - -__END_DECLS -#endif /* !__GL_GL_H */ +/* KallistiGL for KallistiOS ##version## + + libgl/gl.h + Copyright (C) 2013-2014 Josh "PH3NOM" 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. +*/ + +#ifndef __GL_GL_H +#define __GL_GL_H + +#include +__BEGIN_DECLS + +#include + +#include +#include +#include +#include +#include +#include + +/* Primitive Types taken from GL for compatability */ +/* Not all types are implemented in Open GL DC V.1.0 */ +#define GL_POINTS 0x01 +#define GL_LINES 0x02 +#define GL_LINE_LOOP 0x03 +#define GL_LINE_STRIP 0x04 +#define GL_TRIANGLES 0x05 +#define GL_TRIANGLE_STRIP 0x06 +#define GL_TRIANGLE_FAN 0x07 +#define GL_QUADS 0x08 +#define GL_QUAD_STRIP 0x09 +#define GL_POLYGON 0x0A + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 + +/* Scissor box */ +#define GL_SCISSOR_TEST 0x0008 /* capability bit */ +#define GL_SCISSOR_BOX 0x0C10 + +/* 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_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 + +/* Depth buffer */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_COMPONENT 0x1902 + +/* Blending: Simply Need to Map GL constants to PVR constants */ +#define GL_BLEND 0x0BE2 /* capability bit */ +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 + +#define GL_ZERO 0x0 +#define GL_ONE 0x1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 + +/* Misc texture constants */ +#define GL_TEXTURE_2D 0x0001 /* capability bit */ +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_FILTER GL_TEXTURE_MIN_FILTER +#define GL_FILTER_NONE 0x0 +#define GL_FILTER_BILINEAR 0x1 +#define GL_REPEAT 0x2901 +#define GL_CLAMP 0x2900 + +/* Texture Environment */ +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_REPLACE 0x0 +#define GL_MODULATE 0x1 +#define GL_DECAL 0x2 +#define GL_MODULATEALPHA 0x3 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* Texture mapping */ +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +#define GL_MAX_TEXTURE_UNITS 0x2 /* 0 = Opaque, 1 = Translucent / Blended */ + +#define GL_TEXTURE_BINDING_2D 0x8069 + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 + +#define GL_CURRENT_BIT 0x00000001 +#define GL_POINT_BIT 0x00000002 +#define GL_LINE_BIT 0x00000004 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_HINT_BIT 0x00008000 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000FFFFF + +/* Fog */ +#define GL_FOG 0x0004 /* capability bit */ +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_COLOR 0x0B66 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_LINEAR 0x2601 +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 + +/* Hints - Not used by the API, only here for compatibility */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 + +/* Lighting constants */ +#define GL_MAX_LIGHTS 0x0008 + +#define GL_LIGHTING 0x0b50 + +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 + +/* LightParameter */ +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 + +/* MaterialParameter */ +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_NORMALIZE 0x0BA1 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 + +#define GL_SHADE_MODEL 0x0b54 +#define GL_FLAT 0x1d00 +#define GL_SMOOTH 0x1d01 + +/* Data types */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_DOUBLE 0x140A +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 + +/* KOS near Z-CLIPPING */ +#define GL_KOS_NEARZ_CLIPPING 0x0020 /* capability bit */ + +#define GL_UNSIGNED_SHORT_5_6_5 PVR_TXRFMT_RGB565 +#define GL_UNSIGNED_SHORT_5_6_5_REV PVR_TXRFMT_RGB565 +#define GL_UNSIGNED_SHORT_1_5_5_5 PVR_TXRFMT_ARGB1555 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV PVR_TXRFMT_ARGB1555 +#define GL_UNSIGNED_SHORT_4_4_4_4 PVR_TXRFMT_ARGB4444 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV PVR_TXRFMT_ARGB4444 + +#define GL_RGB565_TWID PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED +#define GL_ARGB4444_TWID PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED + +#define GL_RED 0x00 +#define GL_RG 0x01 +#define GL_RGB 0x02 +#define GL_BGR 0x03 +#define GL_RGBA 0x04 +#define GL_BGRA 0x05 + +#define GLbyte char +#define GLshort short +#define GLint int +#define GLfloat float +#define GLdouble float +#define GLvoid void +#define GLushort unsigned short +#define GLuint unsigned int +#define GLenum unsigned int +#define GLsizei unsigned long +#define GLfixed const unsigned int +#define GLclampf float +#define GLubyte unsigned char +#define GLboolean int +#define GL_FALSE 0 +#define GL_TRUE 1 + +#define GLAPI extern +#define APIENTRY + +/* Initialize the GL pipeline. GL will initialize the PVR. */ +GLAPI void APIENTRY glKosInit(); + +/* Start Submission of Primitive Data */ +/* Currently Supported Primitive Types: + -GL_POINTS ( does NOT work with glDrawArrays )( ZClipping NOT supported ) + -GL_TRIANGLES ( works with glDrawArrays )( ZClipping supported ) + -GL_TRIANLGLE_STRIP ( works with glDrawArrays )( ZClipping supported ) + -GL_QUADS ( works with glDrawArrays )( ZClipping supported ) +**/ +GLAPI void APIENTRY glBegin(GLenum mode); + +/* Finish Submission of Primitive Data */ +GLAPI void APIENTRY glEnd(); + +/* Primitive Texture Coordinate Submission */ +GLAPI void APIENTRY glTexCoord2f(GLfloat u, GLfloat v); +GLAPI void APIENTRY glTexCoord2fv(GLfloat *uv); + +/* Primitive Color Submission */ +GLAPI void APIENTRY glColor1ui(GLuint argb); +GLAPI void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a); +GLAPI void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b); +GLAPI void APIENTRY glColor3fv(GLfloat *rgb); +GLAPI void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); +GLAPI void APIENTRY glColor4fv(GLfloat *rgba); + +/* Primitive Normal Submission */ +GLAPI void APIENTRY glNormal3f(float x, float y, float z); +GLAPI void APIENTRY glNormal3fv(float *xyz); + +/* Primitive 2D Position Submission */ +GLAPI void APIENTRY glVertex2f(GLfloat x, GLfloat y); +GLAPI void APIENTRY glVertex2fv(GLfloat *xy); + +/* 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(GLfloat *xy); + +/* Primitive 3D Position Submission */ +GLAPI void APIENTRY(*glVertex3f)(float, float, float); +GLAPI void APIENTRY(*glVertex3fv)(float *); + +/* Enable / Disable Capability */ +/* Currently Supported Capabilities: + GL_TEXTURE_2D + GL_BLEND + GL_DEPTH_TEST + GL_LIGHTING + GL_SCISSOR_TEST + GL_FOG + GL_CULL_FACE + GL_KOS_NEARZ_CLIPPING +*/ +GLAPI void APIENTRY glEnable(GLenum cap); +GLAPI void APIENTRY glDisable(GLenum cap); + +/* Clear Caps */ +GLAPI void APIENTRY glClear(GLuint mode); +GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); + +/* Depth Testing */ +GLAPI void APIENTRY glClearDepthf(GLfloat depth); +#define glClearDepth glClearDepthf +GLAPI void APIENTRY glDepthMask(GLboolean flag); +GLAPI void APIENTRY glDepthFunc(GLenum func); + +/* Hints */ +/* Currently Supported Capabilities: + GL_PERSPECTIVE_CORRECTION_HINT - This will Enable Texture Super-Sampling on the PVR */ +GLAPI void APIENTRY glHint(GLenum target, GLenum mode); + +/* Culling */ +GLAPI void APIENTRY glFrontFace(GLenum mode); +GLAPI void APIENTRY glCullFace(GLenum mode); + +/* Shading - Flat or Goraud */ +GLAPI void APIENTRY glShadeModel(GLenum mode); + +/* Blending */ +GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor); + +/* Texturing */ +GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param); + +GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures); +GLAPI void APIENTRY glDelTextures(GLsizei n, GLuint *textures); +GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture); + +/* Loads texture from SH4 RAM into PVR VRAM */ +GLAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, GLvoid *data); + +/* Bind a Texture that is already in PVR VRAM */ +GLAPI void APIENTRY glKosTexImage2D(GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, GLvoid *data); + +/* GL Array API - Only GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_QUADS are supported */ +GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer); + +GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer); + +/* If a Normal Pointer is set and GL Lighting has been enabled, + Vertex Lighting will be used instead of glColorPointer */ +GLAPI void APIENTRY glNormalPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer); + +/* Use either this OR glNormalPointer to color vertices, NOT both */ +GLAPI void APIENTRY glColorPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer); + +GLAPI void APIENTRY glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer); + +/* Array Data Submission */ +GLAPI void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); + +/* No need to Enable Array Client State... */ +#define glEnableClientState(cap) {;} +#define glDisableClientState(cap) {;} + +/* Transformation / Matrix Functions */ + +GLAPI void APIENTRY glMatrixMode(GLenum mode); + +GLAPI void APIENTRY glLoadIdentity(); + +GLAPI void APIENTRY glLoadMatrixf(const GLfloat *m); +GLAPI void APIENTRY glLoadTransposeMatrixf(const GLfloat *m); +GLAPI void APIENTRY glMultMatrixf(const GLfloat *m); +GLAPI void APIENTRY glMultTransposeMatrixf(const GLfloat *m); + +GLAPI void APIENTRY glPushMatrix(); +GLAPI void APIENTRY glPopMatrix(); + +GLAPI void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z); +#define glTranslated glTranslatef + +GLAPI void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z); +#define glScaled glScalef + +GLAPI void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +#define glRotated glRotatef + +GLAPI void APIENTRY glOrtho(GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat znear, GLfloat zfar); + +GLAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height); + +GLAPI void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height); + +GLAPI void APIENTRY glKosGetMatrix(GLenum mode, GLfloat *params); + + +/* Fog Functions - client must enable GL_FOG for this to take effect */ +GLAPI void APIENTRY glFogi(GLenum pname, GLint param); +GLAPI void APIENTRY glFogf(GLenum pname, GLfloat param); +GLAPI void APIENTRY glFogfv(GLenum pname, const GLfloat *params); + +/* Lighting Functions - client must enable GL_LIGHTING for this to take effect */ + +/* Set Global Ambient Light Color */ +GLAPI void APIENTRY glKosLightAmbient3f(GLfloat r, GLfloat g, GLfloat b); +GLAPI void APIENTRY glKosLightAmbient4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); +GLAPI void APIENTRY glKosLightAmbient3fv(GLfloat *rgb); +GLAPI void APIENTRY glKosLightAmbient4fv(GLfloat *rgba); + +/* 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); + +/* Set Global Material Parameters */ +GLAPI void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param); +GLAPI void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param); +GLAPI void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); + +/* Returns the size needed to store a mip-mapped texture generated by gluBuild2DMipmaps(...) */ +GLAPI GLuint APIENTRY glKosMipMapTexSize(GLuint width, GLuint height); + +/* glGet Functions */ +void glGetIntegerv(GLenum pname, GLint *params); +void glGetFloatv(GLenum pname, GLfloat *params); + +/* Multi-Texture Extensions */ +GLAPI void APIENTRY glActiveTexture(GLenum texture); + +GLAPI void APIENTRY glClientActiveTexture(GLenum texture); + +GLAPI void APIENTRY glMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t); +GLAPI void APIENTRY glMultiTexCoord2fv(GLenum target, const GLfloat *v); + +__END_DECLS +#endif /* !__GL_GL_H */ diff --git a/include/glu.h b/include/glu.h index d60790d..b4d9818 100755 --- a/include/glu.h +++ b/include/glu.h @@ -1,45 +1,45 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/glu.h - Copyright (C) 2013-2014 Josh "PH3NOM" Pearson - - Some functionality adapted from the original KOS libgl: - Copyright (C) 2001 Dan Potter - Copyright (C) 2002 Benoit Miller - -*/ - -#ifndef __GL_GLU_H -#define __GL_GLU_H - -#include -__BEGIN_DECLS - -#include - -#define GLU_FALSE GL_FALSE -#define GLU_TRUE GL_TRUE - -/* Mip-Mapped Textures MUST be square or rectangle */ -GLAPI GLint APIENTRY gluBuild2DMipmaps(GLenum target, GLint internalFormat, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const void *data); - -/* gluPerspective - Set the Perspective for Rendering. */ -GLAPI void APIENTRY gluPerspective(GLdouble fovy, GLdouble aspect, - GLdouble zNear, GLdouble zFar); - -/* gluLookAt - Set Camera Position for Rendering. */ -GLAPI void APIENTRY gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, - GLfloat centerx, GLfloat centery, GLfloat centerz, - GLfloat upx, GLfloat upy, GLfloat upz); - -/* glhLookAtf2 = gluLookAt operating on 3 float vectors. */ -GLAPI void APIENTRY glhLookAtf2(GLfloat *eyePosition3D, - GLfloat *center3D, - GLfloat *upVector3D); - -__END_DECLS - -#endif /* !__GL_GLU_H */ +/* KallistiGL for KallistiOS ##version## + + libgl/glu.h + Copyright (C) 2013-2014 Josh "PH3NOM" Pearson + + Some functionality adapted from the original KOS libgl: + Copyright (C) 2001 Dan Potter + Copyright (C) 2002 Benoit Miller + +*/ + +#ifndef __GL_GLU_H +#define __GL_GLU_H + +#include +__BEGIN_DECLS + +#include + +#define GLU_FALSE GL_FALSE +#define GLU_TRUE GL_TRUE + +/* Mip-Mapped Textures MUST be square or rectangle */ +GLAPI GLint APIENTRY gluBuild2DMipmaps(GLenum target, GLint internalFormat, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const void *data); + +/* gluPerspective - Set the Perspective for Rendering. */ +GLAPI void APIENTRY gluPerspective(GLdouble fovy, GLdouble aspect, + GLdouble zNear, GLdouble zFar); + +/* gluLookAt - Set Camera Position for Rendering. */ +GLAPI void APIENTRY gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, + GLfloat centerx, GLfloat centery, GLfloat centerz, + GLfloat upx, GLfloat upy, GLfloat upz); + +/* glhLookAtf2 = gluLookAt operating on 3 float vectors. */ +GLAPI void APIENTRY glhLookAtf2(GLfloat *eyePosition3D, + GLfloat *center3D, + GLfloat *upVector3D); + +__END_DECLS + +#endif /* !__GL_GLU_H */ diff --git a/include/glut.h b/include/glut.h index c77a5cd..717a2b9 100755 --- a/include/glut.h +++ b/include/glut.h @@ -1,30 +1,30 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/glut.h - Copyright (C) 2014 Josh Pearson - Copyright (C) 2014 Lawrence Sebald - -*/ - -#ifndef __GL_GLUT_H -#define __GL_GLUT_H - -#include -__BEGIN_DECLS - -#include - -/* Flush the Submitted Primitive Data to the GPU for render to screen */ -GLAPI void APIENTRY glutSwapBuffers(); - -/* Flush the Submitted Primitive Data to the GPU for render to texture */ -GLAPI void APIENTRY glutSwapBuffersToTexture(void *dst, GLsizei *x, GLsizei *y); - -/* Copy the Submitted Primitive Data to the GPU for render to texture */ -/* This will leave the Vertex Data in the Main Buffer to be Flushed on the - next frame rendered */ -GLAPI void APIENTRY glutCopyBufferToTexture(void *dst, GLsizei *x, GLsizei *y); - -__END_DECLS - -#endif /* !__GL_GLUT_H */ +/* KallistiGL for KallistiOS ##version## + + libgl/glut.h + Copyright (C) 2014 Josh Pearson + Copyright (C) 2014 Lawrence Sebald + +*/ + +#ifndef __GL_GLUT_H +#define __GL_GLUT_H + +#include +__BEGIN_DECLS + +#include + +/* Flush the Submitted Primitive Data to the GPU for render to screen */ +GLAPI void APIENTRY glutSwapBuffers(); + +/* Flush the Submitted Primitive Data to the GPU for render to texture */ +GLAPI void APIENTRY glutSwapBuffersToTexture(void *dst, GLsizei *x, GLsizei *y); + +/* Copy the Submitted Primitive Data to the GPU for render to texture */ +/* This will leave the Vertex Data in the Main Buffer to be Flushed on the + next frame rendered */ +GLAPI void APIENTRY glutCopyBufferToTexture(void *dst, GLsizei *x, GLsizei *y); + +__END_DECLS + +#endif /* !__GL_GLUT_H */