render: first shot at reworking opengl backend for new batching system. SDL-ryan-batching-renderer
authorRyan C. Gordon <icculus@icculus.org>
Thu, 20 Sep 2018 16:36:54 -0400
branchSDL-ryan-batching-renderer
changeset 12212e5a6ed2f98a3
parent 12211 0d8f33ad5fbb
child 12213 e4f5271ec8cc
render: first shot at reworking opengl backend for new batching system.
src/render/opengl/SDL_render_gl.c
src/render/opengl/SDL_shaders_gl.h
     1.1 --- a/src/render/opengl/SDL_render_gl.c	Thu Sep 20 15:46:02 2018 -0400
     1.2 +++ b/src/render/opengl/SDL_render_gl.c	Thu Sep 20 16:36:54 2018 -0400
     1.3 @@ -51,9 +51,8 @@
     1.4  
     1.5  static const float inv255f = 1.0f / 255.0f;
     1.6  
     1.7 +/* !!! FIXME: delete these predeclarations and just move the functions before their use. */
     1.8  static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
     1.9 -static void GL_WindowEvent(SDL_Renderer * renderer,
    1.10 -                           const SDL_WindowEvent *event);
    1.11  static int GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
    1.12  static SDL_bool GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
    1.13  static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.14 @@ -69,20 +68,17 @@
    1.15                            const SDL_Rect * rect, void **pixels, int *pitch);
    1.16  static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.17  static int GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
    1.18 -static int GL_UpdateViewport(SDL_Renderer * renderer);
    1.19 -static int GL_UpdateClipRect(SDL_Renderer * renderer);
    1.20 -static int GL_RenderClear(SDL_Renderer * renderer);
    1.21 -static int GL_RenderDrawPoints(SDL_Renderer * renderer,
    1.22 -                               const SDL_FPoint * points, int count);
    1.23 -static int GL_RenderDrawLines(SDL_Renderer * renderer,
    1.24 +static int GL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd,
    1.25                                const SDL_FPoint * points, int count);
    1.26 -static int GL_RenderFillRects(SDL_Renderer * renderer,
    1.27 -                              const SDL_FRect * rects, int count);
    1.28 -static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    1.29 -                         const SDL_Rect * srcrect, const SDL_FRect * dstrect);
    1.30 -static int GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    1.31 -                         const SDL_Rect * srcrect, const SDL_FRect * dstrect,
    1.32 -                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
    1.33 +static int GL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd,
    1.34 +                             const SDL_FRect * rects, int count);
    1.35 +static int GL_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
    1.36 +                        const SDL_Rect *srcrect, const SDL_FRect *dstrect);
    1.37 +static int GL_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
    1.38 +                          const SDL_Rect *srcquad, const SDL_FRect *dstrect,
    1.39 +                          const double angle, const SDL_FPoint *center,
    1.40 +                          const SDL_RendererFlip flip);
    1.41 +static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
    1.42  static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    1.43                                 Uint32 pixel_format, void * pixels, int pitch);
    1.44  static void GL_RenderPresent(SDL_Renderer * renderer);
    1.45 @@ -122,14 +118,10 @@
    1.46      GLDEBUGPROCARB next_error_callback;
    1.47      GLvoid *next_error_userparam;
    1.48  
    1.49 +    GLenum textype;
    1.50 +
    1.51      SDL_bool GL_ARB_texture_non_power_of_two_supported;
    1.52      SDL_bool GL_ARB_texture_rectangle_supported;
    1.53 -    struct {
    1.54 -        GL_Shader shader;
    1.55 -        Uint32 color;
    1.56 -        SDL_BlendMode blendMode;
    1.57 -    } current;
    1.58 -
    1.59      SDL_bool GL_EXT_framebuffer_object_supported;
    1.60      GL_FBOList *framebuffers;
    1.61  
    1.62 @@ -157,7 +149,6 @@
    1.63  typedef struct
    1.64  {
    1.65      GLuint texture;
    1.66 -    GLenum type;
    1.67      GLfloat texw;
    1.68      GLfloat texh;
    1.69      GLenum format;
    1.70 @@ -284,21 +275,15 @@
    1.71      return 0;
    1.72  }
    1.73  
    1.74 -static SDL_GLContext SDL_CurrentContext = NULL;
    1.75 -
    1.76  static int
    1.77  GL_ActivateRenderer(SDL_Renderer * renderer)
    1.78  {
    1.79      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    1.80  
    1.81 -    if (SDL_CurrentContext != data->context ||
    1.82 -        SDL_GL_GetCurrentContext() != data->context) {
    1.83 +    if (SDL_GL_GetCurrentContext() != data->context) {
    1.84          if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
    1.85              return -1;
    1.86          }
    1.87 -        SDL_CurrentContext = data->context;
    1.88 -
    1.89 -        GL_UpdateViewport(renderer);
    1.90      }
    1.91  
    1.92      GL_ClearErrors(renderer);
    1.93 @@ -306,33 +291,6 @@
    1.94      return 0;
    1.95  }
    1.96  
    1.97 -/* This is called if we need to invalidate all of the SDL OpenGL state */
    1.98 -static void
    1.99 -GL_ResetState(SDL_Renderer *renderer)
   1.100 -{
   1.101 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.102 -
   1.103 -    if (SDL_GL_GetCurrentContext() == data->context) {
   1.104 -        GL_UpdateViewport(renderer);
   1.105 -    } else {
   1.106 -        GL_ActivateRenderer(renderer);
   1.107 -    }
   1.108 -
   1.109 -    data->current.shader = SHADER_NONE;
   1.110 -    data->current.color = 0xffffffff;
   1.111 -    data->current.blendMode = SDL_BLENDMODE_INVALID;
   1.112 -
   1.113 -    data->glDisable(GL_DEPTH_TEST);
   1.114 -    data->glDisable(GL_CULL_FACE);
   1.115 -    /* This ended up causing video discrepancies between OpenGL and Direct3D */
   1.116 -    /* data->glEnable(GL_LINE_SMOOTH); */
   1.117 -
   1.118 -    data->glMatrixMode(GL_MODELVIEW);
   1.119 -    data->glLoadIdentity();
   1.120 -
   1.121 -    GL_CheckError("", renderer);
   1.122 -}
   1.123 -
   1.124  static void APIENTRY
   1.125  GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
   1.126  {
   1.127 @@ -425,7 +383,6 @@
   1.128          goto error;
   1.129      }
   1.130  
   1.131 -    renderer->WindowEvent = GL_WindowEvent;
   1.132      renderer->GetOutputSize = GL_GetOutputSize;
   1.133      renderer->SupportsBlendMode = GL_SupportsBlendMode;
   1.134      renderer->CreateTexture = GL_CreateTexture;
   1.135 @@ -434,14 +391,12 @@
   1.136      renderer->LockTexture = GL_LockTexture;
   1.137      renderer->UnlockTexture = GL_UnlockTexture;
   1.138      renderer->SetRenderTarget = GL_SetRenderTarget;
   1.139 -    renderer->UpdateViewport = GL_UpdateViewport;
   1.140 -    renderer->UpdateClipRect = GL_UpdateClipRect;
   1.141 -    renderer->RenderClear = GL_RenderClear;
   1.142 -    renderer->RenderDrawPoints = GL_RenderDrawPoints;
   1.143 -    renderer->RenderDrawLines = GL_RenderDrawLines;
   1.144 -    renderer->RenderFillRects = GL_RenderFillRects;
   1.145 -    renderer->RenderCopy = GL_RenderCopy;
   1.146 -    renderer->RenderCopyEx = GL_RenderCopyEx;
   1.147 +    renderer->QueueDrawPoints = GL_QueueDrawPoints;
   1.148 +    renderer->QueueDrawLines = GL_QueueDrawPoints;  /* lines and points queue vertices the same way. */
   1.149 +    renderer->QueueFillRects = GL_QueueFillRects;
   1.150 +    renderer->QueueCopy = GL_QueueCopy;
   1.151 +    renderer->QueueCopyEx = GL_QueueCopyEx;
   1.152 +    renderer->RunCommandQueue = GL_RunCommandQueue;
   1.153      renderer->RenderReadPixels = GL_RenderReadPixels;
   1.154      renderer->RenderPresent = GL_RenderPresent;
   1.155      renderer->DestroyTexture = GL_DestroyTexture;
   1.156 @@ -501,11 +456,13 @@
   1.157          data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
   1.158      }
   1.159  
   1.160 +    data->textype = GL_TEXTURE_2D;
   1.161      if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
   1.162          data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE;
   1.163      } else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
   1.164                 SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
   1.165          data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
   1.166 +        data->textype = GL_TEXTURE_RECTANGLE_ARB;
   1.167      }
   1.168      if (data->GL_ARB_texture_rectangle_supported) {
   1.169          data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
   1.170 @@ -562,7 +519,10 @@
   1.171      data->framebuffers = NULL;
   1.172  
   1.173      /* Set up parameters for rendering */
   1.174 -    GL_ResetState(renderer);
   1.175 +    data->glDisable(GL_DEPTH_TEST);
   1.176 +    data->glDisable(GL_CULL_FACE);
   1.177 +    /* This ended up causing video discrepancies between OpenGL and Direct3D */
   1.178 +    /* data->glEnable(GL_LINE_SMOOTH); */
   1.179  
   1.180      return renderer;
   1.181  
   1.182 @@ -577,17 +537,6 @@
   1.183      return NULL;
   1.184  }
   1.185  
   1.186 -static void
   1.187 -GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   1.188 -{
   1.189 -    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
   1.190 -        event->event == SDL_WINDOWEVENT_SHOWN ||
   1.191 -        event->event == SDL_WINDOWEVENT_HIDDEN) {
   1.192 -        /* Rebind the context to the window area and update matrices */
   1.193 -        SDL_CurrentContext = NULL;
   1.194 -    }
   1.195 -}
   1.196 -
   1.197  static int
   1.198  GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
   1.199  {
   1.200 @@ -707,6 +656,7 @@
   1.201  GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.202  {
   1.203      GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   1.204 +    const GLenum textype = renderdata->textype;
   1.205      GL_TextureData *data;
   1.206      GLint internalFormat;
   1.207      GLenum format, type;
   1.208 @@ -770,19 +720,16 @@
   1.209      texture->driverdata = data;
   1.210  
   1.211      if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
   1.212 -        data->type = GL_TEXTURE_2D;
   1.213          texture_w = texture->w;
   1.214          texture_h = texture->h;
   1.215          data->texw = 1.0f;
   1.216          data->texh = 1.0f;
   1.217      } else if (renderdata->GL_ARB_texture_rectangle_supported) {
   1.218 -        data->type = GL_TEXTURE_RECTANGLE_ARB;
   1.219          texture_w = texture->w;
   1.220          texture_h = texture->h;
   1.221          data->texw = (GLfloat) texture_w;
   1.222          data->texh = (GLfloat) texture_h;
   1.223      } else {
   1.224 -        data->type = GL_TEXTURE_2D;
   1.225          texture_w = power_of_2(texture->w);
   1.226          texture_h = power_of_2(texture->h);
   1.227          data->texw = (GLfloat) (texture->w) / texture_w;
   1.228 @@ -792,17 +739,17 @@
   1.229      data->format = format;
   1.230      data->formattype = type;
   1.231      scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
   1.232 -    renderdata->glEnable(data->type);
   1.233 -    renderdata->glBindTexture(data->type, data->texture);
   1.234 -    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
   1.235 -    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
   1.236 +    renderdata->glEnable(textype);
   1.237 +    renderdata->glBindTexture(textype, data->texture);
   1.238 +    renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
   1.239 +    renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
   1.240      /* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE
   1.241         and setting it causes an INVALID_ENUM error in the latest NVidia drivers.
   1.242      */
   1.243 -    if (data->type != GL_TEXTURE_RECTANGLE_ARB) {
   1.244 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   1.245 +    if (textype != GL_TEXTURE_RECTANGLE_ARB) {
   1.246 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
   1.247                                      GL_CLAMP_TO_EDGE);
   1.248 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   1.249 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
   1.250                                      GL_CLAMP_TO_EDGE);
   1.251      }
   1.252  #ifdef __MACOSX__
   1.253 @@ -816,10 +763,10 @@
   1.254  #define STORAGE_SHARED_APPLE                0x85BF
   1.255  #endif
   1.256      if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   1.257 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
   1.258 +        renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
   1.259                                      GL_STORAGE_SHARED_APPLE);
   1.260      } else {
   1.261 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
   1.262 +        renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
   1.263                                      GL_STORAGE_CACHED_APPLE);
   1.264      }
   1.265      if (texture->access == SDL_TEXTUREACCESS_STREAMING
   1.266 @@ -829,17 +776,17 @@
   1.267          renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   1.268          renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
   1.269                            (data->pitch / SDL_BYTESPERPIXEL(texture->format)));
   1.270 -        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   1.271 +        renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
   1.272                                   texture_h, 0, format, type, data->pixels);
   1.273          renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
   1.274      }
   1.275      else
   1.276  #endif
   1.277      {
   1.278 -        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   1.279 +        renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
   1.280                                   texture_h, 0, format, type, NULL);
   1.281      }
   1.282 -    renderdata->glDisable(data->type);
   1.283 +    renderdata->glDisable(textype);
   1.284      if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   1.285          return -1;
   1.286      }
   1.287 @@ -850,33 +797,33 @@
   1.288  
   1.289          renderdata->glGenTextures(1, &data->utexture);
   1.290          renderdata->glGenTextures(1, &data->vtexture);
   1.291 -        renderdata->glEnable(data->type);
   1.292 +        renderdata->glEnable(textype);
   1.293  
   1.294 -        renderdata->glBindTexture(data->type, data->utexture);
   1.295 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   1.296 +        renderdata->glBindTexture(textype, data->utexture);
   1.297 +        renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
   1.298                                      scaleMode);
   1.299 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   1.300 +        renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
   1.301                                      scaleMode);
   1.302 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   1.303 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
   1.304                                      GL_CLAMP_TO_EDGE);
   1.305 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   1.306 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
   1.307                                      GL_CLAMP_TO_EDGE);
   1.308 -        renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
   1.309 +        renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w+1)/2,
   1.310                                   (texture_h+1)/2, 0, format, type, NULL);
   1.311  
   1.312 -        renderdata->glBindTexture(data->type, data->vtexture);
   1.313 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   1.314 +        renderdata->glBindTexture(textype, data->vtexture);
   1.315 +        renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
   1.316                                      scaleMode);
   1.317 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   1.318 +        renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
   1.319                                      scaleMode);
   1.320 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   1.321 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
   1.322                                      GL_CLAMP_TO_EDGE);
   1.323 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   1.324 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
   1.325                                      GL_CLAMP_TO_EDGE);
   1.326 -        renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
   1.327 +        renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w+1)/2,
   1.328                                   (texture_h+1)/2, 0, format, type, NULL);
   1.329  
   1.330 -        renderdata->glDisable(data->type);
   1.331 +        renderdata->glDisable(textype);
   1.332      }
   1.333  
   1.334      if (texture->format == SDL_PIXELFORMAT_NV12 ||
   1.335 @@ -884,20 +831,20 @@
   1.336          data->nv12 = SDL_TRUE;
   1.337  
   1.338          renderdata->glGenTextures(1, &data->utexture);
   1.339 -        renderdata->glEnable(data->type);
   1.340 +        renderdata->glEnable(textype);
   1.341  
   1.342 -        renderdata->glBindTexture(data->type, data->utexture);
   1.343 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   1.344 +        renderdata->glBindTexture(textype, data->utexture);
   1.345 +        renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
   1.346                                      scaleMode);
   1.347 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   1.348 +        renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
   1.349                                      scaleMode);
   1.350 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   1.351 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
   1.352                                      GL_CLAMP_TO_EDGE);
   1.353 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   1.354 +        renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
   1.355                                      GL_CLAMP_TO_EDGE);
   1.356 -        renderdata->glTexImage2D(data->type, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
   1.357 +        renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
   1.358                                   (texture_h+1)/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
   1.359 -        renderdata->glDisable(data->type);
   1.360 +        renderdata->glDisable(textype);
   1.361      }
   1.362  
   1.363      return GL_CheckError("", renderer);
   1.364 @@ -908,6 +855,7 @@
   1.365                   const SDL_Rect * rect, const void *pixels, int pitch)
   1.366  {
   1.367      GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   1.368 +    const GLenum textype = renderdata->textype;
   1.369      GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   1.370      const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
   1.371  
   1.372 @@ -915,11 +863,11 @@
   1.373  
   1.374      GL_ActivateRenderer(renderer);
   1.375  
   1.376 -    renderdata->glEnable(data->type);
   1.377 -    renderdata->glBindTexture(data->type, data->texture);
   1.378 +    renderdata->glEnable(textype);
   1.379 +    renderdata->glBindTexture(textype, data->texture);
   1.380      renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   1.381      renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp));
   1.382 -    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
   1.383 +    renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
   1.384                                  rect->h, data->format, data->formattype,
   1.385                                  pixels);
   1.386      if (data->yuv) {
   1.387 @@ -928,22 +876,22 @@
   1.388          /* Skip to the correct offset into the next texture */
   1.389          pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
   1.390          if (texture->format == SDL_PIXELFORMAT_YV12) {
   1.391 -            renderdata->glBindTexture(data->type, data->vtexture);
   1.392 +            renderdata->glBindTexture(textype, data->vtexture);
   1.393          } else {
   1.394 -            renderdata->glBindTexture(data->type, data->utexture);
   1.395 +            renderdata->glBindTexture(textype, data->utexture);
   1.396          }
   1.397 -        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.398 +        renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
   1.399                                      (rect->w+1)/2, (rect->h+1)/2,
   1.400                                      data->format, data->formattype, pixels);
   1.401  
   1.402          /* Skip to the correct offset into the next texture */
   1.403          pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
   1.404          if (texture->format == SDL_PIXELFORMAT_YV12) {
   1.405 -            renderdata->glBindTexture(data->type, data->utexture);
   1.406 +            renderdata->glBindTexture(textype, data->utexture);
   1.407          } else {
   1.408 -            renderdata->glBindTexture(data->type, data->vtexture);
   1.409 +            renderdata->glBindTexture(textype, data->vtexture);
   1.410          }
   1.411 -        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.412 +        renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
   1.413                                      (rect->w+1)/2, (rect->h+1)/2,
   1.414                                      data->format, data->formattype, pixels);
   1.415      }
   1.416 @@ -953,12 +901,12 @@
   1.417  
   1.418          /* Skip to the correct offset into the next texture */
   1.419          pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
   1.420 -        renderdata->glBindTexture(data->type, data->utexture);
   1.421 -        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.422 +        renderdata->glBindTexture(textype, data->utexture);
   1.423 +        renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
   1.424                                      (rect->w + 1)/2, (rect->h + 1)/2,
   1.425                                      GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
   1.426      }
   1.427 -    renderdata->glDisable(data->type);
   1.428 +    renderdata->glDisable(textype);
   1.429  
   1.430      return GL_CheckError("glTexSubImage2D()", renderer);
   1.431  }
   1.432 @@ -971,30 +919,31 @@
   1.433                      const Uint8 *Vplane, int Vpitch)
   1.434  {
   1.435      GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   1.436 +    const GLenum textype = renderdata->textype;
   1.437      GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   1.438  
   1.439      GL_ActivateRenderer(renderer);
   1.440  
   1.441 -    renderdata->glEnable(data->type);
   1.442 -    renderdata->glBindTexture(data->type, data->texture);
   1.443 +    renderdata->glEnable(textype);
   1.444 +    renderdata->glBindTexture(textype, data->texture);
   1.445      renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   1.446      renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch);
   1.447 -    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
   1.448 +    renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
   1.449                                  rect->h, data->format, data->formattype,
   1.450                                  Yplane);
   1.451  
   1.452      renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
   1.453 -    renderdata->glBindTexture(data->type, data->utexture);
   1.454 -    renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.455 +    renderdata->glBindTexture(textype, data->utexture);
   1.456 +    renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
   1.457                                  (rect->w + 1)/2, (rect->h + 1)/2,
   1.458                                  data->format, data->formattype, Uplane);
   1.459  
   1.460      renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
   1.461 -    renderdata->glBindTexture(data->type, data->vtexture);
   1.462 -    renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.463 +    renderdata->glBindTexture(textype, data->vtexture);
   1.464 +    renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
   1.465                                  (rect->w + 1)/2, (rect->h + 1)/2,
   1.466                                  data->format, data->formattype, Vplane);
   1.467 -    renderdata->glDisable(data->type);
   1.468 +    renderdata->glDisable(textype);
   1.469  
   1.470      return GL_CheckError("glTexSubImage2D()", renderer);
   1.471  }
   1.472 @@ -1048,7 +997,7 @@
   1.473      texturedata = (GL_TextureData *) texture->driverdata;
   1.474      data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO);
   1.475      /* TODO: check if texture pixel format allows this operation */
   1.476 -    data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texturedata->type, texturedata->texture, 0);
   1.477 +    data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, data->textype, texturedata->texture, 0);
   1.478      /* Check FBO status */
   1.479      status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
   1.480      if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
   1.481 @@ -1057,337 +1006,65 @@
   1.482      return 0;
   1.483  }
   1.484  
   1.485 +/* !!! FIXME: all these Queue* calls set up the vertex buffer the way the immediate mode
   1.486 +   !!! FIXME:  renderer wants it, but this might want to operate differently if we move to
   1.487 +   !!! FIXME:  VBOs at some point. */
   1.488  static int
   1.489 -GL_UpdateViewport(SDL_Renderer * renderer)
   1.490 +GL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
   1.491  {
   1.492 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.493 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), &cmd->data.draw.first);
   1.494 +    size_t i;
   1.495  
   1.496 -    if (SDL_CurrentContext != data->context) {
   1.497 -        /* We'll update the viewport after we rebind the context */
   1.498 -        return 0;
   1.499 +    if (!verts) {
   1.500 +        return -1;
   1.501      }
   1.502  
   1.503 -    if (renderer->target) {
   1.504 -        data->glViewport(renderer->viewport.x, renderer->viewport.y,
   1.505 -                         renderer->viewport.w, renderer->viewport.h);
   1.506 -    } else {
   1.507 -        int w, h;
   1.508 -
   1.509 -        SDL_GL_GetDrawableSize(renderer->window, &w, &h);
   1.510 -        data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
   1.511 -                         renderer->viewport.w, renderer->viewport.h);
   1.512 -    }
   1.513 -
   1.514 -    data->glMatrixMode(GL_PROJECTION);
   1.515 -    data->glLoadIdentity();
   1.516 -    if (renderer->viewport.w && renderer->viewport.h) {
   1.517 -        if (renderer->target) {
   1.518 -            data->glOrtho((GLdouble) 0,
   1.519 -                          (GLdouble) renderer->viewport.w,
   1.520 -                          (GLdouble) 0,
   1.521 -                          (GLdouble) renderer->viewport.h,
   1.522 -                           0.0, 1.0);
   1.523 -        } else {
   1.524 -            data->glOrtho((GLdouble) 0,
   1.525 -                          (GLdouble) renderer->viewport.w,
   1.526 -                          (GLdouble) renderer->viewport.h,
   1.527 -                          (GLdouble) 0,
   1.528 -                           0.0, 1.0);
   1.529 -        }
   1.530 -    }
   1.531 -    data->glMatrixMode(GL_MODELVIEW);
   1.532 -
   1.533 -    return GL_CheckError("", renderer);
   1.534 -}
   1.535 -
   1.536 -static int
   1.537 -GL_UpdateClipRect(SDL_Renderer * renderer)
   1.538 -{
   1.539 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.540 -
   1.541 -    if (renderer->clipping_enabled) {
   1.542 -        const SDL_Rect *rect = &renderer->clip_rect;
   1.543 -        data->glEnable(GL_SCISSOR_TEST);
   1.544 -        if (renderer->target) {
   1.545 -            data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
   1.546 -        } else {
   1.547 -            int w, h;
   1.548 -
   1.549 -            SDL_GL_GetDrawableSize(renderer->window, &w, &h);
   1.550 -            data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
   1.551 -        }
   1.552 -    } else {
   1.553 -        data->glDisable(GL_SCISSOR_TEST);
   1.554 -    }
   1.555 -    return 0;
   1.556 -}
   1.557 -
   1.558 -static void
   1.559 -GL_SetShader(GL_RenderData * data, GL_Shader shader)
   1.560 -{
   1.561 -    if (data->shaders && shader != data->current.shader) {
   1.562 -        GL_SelectShader(data->shaders, shader);
   1.563 -        data->current.shader = shader;
   1.564 -    }
   1.565 -}
   1.566 -
   1.567 -static void
   1.568 -GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   1.569 -{
   1.570 -    Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
   1.571 -
   1.572 -    if (color != data->current.color) {
   1.573 -        data->glColor4f((GLfloat) r * inv255f,
   1.574 -                        (GLfloat) g * inv255f,
   1.575 -                        (GLfloat) b * inv255f,
   1.576 -                        (GLfloat) a * inv255f);
   1.577 -        data->current.color = color;
   1.578 -    }
   1.579 -}
   1.580 -
   1.581 -static void
   1.582 -GL_SetBlendMode(GL_RenderData * data, SDL_BlendMode blendMode)
   1.583 -{
   1.584 -    if (blendMode != data->current.blendMode) {
   1.585 -        if (blendMode == SDL_BLENDMODE_NONE) {
   1.586 -            data->glDisable(GL_BLEND);
   1.587 -        } else {
   1.588 -            data->glEnable(GL_BLEND);
   1.589 -            data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
   1.590 -                                      GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
   1.591 -                                      GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
   1.592 -                                      GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
   1.593 -            data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
   1.594 -        }
   1.595 -        data->current.blendMode = blendMode;
   1.596 -    }
   1.597 -}
   1.598 -
   1.599 -static void
   1.600 -GL_SetDrawingState(SDL_Renderer * renderer)
   1.601 -{
   1.602 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.603 -
   1.604 -    GL_ActivateRenderer(renderer);
   1.605 -
   1.606 -    GL_SetColor(data, renderer->r,
   1.607 -                      renderer->g,
   1.608 -                      renderer->b,
   1.609 -                      renderer->a);
   1.610 -
   1.611 -    GL_SetBlendMode(data, renderer->blendMode);
   1.612 -
   1.613 -    GL_SetShader(data, SHADER_SOLID);
   1.614 -}
   1.615 -
   1.616 -static int
   1.617 -GL_RenderClear(SDL_Renderer * renderer)
   1.618 -{
   1.619 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.620 -
   1.621 -    GL_ActivateRenderer(renderer);
   1.622 -
   1.623 -    data->glClearColor((GLfloat) renderer->r * inv255f,
   1.624 -                       (GLfloat) renderer->g * inv255f,
   1.625 -                       (GLfloat) renderer->b * inv255f,
   1.626 -                       (GLfloat) renderer->a * inv255f);
   1.627 -
   1.628 -    if (renderer->clipping_enabled) {
   1.629 -        data->glDisable(GL_SCISSOR_TEST);
   1.630 -    }
   1.631 -
   1.632 -    data->glClear(GL_COLOR_BUFFER_BIT);
   1.633 -
   1.634 -    if (renderer->clipping_enabled) {
   1.635 -        data->glEnable(GL_SCISSOR_TEST);
   1.636 +    cmd->data.draw.count = count;
   1.637 +    for (i = 0; i < count; i++) {
   1.638 +        *(verts++) = 0.5f + points[i].x;
   1.639 +        *(verts++) = 0.5f + points[i].y;
   1.640      }
   1.641  
   1.642      return 0;
   1.643  }
   1.644  
   1.645  static int
   1.646 -GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
   1.647 -                    int count)
   1.648 +GL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
   1.649  {
   1.650 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.651 -    int i;
   1.652 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (GLfloat), &cmd->data.draw.first);
   1.653 +    size_t i;
   1.654  
   1.655 -    GL_SetDrawingState(renderer);
   1.656 +    if (!verts) {
   1.657 +        return -1;
   1.658 +    }
   1.659  
   1.660 -    data->glBegin(GL_POINTS);
   1.661 -    for (i = 0; i < count; ++i) {
   1.662 -        data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
   1.663 +    cmd->data.draw.count = count;
   1.664 +    for (i = 0; i < count; i++) {
   1.665 +        const SDL_FRect *rect = &rects[i];
   1.666 +        *(verts++) = rect->x;
   1.667 +        *(verts++) = rect->y;
   1.668 +        *(verts++) = rect->x + rect->w;
   1.669 +        *(verts++) = rect->y + rect->h;
   1.670      }
   1.671 -    data->glEnd();
   1.672  
   1.673      return 0;
   1.674  }
   1.675  
   1.676  static int
   1.677 -GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
   1.678 -                   int count)
   1.679 +GL_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   1.680 +             const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1.681  {
   1.682 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.683 -    int i;
   1.684 -
   1.685 -    GL_SetDrawingState(renderer);
   1.686 -
   1.687 -    if (count > 2 &&
   1.688 -        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
   1.689 -        data->glBegin(GL_LINE_LOOP);
   1.690 -        /* GL_LINE_LOOP takes care of the final segment */
   1.691 -        --count;
   1.692 -        for (i = 0; i < count; ++i) {
   1.693 -            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
   1.694 -        }
   1.695 -        data->glEnd();
   1.696 -    } else {
   1.697 -#if defined(__MACOSX__) || defined(__WIN32__)
   1.698 -#else
   1.699 -        int x1, y1, x2, y2;
   1.700 -#endif
   1.701 -
   1.702 -        data->glBegin(GL_LINE_STRIP);
   1.703 -        for (i = 0; i < count; ++i) {
   1.704 -            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
   1.705 -        }
   1.706 -        data->glEnd();
   1.707 -
   1.708 -        /* The line is half open, so we need one more point to complete it.
   1.709 -         * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
   1.710 -         * If we have to, we can use vertical line and horizontal line textures
   1.711 -         * for vertical and horizontal lines, and then create custom textures
   1.712 -         * for diagonal lines and software render those.  It's terrible, but at
   1.713 -         * least it would be pixel perfect.
   1.714 -         */
   1.715 -        data->glBegin(GL_POINTS);
   1.716 -#if defined(__MACOSX__) || defined(__WIN32__)
   1.717 -        /* Mac OS X and Windows seem to always leave the last point open */
   1.718 -        data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
   1.719 -#else
   1.720 -        /* Linux seems to leave the right-most or bottom-most point open */
   1.721 -        x1 = points[0].x;
   1.722 -        y1 = points[0].y;
   1.723 -        x2 = points[count-1].x;
   1.724 -        y2 = points[count-1].y;
   1.725 -
   1.726 -        if (x1 > x2) {
   1.727 -            data->glVertex2f(0.5f + x1, 0.5f + y1);
   1.728 -        } else if (x2 > x1) {
   1.729 -            data->glVertex2f(0.5f + x2, 0.5f + y2);
   1.730 -        }
   1.731 -        if (y1 > y2) {
   1.732 -            data->glVertex2f(0.5f + x1, 0.5f + y1);
   1.733 -        } else if (y2 > y1) {
   1.734 -            data->glVertex2f(0.5f + x2, 0.5f + y2);
   1.735 -        }
   1.736 -#endif
   1.737 -        data->glEnd();
   1.738 -    }
   1.739 -    return GL_CheckError("", renderer);
   1.740 -}
   1.741 -
   1.742 -static int
   1.743 -GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
   1.744 -{
   1.745 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.746 -    int i;
   1.747 -
   1.748 -    GL_SetDrawingState(renderer);
   1.749 -
   1.750 -    for (i = 0; i < count; ++i) {
   1.751 -        const SDL_FRect *rect = &rects[i];
   1.752 -
   1.753 -        data->glRectf(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
   1.754 -    }
   1.755 -    return GL_CheckError("", renderer);
   1.756 -}
   1.757 -
   1.758 -static int
   1.759 -GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture)
   1.760 -{
   1.761 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.762 -    GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   1.763 -
   1.764 -    data->glEnable(texturedata->type);
   1.765 -    if (texturedata->yuv) {
   1.766 -        data->glActiveTextureARB(GL_TEXTURE2_ARB);
   1.767 -        data->glBindTexture(texturedata->type, texturedata->vtexture);
   1.768 -
   1.769 -        data->glActiveTextureARB(GL_TEXTURE1_ARB);
   1.770 -        data->glBindTexture(texturedata->type, texturedata->utexture);
   1.771 -
   1.772 -        data->glActiveTextureARB(GL_TEXTURE0_ARB);
   1.773 -    }
   1.774 -    if (texturedata->nv12) {
   1.775 -        data->glActiveTextureARB(GL_TEXTURE1_ARB);
   1.776 -        data->glBindTexture(texturedata->type, texturedata->utexture);
   1.777 -
   1.778 -        data->glActiveTextureARB(GL_TEXTURE0_ARB);
   1.779 -    }
   1.780 -    data->glBindTexture(texturedata->type, texturedata->texture);
   1.781 -
   1.782 -    if (texture->modMode) {
   1.783 -        GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
   1.784 -    } else {
   1.785 -        GL_SetColor(data, 255, 255, 255, 255);
   1.786 -    }
   1.787 -
   1.788 -    GL_SetBlendMode(data, texture->blendMode);
   1.789 -
   1.790 -    if (texturedata->yuv || texturedata->nv12) {
   1.791 -        switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
   1.792 -        case SDL_YUV_CONVERSION_JPEG:
   1.793 -            if (texturedata->yuv) {
   1.794 -                GL_SetShader(data, SHADER_YUV_JPEG);
   1.795 -            } else if (texture->format == SDL_PIXELFORMAT_NV12) {
   1.796 -                GL_SetShader(data, SHADER_NV12_JPEG);
   1.797 -            } else {
   1.798 -                GL_SetShader(data, SHADER_NV21_JPEG);
   1.799 -            }
   1.800 -            break;
   1.801 -        case SDL_YUV_CONVERSION_BT601:
   1.802 -            if (texturedata->yuv) {
   1.803 -                GL_SetShader(data, SHADER_YUV_BT601);
   1.804 -            } else if (texture->format == SDL_PIXELFORMAT_NV12) {
   1.805 -                GL_SetShader(data, SHADER_NV12_BT601);
   1.806 -            } else {
   1.807 -                GL_SetShader(data, SHADER_NV21_BT601);
   1.808 -            }
   1.809 -            break;
   1.810 -        case SDL_YUV_CONVERSION_BT709:
   1.811 -            if (texturedata->yuv) {
   1.812 -                GL_SetShader(data, SHADER_YUV_BT709);
   1.813 -            } else if (texture->format == SDL_PIXELFORMAT_NV12) {
   1.814 -                GL_SetShader(data, SHADER_NV12_BT709);
   1.815 -            } else {
   1.816 -                GL_SetShader(data, SHADER_NV21_BT709);
   1.817 -            }
   1.818 -            break;
   1.819 -        default:
   1.820 -            return SDL_SetError("Unsupported YUV conversion mode");
   1.821 -        }
   1.822 -    } else {
   1.823 -        GL_SetShader(data, SHADER_RGB);
   1.824 -    }
   1.825 -    return 0;
   1.826 -}
   1.827 -
   1.828 -static int
   1.829 -GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   1.830 -              const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1.831 -{
   1.832 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.833      GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   1.834      GLfloat minx, miny, maxx, maxy;
   1.835      GLfloat minu, maxu, minv, maxv;
   1.836 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 8 * sizeof (GLfloat), &cmd->data.draw.first);
   1.837  
   1.838 -    GL_ActivateRenderer(renderer);
   1.839 -
   1.840 -    if (GL_SetupCopy(renderer, texture) < 0) {
   1.841 +    if (!verts) {
   1.842          return -1;
   1.843      }
   1.844  
   1.845 +    cmd->data.draw.count = 1;
   1.846 +
   1.847      minx = dstrect->x;
   1.848      miny = dstrect->y;
   1.849      maxx = dstrect->x + dstrect->w;
   1.850 @@ -1402,36 +1079,30 @@
   1.851      maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   1.852      maxv *= texturedata->texh;
   1.853  
   1.854 -    data->glBegin(GL_TRIANGLE_STRIP);
   1.855 -    data->glTexCoord2f(minu, minv);
   1.856 -    data->glVertex2f(minx, miny);
   1.857 -    data->glTexCoord2f(maxu, minv);
   1.858 -    data->glVertex2f(maxx, miny);
   1.859 -    data->glTexCoord2f(minu, maxv);
   1.860 -    data->glVertex2f(minx, maxy);
   1.861 -    data->glTexCoord2f(maxu, maxv);
   1.862 -    data->glVertex2f(maxx, maxy);
   1.863 -    data->glEnd();
   1.864 -
   1.865 -    data->glDisable(texturedata->type);
   1.866 -
   1.867 -    return GL_CheckError("", renderer);
   1.868 +    cmd->data.draw.count = 1;
   1.869 +    *(verts++) = minx;
   1.870 +    *(verts++) = miny;
   1.871 +    *(verts++) = maxx;
   1.872 +    *(verts++) = maxy;
   1.873 +    *(verts++) = minu;
   1.874 +    *(verts++) = maxu;
   1.875 +    *(verts++) = minv;
   1.876 +    *(verts++) = maxv;
   1.877 +    return 0;
   1.878  }
   1.879  
   1.880  static int
   1.881 -GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   1.882 -              const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   1.883 -              const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   1.884 +GL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   1.885 +               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   1.886 +               const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   1.887  {
   1.888 -    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.889      GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   1.890      GLfloat minx, miny, maxx, maxy;
   1.891      GLfloat centerx, centery;
   1.892      GLfloat minu, maxu, minv, maxv;
   1.893 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 11 * sizeof (GLfloat), &cmd->data.draw.first);
   1.894  
   1.895 -    GL_ActivateRenderer(renderer);
   1.896 -
   1.897 -    if (GL_SetupCopy(renderer, texture) < 0) {
   1.898 +    if (!verts) {
   1.899          return -1;
   1.900      }
   1.901  
   1.902 @@ -1465,24 +1136,415 @@
   1.903      maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   1.904      maxv *= texturedata->texh;
   1.905  
   1.906 -    /* Translate to flip, rotate, translate to position */
   1.907 -    data->glPushMatrix();
   1.908 -    data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);
   1.909 -    data->glRotated(angle, (GLdouble)0.0, (GLdouble)0.0, (GLdouble)1.0);
   1.910 +    cmd->data.draw.count = 1;
   1.911 +    *(verts++) = minx;
   1.912 +    *(verts++) = miny;
   1.913 +    *(verts++) = maxx;
   1.914 +    *(verts++) = maxy;
   1.915 +    *(verts++) = minu;
   1.916 +    *(verts++) = maxu;
   1.917 +    *(verts++) = minv;
   1.918 +    *(verts++) = maxv;
   1.919 +    *(verts++) = (GLfloat) dstrect->x + centerx;
   1.920 +    *(verts++) = (GLfloat) dstrect->y + centery;
   1.921 +    *(verts++) = (GLfloat) angle;
   1.922 +    return 0;
   1.923 +}
   1.924  
   1.925 -    data->glBegin(GL_TRIANGLE_STRIP);
   1.926 -    data->glTexCoord2f(minu, minv);
   1.927 -    data->glVertex2f(minx, miny);
   1.928 -    data->glTexCoord2f(maxu, minv);
   1.929 -    data->glVertex2f(maxx, miny);
   1.930 -    data->glTexCoord2f(minu, maxv);
   1.931 -    data->glVertex2f(minx, maxy);
   1.932 -    data->glTexCoord2f(maxu, maxv);
   1.933 -    data->glVertex2f(maxx, maxy);
   1.934 -    data->glEnd();
   1.935 -    data->glPopMatrix();
   1.936 +static void
   1.937 +SetDrawState(const GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader,
   1.938 +             Uint32 *current_color, SDL_BlendMode *current_blend, GL_Shader *current_shader,
   1.939 +             SDL_bool *current_texturing)
   1.940 +{
   1.941 +    const Uint8 r = cmd->data.draw.r;
   1.942 +    const Uint8 g = cmd->data.draw.g;
   1.943 +    const Uint8 b = cmd->data.draw.b;
   1.944 +    const Uint8 a = cmd->data.draw.a;
   1.945 +    const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
   1.946 +    const SDL_BlendMode blend = cmd->data.draw.blend;
   1.947  
   1.948 -    data->glDisable(texturedata->type);
   1.949 +    if (color != *current_color) {
   1.950 +        data->glColor4f((GLfloat) r * inv255f, (GLfloat) g * inv255f,
   1.951 +                        (GLfloat) b * inv255f, (GLfloat) a * inv255f);
   1.952 +        *current_color = color;
   1.953 +    }
   1.954 +
   1.955 +    if (blend != *current_blend) {
   1.956 +        if (blend == SDL_BLENDMODE_NONE) {
   1.957 +            data->glDisable(GL_BLEND);
   1.958 +        } else {
   1.959 +            data->glEnable(GL_BLEND);
   1.960 +            data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
   1.961 +                                      GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
   1.962 +                                      GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
   1.963 +                                      GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
   1.964 +            data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
   1.965 +        }
   1.966 +        *current_blend = blend;
   1.967 +    }
   1.968 +
   1.969 +    if (data->shaders && (shader != *current_shader)) {
   1.970 +        GL_SelectShader(data->shaders, shader);
   1.971 +        *current_shader = shader;
   1.972 +    }
   1.973 +
   1.974 +    if ((cmd->data.draw.texture != NULL) != *current_texturing) {
   1.975 +        if (cmd->data.draw.texture == NULL) {
   1.976 +            data->glDisable(data->textype);
   1.977 +            *current_texturing = SDL_FALSE;
   1.978 +        } else {
   1.979 +            data->glEnable(data->textype);
   1.980 +            *current_texturing = SDL_FALSE;
   1.981 +        }
   1.982 +    }
   1.983 +}
   1.984 +
   1.985 +static void
   1.986 +SetCopyState(const GL_RenderData *data, const SDL_RenderCommand *cmd,
   1.987 +             Uint32 *current_color, SDL_BlendMode *current_blend, GL_Shader *current_shader,
   1.988 +             SDL_bool *current_texturing, SDL_Texture **current_texture)
   1.989 +{
   1.990 +    SDL_Texture *texture = cmd->data.draw.texture;
   1.991 +    const GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   1.992 +    GL_Shader shader = SHADER_RGB;
   1.993 +
   1.994 +    if (data->shaders) {
   1.995 +        if (texturedata->yuv || texturedata->nv12) {
   1.996 +            switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
   1.997 +                case SDL_YUV_CONVERSION_JPEG:
   1.998 +                    if (texturedata->yuv) {
   1.999 +                        shader = SHADER_YUV_JPEG;
  1.1000 +                    } else if (texture->format == SDL_PIXELFORMAT_NV12) {
  1.1001 +                        shader = SHADER_NV12_JPEG;
  1.1002 +                    } else {
  1.1003 +                        shader = SHADER_NV21_JPEG;
  1.1004 +                    }
  1.1005 +                    break;
  1.1006 +                case SDL_YUV_CONVERSION_BT601:
  1.1007 +                    if (texturedata->yuv) {
  1.1008 +                        shader = SHADER_YUV_BT601;
  1.1009 +                    } else if (texture->format == SDL_PIXELFORMAT_NV12) {
  1.1010 +                        shader = SHADER_NV12_BT601;
  1.1011 +                    } else {
  1.1012 +                        shader = SHADER_NV21_BT601;
  1.1013 +                    }
  1.1014 +                    break;
  1.1015 +                case SDL_YUV_CONVERSION_BT709:
  1.1016 +                    if (texturedata->yuv) {
  1.1017 +                        shader = SHADER_YUV_BT709;
  1.1018 +                    } else if (texture->format == SDL_PIXELFORMAT_NV12) {
  1.1019 +                        shader = SHADER_NV12_BT709;
  1.1020 +                    } else {
  1.1021 +                        shader = SHADER_NV21_BT709;
  1.1022 +                    }
  1.1023 +                    break;
  1.1024 +                default:
  1.1025 +                    SDL_assert(!"unsupported YUV conversion mode");
  1.1026 +                    break;
  1.1027 +            }
  1.1028 +        }
  1.1029 +    }
  1.1030 +
  1.1031 +    SetDrawState(data, cmd, shader, current_color, current_blend, current_shader, current_texturing);
  1.1032 +
  1.1033 +    if (texture != *current_texture) {
  1.1034 +        const GLenum textype = data->textype;
  1.1035 +        if (texturedata->yuv) {
  1.1036 +            data->glActiveTextureARB(GL_TEXTURE2_ARB);
  1.1037 +            data->glBindTexture(textype, texturedata->vtexture);
  1.1038 +
  1.1039 +            data->glActiveTextureARB(GL_TEXTURE1_ARB);
  1.1040 +            data->glBindTexture(textype, texturedata->utexture);
  1.1041 +        }
  1.1042 +        if (texturedata->nv12) {
  1.1043 +            data->glActiveTextureARB(GL_TEXTURE1_ARB);
  1.1044 +            data->glBindTexture(textype, texturedata->utexture);
  1.1045 +        }
  1.1046 +        data->glActiveTextureARB(GL_TEXTURE0_ARB);
  1.1047 +        data->glBindTexture(textype, texturedata->texture);
  1.1048 +
  1.1049 +        *current_texture = texture;
  1.1050 +    }
  1.1051 +}
  1.1052 +
  1.1053 +static int
  1.1054 +GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  1.1055 +{
  1.1056 +    /* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */
  1.1057 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1.1058 +    SDL_bool clipping_enabled = renderer->clipping_enabled;
  1.1059 +    SDL_Rect viewport;
  1.1060 +    SDL_Texture *bound_texture = NULL;
  1.1061 +    SDL_BlendMode blend = SDL_BLENDMODE_INVALID;
  1.1062 +    GL_Shader shader = SHADER_INVALID;
  1.1063 +    int drawablew = 0, drawableh = 0;
  1.1064 +    SDL_bool cliprect_enabled = SDL_FALSE;
  1.1065 +    SDL_Rect cliprect;
  1.1066 +    const SDL_bool istarget = renderer->target != NULL;
  1.1067 +    Uint32 clear_color = ((renderer->a << 24) | (renderer->r << 16) | (renderer->g << 8) | renderer->b);
  1.1068 +    Uint32 draw_color = clear_color;
  1.1069 +    SDL_bool texturing = SDL_FALSE;
  1.1070 +    size_t i;
  1.1071 +
  1.1072 +    /* !!! FIXME: if we could guarantee the app isn't messing with the GL, too, we wouldn't
  1.1073 +       !!! FIXME:  have to default a bunch of this state at the start. */
  1.1074 +
  1.1075 +    if (GL_ActivateRenderer(renderer) < 0) {
  1.1076 +        return -1;
  1.1077 +    }
  1.1078 +
  1.1079 +    if (!istarget) {
  1.1080 +        SDL_GL_GetDrawableSize(renderer->window, &drawablew, &drawableh);
  1.1081 +    }
  1.1082 +
  1.1083 +    data->glClearColor((GLfloat) renderer->r * inv255f,
  1.1084 +                       (GLfloat) renderer->g * inv255f,
  1.1085 +                       (GLfloat) renderer->b * inv255f,
  1.1086 +                       (GLfloat) renderer->a * inv255f);
  1.1087 +
  1.1088 +    data->glColor4f((GLfloat) renderer->r * inv255f,
  1.1089 +                    (GLfloat) renderer->g * inv255f,
  1.1090 +                    (GLfloat) renderer->b * inv255f,
  1.1091 +                    (GLfloat) renderer->a * inv255f);
  1.1092 +
  1.1093 +    SDL_memcpy(&viewport, &renderer->viewport, sizeof (viewport));
  1.1094 +    data->glMatrixMode(GL_PROJECTION);
  1.1095 +    data->glLoadIdentity();
  1.1096 +    data->glViewport(viewport.x,
  1.1097 +            istarget ? viewport.y : (drawableh - viewport.y - viewport.h),
  1.1098 +            viewport.w, viewport.h);
  1.1099 +    if (viewport.w && viewport.h) {
  1.1100 +        data->glOrtho((GLdouble) 0, (GLdouble) renderer->viewport.w,
  1.1101 +                      (GLdouble) istarget ? 0 : renderer->viewport.h,
  1.1102 +                      (GLdouble) istarget ? renderer->viewport.h : 0,
  1.1103 +                      0.0, 1.0);
  1.1104 +    }
  1.1105 +    data->glMatrixMode(GL_MODELVIEW);
  1.1106 +    data->glLoadIdentity();
  1.1107 +
  1.1108 +    SDL_memcpy(&cliprect, &renderer->clip_rect, sizeof (cliprect));
  1.1109 +    cliprect_enabled = renderer->clipping_enabled;
  1.1110 +    if (cliprect_enabled) {
  1.1111 +        data->glEnable(GL_SCISSOR_TEST);
  1.1112 +    } else {
  1.1113 +        data->glDisable(GL_SCISSOR_TEST);
  1.1114 +    }
  1.1115 +
  1.1116 +    data->glDisable(data->textype);
  1.1117 +
  1.1118 +    data->glScissor(viewport.x + cliprect.x,
  1.1119 +        istarget ? viewport.y + cliprect.y : drawableh - viewport.y - cliprect.y - cliprect.h,
  1.1120 +        cliprect.w, cliprect.h);
  1.1121 +
  1.1122 +    while (cmd) {
  1.1123 +        switch (cmd->command) {
  1.1124 +            case SDL_RENDERCMD_SETVIEWPORT: {
  1.1125 +                if (SDL_memcmp(&cmd->data.viewport, &viewport, sizeof (SDL_Rect)) != 0) {
  1.1126 +                    SDL_memcpy(&viewport, &cmd->data.viewport, sizeof (SDL_Rect));
  1.1127 +                    data->glMatrixMode(GL_PROJECTION);
  1.1128 +                    data->glLoadIdentity();
  1.1129 +                    data->glViewport(viewport.x,
  1.1130 +                        istarget ? viewport.y : (drawableh - viewport.y - viewport.h),
  1.1131 +                        viewport.w, viewport.h);
  1.1132 +                    if (viewport.w && viewport.h) {
  1.1133 +                        data->glOrtho((GLdouble) 0, (GLdouble) renderer->viewport.w,
  1.1134 +                                      (GLdouble) istarget ? 0 : renderer->viewport.h,
  1.1135 +                                      (GLdouble) istarget ? renderer->viewport.h : 0,
  1.1136 +                                      0.0, 1.0);
  1.1137 +                    }
  1.1138 +                    data->glMatrixMode(GL_MODELVIEW);
  1.1139 +                }
  1.1140 +                break;
  1.1141 +            }
  1.1142 +
  1.1143 +            case SDL_RENDERCMD_SETCLIPRECT: {
  1.1144 +                const SDL_Rect *rect = &cmd->data.cliprect.rect;
  1.1145 +                const SDL_bool changed = (SDL_memcmp(&cliprect, rect, sizeof (SDL_Rect)) != 0);
  1.1146 +                if (cliprect_enabled != cmd->data.cliprect.enabled) {
  1.1147 +                    cliprect_enabled = cmd->data.cliprect.enabled;
  1.1148 +                    if (cliprect_enabled) {
  1.1149 +                        data->glEnable(GL_SCISSOR_TEST);
  1.1150 +                    } else {
  1.1151 +                        data->glDisable(GL_SCISSOR_TEST);
  1.1152 +                    }
  1.1153 +                }
  1.1154 +
  1.1155 +                if (cliprect_enabled && changed) {
  1.1156 +                    SDL_memcpy(&cliprect, rect, sizeof (SDL_Rect));
  1.1157 +                    data->glScissor(viewport.x + rect->x,
  1.1158 +                                    istarget ? viewport.y + rect->y : drawableh - viewport.y - rect->y - rect->h,
  1.1159 +                                    rect->w, rect->h);
  1.1160 +                }
  1.1161 +                break;
  1.1162 +            }
  1.1163 +
  1.1164 +            case SDL_RENDERCMD_CLEAR: {
  1.1165 +                const Uint8 r = cmd->data.color.r;
  1.1166 +                const Uint8 g = cmd->data.color.g;
  1.1167 +                const Uint8 b = cmd->data.color.b;
  1.1168 +                const Uint8 a = cmd->data.color.a;
  1.1169 +                const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
  1.1170 +                if (color != clear_color) {
  1.1171 +                    data->glClearColor((GLfloat) r * inv255f, (GLfloat) g * inv255f,
  1.1172 +                                       (GLfloat) b * inv255f, (GLfloat) a * inv255f);
  1.1173 +                    clear_color = color;
  1.1174 +                }
  1.1175 +
  1.1176 +                if (clipping_enabled) {
  1.1177 +                    data->glDisable(GL_SCISSOR_TEST);
  1.1178 +                }
  1.1179 +
  1.1180 +                data->glClear(GL_COLOR_BUFFER_BIT);
  1.1181 +
  1.1182 +                if (clipping_enabled) {
  1.1183 +                    data->glEnable(GL_SCISSOR_TEST);
  1.1184 +                }
  1.1185 +                break;
  1.1186 +            }
  1.1187 +
  1.1188 +            case SDL_RENDERCMD_DRAW_POINTS: {
  1.1189 +                const size_t count = cmd->data.draw.count;
  1.1190 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
  1.1191 +                SetDrawState(data, cmd, SHADER_SOLID, &draw_color, &blend, &shader, &texturing);
  1.1192 +                data->glBegin(GL_POINTS);
  1.1193 +                for (i = 0; i < count; i++, verts += 2) {
  1.1194 +                    data->glVertex2f(verts[0], verts[1]);
  1.1195 +                }
  1.1196 +                data->glEnd();
  1.1197 +                break;
  1.1198 +            }
  1.1199 +
  1.1200 +            case SDL_RENDERCMD_DRAW_LINES: {
  1.1201 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
  1.1202 +                size_t count = cmd->data.draw.count;
  1.1203 +                SetDrawState(data, cmd, SHADER_SOLID, &draw_color, &blend, &shader, &texturing);
  1.1204 +                if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
  1.1205 +                    --count;  /* GL_LINE_LOOP takes care of the final segment */
  1.1206 +                    data->glBegin(GL_LINE_LOOP);
  1.1207 +                    for (i = 0; i < count; ++i, verts += 2) {
  1.1208 +                        data->glVertex2f(verts[0], verts[1]);
  1.1209 +                    }
  1.1210 +                    data->glEnd();
  1.1211 +                } else {
  1.1212 +                    #if defined(__MACOSX__) || defined(__WIN32__)
  1.1213 +                    #else
  1.1214 +                    int x1, y1, x2, y2;
  1.1215 +                    #endif
  1.1216 +
  1.1217 +                    data->glBegin(GL_LINE_STRIP);
  1.1218 +                    for (i = 0; i < count; ++i, verts += 2) {
  1.1219 +                        data->glVertex2f(verts[0], verts[1]);
  1.1220 +                    }
  1.1221 +                    data->glEnd();
  1.1222 +
  1.1223 +                    /* The line is half open, so we need one more point to complete it.
  1.1224 +                     * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
  1.1225 +                     * If we have to, we can use vertical line and horizontal line textures
  1.1226 +                     * for vertical and horizontal lines, and then create custom textures
  1.1227 +                     * for diagonal lines and software render those.  It's terrible, but at
  1.1228 +                     * least it would be pixel perfect.
  1.1229 +                     */
  1.1230 +
  1.1231 +                    data->glBegin(GL_POINTS);
  1.1232 +                    #if defined(__MACOSX__) || defined(__WIN32__)
  1.1233 +                    /* Mac OS X and Windows seem to always leave the last point open */
  1.1234 +                    data->glVertex2f(verts[(count-1)*2], verts[(count*2)-1]);
  1.1235 +                    #else
  1.1236 +                    /* Linux seems to leave the right-most or bottom-most point open */
  1.1237 +                    x1 = verts[0];
  1.1238 +                    y1 = verts[1];
  1.1239 +                    x2 = verts[(count-1)*2];
  1.1240 +                    y2 = verts[(count*2)-1];
  1.1241 +
  1.1242 +                    if (x1 > x2) {
  1.1243 +                        data->glVertex2f(x1, y1);
  1.1244 +                    } else if (x2 > x1) {
  1.1245 +                        data->glVertex2f(x2, y2);
  1.1246 +                    }
  1.1247 +                    if (y1 > y2) {
  1.1248 +                        data->glVertex2f(x1, y1);
  1.1249 +                    } else if (y2 > y1) {
  1.1250 +                        data->glVertex2f(x2, y2);
  1.1251 +                    }
  1.1252 +                    #endif
  1.1253 +                    data->glEnd();
  1.1254 +                }
  1.1255 +                break;
  1.1256 +            }
  1.1257 +
  1.1258 +            case SDL_RENDERCMD_FILL_RECTS: {
  1.1259 +                const size_t count = cmd->data.draw.count;
  1.1260 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
  1.1261 +                SetDrawState(data, cmd, SHADER_SOLID, &draw_color, &blend, &shader, &texturing);
  1.1262 +                for (i = 0; i < count; ++i, verts += 4) {
  1.1263 +                    data->glRectf(verts[0], verts[1], verts[2], verts[3]);
  1.1264 +                }
  1.1265 +                break;
  1.1266 +            }
  1.1267 +
  1.1268 +            case SDL_RENDERCMD_COPY: {
  1.1269 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
  1.1270 +                const GLfloat minx = verts[0];
  1.1271 +                const GLfloat miny = verts[1];
  1.1272 +                const GLfloat maxx = verts[2];
  1.1273 +                const GLfloat maxy = verts[3];
  1.1274 +                const GLfloat minu = verts[4];
  1.1275 +                const GLfloat maxu = verts[5];
  1.1276 +                const GLfloat minv = verts[6];
  1.1277 +                const GLfloat maxv = verts[7];
  1.1278 +                SetCopyState(data, cmd, &draw_color, &blend, &shader, &texturing, &bound_texture);
  1.1279 +                data->glBegin(GL_TRIANGLE_STRIP);
  1.1280 +                data->glTexCoord2f(minu, minv);
  1.1281 +                data->glVertex2f(minx, miny);
  1.1282 +                data->glTexCoord2f(maxu, minv);
  1.1283 +                data->glVertex2f(maxx, miny);
  1.1284 +                data->glTexCoord2f(minu, maxv);
  1.1285 +                data->glVertex2f(minx, maxy);
  1.1286 +                data->glTexCoord2f(maxu, maxv);
  1.1287 +                data->glVertex2f(maxx, maxy);
  1.1288 +                data->glEnd();
  1.1289 +                break;
  1.1290 +            }
  1.1291 +
  1.1292 +            case SDL_RENDERCMD_COPY_EX: {
  1.1293 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
  1.1294 +                const GLfloat minx = verts[0];
  1.1295 +                const GLfloat miny = verts[1];
  1.1296 +                const GLfloat maxx = verts[2];
  1.1297 +                const GLfloat maxy = verts[3];
  1.1298 +                const GLfloat minu = verts[4];
  1.1299 +                const GLfloat maxu = verts[5];
  1.1300 +                const GLfloat minv = verts[6];
  1.1301 +                const GLfloat maxv = verts[7];
  1.1302 +                const GLfloat translatex = verts[8];
  1.1303 +                const GLfloat translatey = verts[9];
  1.1304 +                const GLdouble angle = verts[10];
  1.1305 +                SetCopyState(data, cmd, &draw_color, &blend, &shader, &texturing, &bound_texture);
  1.1306 +
  1.1307 +                /* Translate to flip, rotate, translate to position */
  1.1308 +                data->glPushMatrix();
  1.1309 +                data->glTranslatef(translatex, translatey, 0.0f);
  1.1310 +                data->glRotated(angle, 0.0, 0.0, 1.0);
  1.1311 +                data->glBegin(GL_TRIANGLE_STRIP);
  1.1312 +                data->glTexCoord2f(minu, minv);
  1.1313 +                data->glVertex2f(minx, miny);
  1.1314 +                data->glTexCoord2f(maxu, minv);
  1.1315 +                data->glVertex2f(maxx, miny);
  1.1316 +                data->glTexCoord2f(minu, maxv);
  1.1317 +                data->glVertex2f(minx, maxy);
  1.1318 +                data->glTexCoord2f(maxu, maxv);
  1.1319 +                data->glVertex2f(maxx, maxy);
  1.1320 +                data->glEnd();
  1.1321 +                data->glPopMatrix();
  1.1322 +                break;
  1.1323 +            }
  1.1324 +
  1.1325 +            case SDL_RENDERCMD_NO_OP:
  1.1326 +                break;
  1.1327 +        }
  1.1328 +
  1.1329 +        cmd = cmd->next;
  1.1330 +    }
  1.1331  
  1.1332      return GL_CheckError("", renderer);
  1.1333  }
  1.1334 @@ -1631,19 +1693,21 @@
  1.1335  {
  1.1336      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1.1337      GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
  1.1338 +    const GLenum textype = data->textype;
  1.1339 +
  1.1340      GL_ActivateRenderer(renderer);
  1.1341  
  1.1342 -    data->glEnable(texturedata->type);
  1.1343 +    data->glEnable(textype);
  1.1344      if (texturedata->yuv) {
  1.1345          data->glActiveTextureARB(GL_TEXTURE2_ARB);
  1.1346 -        data->glBindTexture(texturedata->type, texturedata->vtexture);
  1.1347 +        data->glBindTexture(textype, texturedata->vtexture);
  1.1348  
  1.1349          data->glActiveTextureARB(GL_TEXTURE1_ARB);
  1.1350 -        data->glBindTexture(texturedata->type, texturedata->utexture);
  1.1351 +        data->glBindTexture(textype, texturedata->utexture);
  1.1352  
  1.1353          data->glActiveTextureARB(GL_TEXTURE0_ARB);
  1.1354      }
  1.1355 -    data->glBindTexture(texturedata->type, texturedata->texture);
  1.1356 +    data->glBindTexture(textype, texturedata->texture);
  1.1357  
  1.1358      if(texw) *texw = (float)texturedata->texw;
  1.1359      if(texh) *texh = (float)texturedata->texh;
  1.1360 @@ -1656,19 +1720,21 @@
  1.1361  {
  1.1362      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1.1363      GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
  1.1364 +    const GLenum textype = data->textype;
  1.1365 +
  1.1366      GL_ActivateRenderer(renderer);
  1.1367  
  1.1368      if (texturedata->yuv) {
  1.1369          data->glActiveTextureARB(GL_TEXTURE2_ARB);
  1.1370 -        data->glDisable(texturedata->type);
  1.1371 +        data->glDisable(textype);
  1.1372  
  1.1373          data->glActiveTextureARB(GL_TEXTURE1_ARB);
  1.1374 -        data->glDisable(texturedata->type);
  1.1375 +        data->glDisable(textype);
  1.1376  
  1.1377          data->glActiveTextureARB(GL_TEXTURE0_ARB);
  1.1378      }
  1.1379  
  1.1380 -    data->glDisable(texturedata->type);
  1.1381 +    data->glDisable(textype);
  1.1382  
  1.1383      return 0;
  1.1384  }
     2.1 --- a/src/render/opengl/SDL_shaders_gl.h	Thu Sep 20 15:46:02 2018 -0400
     2.2 +++ b/src/render/opengl/SDL_shaders_gl.h	Thu Sep 20 16:36:54 2018 -0400
     2.3 @@ -23,6 +23,7 @@
     2.4  /* OpenGL shader implementation */
     2.5  
     2.6  typedef enum {
     2.7 +    SHADER_INVALID = -1,
     2.8      SHADER_NONE,
     2.9      SHADER_SOLID,
    2.10      SHADER_RGB,