mirror of
https://github.com/Ryujinx/SDL.git
synced 2024-12-23 08:25:31 +00:00
gles2: Make render command queue dynamic.
It now uses a growable linked list that keeps a pool of allocated items for reuse, and reallocs the vertex array as necessary. Testsprite2 can scale to 20,000 (or more!) draws now without drama.
This commit is contained in:
parent
0d3275297d
commit
a2f7af9a47
|
@ -196,6 +196,7 @@ typedef struct GLES2_RenderCommand
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
} draw;
|
} draw;
|
||||||
} data;
|
} data;
|
||||||
|
struct GLES2_RenderCommand *next;
|
||||||
} GLES2_RenderCommand;
|
} GLES2_RenderCommand;
|
||||||
|
|
||||||
typedef struct GLES2_DriverContext
|
typedef struct GLES2_DriverContext
|
||||||
|
@ -220,17 +221,49 @@ typedef struct GLES2_DriverContext
|
||||||
GLuint vertex_buffers[4];
|
GLuint vertex_buffers[4];
|
||||||
GLsizeiptr vertex_buffer_size[4];
|
GLsizeiptr vertex_buffer_size[4];
|
||||||
int current_vertex_buffer;
|
int current_vertex_buffer;
|
||||||
GLES2_RenderCommand render_commands[1024 * 10];
|
GLES2_RenderCommand *render_commands;
|
||||||
int current_render_command;
|
GLES2_RenderCommand *render_commands_tail;
|
||||||
|
GLES2_RenderCommand *render_commands_pool;
|
||||||
int current_vertex_data;
|
int current_vertex_data;
|
||||||
Uint32 command_generation;
|
Uint32 command_generation;
|
||||||
GLfloat vertex_data[1024 * 1024 * 5];
|
GLfloat *vertex_data;
|
||||||
|
GLsizeiptr vertex_data_allocation;
|
||||||
} GLES2_DriverContext;
|
} GLES2_DriverContext;
|
||||||
|
|
||||||
#define GLES2_MAX_CACHED_PROGRAMS 8
|
#define GLES2_MAX_CACHED_PROGRAMS 8
|
||||||
|
|
||||||
static const float inv255f = 1.0f / 255.0f;
|
static const float inv255f = 1.0f / 255.0f;
|
||||||
|
|
||||||
|
static GLES2_RenderCommand *
|
||||||
|
GLES2_AllocateRenderCommand(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
|
||||||
|
GLES2_RenderCommand *retval = NULL;
|
||||||
|
|
||||||
|
/* !!! FIXME: are there threading limitations in SDL's render API? */
|
||||||
|
retval = data->render_commands_pool;
|
||||||
|
if (retval != NULL) {
|
||||||
|
data->render_commands_pool = retval->next;
|
||||||
|
retval->next = NULL;
|
||||||
|
} else {
|
||||||
|
retval = SDL_calloc(1, sizeof (*retval));
|
||||||
|
if (!retval) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_assert((data->render_commands == NULL) == (data->render_commands_tail == NULL));
|
||||||
|
if (data->render_commands_tail != NULL) {
|
||||||
|
data->render_commands_tail->next = retval;
|
||||||
|
} else {
|
||||||
|
data->render_commands = retval;
|
||||||
|
}
|
||||||
|
data->render_commands_tail = retval;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
CompareColors(const Uint8 r1, const Uint8 g1, const Uint8 b1, const Uint8 a1,
|
CompareColors(const Uint8 r1, const Uint8 g1, const Uint8 b1, const Uint8 a1,
|
||||||
const Uint8 r2, const Uint8 g2, const Uint8 b2, const Uint8 a2)
|
const Uint8 r2, const Uint8 g2, const Uint8 b2, const Uint8 a2)
|
||||||
|
@ -481,8 +514,9 @@ GLES2_FlushCommands(SDL_Renderer *renderer)
|
||||||
const int vboidx = data->current_vertex_buffer;
|
const int vboidx = data->current_vertex_buffer;
|
||||||
const GLuint vbo = data->vertex_buffers[vboidx];
|
const GLuint vbo = data->vertex_buffers[vboidx];
|
||||||
const GLsizeiptr dataSizeInBytes = data->current_vertex_data * sizeof (float);
|
const GLsizeiptr dataSizeInBytes = data->current_vertex_data * sizeof (float);
|
||||||
const int totalcmds = data->current_render_command;
|
|
||||||
Uint8 enabled_attrs = (1 << GLES2_ATTRIBUTE_POSITION);
|
Uint8 enabled_attrs = (1 << GLES2_ATTRIBUTE_POSITION);
|
||||||
|
GLES2_RenderCommand *cmd;
|
||||||
|
GLES2_RenderCommand *next;
|
||||||
SDL_Rect viewport;
|
SDL_Rect viewport;
|
||||||
SDL_Texture *bound_texture = NULL;
|
SDL_Texture *bound_texture = NULL;
|
||||||
SDL_BlendMode blend = SDL_BLENDMODE_INVALID;
|
SDL_BlendMode blend = SDL_BLENDMODE_INVALID;
|
||||||
|
@ -491,11 +525,10 @@ GLES2_FlushCommands(SDL_Renderer *renderer)
|
||||||
GLfloat projection[4][4];
|
GLfloat projection[4][4];
|
||||||
SDL_bool cliprect_enabled = SDL_FALSE;
|
SDL_bool cliprect_enabled = SDL_FALSE;
|
||||||
SDL_Rect cliprect;
|
SDL_Rect cliprect;
|
||||||
int i;
|
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
if (totalcmds == 0) { /* nothing to do! */
|
if (data->render_commands == NULL) { /* nothing to do! */
|
||||||
SDL_assert(data->current_vertex_data == 0);
|
SDL_assert(data->current_vertex_data == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -506,7 +539,9 @@ GLES2_FlushCommands(SDL_Renderer *renderer)
|
||||||
data->current_vertex_buffer = 0;
|
data->current_vertex_buffer = 0;
|
||||||
}
|
}
|
||||||
data->current_vertex_data = 0; /* start next VBO at start. */
|
data->current_vertex_data = 0; /* start next VBO at start. */
|
||||||
data->current_render_command = 0;
|
cmd = data->render_commands;
|
||||||
|
data->render_commands = NULL;
|
||||||
|
data->render_commands_tail = NULL;
|
||||||
|
|
||||||
SDL_zero(projection);
|
SDL_zero(projection);
|
||||||
projection[3][0] = -1.0f;
|
projection[3][0] = -1.0f;
|
||||||
|
@ -555,8 +590,7 @@ GLES2_FlushCommands(SDL_Renderer *renderer)
|
||||||
data->glScissor(viewport.x + cliprect.x, drawableh - viewport.y - cliprect.y - cliprect.h, cliprect.w, cliprect.h);
|
data->glScissor(viewport.x + cliprect.x, drawableh - viewport.y - cliprect.y - cliprect.h, cliprect.w, cliprect.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < totalcmds; i++) {
|
while (cmd != NULL) {
|
||||||
const GLES2_RenderCommand *cmd = &data->render_commands[i];
|
|
||||||
switch (cmd->cmd) {
|
switch (cmd->cmd) {
|
||||||
case GLES2_RENDERCMD_VIEWPORT:
|
case GLES2_RENDERCMD_VIEWPORT:
|
||||||
if (SDL_memcmp(&cmd->data.viewport, &viewport, sizeof (SDL_Rect)) != 0) {
|
if (SDL_memcmp(&cmd->data.viewport, &viewport, sizeof (SDL_Rect)) != 0) {
|
||||||
|
@ -713,6 +747,12 @@ GLES2_FlushCommands(SDL_Renderer *renderer)
|
||||||
|
|
||||||
default: SDL_assert(!"Unknown rendering command"); break;
|
default: SDL_assert(!"Unknown rendering command"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* put this command in the pool for reuse, move on to next one. */
|
||||||
|
next = cmd->next;
|
||||||
|
cmd->next = data->render_commands_pool;
|
||||||
|
data->render_commands_pool = cmd;
|
||||||
|
cmd = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->command_generation++;
|
data->command_generation++;
|
||||||
|
@ -734,8 +774,10 @@ GLES2_FlushCommandsIfTextureNeeded(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
static int
|
static int
|
||||||
GLES2_UpdateViewport(SDL_Renderer * renderer)
|
GLES2_UpdateViewport(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
|
||||||
GLES2_RenderCommand *cmd = &data->render_commands[data->current_render_command++];
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
cmd->cmd = GLES2_RENDERCMD_VIEWPORT;
|
cmd->cmd = GLES2_RENDERCMD_VIEWPORT;
|
||||||
SDL_memcpy(&cmd->data.viewport, &renderer->viewport, sizeof (SDL_Rect));
|
SDL_memcpy(&cmd->data.viewport, &renderer->viewport, sizeof (SDL_Rect));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -744,8 +786,10 @@ GLES2_UpdateViewport(SDL_Renderer * renderer)
|
||||||
static int
|
static int
|
||||||
GLES2_UpdateClipRect(SDL_Renderer * renderer)
|
GLES2_UpdateClipRect(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
|
||||||
GLES2_RenderCommand *cmd = &data->render_commands[data->current_render_command++];
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
cmd->cmd = GLES2_RENDERCMD_CLIPRECT;
|
cmd->cmd = GLES2_RENDERCMD_CLIPRECT;
|
||||||
cmd->data.cliprect.enabled = renderer->clipping_enabled;
|
cmd->data.cliprect.enabled = renderer->clipping_enabled;
|
||||||
SDL_memcpy(&cmd->data.cliprect.rect, &renderer->clip_rect, sizeof (SDL_Rect));
|
SDL_memcpy(&cmd->data.cliprect.rect, &renderer->clip_rect, sizeof (SDL_Rect));
|
||||||
|
@ -759,8 +803,25 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
|
||||||
|
|
||||||
/* Deallocate everything */
|
/* Deallocate everything */
|
||||||
if (data) {
|
if (data) {
|
||||||
|
GLES2_RenderCommand *cmd;
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
if (data->render_commands_tail != NULL) {
|
||||||
|
data->render_commands_tail->next = data->render_commands_pool;
|
||||||
|
} else {
|
||||||
|
data->render_commands = data->render_commands_pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = data->render_commands;
|
||||||
|
while (cmd != NULL) {
|
||||||
|
GLES2_RenderCommand *next = cmd->next;
|
||||||
|
SDL_free(cmd);
|
||||||
|
cmd = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(data->vertex_data);
|
||||||
|
|
||||||
{
|
{
|
||||||
GLES2_ShaderCacheEntry *entry;
|
GLES2_ShaderCacheEntry *entry;
|
||||||
GLES2_ShaderCacheEntry *next;
|
GLES2_ShaderCacheEntry *next;
|
||||||
|
@ -1625,8 +1686,10 @@ static void GLES2_RenderPresent(SDL_Renderer *renderer);
|
||||||
static int
|
static int
|
||||||
GLES2_RenderClear(SDL_Renderer * renderer)
|
GLES2_RenderClear(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
|
||||||
GLES2_RenderCommand *cmd = &data->render_commands[data->current_render_command++];
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
cmd->cmd = GLES2_RENDERCMD_CLEAR;
|
cmd->cmd = GLES2_RENDERCMD_CLEAR;
|
||||||
cmd->data.clear.r = renderer->r;
|
cmd->data.clear.r = renderer->r;
|
||||||
cmd->data.clear.g = renderer->g;
|
cmd->data.clear.g = renderer->g;
|
||||||
|
@ -1635,25 +1698,48 @@ GLES2_RenderClear(SDL_Renderer * renderer)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
GLES2_AddVertices(SDL_Renderer *renderer, const GLES2_Attribute attr, const float *vertexData, size_t dataSizeInElements)
|
GLES2_AddVertices(SDL_Renderer *renderer, const GLES2_Attribute attr, const float *vertexData, size_t dataSizeInElements)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
GLES2_RenderCommand *cmd = &data->render_commands[data->current_render_command++];
|
const GLsizeiptr needed = data->current_vertex_data + dataSizeInElements;
|
||||||
GLfloat *vdata = &data->vertex_data[data->current_vertex_data];
|
GLES2_RenderCommand *cmd;
|
||||||
|
GLfloat *vdata;
|
||||||
|
|
||||||
|
if (needed > data->vertex_data_allocation) {
|
||||||
|
const GLsizeiptr newsize = data->vertex_data_allocation * 2;
|
||||||
|
printf("realloc'ing %p to %d\n", data->vertex_data, (int) newsize);
|
||||||
|
void *ptr = SDL_realloc(data->vertex_data, newsize * sizeof (GLfloat));
|
||||||
|
if (ptr == NULL) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->vertex_data = (GLfloat *) ptr;
|
||||||
|
data->vertex_data_allocation = newsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = GLES2_AllocateRenderCommand(renderer);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdata = &data->vertex_data[data->current_vertex_data];
|
||||||
SDL_memcpy(vdata, vertexData, dataSizeInElements * sizeof (GLfloat));
|
SDL_memcpy(vdata, vertexData, dataSizeInElements * sizeof (GLfloat));
|
||||||
cmd->cmd = GLES2_RENDERCMD_ATTR;
|
cmd->cmd = GLES2_RENDERCMD_ATTR;
|
||||||
cmd->data.attr.attr = attr;
|
cmd->data.attr.attr = attr;
|
||||||
cmd->data.attr.offset = data->current_vertex_data * sizeof (GLfloat);
|
cmd->data.attr.offset = data->current_vertex_data * sizeof (GLfloat);
|
||||||
cmd->data.attr.count = dataSizeInElements;
|
cmd->data.attr.count = dataSizeInElements;
|
||||||
data->current_vertex_data += dataSizeInElements;
|
data->current_vertex_data += dataSizeInElements;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLES2_RenderCommand *
|
static int
|
||||||
GLES2_InitSolidDrawCommand(SDL_Renderer *renderer, const GLenum mode, const GLint first, const GLsizei count)
|
GLES2_AddSolidDrawCommand(SDL_Renderer *renderer, const GLenum mode, const GLint first, const GLsizei count)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
|
||||||
GLES2_RenderCommand *cmd = &data->render_commands[data->current_render_command++];
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
cmd->cmd = GLES2_RENDERCMD_DRAW;
|
cmd->cmd = GLES2_RENDERCMD_DRAW;
|
||||||
cmd->data.draw.mode = mode;
|
cmd->data.draw.mode = mode;
|
||||||
cmd->data.draw.first = first;
|
cmd->data.draw.first = first;
|
||||||
|
@ -1666,7 +1752,7 @@ GLES2_InitSolidDrawCommand(SDL_Renderer *renderer, const GLenum mode, const GLin
|
||||||
cmd->data.draw.blend = renderer->blendMode;
|
cmd->data.draw.blend = renderer->blendMode;
|
||||||
cmd->data.draw.imgsrc = GLES2_IMAGESOURCE_SOLID;
|
cmd->data.draw.imgsrc = GLES2_IMAGESOURCE_SOLID;
|
||||||
cmd->data.draw.texture = NULL;
|
cmd->data.draw.texture = NULL;
|
||||||
return cmd;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1674,6 +1760,7 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int cou
|
||||||
{
|
{
|
||||||
GLfloat *vertices = SDL_stack_alloc(GLfloat, count * 2); /* !!! FIXME: We could do this without a stack_alloc... */
|
GLfloat *vertices = SDL_stack_alloc(GLfloat, count * 2); /* !!! FIXME: We could do this without a stack_alloc... */
|
||||||
int idx;
|
int idx;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Emit the specified vertices as points */
|
/* Emit the specified vertices as points */
|
||||||
for (idx = 0; idx < count; ++idx) {
|
for (idx = 0; idx < count; ++idx) {
|
||||||
|
@ -1681,10 +1768,14 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int cou
|
||||||
vertices[(idx * 2) + 1] = points[idx].y + 0.5f;
|
vertices[(idx * 2) + 1] = points[idx].y + 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2);
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2);
|
||||||
GLES2_InitSolidDrawCommand(renderer, GL_POINTS, 0, count);
|
|
||||||
SDL_stack_free(vertices);
|
SDL_stack_free(vertices);
|
||||||
return 0;
|
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = GLES2_AddSolidDrawCommand(renderer, GL_POINTS, 0, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1692,6 +1783,7 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int coun
|
||||||
{
|
{
|
||||||
GLfloat *vertices = SDL_stack_alloc(GLfloat, count * 2); /* !!! FIXME: We could do this without a stack_alloc... */
|
GLfloat *vertices = SDL_stack_alloc(GLfloat, count * 2); /* !!! FIXME: We could do this without a stack_alloc... */
|
||||||
int idx;
|
int idx;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Emit a line strip including the specified vertices */
|
/* Emit a line strip including the specified vertices */
|
||||||
for (idx = 0; idx < count; ++idx) {
|
for (idx = 0; idx < count; ++idx) {
|
||||||
|
@ -1699,8 +1791,10 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int coun
|
||||||
vertices[(idx * 2) + 1] = points[idx].y + 0.5f;
|
vertices[(idx * 2) + 1] = points[idx].y + 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2);
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2);
|
||||||
GLES2_InitSolidDrawCommand(renderer, GL_LINE_STRIP, 0, count);
|
if (rc == 0) {
|
||||||
|
rc = GLES2_AddSolidDrawCommand(renderer, GL_LINE_STRIP, 0, count);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0 /* !!! FIXME: ugh */
|
#if 0 /* !!! FIXME: ugh */
|
||||||
/* We need to close the endpoint of the line */
|
/* We need to close the endpoint of the line */
|
||||||
|
@ -1711,7 +1805,7 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int coun
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_stack_free(vertices);
|
SDL_stack_free(vertices);
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1719,9 +1813,10 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
|
||||||
{
|
{
|
||||||
GLfloat vertices[8];
|
GLfloat vertices[8];
|
||||||
int idx;
|
int idx;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
/* Emit a line loop for each rectangle */
|
/* Emit a line loop for each rectangle */
|
||||||
for (idx = 0; idx < count; ++idx) {
|
for (idx = 0; (rc == 0) && (idx < count); ++idx) {
|
||||||
const SDL_FRect *rect = &rects[idx];
|
const SDL_FRect *rect = &rects[idx];
|
||||||
|
|
||||||
GLfloat xMin = rect->x;
|
GLfloat xMin = rect->x;
|
||||||
|
@ -1738,16 +1833,18 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
|
||||||
vertices[6] = xMax;
|
vertices[6] = xMax;
|
||||||
vertices[7] = yMax;
|
vertices[7] = yMax;
|
||||||
|
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
|
||||||
GLES2_InitSolidDrawCommand(renderer, GL_TRIANGLE_STRIP, 0, 4);
|
if (rc == 0) {
|
||||||
|
rc = GLES2_AddSolidDrawCommand(renderer, GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static GLES2_RenderCommand *
|
static int
|
||||||
GLES2_InitCopyDrawCommand(SDL_Renderer *renderer, SDL_Texture *texture, const Uint8 attrs)
|
GLES2_AddCopyDrawCommand(SDL_Renderer *renderer, SDL_Texture *texture, const Uint8 attrs)
|
||||||
{
|
{
|
||||||
GLES2_RenderCommand *cmd = NULL;
|
GLES2_RenderCommand *cmd = NULL;
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
|
@ -1820,8 +1917,7 @@ GLES2_InitCopyDrawCommand(SDL_Renderer *renderer, SDL_Texture *texture, const Ui
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SDL_SetError("Unsupported texture format");
|
return SDL_SetError("Unsupported texture format");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
||||||
|
@ -1854,14 +1950,16 @@ GLES2_InitCopyDrawCommand(SDL_Renderer *renderer, SDL_Texture *texture, const Ui
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SDL_SetError("Unsupported texture format");
|
return SDL_SetError("Unsupported texture format");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
((GLES2_TextureData *)texture->driverdata)->last_cmd_generation = data->command_generation;
|
((GLES2_TextureData *)texture->driverdata)->last_cmd_generation = data->command_generation;
|
||||||
|
|
||||||
cmd = &data->render_commands[data->current_render_command++];
|
cmd = GLES2_AllocateRenderCommand(renderer);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
cmd->cmd = GLES2_RENDERCMD_DRAW;
|
cmd->cmd = GLES2_RENDERCMD_DRAW;
|
||||||
cmd->data.draw.mode = GL_TRIANGLE_STRIP;
|
cmd->data.draw.mode = GL_TRIANGLE_STRIP;
|
||||||
cmd->data.draw.first = 0;
|
cmd->data.draw.first = 0;
|
||||||
|
@ -1875,7 +1973,7 @@ GLES2_InitCopyDrawCommand(SDL_Renderer *renderer, SDL_Texture *texture, const Ui
|
||||||
cmd->data.draw.imgsrc = sourceType;
|
cmd->data.draw.imgsrc = sourceType;
|
||||||
cmd->data.draw.texture = texture;
|
cmd->data.draw.texture = texture;
|
||||||
|
|
||||||
return cmd;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1883,6 +1981,7 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
const SDL_FRect *dstrect)
|
const SDL_FRect *dstrect)
|
||||||
{
|
{
|
||||||
GLfloat vertices[8];
|
GLfloat vertices[8];
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Emit the textured quad */
|
/* Emit the textured quad */
|
||||||
vertices[0] = dstrect->x;
|
vertices[0] = dstrect->x;
|
||||||
|
@ -1893,20 +1992,25 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
vertices[5] = (dstrect->y + dstrect->h);
|
vertices[5] = (dstrect->y + dstrect->h);
|
||||||
vertices[6] = (dstrect->x + dstrect->w);
|
vertices[6] = (dstrect->x + dstrect->w);
|
||||||
vertices[7] = (dstrect->y + dstrect->h);
|
vertices[7] = (dstrect->y + dstrect->h);
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
|
||||||
|
|
||||||
vertices[0] = srcrect->x / (GLfloat)texture->w;
|
if (rc == 0) {
|
||||||
vertices[1] = srcrect->y / (GLfloat)texture->h;
|
vertices[0] = srcrect->x / (GLfloat)texture->w;
|
||||||
vertices[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
vertices[1] = srcrect->y / (GLfloat)texture->h;
|
||||||
vertices[3] = srcrect->y / (GLfloat)texture->h;
|
vertices[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
vertices[4] = srcrect->x / (GLfloat)texture->w;
|
vertices[3] = srcrect->y / (GLfloat)texture->h;
|
||||||
vertices[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
vertices[4] = srcrect->x / (GLfloat)texture->w;
|
||||||
vertices[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
vertices[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
vertices[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
vertices[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_TEXCOORD, vertices, 8);
|
vertices[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_TEXCOORD, vertices, 8);
|
||||||
|
|
||||||
GLES2_InitCopyDrawCommand(renderer, texture, 0);
|
if (rc == 0) {
|
||||||
return 0;
|
rc = GLES2_AddCopyDrawCommand(renderer, texture, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1915,50 +2019,60 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
{
|
{
|
||||||
const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
|
const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
|
||||||
GLfloat vertices[8];
|
GLfloat vertices[8];
|
||||||
|
int rc;
|
||||||
|
|
||||||
vertices[0] = vertices[2] = vertices[4] = vertices[6] = (GLfloat)SDL_sin(radian_angle);
|
vertices[0] = vertices[2] = vertices[4] = vertices[6] = (GLfloat)SDL_sin(radian_angle);
|
||||||
/* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
|
/* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
|
||||||
vertices[1] = vertices[3] = vertices[5] = vertices[7] = (GLfloat)SDL_cos(radian_angle) - 1.0f;
|
vertices[1] = vertices[3] = vertices[5] = vertices[7] = (GLfloat)SDL_cos(radian_angle) - 1.0f;
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_ANGLE, vertices, 8);
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_ANGLE, vertices, 8);
|
||||||
|
|
||||||
/* Calculate the center of rotation */
|
/* Calculate the center of rotation */
|
||||||
vertices[0] = vertices[2] = vertices[4] = vertices[6] = (center->x + dstrect->x);
|
if (rc == 0) {
|
||||||
vertices[1] = vertices[3] = vertices[5] = vertices[7] = (center->y + dstrect->y);
|
vertices[0] = vertices[2] = vertices[4] = vertices[6] = (center->x + dstrect->x);
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_CENTER, vertices, 8);
|
vertices[1] = vertices[3] = vertices[5] = vertices[7] = (center->y + dstrect->y);
|
||||||
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_CENTER, vertices, 8);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
/* Emit the textured quad */
|
||||||
|
vertices[0] = dstrect->x;
|
||||||
|
vertices[1] = dstrect->y;
|
||||||
|
vertices[2] = (dstrect->x + dstrect->w);
|
||||||
|
vertices[3] = dstrect->y;
|
||||||
|
vertices[4] = dstrect->x;
|
||||||
|
vertices[5] = (dstrect->y + dstrect->h);
|
||||||
|
vertices[6] = (dstrect->x + dstrect->w);
|
||||||
|
vertices[7] = (dstrect->y + dstrect->h);
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL) {
|
||||||
|
const GLfloat tmp = vertices[0];
|
||||||
|
vertices[0] = vertices[4] = vertices[2];
|
||||||
|
vertices[2] = vertices[6] = tmp;
|
||||||
|
}
|
||||||
|
if (flip & SDL_FLIP_VERTICAL) {
|
||||||
|
const GLfloat tmp = vertices[1];
|
||||||
|
vertices[1] = vertices[3] = vertices[5];
|
||||||
|
vertices[5] = vertices[7] = tmp;
|
||||||
|
}
|
||||||
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
|
||||||
|
|
||||||
/* Emit the textured quad */
|
if (rc == 0) {
|
||||||
vertices[0] = dstrect->x;
|
vertices[0] = srcrect->x / (GLfloat)texture->w;
|
||||||
vertices[1] = dstrect->y;
|
vertices[1] = srcrect->y / (GLfloat)texture->h;
|
||||||
vertices[2] = (dstrect->x + dstrect->w);
|
vertices[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
vertices[3] = dstrect->y;
|
vertices[3] = srcrect->y / (GLfloat)texture->h;
|
||||||
vertices[4] = dstrect->x;
|
vertices[4] = srcrect->x / (GLfloat)texture->w;
|
||||||
vertices[5] = (dstrect->y + dstrect->h);
|
vertices[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
vertices[6] = (dstrect->x + dstrect->w);
|
vertices[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
vertices[7] = (dstrect->y + dstrect->h);
|
vertices[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
if (flip & SDL_FLIP_HORIZONTAL) {
|
rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_TEXCOORD, vertices, 8);
|
||||||
const GLfloat tmp = vertices[0];
|
|
||||||
vertices[0] = vertices[4] = vertices[2];
|
if (rc == 0) {
|
||||||
vertices[2] = vertices[6] = tmp;
|
GLES2_AddCopyDrawCommand(renderer, texture, (1 << GLES2_ATTRIBUTE_CENTER) | (1 << GLES2_ATTRIBUTE_ANGLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flip & SDL_FLIP_VERTICAL) {
|
|
||||||
const GLfloat tmp = vertices[1];
|
|
||||||
vertices[1] = vertices[3] = vertices[5];
|
|
||||||
vertices[5] = vertices[7] = tmp;
|
|
||||||
}
|
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
|
|
||||||
|
|
||||||
vertices[0] = srcrect->x / (GLfloat)texture->w;
|
return rc;
|
||||||
vertices[1] = srcrect->y / (GLfloat)texture->h;
|
|
||||||
vertices[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
|
||||||
vertices[3] = srcrect->y / (GLfloat)texture->h;
|
|
||||||
vertices[4] = srcrect->x / (GLfloat)texture->w;
|
|
||||||
vertices[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
|
||||||
vertices[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
|
||||||
vertices[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
|
||||||
GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_TEXCOORD, vertices, 8);
|
|
||||||
|
|
||||||
GLES2_InitCopyDrawCommand(renderer, texture, (1 << GLES2_ATTRIBUTE_CENTER) | (1 << GLES2_ATTRIBUTE_ANGLE));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -2158,6 +2272,15 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
renderer->driverdata = data;
|
renderer->driverdata = data;
|
||||||
renderer->window = window;
|
renderer->window = window;
|
||||||
|
|
||||||
|
data->vertex_data_allocation = 512;
|
||||||
|
data->vertex_data = (GLfloat *) SDL_malloc(data->vertex_data_allocation * sizeof (GLfloat));
|
||||||
|
if (data->vertex_data == NULL) {
|
||||||
|
GLES2_DestroyRenderer(renderer);
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
printf("malloc'd %p\n", data->vertex_data);
|
||||||
|
|
||||||
/* Create an OpenGL ES 2.0 context */
|
/* Create an OpenGL ES 2.0 context */
|
||||||
data->context = SDL_GL_CreateContext(window);
|
data->context = SDL_GL_CreateContext(window);
|
||||||
if (!data->context) {
|
if (!data->context) {
|
||||||
|
|
Loading…
Reference in a new issue