diff --git a/GL/matrix.c b/GL/matrix.c index 2744cb9..5c1fac3 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -15,10 +15,7 @@ GLfloat DEPTH_RANGE_MULTIPLIER_H = (0 + 1) / 2; static Stack __attribute__((aligned(32))) MATRIX_STACKS[4]; // modelview, projection, texture static Matrix4x4 __attribute__((aligned(32))) NORMAL_MATRIX; - -Viewport VIEWPORT = { - 0, 0, 640, 480, 320.0f, 240.0f, 320.0f, 240.0f -}; +static Matrix4x4 __attribute__((aligned(32))) VIEWPORT_MATRIX; static GLenum MATRIX_MODE = GL_MODELVIEW; static GLubyte MATRIX_IDX = 0; @@ -94,12 +91,29 @@ static void transpose(GLfloat* m) { swap(m[11], m[14]); } -static void recalculateNormalMatrix() { +/* When projection matrix changes, need to pre-multiply with viewport transform matrix */ +static void OnProjectionChanged() { + UploadMatrix4x4(&VIEWPORT_MATRIX); + MultiplyMatrix4x4(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); + DownloadMatrix4x4(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); +} + +/* When modelview matrix changes, need to re-compute normal matrix */ +static void OnModelviewChanged() { MEMCPY4(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(Matrix4x4)); inverse((GLfloat*) NORMAL_MATRIX); transpose((GLfloat*) NORMAL_MATRIX); } +static void OnMatrixChanged() { + if(MATRIX_MODE == GL_MODELVIEW) { + OnModelviewChanged(); + } else if(MATRIX_MODE == GL_PROJECTION) { + OnProjectionChanged(); + } +} + + void APIENTRY glMatrixMode(GLenum mode) { MATRIX_MODE = mode; MATRIX_IDX = mode & 0xF; @@ -116,12 +130,13 @@ void APIENTRY glPushMatrix() { void APIENTRY glPopMatrix() { stack_pop(MATRIX_STACKS + MATRIX_IDX); if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); + OnModelviewChanged(); } } void APIENTRY glLoadIdentity() { stack_replace(MATRIX_STACKS + MATRIX_IDX, IDENTITY); + OnMatrixChanged(); } void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) { @@ -141,10 +156,7 @@ void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) { assert(top); DownloadMatrix4x4(top); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } @@ -159,10 +171,7 @@ void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) { UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); MultiplyMatrix4x4(&scale); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { @@ -202,10 +211,7 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); MultiplyMatrix4x4((const Matrix4x4*) &rotate); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } /* Load an arbitrary matrix */ @@ -214,10 +220,7 @@ void APIENTRY glLoadMatrixf(const GLfloat *m) { memcpy(TEMP, m, sizeof(float) * 16); stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } /* Ortho */ @@ -243,6 +246,7 @@ void APIENTRY glOrtho(GLfloat left, GLfloat right, UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); MultiplyMatrix4x4((const Matrix4x4*) &OrthoMatrix); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); + OnMatrixChanged(); } @@ -274,6 +278,7 @@ void APIENTRY glFrustum(GLfloat left, GLfloat right, UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); MultiplyMatrix4x4((const Matrix4x4*) &FrustumMatrix); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); + OnMatrixChanged(); } @@ -285,10 +290,7 @@ void glMultMatrixf(const GLfloat *m) { UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); MultiplyMatrix4x4(&TEMP); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } /* Load an arbitrary transposed matrix */ @@ -319,10 +321,7 @@ void glLoadTransposeMatrixf(const GLfloat *m) { TEMP[M15] = m[15]; stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } /* Multiply the current matrix by an arbitrary transposed matrix */ @@ -352,22 +351,19 @@ void glMultTransposeMatrixf(const GLfloat *m) { UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); MultiplyMatrix4x4((const Matrix4x4*) &TEMP); DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX)); - - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } /* Set the GL viewport */ void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { - VIEWPORT.x = x; - VIEWPORT.y = y; - VIEWPORT.width = width; - VIEWPORT.height = height; - VIEWPORT.hwidth = ((GLfloat) VIEWPORT.width) * 0.5f; - VIEWPORT.hheight = ((GLfloat) VIEWPORT.height) * 0.5f; - VIEWPORT.x_plus_hwidth = VIEWPORT.x + VIEWPORT.hwidth; - VIEWPORT.y_plus_hheight = VIEWPORT.y + VIEWPORT.hheight; + VIEWPORT_MATRIX[0][0] = width * 0.5f; + VIEWPORT_MATRIX[1][1] = -height * 0.5f; + VIEWPORT_MATRIX[2][2] = 1.0f; + VIEWPORT_MATRIX[3][3] = 1.0f; + + VIEWPORT_MATRIX[3][0] = x + width * 0.5f; + VIEWPORT_MATRIX[3][1] = GetVideoMode()->height - (y + height * 0.5f); + OnProjectionChanged(); } /* Set the depth range */ diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index ba00148..cceab78 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -78,9 +78,10 @@ GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) { const float f = _glFastInvert(vertex->w); - /* Convert to NDC and apply viewport */ - vertex->xyz[0] = (vertex->xyz[0] * f * 320) + 320; - vertex->xyz[1] = (vertex->xyz[1] * f * -240) + 240; + /* Convert to screenspace */ + /* (note that vertices have already been viewport transformed) */ + vertex->xyz[0] = vertex->xyz[0] * f; + vertex->xyz[1] = vertex->xyz[1] * f; /* Orthographic projections need to use invZ otherwise we lose the depth information. As w == 1, and clip-space range is -w to +w diff --git a/GL/platforms/software.c b/GL/platforms/software.c index 4245930..bf9ba47 100644 --- a/GL/platforms/software.c +++ b/GL/platforms/software.c @@ -75,17 +75,13 @@ void SceneListBegin(GPUList list) { vertex_counter = 0; } -GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) { +GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex) { const float f = 1.0f / (vertex->w); - /* Convert to NDC and apply viewport */ - vertex->xyz[0] = __builtin_fmaf( - VIEWPORT.hwidth, vertex->xyz[0] * f, VIEWPORT.x_plus_hwidth - ); - - vertex->xyz[1] = h - __builtin_fmaf( - VIEWPORT.hheight, vertex->xyz[1] * f, VIEWPORT.y_plus_hheight - ); + /* Convert to screenspace */ + /* (note that vertices have already been viewport transformed) */ + vertex->xyz[0] = vertex->xyz[0] * f; + vertex->xyz[1] = vertex->xyz[1] * f; if(vertex->w == 1.0f) { vertex->xyz[2] = 1.0f / (1.0001f + vertex->xyz[2]); @@ -143,8 +139,6 @@ void SceneListSubmit(Vertex* v2, int n) { return; } - const float h = GetVideoMode()->height; - uint8_t visible_mask = 0; uint8_t counter = 0; @@ -182,19 +176,19 @@ void SceneListSubmit(Vertex* v2, int n) { switch(visible_mask) { case 15: /* All visible, but final vertex in strip */ { - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); - _glPerspectiveDivideVertex(v1, h); + _glPerspectiveDivideVertex(v1); _glPushHeaderOrVertex(v1); - _glPerspectiveDivideVertex(v2, h); + _glPerspectiveDivideVertex(v2); _glPushHeaderOrVertex(v2); } break; case 7: /* All visible, push the first vertex and move on */ - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); break; case 9: @@ -210,13 +204,13 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v2, v0, b); b->flags = GPU_CMD_VERTEX_EOL; - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); } break; @@ -233,13 +227,13 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v2, v0, b); b->flags = GPU_CMD_VERTEX; - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); _glPushHeaderOrVertex(b); } @@ -262,13 +256,13 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v1, v2, b); b->flags = v2->flags; - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); - _glPerspectiveDivideVertex(c, h); + _glPerspectiveDivideVertex(c); _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); } break; @@ -285,19 +279,19 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v2, v0, b); b->flags = GPU_CMD_VERTEX; - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); _glClipEdge(v1, v2, a); a->flags = v2->flags; - _glPerspectiveDivideVertex(c, h); + _glPerspectiveDivideVertex(c); _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(c); _glPushHeaderOrVertex(a); } @@ -319,17 +313,17 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v1, v2, b); b->flags = GPU_CMD_VERTEX; - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); if(counter % 2 == 1) { _glPushHeaderOrVertex(a); } - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); - _glPerspectiveDivideVertex(c, h); + _glPerspectiveDivideVertex(c); _glPushHeaderOrVertex(c); } break; @@ -349,15 +343,15 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v1, v2, b); b->flags = GPU_CMD_VERTEX; - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); - _glPerspectiveDivideVertex(c, h); + _glPerspectiveDivideVertex(c); _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); c->flags = GPU_CMD_VERTEX_EOL; @@ -380,15 +374,15 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v1, v2, b); b->flags = GPU_CMD_VERTEX; - _glPerspectiveDivideVertex(v0, h); + _glPerspectiveDivideVertex(v0); _glPushHeaderOrVertex(v0); - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); - _glPerspectiveDivideVertex(c, h); + _glPerspectiveDivideVertex(c); _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); _glPushHeaderOrVertex(c); } @@ -411,17 +405,17 @@ void SceneListSubmit(Vertex* v2, int n) { _glClipEdge(v2, v0, b); b->flags = GPU_CMD_VERTEX; - _glPerspectiveDivideVertex(a, h); + _glPerspectiveDivideVertex(a); _glPushHeaderOrVertex(a); - _glPerspectiveDivideVertex(c, h); + _glPerspectiveDivideVertex(c); _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); + _glPerspectiveDivideVertex(b); _glPushHeaderOrVertex(b); _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(d, h); + _glPerspectiveDivideVertex(d); _glPushHeaderOrVertex(d); } break; diff --git a/GL/private.h b/GL/private.h index 5b11c52..758c636 100644 --- a/GL/private.h +++ b/GL/private.h @@ -104,20 +104,6 @@ typedef struct { AlignedVector vector; } PolyList; -typedef struct { - GLint x; - GLint y; - GLint width; - GLint height; - - float x_plus_hwidth; - float y_plus_hheight; - float hwidth; /* width * 0.5f */ - float hheight; /* height * 0.5f */ -} Viewport; - -extern Viewport VIEWPORT; - typedef struct { /* Palette data is always stored in RAM as RGBA8888 and packed as ARGB8888 * when uploaded to the PVR */