Skip to content

Add SDL_RenderGeometryEx #12659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions include/SDL3/SDL_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_RenderGeometryEx
*/
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
SDL_Texture *texture,
Expand Down Expand Up @@ -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_RenderGeometryEx
*/
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
SDL_Texture *texture,
Expand All @@ -2335,6 +2337,52 @@ 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
* 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 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.
*
* \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_RenderGeometryEx(SDL_Renderer *renderer,
SDL_Texture *texture, const SDL_RenderGeometryEx_Arg *arg);

/**
* Read pixels from the current rendering target.
*
Expand Down
83 changes: 73 additions & 10 deletions src/render/SDL_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -5075,6 +5083,60 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
int num_vertices,
const void *indices, int num_indices, int 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_RenderGeometryEx(SDL_Renderer *renderer,
SDL_Texture *texture,
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;
Expand Down Expand Up @@ -5177,7 +5239,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);
Expand Down
1 change: 1 addition & 0 deletions src/render/SDL_sysrender.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
2 changes: 1 addition & 1 deletion src/render/opengl/SDL_glfuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
33 changes: 24 additions & 9 deletions src/render/opengl/SDL_render_gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down
Loading