src/render/software/SDL_render_sw.c
branchSDL-ryan-batching-renderer
changeset 12288 005e1d1bcf05
parent 11958 d7582d7286aa
child 12381 dc9108cd4340
equal deleted inserted replaced
12287:dff7e6ba9137 12288:005e1d1bcf05
    23 #if !SDL_RENDER_DISABLED
    23 #if !SDL_RENDER_DISABLED
    24 
    24 
    25 #include "../SDL_sysrender.h"
    25 #include "../SDL_sysrender.h"
    26 #include "SDL_render_sw_c.h"
    26 #include "SDL_render_sw_c.h"
    27 #include "SDL_hints.h"
    27 #include "SDL_hints.h"
       
    28 #include "SDL_assert.h"
    28 
    29 
    29 #include "SDL_draw.h"
    30 #include "SDL_draw.h"
    30 #include "SDL_blendfillrect.h"
    31 #include "SDL_blendfillrect.h"
    31 #include "SDL_blendline.h"
    32 #include "SDL_blendline.h"
    32 #include "SDL_blendpoint.h"
    33 #include "SDL_blendpoint.h"
    34 #include "SDL_drawpoint.h"
    35 #include "SDL_drawpoint.h"
    35 #include "SDL_rotate.h"
    36 #include "SDL_rotate.h"
    36 
    37 
    37 /* SDL surface based renderer implementation */
    38 /* SDL surface based renderer implementation */
    38 
    39 
    39 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
       
    40 static void SW_WindowEvent(SDL_Renderer * renderer,
       
    41                            const SDL_WindowEvent *event);
       
    42 static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
       
    43 static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
       
    44 static int SW_SetTextureColorMod(SDL_Renderer * renderer,
       
    45                                  SDL_Texture * texture);
       
    46 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
       
    47                                  SDL_Texture * texture);
       
    48 static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
       
    49                                   SDL_Texture * texture);
       
    50 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
    51                             const SDL_Rect * rect, const void *pixels,
       
    52                             int pitch);
       
    53 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
    54                           const SDL_Rect * rect, void **pixels, int *pitch);
       
    55 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
       
    56 static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
       
    57 static int SW_UpdateViewport(SDL_Renderer * renderer);
       
    58 static int SW_UpdateClipRect(SDL_Renderer * renderer);
       
    59 static int SW_RenderClear(SDL_Renderer * renderer);
       
    60 static int SW_RenderDrawPoints(SDL_Renderer * renderer,
       
    61                                const SDL_FPoint * points, int count);
       
    62 static int SW_RenderDrawLines(SDL_Renderer * renderer,
       
    63                               const SDL_FPoint * points, int count);
       
    64 static int SW_RenderFillRects(SDL_Renderer * renderer,
       
    65                               const SDL_FRect * rects, int count);
       
    66 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
       
    67                          const SDL_Rect * srcrect, const SDL_FRect * dstrect);
       
    68 static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
       
    69                           const SDL_Rect * srcrect, const SDL_FRect * dstrect,
       
    70                           const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
       
    71 static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
       
    72                                Uint32 format, void * pixels, int pitch);
       
    73 static void SW_RenderPresent(SDL_Renderer * renderer);
       
    74 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
       
    75 static void SW_DestroyRenderer(SDL_Renderer * renderer);
       
    76 
       
    77 
       
    78 SDL_RenderDriver SW_RenderDriver = {
       
    79     SW_CreateRenderer,
       
    80     {
       
    81      "software",
       
    82      SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
       
    83      8,
       
    84      {
       
    85       SDL_PIXELFORMAT_ARGB8888,
       
    86       SDL_PIXELFORMAT_ABGR8888,
       
    87       SDL_PIXELFORMAT_RGBA8888,
       
    88       SDL_PIXELFORMAT_BGRA8888,
       
    89       SDL_PIXELFORMAT_RGB888,
       
    90       SDL_PIXELFORMAT_BGR888,
       
    91       SDL_PIXELFORMAT_RGB565,
       
    92       SDL_PIXELFORMAT_RGB555
       
    93      },
       
    94      0,
       
    95      0}
       
    96 };
       
    97 
       
    98 typedef struct
    40 typedef struct
    99 {
    41 {
   100     SDL_Surface *surface;
    42     SDL_Surface *surface;
   101     SDL_Surface *window;
    43     SDL_Surface *window;
   102 } SW_RenderData;
    44 } SW_RenderData;
   112     }
    54     }
   113     if (!data->surface) {
    55     if (!data->surface) {
   114         SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
    56         SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
   115         if (surface) {
    57         if (surface) {
   116             data->surface = data->window = surface;
    58             data->surface = data->window = surface;
   117 
       
   118             SW_UpdateViewport(renderer);
       
   119             SW_UpdateClipRect(renderer);
       
   120         }
    59         }
   121     }
    60     }
   122     return data->surface;
    61     return data->surface;
   123 }
       
   124 
       
   125 SDL_Renderer *
       
   126 SW_CreateRendererForSurface(SDL_Surface * surface)
       
   127 {
       
   128     SDL_Renderer *renderer;
       
   129     SW_RenderData *data;
       
   130 
       
   131     if (!surface) {
       
   132         SDL_SetError("Can't create renderer for NULL surface");
       
   133         return NULL;
       
   134     }
       
   135 
       
   136     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
       
   137     if (!renderer) {
       
   138         SDL_OutOfMemory();
       
   139         return NULL;
       
   140     }
       
   141 
       
   142     data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
       
   143     if (!data) {
       
   144         SW_DestroyRenderer(renderer);
       
   145         SDL_OutOfMemory();
       
   146         return NULL;
       
   147     }
       
   148     data->surface = surface;
       
   149     data->window = surface;
       
   150 
       
   151     renderer->WindowEvent = SW_WindowEvent;
       
   152     renderer->GetOutputSize = SW_GetOutputSize;
       
   153     renderer->CreateTexture = SW_CreateTexture;
       
   154     renderer->SetTextureColorMod = SW_SetTextureColorMod;
       
   155     renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
       
   156     renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
       
   157     renderer->UpdateTexture = SW_UpdateTexture;
       
   158     renderer->LockTexture = SW_LockTexture;
       
   159     renderer->UnlockTexture = SW_UnlockTexture;
       
   160     renderer->SetRenderTarget = SW_SetRenderTarget;
       
   161     renderer->UpdateViewport = SW_UpdateViewport;
       
   162     renderer->UpdateClipRect = SW_UpdateClipRect;
       
   163     renderer->RenderClear = SW_RenderClear;
       
   164     renderer->RenderDrawPoints = SW_RenderDrawPoints;
       
   165     renderer->RenderDrawLines = SW_RenderDrawLines;
       
   166     renderer->RenderFillRects = SW_RenderFillRects;
       
   167     renderer->RenderCopy = SW_RenderCopy;
       
   168     renderer->RenderCopyEx = SW_RenderCopyEx;
       
   169     renderer->RenderReadPixels = SW_RenderReadPixels;
       
   170     renderer->RenderPresent = SW_RenderPresent;
       
   171     renderer->DestroyTexture = SW_DestroyTexture;
       
   172     renderer->DestroyRenderer = SW_DestroyRenderer;
       
   173     renderer->info = SW_RenderDriver.info;
       
   174     renderer->driverdata = data;
       
   175 
       
   176     SW_ActivateRenderer(renderer);
       
   177 
       
   178     return renderer;
       
   179 }
       
   180 
       
   181 SDL_Renderer *
       
   182 SW_CreateRenderer(SDL_Window * window, Uint32 flags)
       
   183 {
       
   184     SDL_Surface *surface;
       
   185 
       
   186     surface = SDL_GetWindowSurface(window);
       
   187     if (!surface) {
       
   188         return NULL;
       
   189     }
       
   190     return SW_CreateRendererForSurface(surface);
       
   191 }
    62 }
   192 
    63 
   193 static void
    64 static void
   194 SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
    65 SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   195 {
    66 {
   248 
   119 
   249     if (!texture->driverdata) {
   120     if (!texture->driverdata) {
   250         return -1;
   121         return -1;
   251     }
   122     }
   252     return 0;
   123     return 0;
   253 }
       
   254 
       
   255 static int
       
   256 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
       
   257 {
       
   258     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
       
   259     /* If the color mod is ever enabled (non-white), permanently disable RLE (which doesn't support
       
   260      * color mod) to avoid potentially frequent RLE encoding/decoding.
       
   261      */
       
   262     if ((texture->r & texture->g & texture->b) != 255) {
       
   263         SDL_SetSurfaceRLE(surface, 0);
       
   264     }
       
   265     return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
       
   266                                   texture->b);
       
   267 }
       
   268 
       
   269 static int
       
   270 SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
       
   271 {
       
   272     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
       
   273     /* If the texture ever has multiple alpha values (surface alpha plus alpha channel), permanently
       
   274      * disable RLE (which doesn't support this) to avoid potentially frequent RLE encoding/decoding.
       
   275      */
       
   276     if (texture->a != 255 && surface->format->Amask) {
       
   277         SDL_SetSurfaceRLE(surface, 0);
       
   278     }
       
   279     return SDL_SetSurfaceAlphaMod(surface, texture->a);
       
   280 }
       
   281 
       
   282 static int
       
   283 SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
       
   284 {
       
   285     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
       
   286     /* If add or mod blending are ever enabled, permanently disable RLE (which doesn't support
       
   287      * them) to avoid potentially frequent RLE encoding/decoding.
       
   288      */
       
   289     if ((texture->blendMode == SDL_BLENDMODE_ADD || texture->blendMode == SDL_BLENDMODE_MOD)) {
       
   290         SDL_SetSurfaceRLE(surface, 0);
       
   291     }
       
   292     return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
       
   293 }
   124 }
   294 
   125 
   295 static int
   126 static int
   296 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   127 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   297                  const SDL_Rect * rect, const void *pixels, int pitch)
   128                  const SDL_Rect * rect, const void *pixels, int pitch)
   348     }
   179     }
   349     return 0;
   180     return 0;
   350 }
   181 }
   351 
   182 
   352 static int
   183 static int
   353 SW_UpdateViewport(SDL_Renderer * renderer)
   184 SW_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
   354 {
   185 {
   355     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   186     return 0;  /* nothing to do in this backend. */
   356     SDL_Surface *surface = data->surface;
   187 }
   357 
   188 
   358     if (!surface) {
   189 static int
   359         /* We'll update the viewport after we recreate the surface */
   190 SW_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
   360         return 0;
   191 {
   361     }
   192     SDL_Point *verts = (SDL_Point *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Point), 0, &cmd->data.draw.first);
   362 
   193     size_t i;
   363     SDL_SetClipRect(data->surface, &renderer->viewport);
   194 
       
   195     if (!verts) {
       
   196         return -1;
       
   197     }
       
   198 
       
   199     cmd->data.draw.count = count;
       
   200 
       
   201     if (renderer->viewport.x || renderer->viewport.y) {
       
   202         const int x = renderer->viewport.x;
       
   203         const int y = renderer->viewport.y;
       
   204         for (i = 0; i < count; i++, verts++, points++) {
       
   205             verts->x = (int)(x + points->x);
       
   206             verts->y = (int)(y + points->y);
       
   207         }
       
   208     } else {
       
   209         for (i = 0; i < count; i++, verts++, points++) {
       
   210             verts->x = (int)points->x;
       
   211             verts->y = (int)points->y;
       
   212         }
       
   213     }
       
   214 
   364     return 0;
   215     return 0;
   365 }
   216 }
   366 
   217 
   367 static int
   218 static int
   368 SW_UpdateClipRect(SDL_Renderer * renderer)
   219 SW_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
   369 {
   220 {
   370     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   221     SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
   371     SDL_Surface *surface = data->surface;
   222     size_t i;
   372     if (surface) {
   223 
   373         if (renderer->clipping_enabled) {
   224     if (!verts) {
   374             SDL_Rect clip_rect;
   225         return -1;
   375             clip_rect = renderer->clip_rect;
   226     }
   376             clip_rect.x += renderer->viewport.x;
   227 
   377             clip_rect.y += renderer->viewport.y;
   228     cmd->data.draw.count = count;
   378             SDL_IntersectRect(&renderer->viewport, &clip_rect, &clip_rect);
   229 
   379             SDL_SetClipRect(surface, &clip_rect);
   230     if (renderer->viewport.x || renderer->viewport.y) {
   380         } else {
   231         const int x = renderer->viewport.x;
   381             SDL_SetClipRect(surface, &renderer->viewport);
   232         const int y = renderer->viewport.y;
   382         }
   233 
   383     }
   234         for (i = 0; i < count; i++, verts++, rects++) {
       
   235             verts->x = (int)(x + rects->x);
       
   236             verts->y = (int)(y + rects->y);
       
   237             verts->w = SDL_max((int)rects->w, 1);
       
   238             verts->h = SDL_max((int)rects->h, 1);
       
   239         }
       
   240     } else {
       
   241         for (i = 0; i < count; i++, verts++, rects++) {
       
   242             verts->x = (int)rects->x;
       
   243             verts->y = (int)rects->y;
       
   244             verts->w = SDL_max((int)rects->w, 1);
       
   245             verts->h = SDL_max((int)rects->h, 1);
       
   246         }
       
   247     }
       
   248 
   384     return 0;
   249     return 0;
   385 }
   250 }
   386 
   251 
   387 static int
   252 static int
   388 SW_RenderClear(SDL_Renderer * renderer)
   253 SW_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   389 {
   254              const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   390     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   255 {
   391     Uint32 color;
   256     SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, 2 * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
   392     SDL_Rect clip_rect;
   257 
   393 
   258     if (!verts) {
   394     if (!surface) {
   259         return -1;
   395         return -1;
   260     }
   396     }
   261 
   397 
   262     cmd->data.draw.count = 1;
   398     color = SDL_MapRGBA(surface->format,
   263 
   399                         renderer->r, renderer->g, renderer->b, renderer->a);
   264     SDL_memcpy(verts, srcrect, sizeof (SDL_Rect));
   400 
   265     verts++;
   401     /* By definition the clear ignores the clip rect */
   266 
   402     clip_rect = surface->clip_rect;
   267     if (renderer->viewport.x || renderer->viewport.y) {
   403     SDL_SetClipRect(surface, NULL);
   268         verts->x = (int)(renderer->viewport.x + dstrect->x);
   404     SDL_FillRect(surface, NULL, color);
   269         verts->y = (int)(renderer->viewport.y + dstrect->y);
   405     SDL_SetClipRect(surface, &clip_rect);
   270     } else {
       
   271         verts->x = (int)dstrect->x;
       
   272         verts->y = (int)dstrect->y;
       
   273     }
       
   274     verts->w = (int)dstrect->w;
       
   275     verts->h = (int)dstrect->h;
       
   276 
   406     return 0;
   277     return 0;
   407 }
   278 }
   408 
   279 
   409 static int
   280 typedef struct CopyExData
   410 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
   281 {
   411                     int count)
   282     SDL_Rect srcrect;
   412 {
   283     SDL_Rect dstrect;
   413     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   284     double angle;
   414     SDL_Point *final_points;
   285     SDL_FPoint center;
   415     int i, status;
   286     SDL_RendererFlip flip;
   416 
   287 } CopyExData;
   417     if (!surface) {
   288 
   418         return -1;
   289 static int
   419     }
   290 SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   420 
   291                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   421     final_points = SDL_stack_alloc(SDL_Point, count);
   292                const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   422     if (!final_points) {
   293 {
   423         return SDL_OutOfMemory();
   294     CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
   424     }
   295 
       
   296     if (!verts) {
       
   297         return -1;
       
   298     }
       
   299 
       
   300     cmd->data.draw.count = 1;
       
   301 
       
   302     SDL_memcpy(&verts->srcrect, srcrect, sizeof (SDL_Rect));
       
   303 
   425     if (renderer->viewport.x || renderer->viewport.y) {
   304     if (renderer->viewport.x || renderer->viewport.y) {
   426         int x = renderer->viewport.x;
   305         verts->dstrect.x = (int)(renderer->viewport.x + dstrect->x);
   427         int y = renderer->viewport.y;
   306         verts->dstrect.y = (int)(renderer->viewport.y + dstrect->y);
   428 
       
   429         for (i = 0; i < count; ++i) {
       
   430             final_points[i].x = (int)(x + points[i].x);
       
   431             final_points[i].y = (int)(y + points[i].y);
       
   432         }
       
   433     } else {
   307     } else {
   434         for (i = 0; i < count; ++i) {
   308         verts->dstrect.x = (int)dstrect->x;
   435             final_points[i].x = (int)points[i].x;
   309         verts->dstrect.y = (int)dstrect->y;
   436             final_points[i].y = (int)points[i].y;
   310     }
   437         }
   311     verts->dstrect.w = (int)dstrect->w;
   438     }
   312     verts->dstrect.h = (int)dstrect->h;
   439 
   313     verts->angle = angle;
   440     /* Draw the points! */
   314     SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
   441     if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   315     verts->flip = flip;
   442         Uint32 color = SDL_MapRGBA(surface->format,
   316 
   443                                    renderer->r, renderer->g, renderer->b,
   317     return 0;
   444                                    renderer->a);
   318 }
   445 
   319 
   446         status = SDL_DrawPoints(surface, final_points, count, color);
   320 static int
   447     } else {
   321 SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * texture,
   448         status = SDL_BlendPoints(surface, final_points, count,
   322                 const SDL_Rect * srcrect, const SDL_Rect * final_rect,
   449                                 renderer->blendMode,
   323                 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
   450                                 renderer->r, renderer->g, renderer->b,
   324 {
   451                                 renderer->a);
       
   452     }
       
   453     SDL_stack_free(final_points);
       
   454 
       
   455     return status;
       
   456 }
       
   457 
       
   458 static int
       
   459 SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
       
   460                    int count)
       
   461 {
       
   462     SDL_Surface *surface = SW_ActivateRenderer(renderer);
       
   463     SDL_Point *final_points;
       
   464     int i, status;
       
   465 
       
   466     if (!surface) {
       
   467         return -1;
       
   468     }
       
   469 
       
   470     final_points = SDL_stack_alloc(SDL_Point, count);
       
   471     if (!final_points) {
       
   472         return SDL_OutOfMemory();
       
   473     }
       
   474     if (renderer->viewport.x || renderer->viewport.y) {
       
   475         int x = renderer->viewport.x;
       
   476         int y = renderer->viewport.y;
       
   477 
       
   478         for (i = 0; i < count; ++i) {
       
   479             final_points[i].x = (int)(x + points[i].x);
       
   480             final_points[i].y = (int)(y + points[i].y);
       
   481         }
       
   482     } else {
       
   483         for (i = 0; i < count; ++i) {
       
   484             final_points[i].x = (int)points[i].x;
       
   485             final_points[i].y = (int)points[i].y;
       
   486         }
       
   487     }
       
   488 
       
   489     /* Draw the lines! */
       
   490     if (renderer->blendMode == SDL_BLENDMODE_NONE) {
       
   491         Uint32 color = SDL_MapRGBA(surface->format,
       
   492                                    renderer->r, renderer->g, renderer->b,
       
   493                                    renderer->a);
       
   494 
       
   495         status = SDL_DrawLines(surface, final_points, count, color);
       
   496     } else {
       
   497         status = SDL_BlendLines(surface, final_points, count,
       
   498                                 renderer->blendMode,
       
   499                                 renderer->r, renderer->g, renderer->b,
       
   500                                 renderer->a);
       
   501     }
       
   502     SDL_stack_free(final_points);
       
   503 
       
   504     return status;
       
   505 }
       
   506 
       
   507 static int
       
   508 SW_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
       
   509 {
       
   510     SDL_Surface *surface = SW_ActivateRenderer(renderer);
       
   511     SDL_Rect *final_rects;
       
   512     int i, status;
       
   513 
       
   514     if (!surface) {
       
   515         return -1;
       
   516     }
       
   517 
       
   518     final_rects = SDL_stack_alloc(SDL_Rect, count);
       
   519     if (!final_rects) {
       
   520         return SDL_OutOfMemory();
       
   521     }
       
   522     if (renderer->viewport.x || renderer->viewport.y) {
       
   523         int x = renderer->viewport.x;
       
   524         int y = renderer->viewport.y;
       
   525 
       
   526         for (i = 0; i < count; ++i) {
       
   527             final_rects[i].x = (int)(x + rects[i].x);
       
   528             final_rects[i].y = (int)(y + rects[i].y);
       
   529             final_rects[i].w = SDL_max((int)rects[i].w, 1);
       
   530             final_rects[i].h = SDL_max((int)rects[i].h, 1);
       
   531         }
       
   532     } else {
       
   533         for (i = 0; i < count; ++i) {
       
   534             final_rects[i].x = (int)rects[i].x;
       
   535             final_rects[i].y = (int)rects[i].y;
       
   536             final_rects[i].w = SDL_max((int)rects[i].w, 1);
       
   537             final_rects[i].h = SDL_max((int)rects[i].h, 1);
       
   538         }
       
   539     }
       
   540 
       
   541     if (renderer->blendMode == SDL_BLENDMODE_NONE) {
       
   542         Uint32 color = SDL_MapRGBA(surface->format,
       
   543                                    renderer->r, renderer->g, renderer->b,
       
   544                                    renderer->a);
       
   545         status = SDL_FillRects(surface, final_rects, count, color);
       
   546     } else {
       
   547         status = SDL_BlendFillRects(surface, final_rects, count,
       
   548                                     renderer->blendMode,
       
   549                                     renderer->r, renderer->g, renderer->b,
       
   550                                     renderer->a);
       
   551     }
       
   552     SDL_stack_free(final_rects);
       
   553 
       
   554     return status;
       
   555 }
       
   556 
       
   557 static int
       
   558 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
       
   559               const SDL_Rect * srcrect, const SDL_FRect * dstrect)
       
   560 {
       
   561     SDL_Surface *surface = SW_ActivateRenderer(renderer);
       
   562     SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   325     SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   563     SDL_Rect final_rect;
   326     SDL_Rect tmp_rect;
   564 
       
   565     if (!surface) {
       
   566         return -1;
       
   567     }
       
   568 
       
   569     if (renderer->viewport.x || renderer->viewport.y) {
       
   570         final_rect.x = (int)(renderer->viewport.x + dstrect->x);
       
   571         final_rect.y = (int)(renderer->viewport.y + dstrect->y);
       
   572     } else {
       
   573         final_rect.x = (int)dstrect->x;
       
   574         final_rect.y = (int)dstrect->y;
       
   575     }
       
   576     final_rect.w = (int)dstrect->w;
       
   577     final_rect.h = (int)dstrect->h;
       
   578 
       
   579     if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {
       
   580         return SDL_BlitSurface(src, srcrect, surface, &final_rect);
       
   581     } else {
       
   582         /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
       
   583          * to avoid potentially frequent RLE encoding/decoding.
       
   584          */
       
   585         SDL_SetSurfaceRLE(surface, 0);
       
   586         return SDL_BlitScaled(src, srcrect, surface, &final_rect);
       
   587     }
       
   588 }
       
   589 
       
   590 static int
       
   591 SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
       
   592                 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
       
   593                 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
       
   594 {
       
   595     SDL_Surface *surface = SW_ActivateRenderer(renderer);
       
   596     SDL_Surface *src = (SDL_Surface *) texture->driverdata;
       
   597     SDL_Rect final_rect, tmp_rect;
       
   598     SDL_Surface *src_clone, *src_rotated, *src_scaled;
   327     SDL_Surface *src_clone, *src_rotated, *src_scaled;
   599     SDL_Surface *mask = NULL, *mask_rotated = NULL;
   328     SDL_Surface *mask = NULL, *mask_rotated = NULL;
   600     int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
   329     int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
   601     double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
   330     double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
   602     SDL_BlendMode blendmode;
   331     SDL_BlendMode blendmode;
   607 
   336 
   608     if (!surface) {
   337     if (!surface) {
   609         return -1;
   338         return -1;
   610     }
   339     }
   611 
   340 
   612     if (renderer->viewport.x || renderer->viewport.y) {
       
   613         final_rect.x = (int)(renderer->viewport.x + dstrect->x);
       
   614         final_rect.y = (int)(renderer->viewport.y + dstrect->y);
       
   615     } else {
       
   616         final_rect.x = (int)dstrect->x;
       
   617         final_rect.y = (int)dstrect->y;
       
   618     }
       
   619     final_rect.w = (int)dstrect->w;
       
   620     final_rect.h = (int)dstrect->h;
       
   621 
       
   622     tmp_rect = final_rect;
       
   623     tmp_rect.x = 0;
   341     tmp_rect.x = 0;
   624     tmp_rect.y = 0;
   342     tmp_rect.y = 0;
       
   343     tmp_rect.w = final_rect->w;
       
   344     tmp_rect.h = final_rect->h;
   625 
   345 
   626     /* It is possible to encounter an RLE encoded surface here and locking it is
   346     /* It is possible to encounter an RLE encoded surface here and locking it is
   627      * necessary because this code is going to access the pixel buffer directly.
   347      * necessary because this code is going to access the pixel buffer directly.
   628      */
   348      */
   629     if (SDL_MUSTLOCK(src)) {
   349     if (SDL_MUSTLOCK(src)) {
   651     if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) {
   371     if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) {
   652         blitRequired = SDL_TRUE;
   372         blitRequired = SDL_TRUE;
   653     }
   373     }
   654 
   374 
   655     /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
   375     /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
   656     if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) {
   376     if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) {
   657         blitRequired = SDL_TRUE;
   377         blitRequired = SDL_TRUE;
   658     }
   378     }
   659 
   379 
   660     /* The color and alpha modulation has to be applied before the rotation when using the NONE and MOD blend modes. */
   380     /* The color and alpha modulation has to be applied before the rotation when using the NONE and MOD blend modes. */
   661     if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD) && (alphaMod & rMod & gMod & bMod) != 255) {
   381     if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD) && (alphaMod & rMod & gMod & bMod) != 255) {
   671 
   391 
   672     /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used
   392     /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used
   673      * to clear the pixels in the destination surface. The other steps are explained below.
   393      * to clear the pixels in the destination surface. The other steps are explained below.
   674      */
   394      */
   675     if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
   395     if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
   676         mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
   396         mask = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
   677                                     0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
   397                                     0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
   678         if (mask == NULL) {
   398         if (mask == NULL) {
   679             retval = -1;
   399             retval = -1;
   680         } else {
   400         } else {
   681             SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD);
   401             SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD);
   685     /* Create a new surface should there be a format mismatch or if scaling, cropping,
   405     /* Create a new surface should there be a format mismatch or if scaling, cropping,
   686      * or modulation is required. It's possible to use the source surface directly otherwise.
   406      * or modulation is required. It's possible to use the source surface directly otherwise.
   687      */
   407      */
   688     if (!retval && (blitRequired || applyModulation)) {
   408     if (!retval && (blitRequired || applyModulation)) {
   689         SDL_Rect scale_rect = tmp_rect;
   409         SDL_Rect scale_rect = tmp_rect;
   690         src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
   410         src_scaled = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
   691                                           0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
   411                                           0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
   692         if (src_scaled == NULL) {
   412         if (src_scaled == NULL) {
   693             retval = -1;
   413             retval = -1;
   694         } else {
   414         } else {
   695             SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
   415             SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
   716                 retval = -1;
   436                 retval = -1;
   717             }
   437             }
   718         }
   438         }
   719         if (!retval) {
   439         if (!retval) {
   720             /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
   440             /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
   721             abscenterx = final_rect.x + (int)center->x;
   441             abscenterx = final_rect->x + (int)center->x;
   722             abscentery = final_rect.y + (int)center->y;
   442             abscentery = final_rect->y + (int)center->y;
   723             /* Compensate the angle inversion to match the behaviour of the other backends */
   443             /* Compensate the angle inversion to match the behaviour of the other backends */
   724             sangle = -sangle;
   444             sangle = -sangle;
   725 
   445 
   726             /* Top Left */
   446             /* Top Left */
   727             px = final_rect.x - abscenterx;
   447             px = final_rect->x - abscenterx;
   728             py = final_rect.y - abscentery;
   448             py = final_rect->y - abscentery;
   729             p1x = px * cangle - py * sangle + abscenterx;
   449             p1x = px * cangle - py * sangle + abscenterx;
   730             p1y = px * sangle + py * cangle + abscentery;
   450             p1y = px * sangle + py * cangle + abscentery;
   731 
   451 
   732             /* Top Right */
   452             /* Top Right */
   733             px = final_rect.x + final_rect.w - abscenterx;
   453             px = final_rect->x + final_rect->w - abscenterx;
   734             py = final_rect.y - abscentery;
   454             py = final_rect->y - abscentery;
   735             p2x = px * cangle - py * sangle + abscenterx;
   455             p2x = px * cangle - py * sangle + abscenterx;
   736             p2y = px * sangle + py * cangle + abscentery;
   456             p2y = px * sangle + py * cangle + abscentery;
   737 
   457 
   738             /* Bottom Left */
   458             /* Bottom Left */
   739             px = final_rect.x - abscenterx;
   459             px = final_rect->x - abscenterx;
   740             py = final_rect.y + final_rect.h - abscentery;
   460             py = final_rect->y + final_rect->h - abscentery;
   741             p3x = px * cangle - py * sangle + abscenterx;
   461             p3x = px * cangle - py * sangle + abscenterx;
   742             p3y = px * sangle + py * cangle + abscentery;
   462             p3y = px * sangle + py * cangle + abscentery;
   743 
   463 
   744             /* Bottom Right */
   464             /* Bottom Right */
   745             px = final_rect.x + final_rect.w - abscenterx;
   465             px = final_rect->x + final_rect->w - abscenterx;
   746             py = final_rect.y + final_rect.h - abscentery;
   466             py = final_rect->y + final_rect->h - abscentery;
   747             p4x = px * cangle - py * sangle + abscenterx;
   467             p4x = px * cangle - py * sangle + abscenterx;
   748             p4y = px * sangle + py * cangle + abscentery;
   468             p4y = px * sangle + py * cangle + abscentery;
   749 
   469 
   750             tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
   470             tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
   751             tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
   471             tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
   817         SDL_FreeSurface(src_clone);
   537         SDL_FreeSurface(src_clone);
   818     }
   538     }
   819     return retval;
   539     return retval;
   820 }
   540 }
   821 
   541 
       
   542 static void
       
   543 PrepTextureForCopy(const SDL_RenderCommand *cmd)
       
   544 {
       
   545     const Uint8 r = cmd->data.draw.r;
       
   546     const Uint8 g = cmd->data.draw.g;
       
   547     const Uint8 b = cmd->data.draw.b;
       
   548     const Uint8 a = cmd->data.draw.a;
       
   549     const SDL_BlendMode blend = cmd->data.draw.blend;
       
   550     SDL_Texture *texture = cmd->data.draw.texture;
       
   551     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
       
   552 
       
   553     if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
       
   554         SDL_SetSurfaceRLE(surface, 0);
       
   555         SDL_SetSurfaceColorMod(surface, r, g, b);
       
   556     }
       
   557 
       
   558     if ((texture->modMode & SDL_TEXTUREMODULATE_ALPHA) && surface->format->Amask) {
       
   559         SDL_SetSurfaceRLE(surface, 0);
       
   560         SDL_SetSurfaceAlphaMod(surface, a);
       
   561     }
       
   562 
       
   563     if ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD)) {
       
   564         SDL_SetSurfaceRLE(surface, 0);
       
   565     }
       
   566     SDL_SetSurfaceBlendMode(surface, blend);
       
   567 }
       
   568 
       
   569 static int
       
   570 SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
       
   571 {
       
   572     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
       
   573     SDL_Surface *surface = SW_ActivateRenderer(renderer);
       
   574     const SDL_Rect *viewport = NULL;
       
   575     const SDL_Rect *cliprect = NULL;
       
   576 
       
   577     if (!surface) {
       
   578         return -1;
       
   579     }
       
   580 
       
   581     while (cmd) {
       
   582         switch (cmd->command) {
       
   583             case SDL_RENDERCMD_SETDRAWCOLOR: {
       
   584                 break;  /* Not used in this backend. */
       
   585             }
       
   586 
       
   587             case SDL_RENDERCMD_SETVIEWPORT: {
       
   588                 viewport = &cmd->data.viewport.rect;
       
   589                 SDL_SetClipRect(data->surface, viewport);
       
   590                 break;
       
   591             }
       
   592 
       
   593             case SDL_RENDERCMD_SETCLIPRECT: {
       
   594                 SDL_assert(viewport != NULL);
       
   595                 cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
       
   596                 if (cliprect) {
       
   597                     SDL_Rect clip_rect = { cliprect->x + viewport->x, cliprect->y + viewport->y, cliprect->w, cliprect->h };
       
   598                     SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
       
   599                     SDL_SetClipRect(surface, &clip_rect);
       
   600                 } else {
       
   601                     SDL_SetClipRect(surface, viewport);
       
   602                 }
       
   603                 break;
       
   604             }
       
   605 
       
   606             case SDL_RENDERCMD_CLEAR: {
       
   607                 const Uint8 r = cmd->data.color.r;
       
   608                 const Uint8 g = cmd->data.color.g;
       
   609                 const Uint8 b = cmd->data.color.b;
       
   610                 const Uint8 a = cmd->data.color.a;
       
   611                 const SDL_Rect clip_rect = surface->clip_rect;
       
   612                 /* By definition the clear ignores the clip rect */
       
   613                 SDL_SetClipRect(surface, NULL);
       
   614                 SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
       
   615                 SDL_SetClipRect(surface, &clip_rect);
       
   616                 break;
       
   617             }
       
   618 
       
   619             case SDL_RENDERCMD_DRAW_POINTS: {
       
   620                 const Uint8 r = cmd->data.draw.r;
       
   621                 const Uint8 g = cmd->data.draw.g;
       
   622                 const Uint8 b = cmd->data.draw.b;
       
   623                 const Uint8 a = cmd->data.draw.a;
       
   624                 const size_t count = cmd->data.draw.count;
       
   625                 const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
       
   626                 const SDL_BlendMode blend = cmd->data.draw.blend;
       
   627                 if (blend == SDL_BLENDMODE_NONE) {
       
   628                     SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
       
   629                 } else {
       
   630                     SDL_BlendPoints(surface, verts, count, blend, r, g, b, a);
       
   631                 }
       
   632                 break;
       
   633             }
       
   634 
       
   635             case SDL_RENDERCMD_DRAW_LINES: {
       
   636                 const Uint8 r = cmd->data.draw.r;
       
   637                 const Uint8 g = cmd->data.draw.g;
       
   638                 const Uint8 b = cmd->data.draw.b;
       
   639                 const Uint8 a = cmd->data.draw.a;
       
   640                 const size_t count = cmd->data.draw.count;
       
   641                 const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
       
   642                 const SDL_BlendMode blend = cmd->data.draw.blend;
       
   643                 if (blend == SDL_BLENDMODE_NONE) {
       
   644                     SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
       
   645                 } else {
       
   646                     SDL_BlendLines(surface, verts, count, blend, r, g, b, a);
       
   647                 }
       
   648                 break;
       
   649             }
       
   650 
       
   651             case SDL_RENDERCMD_FILL_RECTS: {
       
   652                 const Uint8 r = cmd->data.draw.r;
       
   653                 const Uint8 g = cmd->data.draw.g;
       
   654                 const Uint8 b = cmd->data.draw.b;
       
   655                 const Uint8 a = cmd->data.draw.a;
       
   656                 const size_t count = cmd->data.draw.count;
       
   657                 const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
       
   658                 const SDL_BlendMode blend = cmd->data.draw.blend;
       
   659                 if (blend == SDL_BLENDMODE_NONE) {
       
   660                     SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
       
   661                 } else {
       
   662                     SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a);
       
   663                 }
       
   664                 break;
       
   665             }
       
   666 
       
   667             case SDL_RENDERCMD_COPY: {
       
   668                 SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
       
   669                 const SDL_Rect *srcrect = verts;
       
   670                 SDL_Rect *dstrect = verts + 1;
       
   671                 SDL_Texture *texture = cmd->data.draw.texture;
       
   672                 SDL_Surface *src = (SDL_Surface *) texture->driverdata;
       
   673 
       
   674                 PrepTextureForCopy(cmd);
       
   675 
       
   676                 if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
       
   677                     SDL_BlitSurface(src, srcrect, surface, dstrect);
       
   678                 } else {
       
   679                     /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
       
   680                      * to avoid potentially frequent RLE encoding/decoding.
       
   681                      */
       
   682                     SDL_SetSurfaceRLE(surface, 0);
       
   683                     SDL_BlitScaled(src, srcrect, surface, dstrect);
       
   684                 }
       
   685                 break;
       
   686             }
       
   687 
       
   688             case SDL_RENDERCMD_COPY_EX: {
       
   689                 const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
       
   690                 PrepTextureForCopy(cmd);
       
   691                 SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
       
   692                                 &copydata->dstrect, copydata->angle, &copydata->center, copydata->flip);
       
   693                 break;
       
   694             }
       
   695 
       
   696             case SDL_RENDERCMD_NO_OP:
       
   697                 break;
       
   698         }
       
   699 
       
   700         cmd = cmd->next;
       
   701     }
       
   702 
       
   703     return 0;
       
   704 }
       
   705 
   822 static int
   706 static int
   823 SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   707 SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   824                     Uint32 format, void * pixels, int pitch)
   708                     Uint32 format, void * pixels, int pitch)
   825 {
   709 {
   826     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   710     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   875 
   759 
   876     SDL_free(data);
   760     SDL_free(data);
   877     SDL_free(renderer);
   761     SDL_free(renderer);
   878 }
   762 }
   879 
   763 
       
   764 SDL_Renderer *
       
   765 SW_CreateRendererForSurface(SDL_Surface * surface)
       
   766 {
       
   767     SDL_Renderer *renderer;
       
   768     SW_RenderData *data;
       
   769 
       
   770     if (!surface) {
       
   771         SDL_SetError("Can't create renderer for NULL surface");
       
   772         return NULL;
       
   773     }
       
   774 
       
   775     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
       
   776     if (!renderer) {
       
   777         SDL_OutOfMemory();
       
   778         return NULL;
       
   779     }
       
   780 
       
   781     data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
       
   782     if (!data) {
       
   783         SW_DestroyRenderer(renderer);
       
   784         SDL_OutOfMemory();
       
   785         return NULL;
       
   786     }
       
   787     data->surface = surface;
       
   788     data->window = surface;
       
   789 
       
   790     renderer->WindowEvent = SW_WindowEvent;
       
   791     renderer->GetOutputSize = SW_GetOutputSize;
       
   792     renderer->CreateTexture = SW_CreateTexture;
       
   793     renderer->UpdateTexture = SW_UpdateTexture;
       
   794     renderer->LockTexture = SW_LockTexture;
       
   795     renderer->UnlockTexture = SW_UnlockTexture;
       
   796     renderer->SetRenderTarget = SW_SetRenderTarget;
       
   797     renderer->QueueSetViewport = SW_QueueSetViewport;
       
   798     renderer->QueueSetDrawColor = SW_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
       
   799     renderer->QueueDrawPoints = SW_QueueDrawPoints;
       
   800     renderer->QueueDrawLines = SW_QueueDrawPoints;  /* lines and points queue vertices the same way. */
       
   801     renderer->QueueFillRects = SW_QueueFillRects;
       
   802     renderer->QueueCopy = SW_QueueCopy;
       
   803     renderer->QueueCopyEx = SW_QueueCopyEx;
       
   804     renderer->RunCommandQueue = SW_RunCommandQueue;
       
   805     renderer->RenderReadPixels = SW_RenderReadPixels;
       
   806     renderer->RenderPresent = SW_RenderPresent;
       
   807     renderer->DestroyTexture = SW_DestroyTexture;
       
   808     renderer->DestroyRenderer = SW_DestroyRenderer;
       
   809     renderer->info = SW_RenderDriver.info;
       
   810     renderer->driverdata = data;
       
   811 
       
   812     SW_ActivateRenderer(renderer);
       
   813 
       
   814     return renderer;
       
   815 }
       
   816 
       
   817 SDL_Renderer *
       
   818 SW_CreateRenderer(SDL_Window * window, Uint32 flags)
       
   819 {
       
   820     SDL_Surface *surface;
       
   821 
       
   822     surface = SDL_GetWindowSurface(window);
       
   823     if (!surface) {
       
   824         return NULL;
       
   825     }
       
   826     return SW_CreateRendererForSurface(surface);
       
   827 }
       
   828 
       
   829 SDL_RenderDriver SW_RenderDriver = {
       
   830     SW_CreateRenderer,
       
   831     {
       
   832      "software",
       
   833      SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
       
   834      8,
       
   835      {
       
   836       SDL_PIXELFORMAT_ARGB8888,
       
   837       SDL_PIXELFORMAT_ABGR8888,
       
   838       SDL_PIXELFORMAT_RGBA8888,
       
   839       SDL_PIXELFORMAT_BGRA8888,
       
   840       SDL_PIXELFORMAT_RGB888,
       
   841       SDL_PIXELFORMAT_BGR888,
       
   842       SDL_PIXELFORMAT_RGB565,
       
   843       SDL_PIXELFORMAT_RGB555
       
   844      },
       
   845      0,
       
   846      0}
       
   847 };
       
   848 
   880 #endif /* !SDL_RENDER_DISABLED */
   849 #endif /* !SDL_RENDER_DISABLED */
   881 
   850 
   882 /* vi: set ts=4 sw=4 expandtab: */
   851 /* vi: set ts=4 sw=4 expandtab: */