From a47f331ceea3bd1df9a232a54bbdc7e66d61c455 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 2 Oct 2024 07:48:44 +1000 Subject: [PATCH] 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);