src/render/software/SDL_render_sw.c
branchSDL-ryan-batching-renderer
changeset 12288 005e1d1bcf05
parent 11958 d7582d7286aa
child 12381 dc9108cd4340
     1.1 --- a/src/render/software/SDL_render_sw.c	Wed Oct 03 19:05:20 2018 -0400
     1.2 +++ b/src/render/software/SDL_render_sw.c	Wed Oct 03 23:37:29 2018 -0400
     1.3 @@ -25,6 +25,7 @@
     1.4  #include "../SDL_sysrender.h"
     1.5  #include "SDL_render_sw_c.h"
     1.6  #include "SDL_hints.h"
     1.7 +#include "SDL_assert.h"
     1.8  
     1.9  #include "SDL_draw.h"
    1.10  #include "SDL_blendfillrect.h"
    1.11 @@ -36,65 +37,6 @@
    1.12  
    1.13  /* SDL surface based renderer implementation */
    1.14  
    1.15 -static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
    1.16 -static void SW_WindowEvent(SDL_Renderer * renderer,
    1.17 -                           const SDL_WindowEvent *event);
    1.18 -static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
    1.19 -static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.20 -static int SW_SetTextureColorMod(SDL_Renderer * renderer,
    1.21 -                                 SDL_Texture * texture);
    1.22 -static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
    1.23 -                                 SDL_Texture * texture);
    1.24 -static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
    1.25 -                                  SDL_Texture * texture);
    1.26 -static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.27 -                            const SDL_Rect * rect, const void *pixels,
    1.28 -                            int pitch);
    1.29 -static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.30 -                          const SDL_Rect * rect, void **pixels, int *pitch);
    1.31 -static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.32 -static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
    1.33 -static int SW_UpdateViewport(SDL_Renderer * renderer);
    1.34 -static int SW_UpdateClipRect(SDL_Renderer * renderer);
    1.35 -static int SW_RenderClear(SDL_Renderer * renderer);
    1.36 -static int SW_RenderDrawPoints(SDL_Renderer * renderer,
    1.37 -                               const SDL_FPoint * points, int count);
    1.38 -static int SW_RenderDrawLines(SDL_Renderer * renderer,
    1.39 -                              const SDL_FPoint * points, int count);
    1.40 -static int SW_RenderFillRects(SDL_Renderer * renderer,
    1.41 -                              const SDL_FRect * rects, int count);
    1.42 -static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    1.43 -                         const SDL_Rect * srcrect, const SDL_FRect * dstrect);
    1.44 -static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    1.45 -                          const SDL_Rect * srcrect, const SDL_FRect * dstrect,
    1.46 -                          const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
    1.47 -static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    1.48 -                               Uint32 format, void * pixels, int pitch);
    1.49 -static void SW_RenderPresent(SDL_Renderer * renderer);
    1.50 -static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.51 -static void SW_DestroyRenderer(SDL_Renderer * renderer);
    1.52 -
    1.53 -
    1.54 -SDL_RenderDriver SW_RenderDriver = {
    1.55 -    SW_CreateRenderer,
    1.56 -    {
    1.57 -     "software",
    1.58 -     SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
    1.59 -     8,
    1.60 -     {
    1.61 -      SDL_PIXELFORMAT_ARGB8888,
    1.62 -      SDL_PIXELFORMAT_ABGR8888,
    1.63 -      SDL_PIXELFORMAT_RGBA8888,
    1.64 -      SDL_PIXELFORMAT_BGRA8888,
    1.65 -      SDL_PIXELFORMAT_RGB888,
    1.66 -      SDL_PIXELFORMAT_BGR888,
    1.67 -      SDL_PIXELFORMAT_RGB565,
    1.68 -      SDL_PIXELFORMAT_RGB555
    1.69 -     },
    1.70 -     0,
    1.71 -     0}
    1.72 -};
    1.73 -
    1.74  typedef struct
    1.75  {
    1.76      SDL_Surface *surface;
    1.77 @@ -114,82 +56,11 @@
    1.78          SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
    1.79          if (surface) {
    1.80              data->surface = data->window = surface;
    1.81 -
    1.82 -            SW_UpdateViewport(renderer);
    1.83 -            SW_UpdateClipRect(renderer);
    1.84          }
    1.85      }
    1.86      return data->surface;
    1.87  }
    1.88  
    1.89 -SDL_Renderer *
    1.90 -SW_CreateRendererForSurface(SDL_Surface * surface)
    1.91 -{
    1.92 -    SDL_Renderer *renderer;
    1.93 -    SW_RenderData *data;
    1.94 -
    1.95 -    if (!surface) {
    1.96 -        SDL_SetError("Can't create renderer for NULL surface");
    1.97 -        return NULL;
    1.98 -    }
    1.99 -
   1.100 -    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   1.101 -    if (!renderer) {
   1.102 -        SDL_OutOfMemory();
   1.103 -        return NULL;
   1.104 -    }
   1.105 -
   1.106 -    data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
   1.107 -    if (!data) {
   1.108 -        SW_DestroyRenderer(renderer);
   1.109 -        SDL_OutOfMemory();
   1.110 -        return NULL;
   1.111 -    }
   1.112 -    data->surface = surface;
   1.113 -    data->window = surface;
   1.114 -
   1.115 -    renderer->WindowEvent = SW_WindowEvent;
   1.116 -    renderer->GetOutputSize = SW_GetOutputSize;
   1.117 -    renderer->CreateTexture = SW_CreateTexture;
   1.118 -    renderer->SetTextureColorMod = SW_SetTextureColorMod;
   1.119 -    renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
   1.120 -    renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
   1.121 -    renderer->UpdateTexture = SW_UpdateTexture;
   1.122 -    renderer->LockTexture = SW_LockTexture;
   1.123 -    renderer->UnlockTexture = SW_UnlockTexture;
   1.124 -    renderer->SetRenderTarget = SW_SetRenderTarget;
   1.125 -    renderer->UpdateViewport = SW_UpdateViewport;
   1.126 -    renderer->UpdateClipRect = SW_UpdateClipRect;
   1.127 -    renderer->RenderClear = SW_RenderClear;
   1.128 -    renderer->RenderDrawPoints = SW_RenderDrawPoints;
   1.129 -    renderer->RenderDrawLines = SW_RenderDrawLines;
   1.130 -    renderer->RenderFillRects = SW_RenderFillRects;
   1.131 -    renderer->RenderCopy = SW_RenderCopy;
   1.132 -    renderer->RenderCopyEx = SW_RenderCopyEx;
   1.133 -    renderer->RenderReadPixels = SW_RenderReadPixels;
   1.134 -    renderer->RenderPresent = SW_RenderPresent;
   1.135 -    renderer->DestroyTexture = SW_DestroyTexture;
   1.136 -    renderer->DestroyRenderer = SW_DestroyRenderer;
   1.137 -    renderer->info = SW_RenderDriver.info;
   1.138 -    renderer->driverdata = data;
   1.139 -
   1.140 -    SW_ActivateRenderer(renderer);
   1.141 -
   1.142 -    return renderer;
   1.143 -}
   1.144 -
   1.145 -SDL_Renderer *
   1.146 -SW_CreateRenderer(SDL_Window * window, Uint32 flags)
   1.147 -{
   1.148 -    SDL_Surface *surface;
   1.149 -
   1.150 -    surface = SDL_GetWindowSurface(window);
   1.151 -    if (!surface) {
   1.152 -        return NULL;
   1.153 -    }
   1.154 -    return SW_CreateRendererForSurface(surface);
   1.155 -}
   1.156 -
   1.157  static void
   1.158  SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   1.159  {
   1.160 @@ -253,46 +124,6 @@
   1.161  }
   1.162  
   1.163  static int
   1.164 -SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   1.165 -{
   1.166 -    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.167 -    /* If the color mod is ever enabled (non-white), permanently disable RLE (which doesn't support
   1.168 -     * color mod) to avoid potentially frequent RLE encoding/decoding.
   1.169 -     */
   1.170 -    if ((texture->r & texture->g & texture->b) != 255) {
   1.171 -        SDL_SetSurfaceRLE(surface, 0);
   1.172 -    }
   1.173 -    return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
   1.174 -                                  texture->b);
   1.175 -}
   1.176 -
   1.177 -static int
   1.178 -SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   1.179 -{
   1.180 -    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.181 -    /* If the texture ever has multiple alpha values (surface alpha plus alpha channel), permanently
   1.182 -     * disable RLE (which doesn't support this) to avoid potentially frequent RLE encoding/decoding.
   1.183 -     */
   1.184 -    if (texture->a != 255 && surface->format->Amask) {
   1.185 -        SDL_SetSurfaceRLE(surface, 0);
   1.186 -    }
   1.187 -    return SDL_SetSurfaceAlphaMod(surface, texture->a);
   1.188 -}
   1.189 -
   1.190 -static int
   1.191 -SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   1.192 -{
   1.193 -    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.194 -    /* If add or mod blending are ever enabled, permanently disable RLE (which doesn't support
   1.195 -     * them) to avoid potentially frequent RLE encoding/decoding.
   1.196 -     */
   1.197 -    if ((texture->blendMode == SDL_BLENDMODE_ADD || texture->blendMode == SDL_BLENDMODE_MOD)) {
   1.198 -        SDL_SetSurfaceRLE(surface, 0);
   1.199 -    }
   1.200 -    return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
   1.201 -}
   1.202 -
   1.203 -static int
   1.204  SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.205                   const SDL_Rect * rect, const void *pixels, int pitch)
   1.206  {
   1.207 @@ -350,251 +181,149 @@
   1.208  }
   1.209  
   1.210  static int
   1.211 -SW_UpdateViewport(SDL_Renderer * renderer)
   1.212 +SW_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
   1.213  {
   1.214 -    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.215 -    SDL_Surface *surface = data->surface;
   1.216 +    return 0;  /* nothing to do in this backend. */
   1.217 +}
   1.218  
   1.219 -    if (!surface) {
   1.220 -        /* We'll update the viewport after we recreate the surface */
   1.221 -        return 0;
   1.222 +static int
   1.223 +SW_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
   1.224 +{
   1.225 +    SDL_Point *verts = (SDL_Point *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Point), 0, &cmd->data.draw.first);
   1.226 +    size_t i;
   1.227 +
   1.228 +    if (!verts) {
   1.229 +        return -1;
   1.230      }
   1.231  
   1.232 -    SDL_SetClipRect(data->surface, &renderer->viewport);
   1.233 +    cmd->data.draw.count = count;
   1.234 +
   1.235 +    if (renderer->viewport.x || renderer->viewport.y) {
   1.236 +        const int x = renderer->viewport.x;
   1.237 +        const int y = renderer->viewport.y;
   1.238 +        for (i = 0; i < count; i++, verts++, points++) {
   1.239 +            verts->x = (int)(x + points->x);
   1.240 +            verts->y = (int)(y + points->y);
   1.241 +        }
   1.242 +    } else {
   1.243 +        for (i = 0; i < count; i++, verts++, points++) {
   1.244 +            verts->x = (int)points->x;
   1.245 +            verts->y = (int)points->y;
   1.246 +        }
   1.247 +    }
   1.248 +
   1.249      return 0;
   1.250  }
   1.251  
   1.252  static int
   1.253 -SW_UpdateClipRect(SDL_Renderer * renderer)
   1.254 +SW_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
   1.255  {
   1.256 -    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.257 -    SDL_Surface *surface = data->surface;
   1.258 -    if (surface) {
   1.259 -        if (renderer->clipping_enabled) {
   1.260 -            SDL_Rect clip_rect;
   1.261 -            clip_rect = renderer->clip_rect;
   1.262 -            clip_rect.x += renderer->viewport.x;
   1.263 -            clip_rect.y += renderer->viewport.y;
   1.264 -            SDL_IntersectRect(&renderer->viewport, &clip_rect, &clip_rect);
   1.265 -            SDL_SetClipRect(surface, &clip_rect);
   1.266 -        } else {
   1.267 -            SDL_SetClipRect(surface, &renderer->viewport);
   1.268 +    SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
   1.269 +    size_t i;
   1.270 +
   1.271 +    if (!verts) {
   1.272 +        return -1;
   1.273 +    }
   1.274 +
   1.275 +    cmd->data.draw.count = count;
   1.276 +
   1.277 +    if (renderer->viewport.x || renderer->viewport.y) {
   1.278 +        const int x = renderer->viewport.x;
   1.279 +        const int y = renderer->viewport.y;
   1.280 +
   1.281 +        for (i = 0; i < count; i++, verts++, rects++) {
   1.282 +            verts->x = (int)(x + rects->x);
   1.283 +            verts->y = (int)(y + rects->y);
   1.284 +            verts->w = SDL_max((int)rects->w, 1);
   1.285 +            verts->h = SDL_max((int)rects->h, 1);
   1.286 +        }
   1.287 +    } else {
   1.288 +        for (i = 0; i < count; i++, verts++, rects++) {
   1.289 +            verts->x = (int)rects->x;
   1.290 +            verts->y = (int)rects->y;
   1.291 +            verts->w = SDL_max((int)rects->w, 1);
   1.292 +            verts->h = SDL_max((int)rects->h, 1);
   1.293          }
   1.294      }
   1.295 +
   1.296      return 0;
   1.297  }
   1.298  
   1.299  static int
   1.300 -SW_RenderClear(SDL_Renderer * renderer)
   1.301 +SW_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   1.302 +             const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1.303  {
   1.304 -    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.305 -    Uint32 color;
   1.306 -    SDL_Rect clip_rect;
   1.307 +    SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, 2 * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
   1.308  
   1.309 -    if (!surface) {
   1.310 +    if (!verts) {
   1.311          return -1;
   1.312      }
   1.313  
   1.314 -    color = SDL_MapRGBA(surface->format,
   1.315 -                        renderer->r, renderer->g, renderer->b, renderer->a);
   1.316 +    cmd->data.draw.count = 1;
   1.317  
   1.318 -    /* By definition the clear ignores the clip rect */
   1.319 -    clip_rect = surface->clip_rect;
   1.320 -    SDL_SetClipRect(surface, NULL);
   1.321 -    SDL_FillRect(surface, NULL, color);
   1.322 -    SDL_SetClipRect(surface, &clip_rect);
   1.323 +    SDL_memcpy(verts, srcrect, sizeof (SDL_Rect));
   1.324 +    verts++;
   1.325 +
   1.326 +    if (renderer->viewport.x || renderer->viewport.y) {
   1.327 +        verts->x = (int)(renderer->viewport.x + dstrect->x);
   1.328 +        verts->y = (int)(renderer->viewport.y + dstrect->y);
   1.329 +    } else {
   1.330 +        verts->x = (int)dstrect->x;
   1.331 +        verts->y = (int)dstrect->y;
   1.332 +    }
   1.333 +    verts->w = (int)dstrect->w;
   1.334 +    verts->h = (int)dstrect->h;
   1.335 +
   1.336 +    return 0;
   1.337 +}
   1.338 +
   1.339 +typedef struct CopyExData
   1.340 +{
   1.341 +    SDL_Rect srcrect;
   1.342 +    SDL_Rect dstrect;
   1.343 +    double angle;
   1.344 +    SDL_FPoint center;
   1.345 +    SDL_RendererFlip flip;
   1.346 +} CopyExData;
   1.347 +
   1.348 +static int
   1.349 +SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   1.350 +               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   1.351 +               const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   1.352 +{
   1.353 +    CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
   1.354 +
   1.355 +    if (!verts) {
   1.356 +        return -1;
   1.357 +    }
   1.358 +
   1.359 +    cmd->data.draw.count = 1;
   1.360 +
   1.361 +    SDL_memcpy(&verts->srcrect, srcrect, sizeof (SDL_Rect));
   1.362 +
   1.363 +    if (renderer->viewport.x || renderer->viewport.y) {
   1.364 +        verts->dstrect.x = (int)(renderer->viewport.x + dstrect->x);
   1.365 +        verts->dstrect.y = (int)(renderer->viewport.y + dstrect->y);
   1.366 +    } else {
   1.367 +        verts->dstrect.x = (int)dstrect->x;
   1.368 +        verts->dstrect.y = (int)dstrect->y;
   1.369 +    }
   1.370 +    verts->dstrect.w = (int)dstrect->w;
   1.371 +    verts->dstrect.h = (int)dstrect->h;
   1.372 +    verts->angle = angle;
   1.373 +    SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
   1.374 +    verts->flip = flip;
   1.375 +
   1.376      return 0;
   1.377  }
   1.378  
   1.379  static int
   1.380 -SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
   1.381 -                    int count)
   1.382 -{
   1.383 -    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.384 -    SDL_Point *final_points;
   1.385 -    int i, status;
   1.386 -
   1.387 -    if (!surface) {
   1.388 -        return -1;
   1.389 -    }
   1.390 -
   1.391 -    final_points = SDL_stack_alloc(SDL_Point, count);
   1.392 -    if (!final_points) {
   1.393 -        return SDL_OutOfMemory();
   1.394 -    }
   1.395 -    if (renderer->viewport.x || renderer->viewport.y) {
   1.396 -        int x = renderer->viewport.x;
   1.397 -        int y = renderer->viewport.y;
   1.398 -
   1.399 -        for (i = 0; i < count; ++i) {
   1.400 -            final_points[i].x = (int)(x + points[i].x);
   1.401 -            final_points[i].y = (int)(y + points[i].y);
   1.402 -        }
   1.403 -    } else {
   1.404 -        for (i = 0; i < count; ++i) {
   1.405 -            final_points[i].x = (int)points[i].x;
   1.406 -            final_points[i].y = (int)points[i].y;
   1.407 -        }
   1.408 -    }
   1.409 -
   1.410 -    /* Draw the points! */
   1.411 -    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   1.412 -        Uint32 color = SDL_MapRGBA(surface->format,
   1.413 -                                   renderer->r, renderer->g, renderer->b,
   1.414 -                                   renderer->a);
   1.415 -
   1.416 -        status = SDL_DrawPoints(surface, final_points, count, color);
   1.417 -    } else {
   1.418 -        status = SDL_BlendPoints(surface, final_points, count,
   1.419 -                                renderer->blendMode,
   1.420 -                                renderer->r, renderer->g, renderer->b,
   1.421 -                                renderer->a);
   1.422 -    }
   1.423 -    SDL_stack_free(final_points);
   1.424 -
   1.425 -    return status;
   1.426 -}
   1.427 -
   1.428 -static int
   1.429 -SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
   1.430 -                   int count)
   1.431 -{
   1.432 -    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.433 -    SDL_Point *final_points;
   1.434 -    int i, status;
   1.435 -
   1.436 -    if (!surface) {
   1.437 -        return -1;
   1.438 -    }
   1.439 -
   1.440 -    final_points = SDL_stack_alloc(SDL_Point, count);
   1.441 -    if (!final_points) {
   1.442 -        return SDL_OutOfMemory();
   1.443 -    }
   1.444 -    if (renderer->viewport.x || renderer->viewport.y) {
   1.445 -        int x = renderer->viewport.x;
   1.446 -        int y = renderer->viewport.y;
   1.447 -
   1.448 -        for (i = 0; i < count; ++i) {
   1.449 -            final_points[i].x = (int)(x + points[i].x);
   1.450 -            final_points[i].y = (int)(y + points[i].y);
   1.451 -        }
   1.452 -    } else {
   1.453 -        for (i = 0; i < count; ++i) {
   1.454 -            final_points[i].x = (int)points[i].x;
   1.455 -            final_points[i].y = (int)points[i].y;
   1.456 -        }
   1.457 -    }
   1.458 -
   1.459 -    /* Draw the lines! */
   1.460 -    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   1.461 -        Uint32 color = SDL_MapRGBA(surface->format,
   1.462 -                                   renderer->r, renderer->g, renderer->b,
   1.463 -                                   renderer->a);
   1.464 -
   1.465 -        status = SDL_DrawLines(surface, final_points, count, color);
   1.466 -    } else {
   1.467 -        status = SDL_BlendLines(surface, final_points, count,
   1.468 -                                renderer->blendMode,
   1.469 -                                renderer->r, renderer->g, renderer->b,
   1.470 -                                renderer->a);
   1.471 -    }
   1.472 -    SDL_stack_free(final_points);
   1.473 -
   1.474 -    return status;
   1.475 -}
   1.476 -
   1.477 -static int
   1.478 -SW_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
   1.479 -{
   1.480 -    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.481 -    SDL_Rect *final_rects;
   1.482 -    int i, status;
   1.483 -
   1.484 -    if (!surface) {
   1.485 -        return -1;
   1.486 -    }
   1.487 -
   1.488 -    final_rects = SDL_stack_alloc(SDL_Rect, count);
   1.489 -    if (!final_rects) {
   1.490 -        return SDL_OutOfMemory();
   1.491 -    }
   1.492 -    if (renderer->viewport.x || renderer->viewport.y) {
   1.493 -        int x = renderer->viewport.x;
   1.494 -        int y = renderer->viewport.y;
   1.495 -
   1.496 -        for (i = 0; i < count; ++i) {
   1.497 -            final_rects[i].x = (int)(x + rects[i].x);
   1.498 -            final_rects[i].y = (int)(y + rects[i].y);
   1.499 -            final_rects[i].w = SDL_max((int)rects[i].w, 1);
   1.500 -            final_rects[i].h = SDL_max((int)rects[i].h, 1);
   1.501 -        }
   1.502 -    } else {
   1.503 -        for (i = 0; i < count; ++i) {
   1.504 -            final_rects[i].x = (int)rects[i].x;
   1.505 -            final_rects[i].y = (int)rects[i].y;
   1.506 -            final_rects[i].w = SDL_max((int)rects[i].w, 1);
   1.507 -            final_rects[i].h = SDL_max((int)rects[i].h, 1);
   1.508 -        }
   1.509 -    }
   1.510 -
   1.511 -    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   1.512 -        Uint32 color = SDL_MapRGBA(surface->format,
   1.513 -                                   renderer->r, renderer->g, renderer->b,
   1.514 -                                   renderer->a);
   1.515 -        status = SDL_FillRects(surface, final_rects, count, color);
   1.516 -    } else {
   1.517 -        status = SDL_BlendFillRects(surface, final_rects, count,
   1.518 -                                    renderer->blendMode,
   1.519 -                                    renderer->r, renderer->g, renderer->b,
   1.520 -                                    renderer->a);
   1.521 -    }
   1.522 -    SDL_stack_free(final_rects);
   1.523 -
   1.524 -    return status;
   1.525 -}
   1.526 -
   1.527 -static int
   1.528 -SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   1.529 -              const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1.530 -{
   1.531 -    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.532 -    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   1.533 -    SDL_Rect final_rect;
   1.534 -
   1.535 -    if (!surface) {
   1.536 -        return -1;
   1.537 -    }
   1.538 -
   1.539 -    if (renderer->viewport.x || renderer->viewport.y) {
   1.540 -        final_rect.x = (int)(renderer->viewport.x + dstrect->x);
   1.541 -        final_rect.y = (int)(renderer->viewport.y + dstrect->y);
   1.542 -    } else {
   1.543 -        final_rect.x = (int)dstrect->x;
   1.544 -        final_rect.y = (int)dstrect->y;
   1.545 -    }
   1.546 -    final_rect.w = (int)dstrect->w;
   1.547 -    final_rect.h = (int)dstrect->h;
   1.548 -
   1.549 -    if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {
   1.550 -        return SDL_BlitSurface(src, srcrect, surface, &final_rect);
   1.551 -    } else {
   1.552 -        /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
   1.553 -         * to avoid potentially frequent RLE encoding/decoding.
   1.554 -         */
   1.555 -        SDL_SetSurfaceRLE(surface, 0);
   1.556 -        return SDL_BlitScaled(src, srcrect, surface, &final_rect);
   1.557 -    }
   1.558 -}
   1.559 -
   1.560 -static int
   1.561 -SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   1.562 -                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   1.563 +SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * texture,
   1.564 +                const SDL_Rect * srcrect, const SDL_Rect * final_rect,
   1.565                  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
   1.566  {
   1.567 -    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.568      SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   1.569 -    SDL_Rect final_rect, tmp_rect;
   1.570 +    SDL_Rect tmp_rect;
   1.571      SDL_Surface *src_clone, *src_rotated, *src_scaled;
   1.572      SDL_Surface *mask = NULL, *mask_rotated = NULL;
   1.573      int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
   1.574 @@ -609,19 +338,10 @@
   1.575          return -1;
   1.576      }
   1.577  
   1.578 -    if (renderer->viewport.x || renderer->viewport.y) {
   1.579 -        final_rect.x = (int)(renderer->viewport.x + dstrect->x);
   1.580 -        final_rect.y = (int)(renderer->viewport.y + dstrect->y);
   1.581 -    } else {
   1.582 -        final_rect.x = (int)dstrect->x;
   1.583 -        final_rect.y = (int)dstrect->y;
   1.584 -    }
   1.585 -    final_rect.w = (int)dstrect->w;
   1.586 -    final_rect.h = (int)dstrect->h;
   1.587 -
   1.588 -    tmp_rect = final_rect;
   1.589      tmp_rect.x = 0;
   1.590      tmp_rect.y = 0;
   1.591 +    tmp_rect.w = final_rect->w;
   1.592 +    tmp_rect.h = final_rect->h;
   1.593  
   1.594      /* It is possible to encounter an RLE encoded surface here and locking it is
   1.595       * necessary because this code is going to access the pixel buffer directly.
   1.596 @@ -653,7 +373,7 @@
   1.597      }
   1.598  
   1.599      /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
   1.600 -    if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) {
   1.601 +    if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) {
   1.602          blitRequired = SDL_TRUE;
   1.603      }
   1.604  
   1.605 @@ -673,7 +393,7 @@
   1.606       * to clear the pixels in the destination surface. The other steps are explained below.
   1.607       */
   1.608      if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
   1.609 -        mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
   1.610 +        mask = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
   1.611                                      0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
   1.612          if (mask == NULL) {
   1.613              retval = -1;
   1.614 @@ -687,7 +407,7 @@
   1.615       */
   1.616      if (!retval && (blitRequired || applyModulation)) {
   1.617          SDL_Rect scale_rect = tmp_rect;
   1.618 -        src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
   1.619 +        src_scaled = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
   1.620                                            0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
   1.621          if (src_scaled == NULL) {
   1.622              retval = -1;
   1.623 @@ -718,32 +438,32 @@
   1.624          }
   1.625          if (!retval) {
   1.626              /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
   1.627 -            abscenterx = final_rect.x + (int)center->x;
   1.628 -            abscentery = final_rect.y + (int)center->y;
   1.629 +            abscenterx = final_rect->x + (int)center->x;
   1.630 +            abscentery = final_rect->y + (int)center->y;
   1.631              /* Compensate the angle inversion to match the behaviour of the other backends */
   1.632              sangle = -sangle;
   1.633  
   1.634              /* Top Left */
   1.635 -            px = final_rect.x - abscenterx;
   1.636 -            py = final_rect.y - abscentery;
   1.637 +            px = final_rect->x - abscenterx;
   1.638 +            py = final_rect->y - abscentery;
   1.639              p1x = px * cangle - py * sangle + abscenterx;
   1.640              p1y = px * sangle + py * cangle + abscentery;
   1.641  
   1.642              /* Top Right */
   1.643 -            px = final_rect.x + final_rect.w - abscenterx;
   1.644 -            py = final_rect.y - abscentery;
   1.645 +            px = final_rect->x + final_rect->w - abscenterx;
   1.646 +            py = final_rect->y - abscentery;
   1.647              p2x = px * cangle - py * sangle + abscenterx;
   1.648              p2y = px * sangle + py * cangle + abscentery;
   1.649  
   1.650              /* Bottom Left */
   1.651 -            px = final_rect.x - abscenterx;
   1.652 -            py = final_rect.y + final_rect.h - abscentery;
   1.653 +            px = final_rect->x - abscenterx;
   1.654 +            py = final_rect->y + final_rect->h - abscentery;
   1.655              p3x = px * cangle - py * sangle + abscenterx;
   1.656              p3y = px * sangle + py * cangle + abscentery;
   1.657  
   1.658              /* Bottom Right */
   1.659 -            px = final_rect.x + final_rect.w - abscenterx;
   1.660 -            py = final_rect.y + final_rect.h - abscentery;
   1.661 +            px = final_rect->x + final_rect->w - abscenterx;
   1.662 +            py = final_rect->y + final_rect->h - abscentery;
   1.663              p4x = px * cangle - py * sangle + abscenterx;
   1.664              p4y = px * sangle + py * cangle + abscentery;
   1.665  
   1.666 @@ -819,6 +539,170 @@
   1.667      return retval;
   1.668  }
   1.669  
   1.670 +static void
   1.671 +PrepTextureForCopy(const SDL_RenderCommand *cmd)
   1.672 +{
   1.673 +    const Uint8 r = cmd->data.draw.r;
   1.674 +    const Uint8 g = cmd->data.draw.g;
   1.675 +    const Uint8 b = cmd->data.draw.b;
   1.676 +    const Uint8 a = cmd->data.draw.a;
   1.677 +    const SDL_BlendMode blend = cmd->data.draw.blend;
   1.678 +    SDL_Texture *texture = cmd->data.draw.texture;
   1.679 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.680 +
   1.681 +    if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
   1.682 +        SDL_SetSurfaceRLE(surface, 0);
   1.683 +        SDL_SetSurfaceColorMod(surface, r, g, b);
   1.684 +    }
   1.685 +
   1.686 +    if ((texture->modMode & SDL_TEXTUREMODULATE_ALPHA) && surface->format->Amask) {
   1.687 +        SDL_SetSurfaceRLE(surface, 0);
   1.688 +        SDL_SetSurfaceAlphaMod(surface, a);
   1.689 +    }
   1.690 +
   1.691 +    if ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD)) {
   1.692 +        SDL_SetSurfaceRLE(surface, 0);
   1.693 +    }
   1.694 +    SDL_SetSurfaceBlendMode(surface, blend);
   1.695 +}
   1.696 +
   1.697 +static int
   1.698 +SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
   1.699 +{
   1.700 +    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.701 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.702 +    const SDL_Rect *viewport = NULL;
   1.703 +    const SDL_Rect *cliprect = NULL;
   1.704 +
   1.705 +    if (!surface) {
   1.706 +        return -1;
   1.707 +    }
   1.708 +
   1.709 +    while (cmd) {
   1.710 +        switch (cmd->command) {
   1.711 +            case SDL_RENDERCMD_SETDRAWCOLOR: {
   1.712 +                break;  /* Not used in this backend. */
   1.713 +            }
   1.714 +
   1.715 +            case SDL_RENDERCMD_SETVIEWPORT: {
   1.716 +                viewport = &cmd->data.viewport.rect;
   1.717 +                SDL_SetClipRect(data->surface, viewport);
   1.718 +                break;
   1.719 +            }
   1.720 +
   1.721 +            case SDL_RENDERCMD_SETCLIPRECT: {
   1.722 +                SDL_assert(viewport != NULL);
   1.723 +                cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
   1.724 +                if (cliprect) {
   1.725 +                    SDL_Rect clip_rect = { cliprect->x + viewport->x, cliprect->y + viewport->y, cliprect->w, cliprect->h };
   1.726 +                    SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
   1.727 +                    SDL_SetClipRect(surface, &clip_rect);
   1.728 +                } else {
   1.729 +                    SDL_SetClipRect(surface, viewport);
   1.730 +                }
   1.731 +                break;
   1.732 +            }
   1.733 +
   1.734 +            case SDL_RENDERCMD_CLEAR: {
   1.735 +                const Uint8 r = cmd->data.color.r;
   1.736 +                const Uint8 g = cmd->data.color.g;
   1.737 +                const Uint8 b = cmd->data.color.b;
   1.738 +                const Uint8 a = cmd->data.color.a;
   1.739 +                const SDL_Rect clip_rect = surface->clip_rect;
   1.740 +                /* By definition the clear ignores the clip rect */
   1.741 +                SDL_SetClipRect(surface, NULL);
   1.742 +                SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
   1.743 +                SDL_SetClipRect(surface, &clip_rect);
   1.744 +                break;
   1.745 +            }
   1.746 +
   1.747 +            case SDL_RENDERCMD_DRAW_POINTS: {
   1.748 +                const Uint8 r = cmd->data.draw.r;
   1.749 +                const Uint8 g = cmd->data.draw.g;
   1.750 +                const Uint8 b = cmd->data.draw.b;
   1.751 +                const Uint8 a = cmd->data.draw.a;
   1.752 +                const size_t count = cmd->data.draw.count;
   1.753 +                const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
   1.754 +                const SDL_BlendMode blend = cmd->data.draw.blend;
   1.755 +                if (blend == SDL_BLENDMODE_NONE) {
   1.756 +                    SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
   1.757 +                } else {
   1.758 +                    SDL_BlendPoints(surface, verts, count, blend, r, g, b, a);
   1.759 +                }
   1.760 +                break;
   1.761 +            }
   1.762 +
   1.763 +            case SDL_RENDERCMD_DRAW_LINES: {
   1.764 +                const Uint8 r = cmd->data.draw.r;
   1.765 +                const Uint8 g = cmd->data.draw.g;
   1.766 +                const Uint8 b = cmd->data.draw.b;
   1.767 +                const Uint8 a = cmd->data.draw.a;
   1.768 +                const size_t count = cmd->data.draw.count;
   1.769 +                const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
   1.770 +                const SDL_BlendMode blend = cmd->data.draw.blend;
   1.771 +                if (blend == SDL_BLENDMODE_NONE) {
   1.772 +                    SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
   1.773 +                } else {
   1.774 +                    SDL_BlendLines(surface, verts, count, blend, r, g, b, a);
   1.775 +                }
   1.776 +                break;
   1.777 +            }
   1.778 +
   1.779 +            case SDL_RENDERCMD_FILL_RECTS: {
   1.780 +                const Uint8 r = cmd->data.draw.r;
   1.781 +                const Uint8 g = cmd->data.draw.g;
   1.782 +                const Uint8 b = cmd->data.draw.b;
   1.783 +                const Uint8 a = cmd->data.draw.a;
   1.784 +                const size_t count = cmd->data.draw.count;
   1.785 +                const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
   1.786 +                const SDL_BlendMode blend = cmd->data.draw.blend;
   1.787 +                if (blend == SDL_BLENDMODE_NONE) {
   1.788 +                    SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
   1.789 +                } else {
   1.790 +                    SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a);
   1.791 +                }
   1.792 +                break;
   1.793 +            }
   1.794 +
   1.795 +            case SDL_RENDERCMD_COPY: {
   1.796 +                SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
   1.797 +                const SDL_Rect *srcrect = verts;
   1.798 +                SDL_Rect *dstrect = verts + 1;
   1.799 +                SDL_Texture *texture = cmd->data.draw.texture;
   1.800 +                SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   1.801 +
   1.802 +                PrepTextureForCopy(cmd);
   1.803 +
   1.804 +                if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
   1.805 +                    SDL_BlitSurface(src, srcrect, surface, dstrect);
   1.806 +                } else {
   1.807 +                    /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
   1.808 +                     * to avoid potentially frequent RLE encoding/decoding.
   1.809 +                     */
   1.810 +                    SDL_SetSurfaceRLE(surface, 0);
   1.811 +                    SDL_BlitScaled(src, srcrect, surface, dstrect);
   1.812 +                }
   1.813 +                break;
   1.814 +            }
   1.815 +
   1.816 +            case SDL_RENDERCMD_COPY_EX: {
   1.817 +                const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
   1.818 +                PrepTextureForCopy(cmd);
   1.819 +                SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
   1.820 +                                &copydata->dstrect, copydata->angle, &copydata->center, copydata->flip);
   1.821 +                break;
   1.822 +            }
   1.823 +
   1.824 +            case SDL_RENDERCMD_NO_OP:
   1.825 +                break;
   1.826 +        }
   1.827 +
   1.828 +        cmd = cmd->next;
   1.829 +    }
   1.830 +
   1.831 +    return 0;
   1.832 +}
   1.833 +
   1.834  static int
   1.835  SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1.836                      Uint32 format, void * pixels, int pitch)
   1.837 @@ -877,6 +761,91 @@
   1.838      SDL_free(renderer);
   1.839  }
   1.840  
   1.841 +SDL_Renderer *
   1.842 +SW_CreateRendererForSurface(SDL_Surface * surface)
   1.843 +{
   1.844 +    SDL_Renderer *renderer;
   1.845 +    SW_RenderData *data;
   1.846 +
   1.847 +    if (!surface) {
   1.848 +        SDL_SetError("Can't create renderer for NULL surface");
   1.849 +        return NULL;
   1.850 +    }
   1.851 +
   1.852 +    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   1.853 +    if (!renderer) {
   1.854 +        SDL_OutOfMemory();
   1.855 +        return NULL;
   1.856 +    }
   1.857 +
   1.858 +    data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
   1.859 +    if (!data) {
   1.860 +        SW_DestroyRenderer(renderer);
   1.861 +        SDL_OutOfMemory();
   1.862 +        return NULL;
   1.863 +    }
   1.864 +    data->surface = surface;
   1.865 +    data->window = surface;
   1.866 +
   1.867 +    renderer->WindowEvent = SW_WindowEvent;
   1.868 +    renderer->GetOutputSize = SW_GetOutputSize;
   1.869 +    renderer->CreateTexture = SW_CreateTexture;
   1.870 +    renderer->UpdateTexture = SW_UpdateTexture;
   1.871 +    renderer->LockTexture = SW_LockTexture;
   1.872 +    renderer->UnlockTexture = SW_UnlockTexture;
   1.873 +    renderer->SetRenderTarget = SW_SetRenderTarget;
   1.874 +    renderer->QueueSetViewport = SW_QueueSetViewport;
   1.875 +    renderer->QueueSetDrawColor = SW_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
   1.876 +    renderer->QueueDrawPoints = SW_QueueDrawPoints;
   1.877 +    renderer->QueueDrawLines = SW_QueueDrawPoints;  /* lines and points queue vertices the same way. */
   1.878 +    renderer->QueueFillRects = SW_QueueFillRects;
   1.879 +    renderer->QueueCopy = SW_QueueCopy;
   1.880 +    renderer->QueueCopyEx = SW_QueueCopyEx;
   1.881 +    renderer->RunCommandQueue = SW_RunCommandQueue;
   1.882 +    renderer->RenderReadPixels = SW_RenderReadPixels;
   1.883 +    renderer->RenderPresent = SW_RenderPresent;
   1.884 +    renderer->DestroyTexture = SW_DestroyTexture;
   1.885 +    renderer->DestroyRenderer = SW_DestroyRenderer;
   1.886 +    renderer->info = SW_RenderDriver.info;
   1.887 +    renderer->driverdata = data;
   1.888 +
   1.889 +    SW_ActivateRenderer(renderer);
   1.890 +
   1.891 +    return renderer;
   1.892 +}
   1.893 +
   1.894 +SDL_Renderer *
   1.895 +SW_CreateRenderer(SDL_Window * window, Uint32 flags)
   1.896 +{
   1.897 +    SDL_Surface *surface;
   1.898 +
   1.899 +    surface = SDL_GetWindowSurface(window);
   1.900 +    if (!surface) {
   1.901 +        return NULL;
   1.902 +    }
   1.903 +    return SW_CreateRendererForSurface(surface);
   1.904 +}
   1.905 +
   1.906 +SDL_RenderDriver SW_RenderDriver = {
   1.907 +    SW_CreateRenderer,
   1.908 +    {
   1.909 +     "software",
   1.910 +     SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
   1.911 +     8,
   1.912 +     {
   1.913 +      SDL_PIXELFORMAT_ARGB8888,
   1.914 +      SDL_PIXELFORMAT_ABGR8888,
   1.915 +      SDL_PIXELFORMAT_RGBA8888,
   1.916 +      SDL_PIXELFORMAT_BGRA8888,
   1.917 +      SDL_PIXELFORMAT_RGB888,
   1.918 +      SDL_PIXELFORMAT_BGR888,
   1.919 +      SDL_PIXELFORMAT_RGB565,
   1.920 +      SDL_PIXELFORMAT_RGB555
   1.921 +     },
   1.922 +     0,
   1.923 +     0}
   1.924 +};
   1.925 +
   1.926  #endif /* !SDL_RENDER_DISABLED */
   1.927  
   1.928  /* vi: set ts=4 sw=4 expandtab: */