From a47f331ceea3bd1df9a232a54bbdc7e66d61c455 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 2 Oct 2024 07:48:44 +1000 Subject: [PATCH 1/5] Initial work on supporting missing primitive modes --- GL/draw.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 167 insertions(+), 22 deletions(-) diff --git a/GL/draw.c b/GL/draw.c index 0a3a1bd..0e426d4 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -435,21 +435,129 @@ GL_FORCE_INLINE void genTriangleStrip(Vertex* output, GLuint count) { output[count - 1].flags = GPU_CMD_VERTEX_EOL; } -static void genTriangleFan(Vertex* output, GLuint count) { - gl_assert(count <= 255); +static void genQuadStrip(Vertex* output, GLuint count) { + Vertex* dst = output + (((count - 2) * 2) - 1); + Vertex* src = output + count;//(count - 1); + for (; count > 2; count -= 2) { + *dst = src[-1]; + (*dst--).flags = GPU_CMD_VERTEX_EOL; + *dst-- = src[-2]; + *dst-- = src[-3]; + *dst-- = src[-4]; + src -= 2; + } +} + +static void genTriangleFan(Vertex* output, GLuint count) { Vertex* dst = output + (((count - 2) * 3) - 1); Vertex* src = output + (count - 1); - GLubyte i = count - 2; - while(i--) { - *dst = *src--; + for (; count > 2; count--) { + *dst = *src--; (*dst--).flags = GPU_CMD_VERTEX_EOL; *dst-- = *src; *dst-- = *output; } } +#define POINTS_COUNT(count) ((count) * 4) +#define POINT_SIZE 0.5f +static void genPoints(Vertex* output, GLuint count) { + Vertex* dst = output + POINTS_COUNT(count) - 1; + Vertex* src = output + count - 1; + + // Expands v to { v + (-S/2,S/2), v + (S/2,S/2), v + (S/2,-S/2), (-S/2,-S/2) } + for (; count > 0; count--, src--) { + *dst = *src; + dst->flags = GPU_CMD_VERTEX_EOL; + dst->xyz[0] -= POINT_SIZE; dst->xyz[1] -= POINT_SIZE; + dst--; + + *dst = *src; + dst->xyz[0] += POINT_SIZE; dst->xyz[1] -= POINT_SIZE; + dst--; + + *dst = *src; + dst->xyz[0] += POINT_SIZE; dst->xyz[1] += POINT_SIZE; + dst--; + + *dst = *src; + dst->xyz[0] -= POINT_SIZE; dst->xyz[1] += POINT_SIZE; + dst--; + } +} + +static void genLines(Vertex* output, GLuint count) { + Vertex* dst = output + ((count/2) * 3) - 1; + Vertex* src = output + (count ) - 1; + + for (; count > 0; count -= 2) { + *dst = *src; + dst->flags = GPU_CMD_VERTEX_EOL; + dst--; src--; + + *dst = *src; + dst--; + + *dst = *src; + dst->xyz[1] += 5; + dst--; src--; + } +} + +static void genLineStrip(Vertex* output, GLuint count) { + Vertex* dst = output + (((count - 1) * 3) - 1); + Vertex* src = output + (count - 1); + + for (; count > 1; count--) { + *dst = *src; + dst->flags = GPU_CMD_VERTEX_EOL; + dst--; src--; + + *dst = *src; + dst--; + + *dst = *src; + dst->xyz[0] += 5; + dst->xyz[1] += 5; + dst--; + } +} + +static void genLineLoop(Vertex* output, GLuint count) { + Vertex* dst = output + ((count * 3) - 1); + Vertex* src = output + (count - 1); + Vertex last = *src; + + for (; count > 1; count--) { + *dst = *src; + dst->flags = GPU_CMD_VERTEX_EOL; + dst--; src--; + + *dst = *src; + dst--; + + *dst = *src; + dst->xyz[0] += 5; + dst->xyz[1] += 5; + dst--; + } + + // Connect first and last points + *dst = last; + dst->flags = GPU_CMD_VERTEX_EOL; + dst--; + + *dst = *output; + dst--; + + *dst = *output; + dst->xyz[0] += 5; + dst->xyz[1] += 5; + dst--; +} + typedef void (*ReadPositionFunc)(const GLubyte*, GLubyte*); typedef void (*ReadDiffuseFunc)(const GLubyte*, GLubyte*); typedef void (*ReadUVFunc)(const GLubyte*, GLubyte*); @@ -891,11 +999,28 @@ static void generate(SubmissionTarget* target, const GLenum mode, const GLsizei case GL_QUADS: genQuads(it, count); break; + case GL_TRIANGLE_STRIP: + genTriangleStrip(it, count); + break; + + case GL_QUAD_STRIP: + genQuadStrip(it, count); + break; case GL_TRIANGLE_FAN: genTriangleFan(it, count); break; - case GL_TRIANGLE_STRIP: - genTriangleStrip(it, count); + + case GL_POINTS: + genPoints(it, count); + break; + case GL_LINES: + genLines(it, count); + break; + case GL_LINE_STRIP: + genLineStrip(it, count); + break; + case GL_LINE_LOOP: + genLineLoop(it, count); break; default: gl_assert(0 && "Not Implemented"); @@ -1093,6 +1218,38 @@ void _glInitSubmissionTarget() { target->extras = &VERTEX_EXTRAS; } +GL_FORCE_INLINE GLuint calcFinalVertices(GLenum mode, GLuint count) { + switch (mode) { + case GL_POINTS: + return POINTS_COUNT(count); + + case GL_LINE_LOOP: + // Triangles generated as {prior vertex, current vertex, current vertex} + // plus one triangle to connect final and initial vertex + // e.g. {v1, v2, v3, v4} produces {v1, v1, v2}, {v2, v2, v3}, {v3, v3, v4}, {v4, v4, v1} + return count * 3; + + case GL_LINE_STRIP: + // Triangles generated as {prior vertex, prior vertex, current vertex} + // e.g. {v1, v2, v3, v4} produces {v1, v1, v2}, {v2, v2, v3}, {v3, v3, v4} + return (count - 1) * 3; + + case GL_LINES: + // Triangles generated as {first vertex, first vertex, second vertex} + // e.g. {v1, v2, v3, v4} produces {v1, v1, v2}, {v3, v3, v4} + return (count / 2) * 3; + + case GL_TRIANGLE_FAN: + // Triangles generated as {first vertex, prior vertex, current vertex} + // e.g. {v1, v2, v3, v4} produces {v1, v2, v3}, {v1, v3, v4} + return (count - 2) * 3; + + case GL_QUAD_STRIP: + //return ((count - 2) / 2) * 4; + return (count - 2) * 2; + } + return count; +} GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type, const GLvoid* indices) { @@ -1102,14 +1259,10 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL TRACE(); /* Do nothing if vertices aren't enabled */ - if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) { - return; - } + if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) return; /* No vertices? Do nothing */ - if(!count) { - return; - } + if(!count) return; /* Polygons are treated as triangle fans, the only time this would be a * problem is if we supported glPolygonMode(..., GL_LINE) but we don't. @@ -1131,14 +1284,6 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL } } - if(mode == GL_LINE_STRIP || mode == GL_LINES) { - fprintf(stderr, "Line drawing is currently unsupported\n"); - return; - } - - // We don't handle this any further, so just make sure we never pass it down */ - gl_assert(mode != GL_POLYGON); - target->output = _glActivePolyList(); gl_assert(target->output); gl_assert(extras); @@ -1147,7 +1292,7 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL GLboolean header_required = (vector_size == 0) || _glGPUStateIsDirty(); - target->count = (mode == GL_TRIANGLE_FAN) ? ((count - 2) * 3) : count; + target->count = calcFinalVertices(mode, count); target->header_offset = vector_size; target->start_offset = target->header_offset + (header_required ? 1 : 0); From 19a76cbefd1bcc0273e232203859b1b7d6d4751d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 2 Oct 2024 19:00:05 +1000 Subject: [PATCH 2/5] Fix lines --- GL/draw.c | 171 ++++++++++++++++++++++++------------------------ GL/private.h | 3 + GL/state.c | 9 ++- include/GL/gl.h | 5 +- 4 files changed, 100 insertions(+), 88 deletions(-) diff --git a/GL/draw.c b/GL/draw.c index 0e426d4..6071542 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -442,17 +442,20 @@ static void genQuadStrip(Vertex* output, GLuint count) { for (; count > 2; count -= 2) { *dst = src[-1]; (*dst--).flags = GPU_CMD_VERTEX_EOL; - *dst-- = src[-2]; *dst-- = src[-3]; + *dst-- = src[-2]; *dst-- = src[-4]; src -= 2; } } +#define TRIFAN_COUNT(count) (((count) - 2) * 3) static void genTriangleFan(Vertex* output, GLuint count) { - Vertex* dst = output + (((count - 2) * 3) - 1); - Vertex* src = output + (count - 1); + Vertex* dst = output + TRIFAN_COUNT(count) - 1; + Vertex* src = output + count - 1; + // Triangles generated as {first vertex, prior vertex, current vertex} + // e.g. {v1, v2, v3, v4} produces {v1, v2, v3}, {v1, v3, v4} for (; count > 2; count--) { *dst = *src--; (*dst--).flags = GPU_CMD_VERTEX_EOL; @@ -462,100 +465,111 @@ static void genTriangleFan(Vertex* output, GLuint count) { } #define POINTS_COUNT(count) ((count) * 4) -#define POINT_SIZE 0.5f static void genPoints(Vertex* output, GLuint count) { Vertex* dst = output + POINTS_COUNT(count) - 1; Vertex* src = output + count - 1; + float half_size = HALF_POINT_SIZE; - // Expands v to { v + (-S/2,S/2), v + (S/2,S/2), v + (S/2,-S/2), (-S/2,-S/2) } + // Expands v to { v + (-S/2,S/2), v + (S/2,S/2), v + (-S/2,S/2), (S/2,-S/2) } for (; count > 0; count--, src--) { *dst = *src; dst->flags = GPU_CMD_VERTEX_EOL; - dst->xyz[0] -= POINT_SIZE; dst->xyz[1] -= POINT_SIZE; + dst->xyz[0] -= half_size; dst->xyz[1] -= half_size; dst--; *dst = *src; - dst->xyz[0] += POINT_SIZE; dst->xyz[1] -= POINT_SIZE; + dst->xyz[0] += half_size; dst->xyz[1] -= half_size; dst--; *dst = *src; - dst->xyz[0] += POINT_SIZE; dst->xyz[1] += POINT_SIZE; + dst->xyz[0] -= half_size; dst->xyz[1] += half_size; dst--; *dst = *src; - dst->xyz[0] -= POINT_SIZE; dst->xyz[1] += POINT_SIZE; + dst->xyz[0] += half_size; dst->xyz[1] += half_size; dst--; } } -static void genLines(Vertex* output, GLuint count) { - Vertex* dst = output + ((count/2) * 3) - 1; - Vertex* src = output + (count ) - 1; +// Heavily based on the pvrline example by jnmartin84 +// Which is based on https://devcry.heiho.net/html/2017/20170820-opengl-line-drawing.html +static Vertex* draw_line(Vertex* dst, Vertex* v1, Vertex* v2) { + Vertex ov1 = *v1; + Vertex ov2 = *v2; + // TODO don't copy unless dst might overlap v1/v2 - for (; count > 0; count -= 2) { - *dst = *src; - dst->flags = GPU_CMD_VERTEX_EOL; - dst--; src--; + // Essentially "expands" a line into a quad by + // 1) Calculating normal of the line from v1 to v2 + // 2) Scaling normal by the line width + // 3) Offseting the endpoints wrt the scaled normal + float dx = ov2.xyz[0] - ov1.xyz[0]; + float dy = ov2.xyz[1] - ov1.xyz[1]; - *dst = *src; - dst--; + float inverse_mag = frsqrt((dx*dx) + (dy*dy)) * HALF_LINE_WIDTH; + float nx = -dy * inverse_mag; + float ny = dx * inverse_mag; - *dst = *src; - dst->xyz[1] += 5; - dst--; src--; - } -} - -static void genLineStrip(Vertex* output, GLuint count) { - Vertex* dst = output + (((count - 1) * 3) - 1); - Vertex* src = output + (count - 1); - - for (; count > 1; count--) { - *dst = *src; - dst->flags = GPU_CMD_VERTEX_EOL; - dst--; src--; - - *dst = *src; - dst--; - - *dst = *src; - dst->xyz[0] += 5; - dst->xyz[1] += 5; - dst--; - } -} - -static void genLineLoop(Vertex* output, GLuint count) { - Vertex* dst = output + ((count * 3) - 1); - Vertex* src = output + (count - 1); - Vertex last = *src; - - for (; count > 1; count--) { - *dst = *src; - dst->flags = GPU_CMD_VERTEX_EOL; - dst--; src--; - - *dst = *src; - dst--; - - *dst = *src; - dst->xyz[0] += 5; - dst->xyz[1] += 5; - dst--; - } - - // Connect first and last points - *dst = last; + // Expand first endpoint both "up" and "down" + *dst = ov1; dst->flags = GPU_CMD_VERTEX_EOL; + dst->xyz[0] += nx; + dst->xyz[1] += ny; dst--; - *dst = *output; + *dst = ov1; + dst->xyz[0] -= nx; + dst->xyz[1] -= ny; dst--; - *dst = *output; - dst->xyz[0] += 5; - dst->xyz[1] += 5; + // Expand second endpoint both "up" and "down" + *dst = ov2; + dst->xyz[0] += nx; + dst->xyz[1] += ny; dst--; + + *dst = ov2; + dst->xyz[0] -= nx; + dst->xyz[1] -= ny; + dst--; + + return dst; +} + +#define LINES_COUNT(count) (((count) / 2) * 4) +static void genLines(Vertex* output, GLuint count) { + Vertex* dst = output + LINES_COUNT(count) - 1; + Vertex* src = output + count - 1; + + // Draws line using two vertices + for (; count >= 2; count -= 2, src -= 2) { + dst = draw_line(dst, src, src - 1); + } +} + +#define LINE_STRIP_COUNT(count) (((count) - 1) * 4) +static void genLineStrip(Vertex* output, GLuint count) { + Vertex* dst = output + LINE_STRIP_COUNT(count) - 1; + Vertex* src = output + count - 1; + + // Draws line using current and prior vertex + for (; count > 1; count--, src--) { + dst = draw_line(dst, src, src - 1); + } +} + +#define LINE_LOOP_COUNT(count) ((count) * 4) +static void genLineLoop(Vertex* output, GLuint count) { + Vertex* dst = output + LINE_LOOP_COUNT(count) - 1; + Vertex* src = output + count - 1; + Vertex last = *src, first = *output; + + // Draws line using current and prior vertex + for (; count > 1; count--, src--) { + dst = draw_line(dst, src, src - 1); + } + + // Connect first and last vertex + draw_line(dst, &first, &last); } typedef void (*ReadPositionFunc)(const GLubyte*, GLubyte*); @@ -1222,27 +1236,14 @@ GL_FORCE_INLINE GLuint calcFinalVertices(GLenum mode, GLuint count) { switch (mode) { case GL_POINTS: return POINTS_COUNT(count); - case GL_LINE_LOOP: - // Triangles generated as {prior vertex, current vertex, current vertex} - // plus one triangle to connect final and initial vertex - // e.g. {v1, v2, v3, v4} produces {v1, v1, v2}, {v2, v2, v3}, {v3, v3, v4}, {v4, v4, v1} - return count * 3; - + return LINE_LOOP_COUNT(count); case GL_LINE_STRIP: - // Triangles generated as {prior vertex, prior vertex, current vertex} - // e.g. {v1, v2, v3, v4} produces {v1, v1, v2}, {v2, v2, v3}, {v3, v3, v4} - return (count - 1) * 3; - + return LINE_STRIP_COUNT(count); case GL_LINES: - // Triangles generated as {first vertex, first vertex, second vertex} - // e.g. {v1, v2, v3, v4} produces {v1, v1, v2}, {v3, v3, v4} - return (count / 2) * 3; - + return LINES_COUNT(count); case GL_TRIANGLE_FAN: - // Triangles generated as {first vertex, prior vertex, current vertex} - // e.g. {v1, v2, v3, v4} produces {v1, v2, v3}, {v1, v3, v4} - return (count - 2) * 3; + return TRIFAN_COUNT(count); case GL_QUAD_STRIP: //return ((count - 2) / 2) * 4; diff --git a/GL/private.h b/GL/private.h index 31a7872..6424e5d 100644 --- a/GL/private.h +++ b/GL/private.h @@ -320,6 +320,9 @@ void _glMatrixLoadModelViewProjection(); extern GLfloat DEPTH_RANGE_MULTIPLIER_L; extern GLfloat DEPTH_RANGE_MULTIPLIER_H; +extern GLfloat HALF_LINE_WIDTH; +extern GLfloat HALF_POINT_SIZE; + Matrix4x4* _glGetProjectionMatrix(); Matrix4x4* _glGetModelViewMatrix(); diff --git a/GL/state.c b/GL/state.c index ef7780f..fd28b2a 100644 --- a/GL/state.c +++ b/GL/state.c @@ -3,7 +3,8 @@ #include #include "private.h" - +GLfloat HALF_LINE_WIDTH = 1.0f / 2.0f; +GLfloat HALF_POINT_SIZE = 1.0f / 2.0f; static struct { GLboolean is_dirty; @@ -773,7 +774,11 @@ GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref) { } void glLineWidth(GLfloat width) { - _GL_UNUSED(width); + HALF_LINE_WIDTH = width / 2.0f; +} + +void glPointSize(GLfloat size) { + HALF_POINT_SIZE = size / 2.0f; } void glPolygonOffset(GLfloat factor, GLfloat units) { diff --git a/include/GL/gl.h b/include/GL/gl.h index 61d434b..d3914de 100644 --- a/include/GL/gl.h +++ b/include/GL/gl.h @@ -552,6 +552,10 @@ GLAPI GLvoid APIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2); GLAPI GLvoid APIENTRY glRectiv(const GLint *v1, const GLint *v2); #define glRectsv glRectiv +/* Primitive configuration */ +GLAPI void APIENTRY glLineWidth(GLfloat width); +GLAPI void APIENTRY glPointSize(GLfloat size); + /* Enable / Disable Capability */ /* Currently Supported Capabilities: GL_TEXTURE_2D @@ -742,7 +746,6 @@ GLAPI GLenum APIENTRY glGetError(void); /* Non Operational Stubs for portability */ GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref); -GLAPI void APIENTRY glLineWidth(GLfloat width); GLAPI void APIENTRY glPolygonMode(GLenum face, GLenum mode); GLAPI void APIENTRY glPolygonOffset(GLfloat factor, GLfloat units); GLAPI void APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params); From 165eb9d5c852bb0454b80638c0a9129929b43833 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 2 Oct 2024 19:28:02 +1000 Subject: [PATCH 3/5] Add primitive modes sample, quad strips partially work Although the second triangle is wrongly culled --- CMakeLists.txt | 1 + GL/draw.c | 18 ++-- samples/primitive_modes/main.c | 189 +++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 samples/primitive_modes/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 048f894..e51c14d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,6 +209,7 @@ gen_sample(scissor samples/scissor/main.c) gen_sample(polymark samples/polymark/main.c) gen_sample(cubes samples/cubes/main.cpp) gen_sample(zclip_test tests/zclip/main.cpp) +gen_sample(primitive_modes samples/primitive_modes/main.c) if(PLATFORM_DREAMCAST) gen_sample(trimark samples/trimark/main.c) diff --git a/GL/draw.c b/GL/draw.c index 6071542..a08be59 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -435,16 +435,20 @@ GL_FORCE_INLINE void genTriangleStrip(Vertex* output, GLuint count) { output[count - 1].flags = GPU_CMD_VERTEX_EOL; } +#define QUADSTRIP_COUNT(count) (((count) - 2) * 2) static void genQuadStrip(Vertex* output, GLuint count) { - Vertex* dst = output + (((count - 2) * 2) - 1); + Vertex* dst = output + QUADSTRIP_COUNT(count) - 1; Vertex* src = output + count;//(count - 1); for (; count > 2; count -= 2) { - *dst = src[-1]; + // Have to copy because of src/dst overlapping on first quad + Vertex src1 = src[-1], src2 = src[-2], src3 = src[-3], src4 = src[-4]; + + *dst = src3; (*dst--).flags = GPU_CMD_VERTEX_EOL; - *dst-- = src[-3]; - *dst-- = src[-2]; - *dst-- = src[-4]; + *dst-- = src4; + *dst-- = src1; + *dst-- = src2; src -= 2; } } @@ -1244,10 +1248,8 @@ GL_FORCE_INLINE GLuint calcFinalVertices(GLenum mode, GLuint count) { return LINES_COUNT(count); case GL_TRIANGLE_FAN: return TRIFAN_COUNT(count); - case GL_QUAD_STRIP: - //return ((count - 2) / 2) * 4; - return (count - 2) * 2; + return QUADSTRIP_COUNT(count); } return count; } diff --git a/samples/primitive_modes/main.c b/samples/primitive_modes/main.c new file mode 100644 index 0000000..db793cc --- /dev/null +++ b/samples/primitive_modes/main.c @@ -0,0 +1,189 @@ +#include +#include +#include + +#ifdef SDL2_BUILD +#include +static SDL_Window* win_handle; +#else +#include +#endif + +static void DrawLineLoop(float y) { + glBegin(GL_LINE_LOOP); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(410.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(490.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(490.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(410.0f, y + 90.0f); + glEnd(); +} + +static void DrawLineStrip(float y) { + glBegin(GL_LINE_STRIP); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(310.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(390.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(390.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(310.0f, y + 90.0f); + glEnd(); +} + +static void DrawLine(float y) { + glBegin(GL_LINES); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(210.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(290.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(290.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(210.0f, y + 90.0f); + + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(230.0f, y + 25.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(250.0f, y + 75.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(260.0f, y + 75.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(280.0f, y + 45.0f); + glEnd(); +} + +static void DrawPoint(float y) { + glBegin(GL_POINTS); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(110.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(190.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(190.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(110.0f, y + 90.0f); + glEnd(); +} + +static void DrawQuad(float y) { + glBegin(GL_QUADS); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(10.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(90.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(90.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(10.0f, y + 90.0f); + + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(110.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(190.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(190.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(110.0f, y + 90.0f); + glEnd(); +} + +static void DrawQuadStrip(float y) { + glBegin(GL_QUAD_STRIP); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(210.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(290.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(290.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(210.0f, y + 90.0f); + + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(310.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(390.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(390.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(310.0f, y + 90.0f); + glEnd(); +} + +static void DrawTriList(float y) { + glBegin(GL_TRIANGLES); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f( 10.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f( 90.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f( 90.0f, y + 90.0f); + + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(110.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(190.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(190.0f, y + 90.0f); + glEnd(); +} + +static void DrawTriStrip(float y) { + glBegin(GL_TRIANGLE_STRIP); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(210.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(290.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(290.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(210.0f, y + 90.0f); + + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(310.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(390.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(390.0f, y + 90.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(310.0f, y + 90.0f); + glEnd(); +} + + +static void DrawTriFan(float y) { + glBegin(GL_TRIANGLE_FAN); + glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(410.0f, y + 10.0f); + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(490.0f, y + 10.0f); + glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(445.0f, y + 90.0f); + + glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(590.0f, y + 10.0f); + glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(510.0f, y + 45.0f); + glEnd(); +} + +int main(int argc, char *argv[]) { +#ifdef SDL2_BUILD + SDL_Init(SDL_INIT_EVERYTHING); + win_handle = SDL_CreateWindow("Shapes", 0, 0, 640, 480, SDL_WINDOW_OPENGL); + SDL_GL_CreateContext(win_handle); +#else + glKosInit(); +#endif + + glClearColor(0.5f, 0.5f, 0.5f, 1); + glViewport(0, 0, 640, 480); + + float mat[4][4] = { 0 }; + float L = 0, T = 0, R = 640, B = 480, N = -100, F = 100; + mat[0][0] = 2.0f / (R - L); + mat[1][1] = 2.0f / (T - B); + mat[2][2] = -2.0f / (F - N); + mat[3][0] = -(R + L) / (R - L); + mat[3][1] = -(T + B) / (T - B); + mat[3][2] = -(F + N) / (F - N); + mat[3][3] = 1; + glLoadMatrixf(mat); + + int running = 1; + + while (running) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +#ifdef SDL2_BUILD + SDL_Event event; + while (SDL_PollEvent(&event)) { + if(event.type == SDL_QUIT) running = 0; + } +#endif + + DrawTriStrip(300); + DrawTriFan(300); + DrawTriList(300); + + DrawQuadStrip(200); + DrawQuad(200); + + glPointSize(5); + DrawPoint(100); + glLineWidth(0.5f); + DrawLineLoop(100); + glLineWidth(2); + DrawLineStrip(100); + glLineWidth(10); + DrawLine(100); + + glPointSize(1); + glLineWidth(1); + DrawPoint(0); + DrawLineLoop(0); + DrawLineStrip(0); + DrawLine(0); + + glShadeModel(GL_FLAT); + DrawQuad(400); + DrawTriStrip(400); + glShadeModel(GL_SMOOTH); + +#ifdef SDL2_BUILD + SDL_GL_SwapWindow(win_handle); +#else + glKosSwapBuffers(); +#endif + } + return 0; +} From 4513b040e2b1e73a6ca4f8369a48836f1627bd96 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 2 Oct 2024 20:07:36 +1000 Subject: [PATCH 4/5] Don't inline less optimal primitive modes --- GL/draw.c | 12 ++++++------ GL/private.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/GL/draw.c b/GL/draw.c index a08be59..07dd976 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -436,7 +436,7 @@ GL_FORCE_INLINE void genTriangleStrip(Vertex* output, GLuint count) { } #define QUADSTRIP_COUNT(count) (((count) - 2) * 2) -static void genQuadStrip(Vertex* output, GLuint count) { +static GL_NO_INLINE void genQuadStrip(Vertex* output, GLuint count) { Vertex* dst = output + QUADSTRIP_COUNT(count) - 1; Vertex* src = output + count;//(count - 1); @@ -454,7 +454,7 @@ static void genQuadStrip(Vertex* output, GLuint count) { } #define TRIFAN_COUNT(count) (((count) - 2) * 3) -static void genTriangleFan(Vertex* output, GLuint count) { +static GL_NO_INLINE void genTriangleFan(Vertex* output, GLuint count) { Vertex* dst = output + TRIFAN_COUNT(count) - 1; Vertex* src = output + count - 1; @@ -469,7 +469,7 @@ static void genTriangleFan(Vertex* output, GLuint count) { } #define POINTS_COUNT(count) ((count) * 4) -static void genPoints(Vertex* output, GLuint count) { +static GL_NO_INLINE void genPoints(Vertex* output, GLuint count) { Vertex* dst = output + POINTS_COUNT(count) - 1; Vertex* src = output + count - 1; float half_size = HALF_POINT_SIZE; @@ -540,7 +540,7 @@ static Vertex* draw_line(Vertex* dst, Vertex* v1, Vertex* v2) { } #define LINES_COUNT(count) (((count) / 2) * 4) -static void genLines(Vertex* output, GLuint count) { +static GL_NO_INLINE void genLines(Vertex* output, GLuint count) { Vertex* dst = output + LINES_COUNT(count) - 1; Vertex* src = output + count - 1; @@ -551,7 +551,7 @@ static void genLines(Vertex* output, GLuint count) { } #define LINE_STRIP_COUNT(count) (((count) - 1) * 4) -static void genLineStrip(Vertex* output, GLuint count) { +static GL_NO_INLINE void genLineStrip(Vertex* output, GLuint count) { Vertex* dst = output + LINE_STRIP_COUNT(count) - 1; Vertex* src = output + count - 1; @@ -562,7 +562,7 @@ static void genLineStrip(Vertex* output, GLuint count) { } #define LINE_LOOP_COUNT(count) ((count) * 4) -static void genLineLoop(Vertex* output, GLuint count) { +static GL_NO_INLINE void genLineLoop(Vertex* output, GLuint count) { Vertex* dst = output + LINE_LOOP_COUNT(count) - 1; Vertex* src = output + count - 1; Vertex last = *src, first = *output; diff --git a/GL/private.h b/GL/private.h index 6424e5d..266af80 100644 --- a/GL/private.h +++ b/GL/private.h @@ -25,6 +25,7 @@ extern void* memcpy4 (void *dest, const void *src, size_t count); #define GL_NO_INSTRUMENT inline __attribute__((no_instrument_function)) #define GL_INLINE_DEBUG GL_NO_INSTRUMENT __attribute__((always_inline)) #define GL_FORCE_INLINE static GL_INLINE_DEBUG +#define GL_NO_INLINE __attribute__((noinline)) #define _GL_UNUSED(x) (void)(x) #define _PACK4(v) ((v * 0xF) / 0xFF) From 2b06418fedffa9ef81539bc1236ac3b7608429f4 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 2 Oct 2024 20:27:28 +1000 Subject: [PATCH 5/5] Fix not compiling on desktop due to relying on KOS specific frsqrt --- GL/draw.c | 2 +- GL/private.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/GL/draw.c b/GL/draw.c index 07dd976..d54e775 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -509,7 +509,7 @@ static Vertex* draw_line(Vertex* dst, Vertex* v1, Vertex* v2) { float dx = ov2.xyz[0] - ov1.xyz[0]; float dy = ov2.xyz[1] - ov1.xyz[1]; - float inverse_mag = frsqrt((dx*dx) + (dy*dy)) * HALF_LINE_WIDTH; + float inverse_mag = fast_rsqrt((dx*dx) + (dy*dy)) * HALF_LINE_WIDTH; float nx = -dy * inverse_mag; float ny = dx * inverse_mag; diff --git a/GL/private.h b/GL/private.h index 266af80..8230f01 100644 --- a/GL/private.h +++ b/GL/private.h @@ -260,6 +260,12 @@ do { \ memcpy_vertex(b, &c); \ } while(0) +#ifdef __DREAMCAST__ +#define fast_rsqrt(x) frsqrt(x) +#else +#define fast_rsqrt(x) (1.0f / __builtin_sqrtf(x)) +#endif + /* ClipVertex doesn't have room for these, so we need to parse them * out separately. Potentially 'w' will be housed here if we support oargb */ typedef struct {