From 989c55b5640095f69a129e15fbd35a4f56012237 Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Fri, 28 Mar 2025 07:50:21 +0800 Subject: [PATCH 1/2] Add SDL_RenderGeometryRawEx --- include/SDL3/SDL_render.h | 41 ++++++++++++++++++++++++++++ src/render/SDL_render.c | 45 ++++++++++++++++++++++++------- src/render/SDL_sysrender.h | 1 + src/render/opengl/SDL_glfuncs.h | 2 +- src/render/opengl/SDL_render_gl.c | 33 ++++++++++++++++------- 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 33b6e1feb9..35de66d8aa 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -2294,6 +2294,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(SDL_Renderer *rende * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderGeometryRaw + * \sa SDL_RenderGeometryRawEx */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, SDL_Texture *texture, @@ -2326,6 +2327,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderGeometry + * \sa SDL_RenderGeometryRawEx */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, @@ -2335,6 +2337,45 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, int num_vertices, const void *indices, int num_indices, int size_indices); + +/** + * Render a list of triangles, optionally using a texture and indices into the + * vertex arrays which can have up to 4 positional coordinates. + * Color and alpha modulation is done per vertex. + * (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored). + * + * \param renderer the rendering context. + * \param texture (optional) The SDL texture to use. + * \param pos vertex positions. + * \param pos_stride byte size to move from one element to the next element. + * \param pos_len how many vertext position coordinates, must be 2, 3, or 4. + * \param color vertex colors (as SDL_FColor). + * \param color_stride byte size to move from one element to the next element. + * \param uv vertex normalized texture coordinates. + * \param uv_stride byte size to move from one element to the next element. + * \param num_vertices number of vertices. + * \param indices (optional) An array of indices into the 'vertices' arrays, + * if NULL all vertices will be rendered in sequential order. + * \param num_indices number of indices. + * \param size_indices index size: 1 (byte), 2 (short), 4 (int). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_RenderGeometry + * \sa SDL_RenderGeometryRaw + */ + extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRawEx(SDL_Renderer *renderer, + SDL_Texture *texture, + const float *pos, int pos_stride, Uint8 pos_len, + const SDL_FColor *color, int color_stride, + const float *uv, int uv_stride, + int num_vertices, + const void *indices, int num_indices, int size_indices); + /** * Read pixels from the current rendering target. * diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 15949f75d6..20fb4dc70d 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -589,6 +589,7 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren if (renderer->gpu_render_state) { renderer->gpu_render_state->last_command_generation = renderer->render_command_generation; } + cmd->data.draw.tentatively_named_rendergeometry_position_coordinate_count = 2; } } return cmd; @@ -722,7 +723,7 @@ static bool QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, } static bool QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, - const float *xy, int xy_stride, + const float *pos, int pos_stride, Uint8 pos_len, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, @@ -734,8 +735,9 @@ static bool QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture); if (cmd) { cmd->data.draw.texture_address_mode = texture_address_mode; + cmd->data.draw.tentatively_named_rendergeometry_position_coordinate_count = SDL_max(2, SDL_min(4, pos_len)); result = renderer->QueueGeometry(renderer, cmd, texture, - xy, xy_stride, + pos, pos_stride, color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices, scale_x, scale_y); @@ -3737,7 +3739,8 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count } result = QueueCmdGeometry(renderer, NULL, - xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0, + xy, xy_stride, 2, + &renderer->color, 0 /* color_stride */, NULL, 0, num_vertices, indices, num_indices, size_indices, 1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP); } @@ -3918,7 +3921,8 @@ static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *textu xy[7] = maxy; result = QueueCmdGeometry(renderer, texture, - xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, + xy, xy_stride, 2, + &texture->color, 0 /* color_stride */, uv, uv_stride, num_vertices, indices, num_indices, size_indices, scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); } else { @@ -4079,7 +4083,7 @@ bool SDL_RenderTextureAffine(SDL_Renderer *renderer, SDL_Texture *texture, result = QueueCmdGeometry( renderer, texture, - xy, xy_stride, + xy, xy_stride, 2, &texture->color, 0 /* color_stride */, uv, uv_stride, num_vertices, indices, num_indices, size_indices, @@ -4231,7 +4235,8 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, xy[7] = (s_minx + c_maxy) + centery; result = QueueCmdGeometry(renderer, texture, - xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, + xy, xy_stride, 2, + &texture->color, 0 /* color_stride */, uv, uv_stride, num_vertices, indices, num_indices, size_indices, scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); } else { @@ -4283,7 +4288,8 @@ static bool SDL_RenderTextureTiled_Wrap(SDL_Renderer *renderer, SDL_Texture *tex const SDL_RenderViewState *view = renderer->view; return QueueCmdGeometry(renderer, texture, - xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, + xy, xy_stride, 2, + &texture->color, 0 /* color_stride */, uv, uv_stride, num_vertices, indices, num_indices, size_indices, view->current_scale.x, view->current_scale.y, SDL_TEXTURE_ADDRESS_WRAP); } @@ -5030,7 +5036,8 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Log("Triangle %d %d %d - is_uniform:%d is_rectangle:%d", prev[0], prev[1], prev[2], is_uniform, is_rectangle); #endif result = QueueCmdGeometry(renderer, texture, - xy, xy_stride, color, color_stride, uv, uv_stride, + xy, xy_stride, 2, + color, color_stride, uv, uv_stride, num_vertices, prev, 3, 4, scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); if (!result) { @@ -5050,7 +5057,8 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Log("Last triangle %d %d %d", prev[0], prev[1], prev[2]); #endif result = QueueCmdGeometry(renderer, texture, - xy, xy_stride, color, color_stride, uv, uv_stride, + xy, xy_stride, 2, + color, color_stride, uv, uv_stride, num_vertices, prev, 3, 4, scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); if (!result) { @@ -5074,6 +5082,22 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices) +{ + return SDL_RenderGeometryRawEx(renderer, texture, + xy, xy_stride, 2, + color, color_stride, + uv, uv_stride, + num_vertices, + indices, num_indices, size_indices); +} + +bool SDL_RenderGeometryRawEx(SDL_Renderer *renderer, + SDL_Texture *texture, + const float *xy, int xy_stride, Uint8 pos_len, + const SDL_FColor *color, int color_stride, + const float *uv, int uv_stride, + int num_vertices, + const void *indices, int num_indices, int size_indices) { int i; int count = indices ? num_indices : num_vertices; @@ -5177,7 +5201,8 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer, const SDL_RenderViewState *view = renderer->view; return QueueCmdGeometry(renderer, texture, - xy, xy_stride, color, color_stride, uv, uv_stride, + xy, xy_stride, pos_len, + color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices, view->current_scale.x, view->current_scale.y, texture_address_mode); diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 2e6cc76cde..6fd8bc37c6 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -189,6 +189,7 @@ typedef struct SDL_RenderCommand SDL_ScaleMode texture_scale_mode; SDL_TextureAddressMode texture_address_mode; SDL_GPURenderState *gpu_render_state; + Uint8 tentatively_named_rendergeometry_position_coordinate_count; } draw; struct { diff --git a/src/render/opengl/SDL_glfuncs.h b/src/render/opengl/SDL_glfuncs.h index 7e9f26596f..1997c11145 100644 --- a/src/render/opengl/SDL_glfuncs.h +++ b/src/render/opengl/SDL_glfuncs.h @@ -108,7 +108,7 @@ SDL_PROC_UNUSED(void, glCullFace, (GLenum mode)) SDL_PROC_UNUSED(void, glDeleteLists, (GLuint list, GLsizei range)) SDL_PROC(void, glDeleteTextures, (GLsizei n, const GLuint *textures)) SDL_PROC(void, glDepthFunc, (GLenum func)) -SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag)) +SDL_PROC(void, glDepthMask, (GLboolean flag)) SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar)) SDL_PROC(void, glDisable, (GLenum cap)) SDL_PROC(void, glDisableClientState, (GLenum array)) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 093119b22e..a7061f29cc 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -921,8 +921,9 @@ static bool GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL int i; int count = indices ? num_indices : num_vertices; GLfloat *verts; - size_t sz = 2 * sizeof(GLfloat) + 4 * sizeof(GLfloat) + (texture ? 2 : 0) * sizeof(GLfloat); + size_t sz = 4 * sizeof(GLfloat) + 4 * sizeof(GLfloat) + (texture ? 2 : 0) * sizeof(GLfloat); const float color_scale = cmd->data.draw.color_scale; + Uint8 pos_len = cmd->data.draw.tentatively_named_rendergeometry_position_coordinate_count; verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first); if (!verts) { @@ -954,6 +955,8 @@ static bool GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL *(verts++) = xy_[0] * scale_x; *(verts++) = xy_[1] * scale_y; + *(verts++) = pos_len > 2 ? xy_[2] : 0; + *(verts++) = pos_len > 3 ? xy_[3] : 1; col_ = (SDL_FColor *)((char *)color + j * color_stride); *(verts++) = col_->r * color_scale; @@ -976,6 +979,9 @@ static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, cons bool vertex_array; bool color_array; bool texture_array; + bool isCmdRenderGeometry = (cmd->command == SDL_RENDERCMD_GEOMETRY); + bool isCmdDrawPoints = (cmd->command == SDL_RENDERCMD_DRAW_POINTS); + bool isCmdDrawLines = (cmd->command == SDL_RENDERCMD_DRAW_LINES); if (data->drawstate.viewport_dirty) { const bool istarget = data->drawstate.target != NULL; @@ -1004,6 +1010,14 @@ static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, cons data->drawstate.cliprect_enabled_dirty = false; } + if (isCmdRenderGeometry && cmd->data.draw.tentatively_named_rendergeometry_position_coordinate_count > 2) { + data->glEnable(GL_DEPTH_TEST); + data->glDepthMask(GL_TRUE); + } else { + data->glDisable(GL_DEPTH_TEST); + data->glDepthMask(GL_FALSE); + } + if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) { const SDL_Rect *viewport = &data->drawstate.viewport; const SDL_Rect *rect = &data->drawstate.cliprect; @@ -1045,8 +1059,8 @@ static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, cons data->drawstate.texturing_dirty = false; } - vertex_array = cmd->command == SDL_RENDERCMD_DRAW_POINTS || cmd->command == SDL_RENDERCMD_DRAW_LINES || cmd->command == SDL_RENDERCMD_GEOMETRY; - color_array = cmd->command == SDL_RENDERCMD_GEOMETRY; + vertex_array = isCmdDrawPoints || isCmdDrawLines || isCmdRenderGeometry; + color_array = isCmdRenderGeometry; texture_array = cmd->data.draw.texture != NULL; if (vertex_array != data->drawstate.vertex_array) { @@ -1345,7 +1359,7 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled; } - data->glClear(GL_COLOR_BUFFER_BIT); + data->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); break; } @@ -1411,6 +1425,7 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v SDL_RenderCommand *finalcmd = cmd; SDL_RenderCommand *nextcmd = cmd->next; size_t count = cmd->data.draw.count; + Uint8 pos_len = cmd->data.draw.tentatively_named_rendergeometry_position_coordinate_count; int ret; while (nextcmd) { const SDL_RenderCommandType nextcmdtype = nextcmd->command; @@ -1447,12 +1462,12 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v } else { // SetDrawState handles glEnableClientState. if (thistexture) { - data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 8, verts + 0); - data->glColorPointer(4, GL_FLOAT, sizeof(float) * 8, verts + 2); - data->glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 8, verts + 6); + data->glVertexPointer(pos_len, GL_FLOAT, sizeof(float) * 10, verts + 0); + data->glColorPointer(4, GL_FLOAT, sizeof(float) * 10, verts + 4); + data->glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 10, verts + 8); } else { - data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 6, verts + 0); - data->glColorPointer(4, GL_FLOAT, sizeof(float) * 6, verts + 2); + data->glVertexPointer(pos_len, GL_FLOAT, sizeof(float) * 8, verts + 0); + data->glColorPointer(4, GL_FLOAT, sizeof(float) * 8, verts + 4); } } From 72c0fd1017f8ca4e5abd7b91c8de50611ca3cf66 Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Fri, 28 Mar 2025 12:51:29 +0800 Subject: [PATCH 2/2] use argument struct, rename to RenderGeometryEx --- include/SDL3/SDL_render.h | 49 ++++++++++++++++++------------- src/render/SDL_render.c | 62 +++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 35de66d8aa..7f8ef18e78 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -2294,7 +2294,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(SDL_Renderer *rende * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderGeometryRaw - * \sa SDL_RenderGeometryRawEx + * \sa SDL_RenderGeometryEx */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, SDL_Texture *texture, @@ -2327,7 +2327,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderGeometry - * \sa SDL_RenderGeometryRawEx + * \sa SDL_RenderGeometryEx */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, @@ -2337,6 +2337,29 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, int num_vertices, const void *indices, int num_indices, int size_indices); +/** + * Argument struct for SDL_RenderGeometryEx. + * + * \since This struct is available since SDL 3.4.0. + */ + typedef struct SDL_RenderGeometryEx_Arg + { + size_t arg_size; /**< the size of this struct, must be set with sizeof() */ + int ver_len; /**< number of vertices. */ + + const void *map; /**< (optional) An array of indices into the 'vertices' arrays, if NULL all vertices will be rendered in sequential order. */ + int map_size; /**< index size: 1 (byte), 2 (short), 4 (int). */ + int map_len; /**< number of indices. */ + const float *pos; /**< vertex positions. */ + int pos_stride; /**< byte size to move from one element to the next element. */ + int pos_len; /**< how many vertext position coordinates, must be 2, 3, or 4. */ + const SDL_FColor *col; /**< vertex colors (as SDL_FColor). */ + int col_stride; /**< byte size to move from one element to the next element. */ + + const float *tex; /**< vertex normalized texture coordinates. */ + int tex_stride; /**< byte size to move from one element to the next element. */ + +} SDL_RenderGeometryEx_Arg; /** * Render a list of triangles, optionally using a texture and indices into the @@ -2346,18 +2369,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, * * \param renderer the rendering context. * \param texture (optional) The SDL texture to use. - * \param pos vertex positions. - * \param pos_stride byte size to move from one element to the next element. - * \param pos_len how many vertext position coordinates, must be 2, 3, or 4. - * \param color vertex colors (as SDL_FColor). - * \param color_stride byte size to move from one element to the next element. - * \param uv vertex normalized texture coordinates. - * \param uv_stride byte size to move from one element to the next element. - * \param num_vertices number of vertices. - * \param indices (optional) An array of indices into the 'vertices' arrays, - * if NULL all vertices will be rendered in sequential order. - * \param num_indices number of indices. - * \param size_indices index size: 1 (byte), 2 (short), 4 (int). + * \param arg pointer to an SDL_RenderGeometryEx_Arg struct of vertex info. * \returns true on success or false on failure; call SDL_GetError() for more * information. * @@ -2368,13 +2380,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, * \sa SDL_RenderGeometry * \sa SDL_RenderGeometryRaw */ - extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRawEx(SDL_Renderer *renderer, - SDL_Texture *texture, - const float *pos, int pos_stride, Uint8 pos_len, - const SDL_FColor *color, int color_stride, - const float *uv, int uv_stride, - int num_vertices, - const void *indices, int num_indices, int size_indices); + extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryEx(SDL_Renderer *renderer, + SDL_Texture *texture, const SDL_RenderGeometryEx_Arg *arg); /** * Read pixels from the current rendering target. diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 20fb4dc70d..7d8ee29eb1 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -5083,22 +5083,60 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer, int num_vertices, const void *indices, int num_indices, int size_indices) { - return SDL_RenderGeometryRawEx(renderer, texture, - xy, xy_stride, 2, - color, color_stride, - uv, uv_stride, - num_vertices, - indices, num_indices, size_indices); + SDL_RenderGeometryEx_Arg arg; + arg.arg_size = sizeof(SDL_RenderGeometryEx_Arg); + arg.pos = xy; + arg.pos_stride = xy_stride; + arg.pos_len = 2; + arg.col = color; + arg.col_stride = color_stride; + arg.tex = uv; + arg.tex_stride = uv_stride; + arg.ver_len = num_vertices; + arg.map = indices; + arg.map_len = num_indices; + arg.map_size = size_indices; + return SDL_RenderGeometryEx(renderer, texture, &arg); } -bool SDL_RenderGeometryRawEx(SDL_Renderer *renderer, +bool SDL_RenderGeometryEx(SDL_Renderer *renderer, SDL_Texture *texture, - const float *xy, int xy_stride, Uint8 pos_len, - const SDL_FColor *color, int color_stride, - const float *uv, int uv_stride, - int num_vertices, - const void *indices, int num_indices, int size_indices) + const SDL_RenderGeometryEx_Arg *arg) { + if (!arg) { + return false; + } + + const float *xy; + int xy_stride; + int pos_len; + const SDL_FColor *color; + int color_stride; + const float *uv; + int uv_stride; + int num_vertices; + const void *indices; + int num_indices; + int size_indices; + + if (arg->arg_size < sizeof(SDL_RenderGeometryEx_Arg)) { + // older ABI with fewer arguments, set fallback values + return false; // placeholder for now + } else { + xy = arg->pos; + xy_stride = arg->pos_stride; + pos_len = arg->pos_len; + color = arg->col; + color_stride = arg->col_stride; + uv = arg->tex; + uv_stride = arg->tex_stride; + num_vertices = arg->ver_len; + indices = arg->map; + num_indices = arg->map_len; + size_indices = arg->map_size; + } + + int i; int count = indices ? num_indices : num_vertices; SDL_TextureAddressMode texture_address_mode;