Add SDL_RenderGeometryRawEx

This commit is contained in:
expikr 2025-03-28 07:50:21 +08:00
parent eed94cb034
commit 989c55b564
5 changed files with 102 additions and 20 deletions

View file

@ -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.
*

View file

@ -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);

View file

@ -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
{

View file

@ -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))

View file

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