diff --git a/GL/draw.c b/GL/draw.c index 3d2d082..47ce853 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -946,35 +946,6 @@ static void light(SubmissionTarget* target) { _glPerformLighting(vertex, ES, target->count); } -GL_FORCE_INLINE void divide(SubmissionTarget* target) { - TRACE(); - - /* Perform perspective divide on each vertex */ - Vertex* vertex = _glSubmissionTargetStart(target); - - const float h = GetVideoMode()->height; - - ITERATE(target->count) { - const float f = MATH_Fast_Invert(vertex->w); - - /* Convert to NDC and apply viewport */ - vertex->xyz[0] = MATH_fmac( - VIEWPORT.hwidth, vertex->xyz[0] * f, VIEWPORT.x_plus_hwidth - ); - vertex->xyz[1] = h - MATH_fmac( - VIEWPORT.hheight, vertex->xyz[1] * f, VIEWPORT.y_plus_hheight - ); - - /* Apply depth range */ - vertex->xyz[2] = MAX( - 1.0f - MATH_fmac(vertex->xyz[2] * f, 0.5f, 0.5f), - PVR_MIN_Z - ); - - ++vertex; - } -} - GL_FORCE_INLINE int _calc_pvr_face_culling() { if(!_glIsCullingEnabled()) { return GPU_CULLING_SMALL; diff --git a/GL/matrix.c b/GL/matrix.c index d70a104..104f8a1 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -15,13 +15,12 @@ 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 Matrix4x4 __attribute__((aligned(32))) PROJECTION_MATRIX; static GLenum MATRIX_MODE = GL_MODELVIEW; static GLubyte MATRIX_IDX = 0; +static GLboolean NORMAL_DIRTY, PROJECTION_DIRTY; static const Matrix4x4 __attribute__((aligned(32))) IDENTITY = { 1.0f, 0.0f, 0.0f, 0.0f, @@ -94,12 +93,28 @@ 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 UpdateProjectionMatrix() { + PROJECTION_DIRTY = false; + UploadMatrix4x4(&VIEWPORT_MATRIX); + MultiplyMatrix4x4(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); + DownloadMatrix4x4(&PROJECTION_MATRIX); +} + +/* When modelview matrix changes, need to re-compute normal matrix */ +static void UpdateNormalMatrix() { + NORMAL_DIRTY = false; 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) NORMAL_DIRTY = true; + if(MATRIX_MODE == GL_PROJECTION) PROJECTION_DIRTY = true; +} + + void APIENTRY glMatrixMode(GLenum mode) { MATRIX_MODE = mode; MATRIX_IDX = mode & 0xF; @@ -111,17 +126,17 @@ void APIENTRY glPushMatrix() { void* ret = stack_push(MATRIX_STACKS + MATRIX_IDX, top); (void) ret; assert(ret); + OnMatrixChanged(); } void APIENTRY glPopMatrix() { stack_pop(MATRIX_STACKS + MATRIX_IDX); - if(MATRIX_MODE == GL_MODELVIEW) { - recalculateNormalMatrix(); - } + OnMatrixChanged(); } 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) { @@ -207,10 +216,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 */ @@ -219,10 +225,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 */ @@ -248,6 +251,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(); } @@ -279,6 +283,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(); } @@ -290,10 +295,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 */ @@ -324,10 +326,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 */ @@ -357,22 +356,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[M0] = width * 0.5f; + VIEWPORT_MATRIX[M5] = height * -0.5f; + VIEWPORT_MATRIX[M10] = 1.0f; + VIEWPORT_MATRIX[M15] = 1.0f; + + VIEWPORT_MATRIX[M12] = x + width * 0.5f; + VIEWPORT_MATRIX[M13] = GetVideoMode()->height - (y + height * 0.5f); + PROJECTION_DIRTY = true; } /* Set the depth range */ @@ -464,14 +460,17 @@ void _glMatrixLoadModelView() { } void _glMatrixLoadProjection() { - UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); + if (PROJECTION_DIRTY) UpdateProjectionMatrix(); + UploadMatrix4x4(&PROJECTION_MATRIX); } void _glMatrixLoadModelViewProjection() { - UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); + if (PROJECTION_DIRTY) UpdateProjectionMatrix(); + UploadMatrix4x4(&PROJECTION_MATRIX); MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); } void _glMatrixLoadNormal() { + if (NORMAL_DIRTY) UpdateNormalMatrix(); UploadMatrix4x4((const Matrix4x4*) &NORMAL_MATRIX); } diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index d7c19de..52e31c8 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -79,9 +79,10 @@ GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h, i for(int v = 0; v < count; ++v) { const float f = _glFastInvert(vertex[v].w); - /* Convert to NDC and apply viewport */ - vertex[v].xyz[0] = (vertex[v].xyz[0] * f * 320) + 320; - vertex[v].xyz[1] = (vertex[v].xyz[1] * f * -240) + 240; + /* Convert to screenspace */ + /* (note that vertices have already been viewport transformed) */ + vertex->xyz[0] *= f; + 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 */