|
@@ -28,6 +28,16 @@
|
|
|
#include "../../video/SDL_blit.h"
|
|
|
#include "SDL_shaders_gles2.h"
|
|
|
|
|
|
+/* WebGL doesn't offer client-side arrays, so use Vertex Buffer Objects
|
|
|
+ on Emscripten, which converts GLES2 into WebGL calls.
|
|
|
+ In all other cases, attempt to use client-side arrays, as they tend to
|
|
|
+ be faster. */
|
|
|
+#if defined(__EMSCRIPTEN__)
|
|
|
+#define USE_VERTEX_BUFFER_OBJECTS 1
|
|
|
+#else
|
|
|
+#define USE_VERTEX_BUFFER_OBJECTS 0
|
|
|
+#endif
|
|
|
+
|
|
|
/* To prevent unnecessary window recreation,
|
|
|
* these should match the defaults selected in SDL_GL_ResetAttributes
|
|
|
*/
|
|
@@ -151,9 +161,12 @@ typedef struct GLES2_RenderData
|
|
|
GLES2_ProgramCache program_cache;
|
|
|
Uint8 clear_r, clear_g, clear_b, clear_a;
|
|
|
|
|
|
+#if USE_VERTEX_BUFFER_OBJECTS
|
|
|
GLuint vertex_buffers[8];
|
|
|
size_t vertex_buffer_size[8];
|
|
|
int current_vertex_buffer;
|
|
|
+#endif
|
|
|
+
|
|
|
GLES2_DrawStateCache drawstate;
|
|
|
} GLES2_RenderData;
|
|
|
|
|
@@ -844,7 +857,7 @@ GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
|
|
|
+SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc, void *vertices)
|
|
|
{
|
|
|
SDL_Texture *texture = cmd->data.draw.texture;
|
|
|
const SDL_BlendMode blend = cmd->data.draw.blend;
|
|
@@ -926,7 +939,7 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
|
|
|
}
|
|
|
|
|
|
if (texture) {
|
|
|
- SDL_Vertex *verts = (SDL_Vertex *) (cmd->data.draw.first);
|
|
|
+ SDL_Vertex *verts = (SDL_Vertex *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
|
|
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
|
|
|
}
|
|
|
|
|
@@ -960,7 +973,7 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
|
|
|
|
|
|
/* all drawing commands use this */
|
|
|
{
|
|
|
- SDL_VertexSolid *verts = (SDL_VertexSolid *) (cmd->data.draw.first);
|
|
|
+ SDL_VertexSolid *verts = (SDL_VertexSolid *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
|
|
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *) &verts->position);
|
|
|
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE /* Normalized */, stride, (const GLvoid *) &verts->color);
|
|
|
}
|
|
@@ -969,7 +982,7 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
|
|
|
+SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices)
|
|
|
{
|
|
|
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
|
|
|
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
|
@@ -1079,7 +1092,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return SetDrawState(data, cmd, sourceType);
|
|
|
+ return SetDrawState(data, cmd, sourceType, vertices);
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -1087,8 +1100,11 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|
|
{
|
|
|
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
|
|
|
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
|
|
|
+
|
|
|
+#if USE_VERTEX_BUFFER_OBJECTS
|
|
|
const int vboidx = data->current_vertex_buffer;
|
|
|
const GLuint vbo = data->vertex_buffers[vboidx];
|
|
|
+#endif
|
|
|
|
|
|
if (GLES2_ActivateRenderer(renderer) < 0) {
|
|
|
return -1;
|
|
@@ -1106,6 +1122,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#if USE_VERTEX_BUFFER_OBJECTS
|
|
|
/* upload the new VBO data for this set of commands. */
|
|
|
data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
|
if (data->vertex_buffer_size[vboidx] < vertsize) {
|
|
@@ -1120,6 +1137,8 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|
|
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
|
|
|
data->current_vertex_buffer = 0;
|
|
|
}
|
|
|
+ vertices = NULL; /* attrib pointers will be offsets into the VBO. */
|
|
|
+#endif
|
|
|
|
|
|
while (cmd) {
|
|
|
switch (cmd->command) {
|
|
@@ -1184,7 +1203,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|
|
break;
|
|
|
|
|
|
case SDL_RENDERCMD_DRAW_LINES: {
|
|
|
- if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
|
|
|
+ if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID, vertices) == 0) {
|
|
|
size_t count = cmd->data.draw.count;
|
|
|
if (count > 2) {
|
|
|
/* joined lines cannot be grouped */
|
|
@@ -1242,9 +1261,9 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|
|
}
|
|
|
|
|
|
if (thistexture) {
|
|
|
- ret = SetCopyState(renderer, cmd);
|
|
|
+ ret = SetCopyState(renderer, cmd, vertices);
|
|
|
} else {
|
|
|
- ret = SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID);
|
|
|
+ ret = SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID, vertices);
|
|
|
}
|
|
|
|
|
|
if (ret == 0) {
|
|
@@ -1308,8 +1327,10 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
|
|
|
data->framebuffers = nextnode;
|
|
|
}
|
|
|
|
|
|
+#if USE_VERTEX_BUFFER_OBJECTS
|
|
|
data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
|
|
|
GL_CheckError("", renderer);
|
|
|
+#endif
|
|
|
|
|
|
SDL_GL_DeleteContext(data->context);
|
|
|
}
|
|
@@ -2071,8 +2092,10 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
|
|
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
|
|
|
renderer->info.max_texture_height = value;
|
|
|
|
|
|
+#if USE_VERTEX_BUFFER_OBJECTS
|
|
|
/* we keep a few of these and cycle through them, so data can live for a few frames. */
|
|
|
data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
|
|
|
+#endif
|
|
|
|
|
|
data->framebuffers = NULL;
|
|
|
data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
|