From 40678836e015031f3a16ff096094828b5f046b06 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Sun, 25 Apr 2021 13:05:56 +0100 Subject: [PATCH] Refactor viewport handling --- GL/draw.c | 37 +++++++++++++++++++++++++++++++++---- GL/matrix.c | 48 +++++++++++++++++++++--------------------------- GL/private.h | 17 ++++++++++++++++- 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/GL/draw.c b/GL/draw.c index 6d204d2..04e5734 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -1075,7 +1075,6 @@ static void light(SubmissionTarget* target) { VertexExtra* extra = aligned_vector_at(target->extras, 0); EyeSpaceData* eye_space = (EyeSpaceData*) eye_space_data->data; - _glMatrixLoadModelView(); mat_transform3(vertex->xyz, eye_space->xyz, target->count, sizeof(Vertex), sizeof(EyeSpaceData)); _glMatrixLoadNormal(); @@ -1093,8 +1092,20 @@ GL_FORCE_INLINE void divide(SubmissionTarget* target) { ITERATE(target->count) { float f = MATH_Fast_Invert(vertex->w); + + /* Convert to NDC */ vertex->xyz[0] *= f; vertex->xyz[1] *= f; + + /* Apply viewport */ + vertex->xyz[0] = MATH_fmac( + VIEWPORT.hwidth, vertex->xyz[0], VIEWPORT.x_plus_hwidth + ); + vertex->xyz[1] = GetVideoMode()->height - MATH_fmac( + VIEWPORT.hheight, vertex->xyz[1], 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 @@ -1217,15 +1228,33 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL /* Make room for the vertices and header */ aligned_vector_extend(&target->output->vector, target->count + 1); - _glApplyRenderMatrix(); /* Apply the Render Matrix Stack */ + /* If we're lighting, then we need to do some work in + * eye-space, so we only transform vertices by the modelview + * matrix, and then later multiply by projection. + * + * If we're not doing lighting though we can optimise by taking + * vertices straight to clip-space */ + if(doLighting) { + _glMatrixLoadModelView(); + } else { + _glMatrixLoadModelViewProjection(); + } + + /* If we're FAST_PATH_ENABLED, then this will do the transform for us */ generate(target, mode, first, count, (GLubyte*) indices, type); + /* No fast path, then we have to do another iteration :( */ + if(!FAST_PATH_ENABLED) { + /* Multiply by modelview */ + transform(target); + } + if(doLighting){ light(target); - } - if(!FAST_PATH_ENABLED) { + /* OK eye-space work done, now move into clip space */ + _glMatrixLoadProjection(); transform(target); } diff --git a/GL/matrix.c b/GL/matrix.c index ee71a94..e01298d 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -13,12 +13,12 @@ GLfloat DEPTH_RANGE_MULTIPLIER_L = (1 - 0) / 2; GLfloat DEPTH_RANGE_MULTIPLIER_H = (0 + 1) / 2; -/* Viewport size */ -static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height; - static Stack MATRIX_STACKS[3]; // modelview, projection, texture static Matrix4x4 NORMAL_MATRIX __attribute__((aligned(32))); -static Matrix4x4 SCREENVIEW_MATRIX __attribute__((aligned(32))); + +Viewport VIEWPORT = { + 0, 0, 640, 480, 320.0f, 240.0f, 320.0f, 240.0f +}; static GLenum MATRIX_MODE = GL_MODELVIEW; static GLubyte MATRIX_IDX = 0; @@ -50,7 +50,6 @@ void _glInitMatrices() { stack_push(&MATRIX_STACKS[2], IDENTITY); MEMCPY4(NORMAL_MATRIX, IDENTITY, sizeof(Matrix4x4)); - MEMCPY4(SCREENVIEW_MATRIX, IDENTITY, sizeof(Matrix4x4)); const VideoMode* vid_mode = GetVideoMode(); @@ -370,22 +369,14 @@ void glMultTransposeMatrixf(const GLfloat *m) { /* Set the GL viewport */ void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { - const VideoMode* vid_mode = GetVideoMode(); - - gl_viewport_x1 = x; - gl_viewport_y1 = y; - gl_viewport_width = width; - gl_viewport_height = height; - - GLfloat hw = ((GLfloat) width) / 2.0f; - GLfloat hh = ((GLfloat) height) / 2.0f; - y *= -1; // Flip - - SCREENVIEW_MATRIX[M0] = hw; - SCREENVIEW_MATRIX[M5] = -hh; - SCREENVIEW_MATRIX[M10] = 1; - SCREENVIEW_MATRIX[M12] = hw + x; - SCREENVIEW_MATRIX[M13] = vid_mode->height - hh + y; + 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; } /* Set the depth range */ @@ -468,12 +459,6 @@ void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx, DownloadMatrix4x4(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); } -void _glApplyRenderMatrix() { - UploadMatrix4x4((const Matrix4x4*) &SCREENVIEW_MATRIX); - MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); - MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); -} - void _glMatrixLoadTexture() { UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF))); } @@ -482,6 +467,15 @@ void _glMatrixLoadModelView() { UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); } +void _glMatrixLoadProjection() { + UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); +} + +void _glMatrixLoadModelViewProjection() { + UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); + MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); +} + void _glMatrixLoadNormal() { UploadMatrix4x4((const Matrix4x4*) &NORMAL_MATRIX); } diff --git a/GL/private.h b/GL/private.h index f9cd113..c099360 100644 --- a/GL/private.h +++ b/GL/private.h @@ -98,6 +98,20 @@ 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 */ @@ -278,8 +292,9 @@ void _glInitFramebuffers(); void _glMatrixLoadNormal(); void _glMatrixLoadModelView(); +void _glMatrixLoadProjection(); void _glMatrixLoadTexture(); -void _glApplyRenderMatrix(); +void _glMatrixLoadModelViewProjection(); extern GLfloat DEPTH_RANGE_MULTIPLIER_L; extern GLfloat DEPTH_RANGE_MULTIPLIER_H;