Updated changelog/relnotes, moved most addons into their own tree

This commit is contained in:
Dan Potter 2003-10-13 00:41:10 +00:00
commit cbe2111cd8
17 changed files with 2910 additions and 0 deletions

15
Makefile Executable file
View File

@ -0,0 +1,15 @@
# KallistiOS ##version##
#
# addons/libgl Makefile
# (c)2001 Dan Potter
#
# $Id: Makefile,v 1.5 2003/02/27 04:25:39 bardtx Exp $
TARGET = libgl.a
OBJS = gldepth.o gldraw.o glkos.o gllight.o glmisc.o
OBJS += gltex.o gltrans.o glvars.o glblend.o glfog.o glmodifier.o glnzclip.o
SUBDIRS =
include ../Makefile.prefab

79
glblend.c Normal file
View File

@ -0,0 +1,79 @@
/* KallistiGL for KOS ##version##
glblend.c
(c)2002 Benoit Miller
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include <assert.h>
CVSID("$Id: glblend.c,v 1.3 2002/04/03 03:33:38 axlen Exp $");
/* Blending */
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(sfactor) {
case GL_ZERO:
gl_blend_src = PVR_BLEND_ZERO;
break;
case GL_ONE:
gl_blend_src = PVR_BLEND_ONE;
break;
case GL_DST_COLOR:
gl_blend_src = PVR_BLEND_DESTCOLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
gl_blend_src = PVR_BLEND_INVDESTCOLOR;
break;
case GL_SRC_ALPHA:
gl_blend_src = PVR_BLEND_SRCALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
gl_blend_src = PVR_BLEND_INVSRCALPHA;
break;
case GL_DST_ALPHA:
gl_blend_src = PVR_BLEND_DESTALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
gl_blend_src = PVR_BLEND_INVDESTALPHA;
break;
default:
assert_msg(0, "Invalid source blending function.");
}
switch(dfactor) {
case GL_ZERO:
gl_blend_dst = PVR_BLEND_ZERO;
break;
case GL_ONE:
gl_blend_dst = PVR_BLEND_ONE;
break;
case GL_SRC_COLOR:
gl_blend_dst = PVR_BLEND_DESTCOLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
gl_blend_dst = PVR_BLEND_INVDESTCOLOR;
break;
case GL_SRC_ALPHA:
gl_blend_dst = PVR_BLEND_SRCALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
gl_blend_dst = PVR_BLEND_INVSRCALPHA;
break;
case GL_DST_ALPHA:
gl_blend_dst = PVR_BLEND_DESTALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
gl_blend_dst = PVR_BLEND_INVDESTALPHA;
break;
default:
assert_msg(0, "Invalid destination blending function");
}
gl_pbuf_submitted = GL_FALSE;
}

97
glclip.h Normal file
View File

@ -0,0 +1,97 @@
/* KallistiGL for KOS ##version##
Near Z Clipper
(c) Trilinear
Trilinear@hotmail.com
$Id: glclip.h,v 1.2 2002/06/28 04:47:02 axlen Exp $
*/
#ifndef __GLCLIP_H
#define __GLCLIP_H
#include <GL/gl.h>
#include "glinternal.h"
#define MAXZ 0.0001f /* if z is negative, it is behind the camera */
inline void CopyV(gl_vertex_t *vertold, gl_vertex_t *vertnew) {
/* memcpy(vertnew, vertold, sizeof(gl_vertex_t)); */
vertnew->flags = vertold->flags;
vertnew->x = vertold->x;
vertnew->y = vertold->y;
vertnew->z = vertold->z;
vertnew->w = vertold->w;
vertnew->u = vertold->u;
vertnew->v = vertold->v;
vertnew->argb = vertold->argb;
vertnew->oargb = vertold->oargb;
}
inline void FindZ(gl_vertex_t *vertnew, gl_vertex_t *vert1, gl_vertex_t *vert2) {
float diffz;
/* z is indp variable because we know it changes, thus no div 0 error */
vertnew->z = gl_frustum.znear;
vertnew->w = vert1->w + (gl_frustum.znear-vert1->z)*(vert1->w - vert2->w)/(vert1->z - vert2->z);
vertnew->x = vert1->x + (gl_frustum.znear-vert1->z)*(vert1->x - vert2->x)/(vert1->z - vert2->z);
vertnew->y = vert1->y + (gl_frustum.znear-vert1->z)*(vert1->y - vert2->y)/(vert1->z - vert2->z);
diffz = (vert1->z-vertnew->z)/(vert1->z-vert2->z);
vertnew->u = (diffz)*vert2->u + (1.0f-diffz)*vert1->u;
vertnew->v = (diffz)*vert2->v + (1.0f-diffz)*vert1->v;
}
inline int ZClipTex(gl_vertex_t *vert)
/* returns 0 for full clip, 3 for triangle output and 4 for quad output
based on sutherland-hodgeman clip algorithm */
{
int i,j;
gl_vertex_t tempvert[4];
if (vert[0].z < gl_frustum.znear || vert[1].z < gl_frustum.znear || vert[2].z < gl_frustum.znear) {/* one or more parts behind camera */
j=0;
CopyV(&vert[0],&vert[3]);/* copy first to next after last to make cyclic */
for(i=0; i<3; i++) {
if (vert[i].z >= gl_frustum.znear && vert[i+1].z >= gl_frustum.znear) { /* both in */
CopyV(&vert[i],&tempvert[j]);
j++;
}else if (vert[i].z < gl_frustum.znear && vert[i+1].z >= gl_frustum.znear) {/* this out, next in */
CopyV(&vert[i],&tempvert[j]);
FindZ(&tempvert[j],&vert[i],&vert[i+1]);
j++;
}else if (vert[i].z >= gl_frustum.znear && vert[i+1].z < gl_frustum.znear) {/* this in, next out */
CopyV(&vert[i],&tempvert[j]);
CopyV(&vert[i+1],&tempvert[j+1]);
FindZ(&tempvert[j+1],&vert[i],&vert[i+1]);
j+=2;
}/* both out, ignore */
}
switch (j) {
case 3:
CopyV(&tempvert[0],&vert[0]);
CopyV(&tempvert[1],&vert[1]);
CopyV(&tempvert[2],&vert[2]);
return 3;
case 4:
CopyV(&tempvert[0],&vert[0]);
CopyV(&tempvert[1],&vert[1]);
CopyV(&tempvert[2],&vert[3]);
CopyV(&tempvert[3],&vert[2]);
return 4;
}/* if j==0 we return 0 which we are about to do anyway */
}else{/* is all in front of camera */
return 3;
}
return 0;/* if it isn't one of the above it is an invalid poly or completely behind camera */
}
#endif /* __GLCLIP_H */

74
gldepth.c Normal file
View File

@ -0,0 +1,74 @@
/* KallistiGL for KOS ##version##
gldepth.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include <assert.h>
#include <stdio.h>
CVSID("$Id: gldepth.c,v 1.7 2002/04/03 03:34:22 axlen Exp $");
/* Depth buffer (non-functional, just stubs) */
void glClearDepth(GLclampd depth) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
}
void glDepthFunc(GLenum func) {
/* Note regarding the mapping of OpenGL depth stuff to the PVR2DC:
The depth compare modes should be "conceptually" the same except
for two points:
1) You have a floating point "Depth buffer" and
2) DC uses 1/W to compare so 1 (or higher if your clipping
is off!) = near and 0=infinity.
Therefore > or >= is probably what you want for closer objects to be visible. - Simon Fenney
*/
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(func)
{
case GL_ALWAYS:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_ALWAYS;
break;
case GL_LESS:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_GEQUAL;
break;
case GL_NOTEQUAL:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_NOTEQUAL;
break;
case GL_LEQUAL:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_GREATER;
break;
case GL_GREATER:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_LEQUAL;
break;
case GL_EQUAL:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_EQUAL;
break;
case GL_GEQUAL:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_LESS;
break;
case GL_NEVER:
gl_poly_cxt.depth.comparison = PVR_DEPTHCMP_NEVER;
break;
default:
assert_msg(0, "Invalid depth comparison function.");
}
gl_pbuf_submitted = GL_FALSE;
}
void glDepthMask(GLboolean flag) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
if (flag) {
gl_poly_cxt.depth.write = PVR_DEPTHWRITE_ENABLE;
} else {
gl_poly_cxt.depth.write = PVR_DEPTHWRITE_DISABLE;
}
gl_pbuf_submitted = GL_FALSE;
}

595
gldraw.c Normal file
View File

@ -0,0 +1,595 @@
/* KallistiGL for KOS ##version##
gldraw.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include <assert.h>
#include <string.h>
#include <malloc.h>
#include <dc/pvr.h>
CVSID("$Id: gldraw.c,v 1.23 2002/09/05 07:36:23 bardtx Exp $");
/* internal prototypes */
static void send_user_clip();
/* Drawing functions */
/* This portion of the pipeline will change drastically */
/* Current vertex attributes (move to global?) */
static GLuint vert_rgba = 0xffffffff;
static GLfloat vert_u = 0.0f, vert_v = 0.0f;
/* Make sure the proper matrices are in the matrix registers */
static void fix_matrices() {
if (gl_matrix_dirty) {
mat_identity();
glKosMatrixApply(GL_KOS_SCREENVIEW);
glKosMatrixApply(GL_PROJECTION);
glKosMatrixApply(GL_MODELVIEW);
gl_matrix_dirty = GL_FALSE;
}
}
/* Negative 1/w values annoy the pvr, so check for them */
static inline int check_w(gl_vertex_t *vert, int n) {
int i;
for(i=0; i<n; i++)
if (vert[i].z < 0) return 0;
return 1;
}
static short xor[2][2] ={
{1,0}, /* FFCW, FFCCW */
{0,1} /* BFCW, BFCCW */
};
/* GL_POINTS always visible! */
static void end_points() {
int i;
volatile pvr_vertex_t *vert;
pvr_dr_state_t dr_state;
float size1 = (xor[(gl_cull_mode == GL_BACK)][(gl_front_face == GL_CCW)]) ?
gl_point_size : -gl_point_size;
float size2 = ABS(size1);
pvr_dr_init(dr_state);
/* Should be one point in the buffer */
assert_msg(gl_vbuf_top >= 1, "Need at least one point.");
/* create a point using a quad */
memcpy(&gl_vbuf[1], &gl_vbuf[0], sizeof(gl_vertex_t));
memcpy(&gl_vbuf[2], &gl_vbuf[0], sizeof(gl_vertex_t));
memcpy(&gl_vbuf[3], &gl_vbuf[0], sizeof(gl_vertex_t));
gl_vbuf[3].flags = PVR_CMD_VERTEX_EOL;
mat_transform((vector_t*)&gl_vbuf[0].x, (vector_t*)&gl_xbuf[0].x, 4, sizeof(gl_vertex_t));
gl_xbuf[0].x += size1;
gl_xbuf[0].y += size2;
gl_xbuf[1].x += size1;
gl_xbuf[1].y -= size2;
gl_xbuf[2].x -= size1;
gl_xbuf[2].y += size2;
gl_xbuf[3].x -= size1;
gl_xbuf[3].y -= size2;
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, 4))
for (i=0; i<4; i++) {
vert = pvr_dr_target(dr_state);
vert->flags = gl_vbuf[i].flags;
vert->x = gl_xbuf[i].x;
vert->y = gl_xbuf[i].y;
vert->z = gl_xbuf[i].z;
vert->u = gl_vbuf[i].u;
vert->v = gl_vbuf[i].v;
vert->argb = gl_vbuf[i].argb;
vert->oargb = gl_vbuf[i].oargb;
pvr_dr_commit(vert);
}
}
static void end_triangles() {
int i;
volatile pvr_vertex_t *vert;
pvr_dr_state_t dr_state;
pvr_dr_init(dr_state);
/* Should be three points in the buffer */
assert_msg(gl_vbuf_top == 3, "Wrong number of vertices.");
gl_vbuf[2].flags = PVR_CMD_VERTEX_EOL;
/* mat_transform((vector_t*)&gl_vbuf[0].x, (vector_t*)&gl_xbuf[0].x, 3,
sizeof(gl_vertex_t)); */
for (i=0; i<gl_vbuf_top; i++) {
float x = gl_vbuf[i].x, y = gl_vbuf[i].y, z = gl_vbuf[i].z, w = 1.0f;
mat_trans_single4(x, y, z, w);
gl_xbuf[i].x = x;
gl_xbuf[i].y = y;
if (w == 1.0f)
gl_xbuf[i].z = ((gl_viewport_scale[2] * z) + gl_viewport_offset[2]);
else
gl_xbuf[i].z = w;
}
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, 3))
for (i=0; i<3; i++) {
vert = pvr_dr_target(dr_state);
vert->flags = gl_vbuf[i].flags;
vert->x = gl_xbuf[i].x;
vert->y = gl_xbuf[i].y;
vert->z = gl_xbuf[i].z;
vert->u = gl_vbuf[i].u;
vert->v = gl_vbuf[i].v;
vert->argb = gl_vbuf[i].argb;
vert->oargb = gl_vbuf[i].oargb;
pvr_dr_commit(vert);
}
}
static void end_triangle_strip() {
int i;
volatile pvr_vertex_t *vert;
pvr_dr_state_t dr_state;
pvr_dr_init(dr_state);
/* Should be at least 3 points in the buffer */
assert_msg(gl_vbuf_top >= 3, "Need at least three vertices.");
gl_vbuf[gl_vbuf_top-1].flags = PVR_CMD_VERTEX_EOL;
/* mat_transform((vector_t*)&gl_vbuf[0].x, (vector_t*)&gl_xbuf[0].x,
gl_vbuf_top, sizeof(gl_vertex_t)); */
for (i=0; i<gl_vbuf_top; i++) {
float x = gl_vbuf[i].x, y = gl_vbuf[i].y, z = gl_vbuf[i].z, w = 1.0f;
mat_trans_single4(x, y, z, w);
gl_xbuf[i].x = x;
gl_xbuf[i].y = y;
if (w == 1.0f)
gl_xbuf[i].z = ((gl_viewport_scale[2] * z) + gl_viewport_offset[2]);
else
gl_xbuf[i].z = w;
}
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, gl_vbuf_top))
for (i=0; i<gl_vbuf_top; i++) {
vert = pvr_dr_target(dr_state);
vert->flags = gl_vbuf[i].flags;
vert->x = gl_xbuf[i].x;
vert->y = gl_xbuf[i].y;
vert->z = gl_xbuf[i].z;
vert->u = gl_vbuf[i].u;
vert->v = gl_vbuf[i].v;
vert->argb = gl_vbuf[i].argb;
vert->oargb = gl_vbuf[i].oargb;
pvr_dr_commit(vert);
}
}
static void end_quads() {
int i, j, order[4] = {3, 0, 2, 1};
volatile pvr_vertex_t *vert;
pvr_dr_state_t dr_state;
pvr_dr_init(dr_state);
/* Should be four points in the buffer */
assert_msg(gl_vbuf_top == 4, "Wrong number of vertices.");
gl_vbuf[order[3]].flags = PVR_CMD_VERTEX_EOL;
/* mat_transform((vector_t*)&gl_vbuf[0].x, (vector_t*)&gl_xbuf[0].x, 4,
sizeof(gl_vertex_t)); */
for (i=0; i<gl_vbuf_top; i++) {
float x = gl_vbuf[i].x, y = gl_vbuf[i].y, z = gl_vbuf[i].z, w = 1.0f;
mat_trans_single4(x, y, z, w);
gl_xbuf[i].x = x;
gl_xbuf[i].y = y;
if (w == 1.0f)
gl_xbuf[i].z = ((gl_viewport_scale[2] * z) + gl_viewport_offset[2]);
else
gl_xbuf[i].z = w;
}
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, 4))
for (i=0; i<4; i++) {
j = order[i];
vert = pvr_dr_target(dr_state);
vert->flags = gl_vbuf[j].flags;
vert->x = gl_xbuf[j].x;
vert->y = gl_xbuf[j].y;
vert->z = gl_xbuf[j].z;
vert->u = gl_vbuf[j].u;
vert->v = gl_vbuf[j].v;
vert->argb = gl_vbuf[j].argb;
vert->oargb = gl_vbuf[j].oargb;
pvr_dr_commit(vert);
}
}
static void end_quad_strip() {
int i;
volatile pvr_vertex_t *vert;
pvr_dr_state_t dr_state;
pvr_dr_init(dr_state);
/* Should be at least 4 points in the buffer */
assert_msg(gl_vbuf_top >= 4, "Need at least four vertices.");
/* OpenGL specs that any dangling vertex be chopped, which
we have to do since we're rendering as a tri-strip. */
if(gl_vbuf_top & 0x0001)
gl_vbuf_top--;
gl_vbuf[gl_vbuf_top-1].flags = PVR_CMD_VERTEX_EOL;
for (i=0; i<gl_vbuf_top; i++) {
float x = gl_vbuf[i].x, y = gl_vbuf[i].y, z = gl_vbuf[i].z, w = 1.0f;
mat_trans_single4(x, y, z, w);
gl_xbuf[i].x = x;
gl_xbuf[i].y = y;
if (w == 1.0f)
gl_xbuf[i].z = ((gl_viewport_scale[2] * z) + gl_viewport_offset[2]);
else
gl_xbuf[i].z = w;
}
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, gl_vbuf_top))
for (i=0; i<gl_vbuf_top; i++) {
vert = pvr_dr_target(dr_state);
vert->flags = gl_vbuf[i].flags;
vert->x = gl_xbuf[i].x;
vert->y = gl_xbuf[i].y;
vert->z = gl_xbuf[i].z;
vert->u = gl_vbuf[i].u;
vert->v = gl_vbuf[i].v;
vert->argb = gl_vbuf[i].argb;
vert->oargb = gl_vbuf[i].oargb;
pvr_dr_commit(vert);
}
}
static void end_polygon() {
int i, j_frn, j_bck;
volatile pvr_vertex_t *vert;
gl_vertex_t *gl_tvbuf;
pvr_dr_state_t dr_state;
pvr_dr_init(dr_state);
/* Should be at least 3 points in the buffer */
assert_msg(gl_vbuf_top >= 3, "Need at least three vertices.");
/* Have to alter linear vertex order to staggered Triangle strip order
performance will suffer, but it does on all cards. */
gl_tvbuf = malloc(sizeof(gl_vertex_t) * (gl_vbuf_top));
assert_msg(gl_tvbuf != NULL, "Not enough memory for GL_POLYGON");
gl_tvbuf[0] = gl_vbuf[0];
gl_tvbuf[1] = gl_vbuf[1];
i = 2; /* the first 2 vertices are in proper order. */
j_frn = i;
j_bck = gl_vbuf_top - 1;
do {
gl_tvbuf[i++] = gl_vbuf[j_bck]; /* move data */
if (i < gl_vbuf_top) {
gl_tvbuf[i++] = gl_vbuf[j_frn];
j_frn++;
j_bck--;
}
} while (i < gl_vbuf_top);
memcpy(gl_vbuf, gl_tvbuf, sizeof(gl_vertex_t) * gl_vbuf_top);
free(gl_tvbuf);
gl_vbuf[gl_vbuf_top-1].flags = PVR_CMD_VERTEX_EOL;
for (i=0; i<gl_vbuf_top; i++) {
float x = gl_vbuf[i].x, y = gl_vbuf[i].y, z = gl_vbuf[i].z, w = 1.0f;
mat_trans_single4(x, y, z, w);
gl_xbuf[i].x = x;
gl_xbuf[i].y = y;
if (w == 1.0f)
gl_xbuf[i].z = ((gl_viewport_scale[2] * z) + gl_viewport_offset[2]);
else
gl_xbuf[i].z = w;
}
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, gl_vbuf_top))
for (i=0; i<gl_vbuf_top; i++) {
vert = pvr_dr_target(dr_state);
vert->flags = gl_vbuf[i].flags;
vert->x = gl_xbuf[i].x;
vert->y = gl_xbuf[i].y;
vert->z = gl_xbuf[i].z;
vert->u = gl_vbuf[i].u;
vert->v = gl_vbuf[i].v;
vert->argb = gl_vbuf[i].argb;
vert->oargb = gl_vbuf[i].oargb;
pvr_dr_commit(vert);
}
}
static void check_end() {
/* What type of primitive was it? */
switch(gl_prim_type) {
case GL_POINTS:
end_points();
gl_vbuf_top = 0;
break;
case GL_TRIANGLES:
if (gl_vbuf_top == 3) {
end_triangles();
gl_vbuf_top = 0;
}
break;
case GL_TRIANGLE_STRIP:
break;
case GL_QUADS:
if (gl_vbuf_top == 4) {
end_quads();
gl_vbuf_top = 0;
}
break;
case GL_QUAD_STRIP:
break;
case GL_POLYGON:
break;
default:
assert_msg(0, "gl_prim_type: Unknown primitive type.");
}
}
static pvr_poly_hdr_t polyhdr;
void send_poly_hdr(void) {
if (TXR_ENABLED) {
memcpy(&gl_poly_cxt.txr, &gl_cur_texture->txr, sizeof(gl_poly_cxt.txr));
}
switch(gl_active_list) {
case GL_LIST_OPAQUE_POLY:
gl_poly_cxt.gen.alpha = PVR_ALPHA_DISABLE;
gl_poly_cxt.txr.alpha = PVR_TXRALPHA_ENABLE;
gl_poly_cxt.blend.src = PVR_BLEND_ONE;
gl_poly_cxt.blend.dst = PVR_BLEND_ZERO;
break;
case GL_LIST_OPAQUE_MOD:
break;
case GL_LIST_TRANS_POLY:
case GL_LIST_PUNCHTHRU:
gl_poly_cxt.gen.alpha = PVR_ALPHA_ENABLE;
gl_poly_cxt.txr.alpha = PVR_TXRALPHA_ENABLE;
gl_poly_cxt.blend.src = gl_blend_src;
gl_poly_cxt.blend.dst = gl_blend_dst;
break;
case GL_LIST_TRANS_MOD:
break;
}
/* Set states that we couldn't before */
if (gl_cull_face)
{
if (gl_cull_mode == GL_BACK)
if (gl_front_face == GL_CW)
gl_poly_cxt.gen.culling = PVR_CULLING_CCW;
else
gl_poly_cxt.gen.culling = PVR_CULLING_CW;
else
if (gl_front_face == 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(&polyhdr, &gl_poly_cxt);
pvr_prim(&polyhdr, sizeof(pvr_poly_hdr_t));
}
/* This can be used for KGL Direct Rendering */
void glKosPolyHdrSend() {
send_poly_hdr();
}
void glBegin(GLenum mode) {
/* Submit the user clip rectangle (if necessary) */
if (gl_scissor_dirty) {
send_user_clip();
gl_scissor_dirty = GL_FALSE;
}
/* Submit the poly buffer (if necessary) */
if (!gl_pbuf_submitted) {
send_poly_hdr();
gl_pbuf_submitted = GL_TRUE;
}
if (ZCLIP_ENABLED || LIGHTING_ENABLED)
fix_vfzclip_matrices();
else
fix_matrices();
gl_prim_type = mode;
gl_vbuf_top = 0;
}
void glEnd(void) {
if (MODIFIER_ENABLED) {
modifier_end();
return;
} else if (ZCLIP_ENABLED || LIGHTING_ENABLED) {
vfzclip_end();
return;
}
/* What type of primitive was it? */
switch(gl_prim_type) {
case GL_POINTS:
break;
case GL_TRIANGLES:
break;
case GL_TRIANGLE_STRIP:
end_triangle_strip();
break;
case GL_QUADS:
break;
case GL_QUAD_STRIP:
end_quad_strip();
break;
case GL_POLYGON:
end_polygon();
break;
default:
assert_msg(0, "gl_prim_type: Unknown primitive type.");
}
gl_prim_type = 0;
}
static float autouv[4][2] = {
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f}
};
void glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
gl_vbuf[gl_vbuf_top].flags = PVR_CMD_VERTEX;
gl_vbuf[gl_vbuf_top].x = x;
gl_vbuf[gl_vbuf_top].y = y;
gl_vbuf[gl_vbuf_top].z = z;
gl_vbuf[gl_vbuf_top].w = 1.0f;
if (AUTOUV_ENABLED) {
vert_u = autouv[gl_vbuf_top][0];
vert_v = autouv[gl_vbuf_top][1];
}
gl_vbuf[gl_vbuf_top].u = vert_u;
gl_vbuf[gl_vbuf_top].v = vert_v;
gl_vbuf[gl_vbuf_top].argb = vert_rgba;
gl_vbuf[gl_vbuf_top].oargb = 0xff000000;
gl_vbuf_top++;
assert_msg(gl_vbuf_top < VBUF_SIZE, "Vertex buffer overflow");
if (MODIFIER_ENABLED)
modifier_check_end();
else if (ZCLIP_ENABLED || LIGHTING_ENABLED)
vfzclip_check_end();
else
check_end();
}
void glVertex3fv(GLfloat *v) {
glVertex3f(*v, *(v+1), *(v+2));
}
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) {
}
void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
vert_rgba = (alpha << 24) | (red << 16) | (green << 8) | blue;
}
void glColor3f(GLfloat red, GLfloat green, GLfloat blue) {
vert_rgba = (0xff << 24) |
((uint32)(red * 0xff) << 16) |
((uint32)(green * 0xff) << 8) |
((uint32)(blue * 0xff));
}
void glColor3fv(GLfloat *v) {
glColor3f(*v, *(v+1), *(v+2));
}
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
vert_rgba = ((uint32)(alpha * 0xff) << 24) |
((uint32)(red * 0xff) << 16) |
((uint32)(green * 0xff) << 8) |
((uint32)(blue * 0xff));
}
void glColor4fv(GLfloat *v) {
glColor4f(*v, *(v+1), *(v+2), *(v+3));
}
void glTexCoord2f(GLfloat s, GLfloat t) {
vert_u = s;
vert_v = t;
}
void glTexCoord2fv(GLfloat *v) {
vert_u = *v;
vert_v = *(v+1);
}
static pvr_poly_hdr_t user_clip = {
PVR_CMD_USERCLIP, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
static void send_user_clip() {
pvr_prim(&user_clip, sizeof(pvr_poly_hdr_t));
}
/* Setup the hardware user clip rectangle. It will be sent during glBegin.
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) {
GLint minx, miny, maxx, maxy;
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
assert((width >= 0) && (height >= 0));
gl_scissor_x = x;
gl_scissor_y = y;
gl_scissor_width = CLAMP(width, 0, gl_screen_width);
gl_scissor_height = CLAMP(height, 0, gl_screen_height);
minx = gl_scissor_x;
/* force the origin to the lower left-hand corner of the screen */
miny = /**/(gl_screen_height - gl_scissor_height) - /**/ gl_scissor_y;
maxx = (gl_scissor_width + minx);
maxy = (gl_scissor_height + miny);
/* load command structure while mapping screen coords to TA tiles */
user_clip.d1 = CLAMP(minx/32, 0, gl_screen_width/32);
user_clip.d2 = CLAMP(miny/32, 0, gl_screen_height/32);
user_clip.d3 = CLAMP((maxx/32)-1, 0, gl_screen_width/32);
user_clip.d4 = CLAMP((maxy/32)-1, 0, gl_screen_height/32);
gl_scissor_dirty = GL_TRUE;
gl_pbuf_submitted = GL_FALSE;
}

180
glfog.c Normal file
View File

@ -0,0 +1,180 @@
/* KallistiGL for KOS ##version##
glfog.c
(c)2002 Paul Boese
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include <assert.h>
#include <dc/pvr.h>
CVSID("$Id: glfog.c,v 1.2 2002/04/03 03:36:15 axlen Exp $");
#define TEST_EQ_4V(a,b) ((a)[0] == (b)[0] && \
(a)[1] == (b)[1] && \
(a)[2] == (b)[2] && \
(a)[3] == (b)[3])
/* Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */
#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F))
/* prototypes */
void Fogfv( GLenum pname, const GLfloat *params );
void DCFogfv( GLenum pname, const GLfloat *params );
/* functions */
void glFogf(GLenum pname, GLfloat param)
{
glFogfv(pname, &param);
}
void glFogi(GLenum pname, GLint param )
{
GLfloat fparam = (GLfloat) param;
glFogfv(pname, &fparam);
}
void glFogiv(GLenum pname, const GLint *params )
{
GLfloat p[4];
switch (pname) {
case GL_FOG_MODE:
case GL_FOG_DENSITY:
case GL_FOG_START:
case GL_FOG_END:
case GL_FOG_INDEX:
p[0] = (GLfloat) *params;
break;
case GL_FOG_COLOR:
p[0] = INT_TO_FLOAT( params[0] );
p[1] = INT_TO_FLOAT( params[1] );
p[2] = INT_TO_FLOAT( params[2] );
p[3] = INT_TO_FLOAT( params[3] );
break;
default:
/* Error will be caught later in Fogfv */
;
}
glFogfv(pname, p);
}
void glFogfv( GLenum pname, const GLfloat *params )
{
GLenum m;
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch (pname) {
case GL_FOG_MODE:
m = (GLenum) (GLint) *params;
switch (m) {
case GL_LINEAR:
case GL_EXP:
case GL_EXP2:
break;
default:
assert_msg(0, "Unknown fog mode.");
return;
}
if (gl_fog_mode == m)
return;
/* flush vertices here */
gl_fog_mode = m;
break;
case GL_FOG_DENSITY:
if (*params<0.0) {
assert_msg(0, "Invalid value - fog density < zero.");
return;
}
if (gl_fog_density == *params)
return;
/* flush vertices here */
gl_fog_density = *params;
break;
case GL_FOG_START:
if (gl_fog_start == *params)
return;
/* flush vertices here */
gl_fog_start = *params;
break;
case GL_FOG_END:
if (gl_fog_end == *params)
return;
/* flush vertices here */
gl_fog_end = *params;
break;
case GL_FOG_INDEX:
if (gl_fog_index == *params)
return;
/* flush vertices here */
gl_fog_index = *params;
break;
case GL_FOG_COLOR:
if (TEST_EQ_4V(gl_fog_color, params))
return;
/* flush vertices here */
gl_fog_color[0] = params[0];
gl_fog_color[1] = params[1];
gl_fog_color[2] = params[2];
gl_fog_color[3] = params[3];
break;
default:
assert_msg(0, "Invalid parameter.");
return;
}
DCFogfv( pname, params );
}
/* DC specific interface for fog */
void fog_table_color4fv(GLfloat *v) {
pvr_fog_table_color(*(v+3), *v, *(v+1), *(v+2));
}
/* void fog_set_vertex_color4fv(GLfloat *v) {
pvr_fog_vertex_color(*(v+3), *v, *(v+1), *(v+2));
} */
void DCFogfv( GLenum pname, const GLfloat *params ) {
/* Just drop thru here and setup DC registers using dcutils fog.
**
** Future Note:
** We should have a GL_KOS_FOG_TYPE enum that will give the user
** a choice of GL_KOS_FOG_TABLE, GL_KOS_FOG_VERTEX, and maybe
** GL_KOS_FOG_TABLE2
*/
switch (pname) {
case GL_FOG_START:
case GL_FOG_END:
pvr_fog_far_depth(gl_fog_end);
case GL_FOG_INDEX:
case GL_FOG_DENSITY:
case GL_FOG_COLOR:
fog_table_color4fv(gl_fog_color);
/* fog_set_vertex_color4fv(gl_fog_color); */
case GL_FOG_MODE:
switch (gl_fog_mode) {
case GL_EXP:
pvr_fog_table_exp(gl_fog_density);
break;
case GL_EXP2:
pvr_fog_table_exp2(gl_fog_density);
break;
case GL_LINEAR:
pvr_fog_table_linear(gl_fog_start, gl_fog_end);
break;
}
default:
;
}
}

166
glinternal.h Normal file
View File

@ -0,0 +1,166 @@
/* KallistiGL for KOS ##version##
glinternal.c
(c)2001 Dan Potter
$Id: glinternal.h,v 1.13 2002/09/05 07:36:23 bardtx Exp $
*/
#ifndef __GL_GLINTERNAL_H
#define __GL_GLINTERNAL_H
/* Implementation details; not to be used externally */
#include <GL/gl.h>
#include <dc/pvr.h>
#include <dc/matrix.h>
/* AFAIK, the PowerVR simulates a 32bit depth buffer */
#define DEPTHBUFFER_MAX ((GLfloat)0xffffffff)
/* "Clear color" -- really the background plane color */
extern GLfloat gl_clear_color[4];
/* Capability mask (for glEnable() and glDisable()) */
extern GLbitfield gl_capabilities;
/* Enabled lists (PVR specific) */
extern GLbitfield gl_enabled_lists;
/* Current primitive type (GL_TRIANGLES, etc) */
extern GLenum gl_prim_type;
/* Current polygon context */
extern pvr_poly_cxt_t gl_poly_cxt;
/* Poly header buffer submitted? */
extern GLboolean gl_pbuf_submitted;
/* Current Blend functions */
extern GLint gl_blend_src;
extern GLint gl_blend_dst;
/* Currently selected texture header */
extern pvr_poly_cxt_t *gl_cur_texture;
/* a "null" texture header for colored polys */
extern pvr_poly_cxt_t gl_null_texture;
/* Depth range */
extern GLclampf gl_depthrange_near;
extern GLclampf gl_depthrange_far;
/* Screen size */
extern GLsizei gl_screen_width;
extern GLsizei gl_screen_height;
/* Viewport size */
extern GLint gl_viewport_x1, gl_viewport_y1,
gl_viewport_width, gl_viewport_height;
/* Viewport mapping */
extern GLfloat gl_viewport_scale[3];
extern GLfloat gl_viewport_offset[3];
/* Scissor clipping */
extern GLint gl_scissor_x;
extern GLint gl_scissor_y;
extern GLsizei gl_scissor_width;
extern GLsizei gl_scissor_height;
extern GLboolean gl_scissor_dirty;
/* Transformation matrices; possibilities are:
GL_MODELVIEW
GL_PROJECTION
GL_TEXTURE
*/
extern matrix_t gl_trans_mats[GL_MATRIX_COUNT] __attribute__((aligned(32)));
extern int gl_matrix_mode;
extern GLboolean gl_matrix_dirty;
/* Frustum attributes */
typedef struct {
float left, right, bottom, top, znear, zfar;
} gl_frustum_t;
extern gl_frustum_t gl_frustum;
/* Some happy macros */
#define TXR_ENABLED (gl_capabilities & GL_TEXTURE_2D)
#define AUTOUV_ENABLED (gl_capabilities & GL_KOS_AUTO_UV)
#define FOG_ENABLED (gl_capabilities & GL_FOG)
#define BLEND_ENABLED (gl_capabilities & GL_BLEND)
#define SCISSOR_ENABLED (gl_capabilities & GL_SCISSOR_TEST)
#define USERCLIP_OUTSIDE_ENABLED (gl_capabilities & GL_KOS_USERCLIP_OUTSIDE)
#define MODIFIER_ENABLED (gl_capabilities & GL_KOS_MODIFIER)
#define CHEAP_SHADOW_ENABLED (gl_capabilities & GL_KOS_CHEAP_SHADOW)
#define ZCLIP_ENABLED (gl_capabilities & GL_KOS_NEARZ_CLIPPING)
#define LIGHTING_ENABLED (gl_capabilities & GL_LIGHT0)
/* Currently active list */
extern GLbitfield gl_active_list;
/* Face culling enabled/disabled */
extern GLboolean gl_cull_face;
/* Front face */
extern GLenum gl_front_face;
/* Culling mode */
extern GLenum gl_cull_mode;
/* Fog Attributes */
extern GLfloat gl_fog_color[4];
extern GLfloat gl_fog_density;
extern GLfloat gl_fog_start;
extern GLfloat gl_fog_end;
extern GLfloat gl_fog_index; /* unused */
extern GLenum gl_fog_mode;
/* Point size */
extern GLfloat gl_point_size;
/* Vertex buffers
It is important to align the vertex buffers for use with the
the direct render API. I found 8192 gave the best results, but 32,
64, and 1024 also worked well. To see cache thrashing in action try
setting the alignment to 16384 or 32768. The polys per second will
drop by about half.
mat_transform seems to work best when the source and destination buffers
are seperate. Therefore we have a pre and post transform vertex buffer
I'm quite aware of how wasteful this is. It's a simple matter that this
is how you have to treat the PVR to get decent poly drawing rates.
What's needed is a way to collect long vertex [Strips, Fans, Polygons]
and blast them to the store queue every 16 to 32 verts all the while
maintaining the proper PVR_CMD_VERTEX and ...EOL requirements. One
way might be to keep a copy of the last vertex submitted and toss
it to the PVR in the glEnd statement. You will have to keep track of
verts whose z values go < 0 and either clip them to the view frustum or
cull them entirely. But you'll have to do this carefully because the PVR
does not like degenerate triangles or strips. */
typedef struct {
uint32 flags;
float x, y, z, w;
float u, v;
uint32 argb, oargb;
} gl_vertex_t;
#define VBUF_SIZE 128
/* Pre-xformed vertex buffer */
extern gl_vertex_t gl_vbuf[VBUF_SIZE] __attribute__((aligned(8192)));
/* Post-xformed vertex buffer */
extern gl_vertex_t gl_xbuf[VBUF_SIZE] __attribute__((aligned(8192)));
extern int gl_vbuf_top;
/* some internal prototypes */
extern void modifier_check_end();
extern void modifier_end();
extern void fix_vfzclip_matrices();
extern void vfzclip_check_end();
extern void vfzclip_end();
#endif /* __GL_GLINTERNAL_H */

212
glkos.c Normal file
View File

@ -0,0 +1,212 @@
/* KallistiGL for KOS ##version##
glkos.c
(c)2001 Dan Potter
*/
#include <stdio.h>
#include <string.h>
#include <dc/video.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
CVSID("$Id: glkos.c,v 1.14 2002/09/05 07:36:23 bardtx Exp $");
/* KOS-specific APIs */
int glKosInit() {
GLfloat w, h;
static pvr_stats_t pvr_stats;
if (pvr_get_stats(&pvr_stats)) {
dbglog(DBG_ERROR, "gl: glKosInit - No PVR lists enabled!");
return -1;
}
/* Pre-initialize all the globals */
gl_clear_color[0] =
gl_clear_color[1] =
gl_clear_color[2] =
gl_clear_color[3] = 0.0f;
gl_capabilities = 0;
gl_prim_type = 0;
gl_pbuf_submitted = GL_FALSE;
gl_enabled_lists = pvr_stats.enabled_list_mask | GL_LIST_END;
gl_active_list = GL_LIST_NONE;
/* Reset all matrices */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
/* Setup the basic polygon context */
pvr_poly_cxt_col(&gl_poly_cxt, PVR_LIST_OP_POLY);
/* Adjust context for GL conformance */
gl_poly_cxt.gen.culling = PVR_CULLING_NONE;
/* Make a NULL Texture */
pvr_poly_cxt_col(&gl_null_texture, PVR_LIST_OP_POLY);
gl_cur_texture = &gl_null_texture;
glKosGetScreenSize(&w, &h);
/* The screen w & h is used internally by some functions */
gl_screen_width = (GLsizei)w; gl_screen_height = (GLsizei)h;
/* Initialize the viewport */
glDepthRange(0.0f, 1.0f);
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
/* Initialize the scissor test rectangle */
glScissor(0, 0, (GLsizei)w, (GLsizei)h);
/* Initialize fog */
glFogi(GL_FOG_MODE, GL_EXP);
return 0;
}
void glKosShutdown() {
}
void glKosGetScreenSize(GLfloat *w, GLfloat *h) {
*w = vid_mode->width;
*h = vid_mode->height;
}
static void _gl_list_begin(uint32 list) {
pvr_list_begin(list);
gl_poly_cxt.list_type = list;
}
void glKosBeginFrame() {
uint32 tmp_list;
pvr_wait_ready();
pvr_scene_begin();
gl_pbuf_submitted = GL_FALSE;
gl_active_list = GL_LIST_FIRST;
/* we can't assume GL_LIST_OPAQUE_POLY is the first enabled list
anymore! Advance to the first enabled list if opaque list is
not first already. */
tmp_list = gl_active_list;
if (!(gl_active_list&gl_enabled_lists)) {
do {
tmp_list = gl_active_list = (gl_active_list << 1);
tmp_list &= gl_enabled_lists;
} while(tmp_list==0);
}
switch(gl_active_list) {
case GL_LIST_OPAQUE_POLY:
_gl_list_begin(PVR_LIST_OP_POLY);
break;
case GL_LIST_OPAQUE_MOD:
_gl_list_begin(PVR_LIST_OP_MOD);
break;
case GL_LIST_TRANS_POLY:
_gl_list_begin(PVR_LIST_TR_POLY);
break;
case GL_LIST_TRANS_MOD:
_gl_list_begin(PVR_LIST_TR_MOD);
break;
case GL_LIST_PUNCHTHRU:
_gl_list_begin(PVR_LIST_PT_POLY);
break;
case GL_LIST_END:
/* no lists were enabled!?! */
dbglog(DBG_ERROR, "gl: no lists enabled in glKosBeginFrame!");
/* this is probably a bailout condition! */
break;
}
}
void glKosFinishFrame() {
while (gl_active_list != GL_LIST_NONE)
glKosFinishList();
pvr_scene_finish();
}
void glKosFinishList() {
uint32 tmp_list;
if (gl_active_list == GL_LIST_NONE)
return;
pvr_list_finish();
/* Advance to the next list */
tmp_list = gl_active_list;
do {
tmp_list = gl_active_list = (gl_active_list << 1);
tmp_list &= gl_enabled_lists;
} while(tmp_list==0);
switch(gl_active_list) {
case GL_LIST_OPAQUE_MOD:
_gl_list_begin(PVR_LIST_OP_MOD);
break;
case GL_LIST_TRANS_POLY:
_gl_list_begin(PVR_LIST_TR_POLY);
break;
case GL_LIST_TRANS_MOD:
_gl_list_begin(PVR_LIST_TR_MOD);
break;
case GL_LIST_PUNCHTHRU:
_gl_list_begin(PVR_LIST_PT_POLY);
break;
case GL_LIST_END:
gl_active_list = GL_LIST_NONE;
}
/* We haven't submitted the new poly headers */
gl_pbuf_submitted = GL_FALSE;
}
/* This can be used for KGL Direct Rendering: applies one of the GL
matrices to the matrix registers and lets you do whatever you
want after that. */
static matrix_t msv __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 glKosMatrixApply(GLenum mode) {
gl_matrix_dirty = GL_TRUE;
if (mode < GL_KOS_SCREENVIEW) {
mat_apply(gl_trans_mats + mode);
} else {
msv[0][0] = gl_viewport_scale[0];
msv[1][1] = -gl_viewport_scale[1];
msv[3][0] = gl_viewport_offset[0];
msv[3][1] = gl_screen_height - gl_viewport_offset[1];
mat_apply(&msv);
}
}
/* A matrix clear function, for completeness */
void glKosMatrixIdent() {
gl_matrix_dirty = GL_TRUE;
mat_identity();
}
/* Tell KGL that the poly header is dirty again (i.e., you did something
manually that it doesn't know about) */
void glKosPolyHdrDirty() {
gl_pbuf_submitted = GL_FALSE;
}
/* Tell KGL that the matrix registers are dirty (i.e., you did something
manually that it doesn't know about). Note that this does not include
the above functions because those already take this step. */
void glKosMatrixDirty() {
gl_matrix_dirty = GL_TRUE;
}

29
gllight.c Normal file
View File

@ -0,0 +1,29 @@
/* KallistiGL for KOS ##version##
gllight.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include "assert.h"
CVSID("$Id: gllight.c,v 1.5 2002/04/03 03:36:53 axlen Exp $");
/* Lighting */
void glShadeModel(GLenum mode) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(mode)
{
case GL_FLAT:
gl_poly_cxt.gen.shading = PVR_SHADE_FLAT;
break;
case GL_SMOOTH:
gl_poly_cxt.gen.shading = PVR_SHADE_GOURAUD;
break;
}
}

20
glmacros.h Normal file
View File

@ -0,0 +1,20 @@
/* GL for KOS ##version##
glmacros.c
(c)2001 Paul Boese
$Id: glmacros.h,v 1.5 2002/06/28 04:57:31 axlen Exp $
*/
#ifndef __GL_GLMACROS_H
#define __GL_GLMACROS_H
#define ABS(n) ( (n)<(0.0f) ? (-n):(n) )
#define NEG(n) ( (n)>(0.0f) ? (-n):(n) )
#define CLAMP01(x) ( (x)<(0.0f) ? ((0.0f)) : ((x)>(1.0f) ? ((1.0f)) : (x)) )
/* Clamp X to [MIN,MAX]: */
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
#endif /* __GL_GLMACROS_H */

232
glmisc.c Normal file
View File

@ -0,0 +1,232 @@
/* KallistiGL for KOS ##version##
glmisc.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
CVSID("$Id: glmisc.c,v 1.17 2002/07/08 05:28:28 axlen Exp $");
/* Miscellaneous APIs */
/* Set the background clear color */
void glClearColor(GLclampf red,
GLclampf green,
GLclampf blue,
GLclampf alpha) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
gl_clear_color[0] = CLAMP01(red);
gl_clear_color[1] = CLAMP01(green);
gl_clear_color[2] = CLAMP01(blue);
gl_clear_color[3] = CLAMP01(alpha);
pvr_set_bg_color(gl_clear_color[0]*gl_clear_color[3],
gl_clear_color[1]*gl_clear_color[3],
gl_clear_color[2]*gl_clear_color[3]);
}
/* NOP: there's nothing to clear on the PVR2 */
void glClear(GLbitfield mask) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
}
/* Set front face */
void glFrontFace(GLenum mode) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(mode) {
case GL_CW:
case GL_CCW:
gl_front_face = mode;
gl_pbuf_submitted = GL_FALSE;
break;
}
}
/* Set face culling mode */
void glCullFace(GLenum mode) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(mode) {
case GL_FRONT:
case GL_BACK:
gl_cull_mode = mode;
gl_pbuf_submitted = GL_FALSE;
break;
}
}
/* Enable / disable capabilities */
void glEnable(GLenum cap) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(cap) {
case GL_TEXTURE_2D:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.txr.enable = PVR_TEXTURE_ENABLE;
break;
case GL_BLEND:
if (gl_active_list != GL_LIST_TRANS_POLY) {
dbglog(DBG_ERROR, "gl: invalid list to enable GL_BLEND inside");
return;
}
break;
case GL_CULL_FACE:
gl_pbuf_submitted = GL_FALSE;
gl_cull_face = GL_TRUE;
break;
case GL_FOG:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.fog_type = PVR_FOG_TABLE;
break;
case GL_SCISSOR_TEST:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.clip_mode = PVR_USERCLIP_INSIDE;
if (USERCLIP_OUTSIDE_ENABLED)
gl_capabilities &= ~((GLbitfield)GL_KOS_USERCLIP_OUTSIDE);
break;
case GL_KOS_USERCLIP_OUTSIDE:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.clip_mode = PVR_USERCLIP_OUTSIDE;
if (SCISSOR_ENABLED)
gl_capabilities &= ~((GLbitfield)GL_SCISSOR_TEST);
break;
case GL_KOS_MODIFIER:
assert_msg(0, "GL_KOS_MODIFER not implemented");
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.fmt.modifier = PVR_MODIFIER_ENABLE;
break;
case GL_KOS_CHEAP_SHADOW:
assert_msg(0, "GL_KOS_CHEAP_SHADOW not implemented");
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.modifier_mode = PVR_MODIFIER_CHEAP_SHADOW;
break;
case GL_KOS_NEARZ_CLIPPING:
gl_matrix_dirty = GL_TRUE;
break;
case GL_LIGHT0:
assert_msg(0, "GL_LIGHTi not implemented");
break;
}
gl_capabilities |= (GLbitfield)cap;
}
void glDisable(GLenum cap) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(cap) {
case GL_TEXTURE_2D:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.txr.enable = PVR_TEXTURE_DISABLE;
break;
case GL_BLEND:
if (gl_active_list == GL_LIST_TRANS_POLY) {
dbglog(DBG_ERROR, "gl: invalid list to disable GL_BLEND inside");
return;
}
break;
case GL_CULL_FACE:
gl_pbuf_submitted = GL_FALSE;
gl_cull_face = GL_FALSE;
break;
case GL_FOG:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.fog_type = PVR_FOG_DISABLE;
break;
case GL_SCISSOR_TEST:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.clip_mode = PVR_USERCLIP_DISABLE;
if (USERCLIP_OUTSIDE_ENABLED)
gl_capabilities &= ~((GLbitfield)GL_KOS_USERCLIP_OUTSIDE);
break;
case GL_KOS_USERCLIP_OUTSIDE:
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.clip_mode = PVR_USERCLIP_DISABLE;
if (SCISSOR_ENABLED)
gl_capabilities &= ~((GLbitfield)GL_SCISSOR_TEST);
break;
case GL_KOS_MODIFIER:
assert_msg(0, "GL_KOS_MODIFER not implemented");
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.fmt.modifier = PVR_MODIFIER_DISABLE;
break;
case GL_KOS_CHEAP_SHADOW:
assert_msg(0, "GL_KOS_CHEAP_SHADOW not implemented");
gl_pbuf_submitted = GL_FALSE;
gl_poly_cxt.gen.modifier_mode = PVR_MODIFIER_NORMAL;
break;
case GL_KOS_NEARZ_CLIPPING:
gl_matrix_dirty = GL_TRUE;
break;
case GL_LIGHT0:
assert_msg(0, "GL_LIGHTi not implemented");
break;
}
gl_capabilities &= ~((GLbitfield)cap);
}
/* We have no rendering pipeline yet, so this is a NOP */
void glFlush() {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
}
/* There aren't any useful hints to set yet, so this is a NOP */
void glHint(GLenum target, GLenum mode) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
}
void glPointSize(GLfloat size) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
gl_point_size = CLAMP(size, 0.0f, 100.0f);
}
/* These strings should go somewhere else */
const GLubyte *glGetString(GLenum name) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(name) {
case GL_VENDOR:
return "Cryptic Allusions";
case GL_RENDERER:
return "KallistiOS";
case GL_VERSION:
return "1.1";
case GL_EXTENSIONS:
return "GL_ARB_transpose_matrix ";
}
return "";
}
/* A limited view into the guts of KGL - This will change! */
void glGetFloatv(GLenum pname, GLfloat *params) {
int i, j;
matrix_t *pmat = (matrix_t*)params;
switch(pname) {
case GL_MODELVIEW_MATRIX:
for (i=0; i<4; i++)
for (j=0; j<4; j++)
(*pmat)[i][j] = gl_trans_mats[GL_MODELVIEW][i][j];
break;
case GL_PROJECTION_MATRIX:
for (i=0; i<4; i++)
for (j=0; j<4; j++)
(*pmat)[i][j] = gl_trans_mats[GL_PROJECTION][i][j];
break;
case GL_TEXTURE_MATRIX:
for (i=0; i<4; i++)
for (j=0; j<4; j++)
(*pmat)[i][j] = gl_trans_mats[GL_TEXTURE][i][j];
break;
default:
assert_msg(0, "not glGet param not implemented");
}
}

214
glmodifier.c Normal file
View File

@ -0,0 +1,214 @@
/* KallistiGL for KOS ##version##
glmodifier.c
(c)2002 Paul Boese
NOTE: This module is experimental, incomplete, and non-working
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include <assert.h>
#include <string.h>
#include <malloc.h>
#include <dc/matrix.h>
#include <dc/pvr.h>
CVSID("$Id");
volatile pvr_modifier_vol_t *volume;
static pvr_modifier_vol_t vol_vbuf, vol_xbuf;
pvr_dr_state_t dr_state;
static GLint mod_type = -1;
/* local buffer for textured, packed-color, affected by modifier vertex */
pvr_vertex_tpcm_t vert_xbuf = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
/* Negative 1/w values annoy the pvr, so check for them */
static inline int check_w(pvr_vertex_t *vert, int n) {
int i;
for(i=0; i<n; i++)
if (vert[i].z < 0) return 0;
return 1;
}
/* Make sure the proper matrices are in the matrix registers */
static void fix_matrices() {
if (gl_matrix_dirty) {
mat_identity();
glKosMatrixApply(GL_KOS_SCREENVIEW);
glKosMatrixApply(GL_PROJECTION);
glKosMatrixApply(GL_MODELVIEW);
gl_matrix_dirty = GL_FALSE;
}
}
static pvr_poly_hdr_t mod_hdr = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
void send_mod_hdr(void) {
mod_hdr.cmd = PVR_CMD_MODIFIER;
mod_hdr.mode1 = (mod_type << PVR_TA_PM1_MODIFIERINST_SHIFT) & PVR_TA_PM1_MODIFIERINST_MASK;
switch(gl_active_list) {
case GL_LIST_OPAQUE_MOD:
mod_hdr.cmd |= (PVR_LIST_OP_MOD << PVR_TA_CMD_TYPE_SHIFT) & PVR_TA_CMD_TYPE_MASK;
break;
case GL_LIST_TRANS_MOD:
mod_hdr.cmd |= (PVR_LIST_TR_MOD << PVR_TA_CMD_TYPE_SHIFT) & PVR_TA_CMD_TYPE_MASK;
break;
default:
assert_msg(0, "wrong list specified");
break;
}
pvr_prim(&mod_hdr, sizeof(pvr_poly_hdr_t));
}
void glKosModBegin(GLenum mode) {
assert_msg(0,"not implemented");
mod_type = mode;
//pvr_dr_init(dr_state);
send_mod_hdr();
fix_matrices();
}
void glKosModEnd(void) {
assert_msg(0,"not implemented");
mod_type = -1;
}
void glKosModVolume9f(GLfloat ax, GLfloat ay, GLfloat az,
GLfloat bx, GLfloat by, GLfloat bz,
GLfloat cx, GLfloat cy, GLfloat cz) {
assert_msg(0,"not implemented");
vol_vbuf.flags = PVR_CMD_VERTEX_EOL;
vol_vbuf.ax = ax;
vol_vbuf.ay = ay;
vol_vbuf.az = az;
vol_vbuf.bx = bx;
vol_vbuf.by = by;
vol_vbuf.bz = bz;
vol_vbuf.cx = cx;
vol_vbuf.cy = cy;
vol_vbuf.cz = cz;
mat_transform((vector_t*)&vol_vbuf.ax, (vector_t*)&vol_xbuf.ax, 3, sizeof(vector_t));
/* Can't use the alternating store queues cuz we're sending
* 64 bytes at once with this vertex type
*/
vol_xbuf.flags = vol_vbuf.flags;
vol_xbuf.d1 = vol_xbuf.d2 = vol_xbuf.d3 = 0;
vol_xbuf.d4 = vol_xbuf.d5 = vol_xbuf.d6 = 0;
pvr_prim(&vol_xbuf, sizeof(pvr_modifier_vol_t));
//printf("[%2.2f, %2.2f]\n", cz, vol_xbuf.cz);
}
static void end_quads() {
int i, j, order[4] = {3, 0, 2, 1};
/* Should be four points in the buffer */
assert_msg(gl_vbuf_top == 4, "Wrong number of vertices.");
gl_vbuf[order[3]].flags = PVR_CMD_VERTEX_EOL;
/* mat_transform((vector_t*)&gl_vbuf[0].x, (vector_t*)&gl_xbuf[0].x, 4,
sizeof(pvr_vertex_t)); */
for (i=0; i<4; i++) {
float x = gl_vbuf[i].x, y = gl_vbuf[i].y, z = gl_vbuf[i].z, w = 1.0f;
mat_trans_single4(x, y, z, w);
gl_xbuf[i].x = x;
gl_xbuf[i].y = y;
if (w == 1.0f)
gl_xbuf[i].z = ((gl_viewport_scale[2] * z) + gl_viewport_offset[2]);
else
gl_xbuf[i].z = w;
}
/* Throw it all to the TA using direct render */
if (check_w(gl_xbuf, 4))
for (i=0; i<4; i++) {
j = order[i];
vert_xbuf.flags = gl_vbuf[j].flags;
vert_xbuf.x = gl_xbuf[j].x;
vert_xbuf.y = gl_xbuf[j].y;
vert_xbuf.z = gl_xbuf[j].z;
vert_xbuf.u0 = gl_vbuf[j].u;
vert_xbuf.v0 = gl_vbuf[j].v;
vert_xbuf.argb0 = gl_vbuf[j].argb;
vert_xbuf.oargb0 = gl_vbuf[j].oargb;
vert_xbuf.u1 = 0.0f;
vert_xbuf.v1 = 0.0f;
vert_xbuf.argb1 = 0xff00ff00;
vert_xbuf.oargb1 = 0xffff0000;
pvr_prim(&vert_xbuf, sizeof(pvr_vertex_tpcm_t));
}
}
void modifier_check_end() {
/* What type of primitive was it? */
switch(gl_prim_type) {
case GL_POINTS:
//end_points();
gl_vbuf_top = 0;
break;
case GL_TRIANGLES:
if (gl_vbuf_top == 3) {
//end_triangles();
gl_vbuf_top = 0;
}
break;
case GL_TRIANGLE_STRIP:
break;
case GL_QUADS:
if (gl_vbuf_top == 4) {
end_quads();
gl_vbuf_top = 0;
}
break;
case GL_QUAD_STRIP:
break;
case GL_POLYGON:
break;
default:
assert_msg(0, "gl_prim_type: Unknown primitive type.");
}
}
void modifier_end(void) {
/* What type of primitive was it? */
switch(gl_prim_type) {
case GL_POINTS:
break;
case GL_TRIANGLES:
break;
case GL_TRIANGLE_STRIP:
//end_triangle_strip();
break;
case GL_QUADS:
break;
case GL_QUAD_STRIP:
//end_quad_strip();
break;
case GL_POLYGON:
//end_polygon();
break;
default:
assert_msg(0, "gl_prim_type: Unknown primitive type.");
}
gl_prim_type = 0;
}

184
glnzclip.c Normal file
View File

@ -0,0 +1,184 @@
/* KallistiGL for KOS ##version##
glnzclip.c
(c)2002 Paul Boese
Near Z Clipped primatives
*/
/* This is experimental and subject to change - Currently only supports
GL_TRIANGLES.
Note: this file was originally named glvfzclip.c. Not entirely
correct. My Oops!
*/
#include <kos.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include "glclip.h" /* Trilinear's inline near z clipper code */
#include <assert.h>
#include <dc/matrix.h>
#include <dc/pvr.h>
CVSID("$Id:");
/* Some local tranform stuff. It is generally faster to clip and
light verts in view-space. The transform has been broken into
two pieces to make that possibe. */
static matrix_t mvp __attribute__((aligned(32)));
/* Make sure the proper matrices are in the matrix registers */
void fix_vfzclip_matrices() {
if (gl_matrix_dirty) {
mat_load(gl_trans_mats + GL_PROJECTION);
mat_apply(gl_trans_mats + GL_MODELVIEW);
mat_store(&mvp);
gl_matrix_dirty = GL_FALSE;
}
}
static uint32 frms = 0;
/* translate verts from model-space to view-space */
static void xltmodel(gl_vertex_t *invert, gl_vertex_t *outvert, int num) {
int i;
gl_vertex_t *ip, *op;
for (i=0; i<num; i++) {
ip = &invert[i];
op = &outvert[i];
/* Transform the vertex position by the MVP matrices - assume invert.w is always 1.0 */
op->x = (mvp[0][0] * ip->x) + (mvp[1][0] * ip->y) + (mvp[2][0] * ip->z) + (mvp[3][0] * ip->w);
op->y = (mvp[0][1] * ip->x) + (mvp[1][1] * ip->y) + (mvp[2][1] * ip->z) + (mvp[3][1] * ip->w);
op->z = (mvp[0][2] * ip->x) + (mvp[1][2] * ip->y) + (mvp[2][2] * ip->z) + (mvp[3][2] * ip->w);
op->w = (mvp[0][3] * ip->x) + (mvp[1][3] * ip->y) + (mvp[2][3] * ip->z) + (mvp[3][3] * ip->w);
/* copy other attributes */
op->flags = ip->flags;
op->u = ip->u;
op->v = ip->v;
op->argb = ip->argb;
op->oargb = ip ->oargb;
if ((frms++)%20000 == 0)
printf("z=%03.3f, w=%03.3f\n", op->z, op->w);
}
}
/* translate verts from view-space to the screen */
static void xltview(gl_vertex_t *invert, gl_vertex_t *outvert, int num) {
int i;
gl_vertex_t *ip, *op;
for (i=0; i<num; i++) {
ip = &invert[i];
op = &outvert[i];
/* perspective divide */
op->x = (ip->x /= ip->w);
op->y = (ip->y /= ip->w);
op->z = (ip->z /= ip->w);
/* Perform viewport mapping (note: this implicitly flips the y-axis) */
op->x = (gl_viewport_scale[0] * op->x) + gl_viewport_offset[0];
op->y = gl_screen_height - ((gl_viewport_scale[1] * op->y) + gl_viewport_offset[1]);
op->z = (ip->w == 1.0) ? (gl_viewport_scale[2] * op->z) + gl_viewport_offset[2] : 1.0f / ip->w;
}
}
static void end_triangles() {
int i, rslt;
volatile pvr_vertex_t *vert;
pvr_dr_state_t dr_state;
pvr_dr_init(dr_state);
/* Should be three points in the buffer */
assert_msg(gl_vbuf_top == 3, "Wrong number of vertices.");
xltmodel(gl_vbuf, gl_xbuf, 3);
rslt = ZClipTex(gl_xbuf);
xltview(gl_xbuf, gl_xbuf, rslt);
/* Throw it all to the TA using direct render */
if (rslt!=0) {
gl_xbuf[rslt-1].flags = PVR_CMD_VERTEX_EOL;
for (i=0; i<rslt; i++) {
vert = pvr_dr_target(dr_state);
vert->flags = gl_xbuf[i].flags;
vert->x = gl_xbuf[i].x;
vert->y = gl_xbuf[i].y;
vert->z = gl_xbuf[i].z;
vert->u = gl_xbuf[i].u;
vert->v = gl_xbuf[i].v;
vert->argb = gl_xbuf[i].argb;
vert->oargb = gl_xbuf[i].oargb;
pvr_dr_commit(vert);
}
}
}
void vfzclip_check_end() {
/* What type of primitive was it? */
switch(gl_prim_type) {
case GL_POINTS:
//end_points();
assert_msg(0, "GL_POINTS not supported");
gl_vbuf_top = 0;
break;
case GL_TRIANGLES:
if (gl_vbuf_top == 3) {
end_triangles();
gl_vbuf_top = 0;
}
break;
case GL_TRIANGLE_STRIP:
assert_msg(0, "GL_TRIANGE_STRIP not supported");
break;
case GL_QUADS:
assert_msg(0, "GL_QUADS not supported");
if (gl_vbuf_top == 4) {
//end_quads();
gl_vbuf_top = 0;
}
break;
case GL_QUAD_STRIP:
assert_msg(0, "GL_QUAD_STRIP not supported");
break;
case GL_POLYGON:
assert_msg(0, "GL_POLYGON not supported");
break;
default:
assert_msg(0, "gl_prim_type: Unknown primitive type.");
}
}
void vfzclip_end(void) {
/* What type of primitive was it? */
switch(gl_prim_type) {
case GL_POINTS:
break;
case GL_TRIANGLES:
break;
case GL_TRIANGLE_STRIP:
//end_triangle_strip();
break;
case GL_QUADS:
break;
case GL_QUAD_STRIP:
//end_quad_strip();
break;
case GL_POLYGON:
//end_polygon();
break;
default:
assert_msg(0, "gl_prim_type: Unknown primitive type.");
}
gl_prim_type = 0;
}

190
gltex.c Normal file
View File

@ -0,0 +1,190 @@
/* KallistiGL for KOS ##version##
gltex.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include "glmacros.h"
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
CVSID("$Id: gltex.c,v 1.11 2002/09/05 07:36:23 bardtx Exp $");
/* Texture handling */
/* Allocate "texture structures" (really poly context structs) */
void glGenTextures(GLsizei n, GLuint *textures) {
int i;
pvr_poly_cxt_t *p;
for (i=0; i<n; i++) {
p = (pvr_poly_cxt_t*)malloc(sizeof(pvr_poly_cxt_t));
/* initial state for this texture object */
p->txr.env = PVR_TXRENV_MODULATE;
p->txr.enable = PVR_TEXTURE_ENABLE;
p->txr.filter = PVR_FILTER_NONE;
p->txr.alpha = PVR_TXRALPHA_DISABLE;
p->txr.mipmap = PVR_MIPMAP_DISABLE;
p->txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
p->txr.uv_flip = PVR_UVFLIP_NONE;
p->txr.uv_clamp = PVR_UVCLAMP_NONE;
p->txr.format = PVR_TXRFMT_NONE;
p->txr.base = NULL;
p->txr.width = -1;
p->txr.height = -1;
textures[i] = (GLuint)p;
}
}
/* Delete textures from VRAM */
void glDeleteTextures(GLsizei n, const GLuint *textures) {
int i;
for (i=0; i<n; i++) {
pvr_mem_free(((pvr_poly_cxt_t *)textures[i])->txr.base);
free((void*)textures[i]);
}
}
/* Bind a texture */
void glBindTexture(GLenum type, GLuint texture) {
assert(type == GL_TEXTURE_2D);
gl_cur_texture = (pvr_poly_cxt_t *)texture;
gl_pbuf_submitted = GL_FALSE;
}
/* Load a texture from a 2D image */
void glTexImage2D(GLenum target, GLint level,
GLint internal_fmt,
GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type,
const GLvoid *pixels) {
pvr_ptr_t txr;
assert_msg(border == 0 && level == 0, "Borders and levels not supported.");
assert_msg((internal_fmt & ~1) == (format & ~1), "Pixel conversion not supported.");
/* Allocate space for it */
txr = pvr_mem_malloc(width * height * 2);
/* Load the texture data */
if ((internal_fmt & 1) != (format & 1))
pvr_txr_load_ex((GLvoid *)pixels, txr, width, height, PVR_TXRLOAD_16BPP);
else
pvr_txr_load((GLvoid *)pixels, txr, width * height * 2);
/* Store texture state in context */
gl_cur_texture->txr.width = width;
gl_cur_texture->txr.height = height;
gl_cur_texture->txr.format = internal_fmt;
gl_cur_texture->txr.base = txr;
gl_pbuf_submitted = GL_FALSE;
}
/* KOS shortcut function (if you loaded your own texture) */
void glKosTex2D(GLint internal_fmt, GLsizei width, GLsizei height,
pvr_ptr_t txr_address) {
/* Store texture state in context */
gl_cur_texture->txr.width = width;
gl_cur_texture->txr.height = height;
gl_cur_texture->txr.format = internal_fmt;
gl_cur_texture->txr.base = txr_address;
gl_pbuf_submitted = GL_FALSE;
}
/* Texture environment */
void glTexEnvi(GLenum target, GLenum pname, GLint param) {
assert(target == GL_TEXTURE_2D);
assert(pname == GL_TEXTURE_ENV_MODE);
switch(param) {
case GL_REPLACE:
gl_cur_texture->txr.env = PVR_TXRENV_REPLACE;
break;
case GL_MODULATE:
gl_cur_texture->txr.env = PVR_TXRENV_MODULATE;
break;
case GL_DECAL:
gl_cur_texture->txr.env = PVR_TXRENV_DECAL;
break;
case GL_MODULATEALPHA:
gl_cur_texture->txr.env = PVR_TXRENV_MODULATEALPHA;
break;
}
gl_pbuf_submitted = GL_FALSE;
}
/* Texture parameter */
void glTexParameteri(GLenum target, GLenum pname, GLint param) {
assert(target == GL_TEXTURE_2D);
switch(pname) {
case GL_TEXTURE_FILTER:
switch(param) {
case GL_FILTER_NONE:
gl_cur_texture->txr.filter = PVR_FILTER_NONE;
break;
case GL_FILTER_BILINEAR:
gl_cur_texture->txr.filter = PVR_FILTER_BILINEAR;
break;
default:
assert_msg(0, "Unknown texture filter.");
break;
}
break;
case GL_TEXTURE_WRAP_S: /* adjust state of UVCLAMP_U */
switch(param) {
case GL_REPEAT:
if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_UV)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_V;
else if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_U)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_NONE;
break;
case GL_CLAMP:
if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_NONE)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_U;
else if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_V)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_UV;
break;
default:
assert_msg(0, "Unknown texture wrap mode.");
break;
}
break;
case GL_TEXTURE_WRAP_T: /* adjust state of UVCLAMP_V */
switch(param) {
case GL_REPEAT:
if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_UV)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_U;
else if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_V)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_NONE;
break;
case GL_CLAMP:
if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_NONE)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_V;
else if (gl_cur_texture->txr.uv_clamp == PVR_UVCLAMP_U)
gl_cur_texture->txr.uv_clamp = PVR_UVCLAMP_UV;
break;
default:
assert_msg(0, "Unknown texture wrap mode.");
break;
}
break;
default:
assert_msg(0, "Unknown parameter name (pname).");
break;
}
gl_pbuf_submitted = GL_FALSE;
}

520
gltrans.c Normal file
View File

@ -0,0 +1,520 @@
/* KallistiGL for KOS ##version##
gltrans.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
#include <assert.h>
#include <string.h>
#include <dc/fmath.h>
#include <dc/matrix.h>
CVSID("$Id: gltrans.c,v 1.13 2002/09/05 07:36:23 bardtx Exp $");
/* Transformation APIs */
/* Modus operandi, as it were
The transformation API will store N matrices, representing the various
GL matrix modes (projection, modelview, texture) and gl_matrix_mode will
point to the currently selected on. All matrix operations will load the matrix
from its array position, perform the math on that matrix, and store it back
into the array.
When gldraw() uses the matrices, it will pull the matrices it needs and
multiply them out in registers before applying them to vectors.
*/
#define DEG2RAD (F_PI / 180.0f)
#define RAD2DEG (180.0f / F_PI)
/* Matrix stacks (move to global?) */
#define MAT_MV_STACK_CNT 32
#define MAT_P_STACK_CNT 2
#define MAT_T_STACK_CNT 2
static matrix_t gl_mat_mv_stack[MAT_MV_STACK_CNT] __attribute__((aligned(32)));
static int gl_mat_mv_stack_top = 0;
static matrix_t gl_mat_p_stack[MAT_P_STACK_CNT] __attribute__((aligned(32)));
static int gl_mat_p_stack_top = 0;
static matrix_t gl_mat_t_stack[MAT_T_STACK_CNT] __attribute__((aligned(32)));
static int gl_mat_t_stack_top = 0;
/* Frustum stack */
static gl_frustum_t gl_frustum_stack[MAT_P_STACK_CNT];
static int gl_frustum_stack_top = 0;
/* Set which matrix we are working on */
void glMatrixMode(GLenum mode) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
gl_matrix_mode = mode;
gl_matrix_dirty = GL_TRUE;
}
/* Load the identitiy matrix */
void glLoadIdentity(void) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
mat_identity();
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
static matrix_t ml __attribute__((aligned(32)));
/* Load an arbitrary matrix */
void glLoadMatrixf(const GLfloat *m) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
memcpy(ml, m, sizeof(matrix_t));
mat_load(&ml);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
/* Load an arbitrary transposed matrix */
void glLoadTransposeMatrixf(const GLfloat *m) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
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(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
/* Multiply the current matrix by an arbitrary matrix */
void glMultMatrixf(const GLfloat *m) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
memcpy(ml, m, sizeof(matrix_t));
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&ml);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
/* Multiply the current matrix by an arbitrary transposed matrix */
void glMultTransposeMatrixf(const GLfloat *m) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
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(gl_trans_mats + gl_matrix_mode);
mat_apply(&ml);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
/* Set the depth range */
void glDepthRange(GLclampf n, GLclampf f) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
/* clamp the values... */
if (n < 0.0f) n = 0.0f;
if (n > 1.0f) n = 1.0f;
if (f < 0.0f) f = 0.0f;
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) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
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;
/* Flip the Y-axis */
//gl_viewport_scale[1] *= -1.0f;
/* FIXME: Why does the depth value need some nudging?
* This makes polys with Z=0 work.
*/
gl_viewport_offset[2] += 0.0001f;
}
/* Located here for now */
void gluPerspective(GLfloat angle, GLfloat aspect,
GLfloat znear, GLfloat zfar) {
GLfloat xmin, xmax, ymin, ymax;
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
ymax = znear * ftan(angle * F_PI / 360.0f);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, znear, zfar);
}
static matrix_t mf __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 }
};
void glFrustum(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat znear, GLfloat zfar) {
GLfloat x, y, a, b, c, d;
gl_frustum.left = left;
gl_frustum.right = right;
gl_frustum.bottom = bottom;
gl_frustum.top = top;
gl_frustum.znear = znear;
gl_frustum.zfar = zfar;
assert(znear > 0.0f);
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
x = (2.0f * znear) / (right - left);
y = (2.0f * znear) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(zfar + znear) / (zfar - znear);
d = -(2.0f * zfar * znear) / (zfar - znear);
mf[0][0] = x;
mf[2][0] = a;
mf[1][1] = y;
mf[2][1] = b;
mf[2][2] = c;
mf[3][2] = d;
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&mf);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
static matrix_t mo __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 }
};
void glOrtho(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat znear, GLfloat zfar) {
GLfloat x, y, z;
GLfloat tx, ty, tz;
gl_frustum.znear = 0.001;
gl_frustum.zfar = 100;
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
x = 2.0f / (right - left);
y = 2.0f / (top - bottom);
z = -2.0f / (zfar - znear);
tx = -(right + left) / (right - left);
ty = -(top + bottom) / (top - bottom);
tz = -(zfar + znear) / (zfar - znear);
mo[0][0] = x;
mo[1][1] = y;
mo[2][2] = z;
mo[3][0] = tx;
mo[3][1] = ty;
mo[3][2] = tz;
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&mo);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
void glPushMatrix(void) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch (gl_matrix_mode)
{
case GL_MODELVIEW:
assert_msg(gl_mat_mv_stack_top < MAT_MV_STACK_CNT, "Modelview stack overflow.");
memcpy(gl_mat_mv_stack + gl_mat_mv_stack_top,
gl_trans_mats + gl_matrix_mode,
sizeof(matrix_t));
gl_mat_mv_stack_top++;
break;
case GL_PROJECTION:
assert_msg(gl_mat_p_stack_top < MAT_P_STACK_CNT, "Projection stack overflow.");
memcpy(gl_mat_p_stack + gl_mat_p_stack_top,
gl_trans_mats + gl_matrix_mode,
sizeof(matrix_t));
gl_mat_p_stack_top++;
memcpy(gl_frustum_stack + gl_frustum_stack_top,
&gl_frustum,
sizeof(gl_frustum_t));
gl_frustum_stack_top++;
break;
case GL_TEXTURE:
assert_msg(gl_mat_t_stack_top < MAT_T_STACK_CNT, "Texture stack overflow.");
memcpy(gl_mat_t_stack + gl_mat_t_stack_top,
gl_trans_mats + gl_matrix_mode,
sizeof(matrix_t));
gl_mat_t_stack_top++;
break;
}
}
void glPopMatrix(void) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
switch(gl_matrix_mode)
{
case GL_MODELVIEW:
assert_msg(gl_mat_mv_stack_top > 0, "Modelview stack underflow.");
gl_mat_mv_stack_top--;
memcpy(gl_trans_mats + gl_matrix_mode,
gl_mat_mv_stack + gl_mat_mv_stack_top,
sizeof(matrix_t));
break;
case GL_PROJECTION:
assert_msg(gl_mat_p_stack_top > 0, "Projection stack underflow.");
gl_mat_p_stack_top--;
memcpy(gl_trans_mats + gl_matrix_mode,
gl_mat_p_stack + gl_mat_p_stack_top,
sizeof(matrix_t));
gl_frustum_stack_top--;
memcpy(&gl_frustum,
gl_frustum_stack + gl_frustum_stack_top,
sizeof(gl_frustum_t));
break;
case GL_TEXTURE:
assert_msg(gl_mat_t_stack_top > 0, "Texture stack underflow.");
gl_mat_t_stack_top--;
memcpy(gl_trans_mats + gl_matrix_mode,
gl_mat_t_stack + gl_mat_t_stack_top,
sizeof(matrix_t));
break;
}
gl_matrix_dirty = GL_TRUE;
}
static matrix_t mr __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 }
};
void glRotatef(GLfloat angle,
GLfloat x, GLfloat y, GLfloat z) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
GLfloat rcos = fcos(angle * DEG2RAD);
GLfloat rsin = fsin(angle * DEG2RAD);
GLfloat invrcos = (1.0f - rcos);
GLfloat mag = fsqrt(x*x + y*y + z*z);
GLfloat xx, yy, zz, xy, yz, zx;
if (mag < 1.0e-6) {
/* Rotation vector is too small to be significant */
return;
}
/* Normalize the rotation vector */
x /= mag;
y /= mag;
z /= mag;
xx = x * x;
yy = y * y;
zz = z * z;
xy = (x * y * invrcos);
yz = (y * z * invrcos);
zx = (z * x * invrcos);
/* Generate the rotation matrix */
mr[0][0] = xx + rcos * (1.0f - xx);
mr[2][1] = yz - x * rsin;
mr[1][2] = yz + x * rsin;
mr[1][1] = yy + rcos * (1.0f - yy);
mr[2][0] = zx + y * rsin;
mr[0][2] = zx - y * rsin;
mr[2][2] = zz + rcos * (1.0f - zz);
mr[1][0] = xy - z * rsin;
mr[0][1] = xy + z * rsin;
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&mr);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
static matrix_t ms __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 }
};
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
ms[0][0] = x;
ms[1][1] = y;
ms[2][2] = z;
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&ms);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
static matrix_t mt __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 glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
mt[3][0] = x;
mt[3][1] = y;
mt[3][2] = z;
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&mt);
mat_store(gl_trans_mats + gl_matrix_mode);
gl_matrix_dirty = GL_TRUE;
}
/* XXX - these should be in glu */
void normalize(float v[3])
{
float r;
r = fsqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
if (r == 0.0) return;
v[0] /= r;
v[1] /= r;
v[2] /= r;
}
void cross(float v1[3], float v2[3], float result[3])
{
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];
}
static matrix_t ml __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 }
};
/* XXX - should move to glu */
void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
GLfloat upz)
{
float forward[3], side[3], up[3];
assert_msg(!gl_prim_type, "Not allowed within glBegin/glEnd pair.");
forward[0] = centerx - eyex;
forward[1] = centery - eyey;
forward[2] = centerz - eyez;
up[0] = upx;
up[1] = upy;
up[2] = upz;
normalize(forward);
/* Side = forward x up */
cross(forward, up, side);
normalize(side);
/* Recompute up as: up = side x forward */
cross(side, forward, up);
ml[0][0] = side[0];
ml[1][0] = side[1];
ml[2][0] = side[2];
ml[0][1] = up[0];
ml[1][1] = up[1];
ml[2][1] = up[2];
ml[0][2] = -forward[0];
ml[1][2] = -forward[1];
ml[2][2] = -forward[2];
mat_load(gl_trans_mats + gl_matrix_mode);
mat_apply(&ml);
mat_store(gl_trans_mats + gl_matrix_mode);
glTranslatef(-eyex, -eyey, -eyez);
}

103
glvars.c Normal file
View File

@ -0,0 +1,103 @@
/* KallistiGL for KOS ##version##
glvars.c
(c)2001 Dan Potter
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "glinternal.h"
CVSID("$Id: glvars.c,v 1.11 2002/06/28 04:52:42 axlen Exp $");
/* Variable definitions */
/* Background clear color (not currently used) */
GLfloat gl_clear_color[4];
/* Capabilities bitfield: toggles for glEnable() / glDisable() */
GLbitfield gl_capabilities;
/* Current primitive type (or -1) */
GLenum gl_prim_type;
/* Current polygon context */
pvr_poly_cxt_t gl_poly_cxt;
/* Poly header buffer submitted? */
GLboolean gl_pbuf_submitted;
/* Current Blend functions */
GLint gl_blend_src = PVR_BLEND_SRCALPHA;
GLint gl_blend_dst = PVR_BLEND_INVSRCALPHA;
/* Currently selected texture */
pvr_poly_cxt_t *gl_cur_texture;
/* Null texture for colored polys */
pvr_poly_cxt_t gl_null_texture;
/* Screen size */
GLsizei gl_screen_width;
GLsizei gl_screen_height;
/* Viewport size */
GLint gl_viewport_x1, gl_viewport_y1,
gl_viewport_width, gl_viewport_height;
/* Viewport mapping */
GLfloat gl_viewport_scale[3];
GLfloat gl_viewport_offset[3];
/* Scissor clipping */
GLint gl_scissor_x;
GLint gl_scissor_y;
GLsizei gl_scissor_width;
GLsizei gl_scissor_height;
GLboolean gl_scissor_dirty = GL_FALSE;
/* Depth range */
GLclampf gl_depthrange_near;
GLclampf gl_depthrange_far;
/* Transformation matrices */
matrix_t gl_trans_mats[GL_MATRIX_COUNT] __attribute__((aligned(32)));
int gl_matrix_mode;
GLboolean gl_matrix_dirty;
/* Frustum attributes */
gl_frustum_t gl_frustum;
/* Enabled lists */
GLbitfield gl_enabled_lists;
/* Currently active list */
GLbitfield gl_active_list;
/* Face culling enabled/disabled */
GLboolean gl_cull_face = GL_FALSE;
/* Front face */
GLenum gl_front_face = GL_CCW;
/* Culling mode */
GLenum gl_cull_mode = GL_BACK;
/* Fog Attributes */
GLfloat gl_fog_color[4] = {0.5f, 0.5f, 0.5f, 1.0f}; /* r, g, b, a */
GLfloat gl_fog_density = 1.0f; /* Density >= 0.0 - exp exp2 fog */
GLfloat gl_fog_start = 0.0f; /* linear fog */
GLfloat gl_fog_end = 1.0f; /* linear fog */
GLfloat gl_fog_index = 0.0f; /* unused */
GLenum gl_fog_mode = GL_EXP;
/* Point size */
GLfloat gl_point_size = 1.0f;
/* Vertex buffers */
/* Pre-xformed vertex buffer */
gl_vertex_t gl_vbuf[VBUF_SIZE] __attribute__((aligned(8192)));
/* Post-xformed vertex buffer */
gl_vertex_t gl_xbuf[VBUF_SIZE] __attribute__((aligned(8192)));
int gl_vbuf_top;

0
kos/dreamcast.cnf Normal file
View File