src/video/SDL_renderer_sw.c
author Edgar Simo <bobbens@gmail.com>
Sun, 06 Jul 2008 17:06:37 +0000
branchgsoc2008_force_feedback
changeset 2498 ab567bd667bf
parent 2267 c785543d1843
child 2698 e1da92da346c
permissions -rw-r--r--
Fixed various mistakes in the doxygen.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_video.h"
    25 #include "SDL_sysvideo.h"
    26 #include "SDL_pixels_c.h"
    27 #include "SDL_rect_c.h"
    28 #include "SDL_yuv_sw_c.h"
    29 
    30 
    31 /* SDL surface based renderer implementation */
    32 
    33 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
    34 static int SW_ActivateRenderer(SDL_Renderer * renderer);
    35 static int SW_DisplayModeChanged(SDL_Renderer * renderer);
    36 static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    37 static int SW_QueryTexturePixels(SDL_Renderer * renderer,
    38                                  SDL_Texture * texture, void **pixels,
    39                                  int *pitch);
    40 static int SW_SetTexturePalette(SDL_Renderer * renderer,
    41                                 SDL_Texture * texture,
    42                                 const SDL_Color * colors, int firstcolor,
    43                                 int ncolors);
    44 static int SW_GetTexturePalette(SDL_Renderer * renderer,
    45                                 SDL_Texture * texture, SDL_Color * colors,
    46                                 int firstcolor, int ncolors);
    47 static int SW_SetTextureColorMod(SDL_Renderer * renderer,
    48                                  SDL_Texture * texture);
    49 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
    50                                  SDL_Texture * texture);
    51 static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
    52                                   SDL_Texture * texture);
    53 static int SW_SetTextureScaleMode(SDL_Renderer * renderer,
    54                                   SDL_Texture * texture);
    55 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    56                             const SDL_Rect * rect, const void *pixels,
    57                             int pitch);
    58 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    59                           const SDL_Rect * rect, int markDirty, void **pixels,
    60                           int *pitch);
    61 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    62 static void SW_DirtyTexture(SDL_Renderer * renderer,
    63                             SDL_Texture * texture, int numrects,
    64                             const SDL_Rect * rects);
    65 static int SW_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
    66                          Uint8 a, const SDL_Rect * rect);
    67 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    68                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
    69 static void SW_RenderPresent(SDL_Renderer * renderer);
    70 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    71 static void SW_DestroyRenderer(SDL_Renderer * renderer);
    72 
    73 
    74 SDL_RenderDriver SW_RenderDriver = {
    75     SW_CreateRenderer,
    76     {
    77      "software",
    78      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
    79       SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
    80       SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC),
    81      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
    82       SDL_TEXTUREMODULATE_ALPHA),
    83      (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
    84       SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
    85       SDL_TEXTUREBLENDMODE_MOD),
    86      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST),
    87      11,
    88      {
    89       SDL_PIXELFORMAT_INDEX8,
    90       SDL_PIXELFORMAT_RGB555,
    91       SDL_PIXELFORMAT_RGB565,
    92       SDL_PIXELFORMAT_RGB888,
    93       SDL_PIXELFORMAT_BGR888,
    94       SDL_PIXELFORMAT_ARGB8888,
    95       SDL_PIXELFORMAT_RGBA8888,
    96       SDL_PIXELFORMAT_ABGR8888,
    97       SDL_PIXELFORMAT_BGRA8888,
    98       SDL_PIXELFORMAT_YUY2,
    99       SDL_PIXELFORMAT_UYVY},
   100      0,
   101      0}
   102 };
   103 
   104 typedef struct
   105 {
   106     Uint32 format;
   107     SDL_bool updateSize;
   108     int current_texture;
   109     SDL_Texture *texture[3];
   110     SDL_Surface surface;
   111     SDL_Renderer *renderer;
   112     SDL_DirtyRectList dirty;
   113 } SW_RenderData;
   114 
   115 static SDL_Texture *
   116 CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h)
   117 {
   118     SDL_Texture *texture;
   119 
   120     texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
   121     if (!texture) {
   122         SDL_OutOfMemory();
   123         return NULL;
   124     }
   125 
   126     texture->format = format;
   127     texture->access = SDL_TEXTUREACCESS_STREAMING;
   128     texture->w = w;
   129     texture->h = h;
   130     texture->renderer = renderer;
   131 
   132     if (renderer->CreateTexture(renderer, texture) < 0) {
   133         SDL_free(texture);
   134         return NULL;
   135     }
   136     return texture;
   137 }
   138 
   139 static void
   140 DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   141 {
   142     renderer->DestroyTexture(renderer, texture);
   143     SDL_free(texture);
   144 }
   145 
   146 static int
   147 DisplayPaletteChanged(void *userdata, SDL_Palette * palette)
   148 {
   149     SW_RenderData *data = (SW_RenderData *) userdata;
   150     int i;
   151 
   152     for (i = 0; i < SDL_arraysize(data->texture); ++i) {
   153         if (data->texture[i] && data->renderer->SetTexturePalette) {
   154             data->renderer->SetTexturePalette(data->renderer,
   155                                               data->texture[i],
   156                                               palette->colors, 0,
   157                                               palette->ncolors);
   158         }
   159     }
   160     return 0;
   161 }
   162 
   163 void
   164 Setup_SoftwareRenderer(SDL_Renderer * renderer)
   165 {
   166     renderer->CreateTexture = SW_CreateTexture;
   167     renderer->QueryTexturePixels = SW_QueryTexturePixels;
   168     renderer->SetTexturePalette = SW_SetTexturePalette;
   169     renderer->GetTexturePalette = SW_GetTexturePalette;
   170     renderer->SetTextureColorMod = SW_SetTextureColorMod;
   171     renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
   172     renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
   173     renderer->SetTextureScaleMode = SW_SetTextureScaleMode;
   174     renderer->UpdateTexture = SW_UpdateTexture;
   175     renderer->LockTexture = SW_LockTexture;
   176     renderer->UnlockTexture = SW_UnlockTexture;
   177     renderer->DirtyTexture = SW_DirtyTexture;
   178     renderer->DestroyTexture = SW_DestroyTexture;
   179 
   180     renderer->info.mod_modes = SW_RenderDriver.info.mod_modes;
   181     renderer->info.blend_modes = SW_RenderDriver.info.blend_modes;
   182     renderer->info.scale_modes = SW_RenderDriver.info.scale_modes;
   183     renderer->info.num_texture_formats =
   184         SW_RenderDriver.info.num_texture_formats;
   185     SDL_memcpy(renderer->info.texture_formats,
   186                SW_RenderDriver.info.texture_formats,
   187                sizeof(renderer->info.texture_formats));;
   188     renderer->info.max_texture_width = SW_RenderDriver.info.max_texture_width;
   189     renderer->info.max_texture_height =
   190         SW_RenderDriver.info.max_texture_height;
   191 }
   192 
   193 SDL_Renderer *
   194 SW_CreateRenderer(SDL_Window * window, Uint32 flags)
   195 {
   196     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   197     SDL_DisplayMode *displayMode = &display->current_mode;
   198     SDL_Renderer *renderer;
   199     SW_RenderData *data;
   200     int i, n;
   201     int bpp;
   202     Uint32 Rmask, Gmask, Bmask, Amask;
   203     Uint32 renderer_flags;
   204     const char *desired_driver;
   205 
   206     if (!SDL_PixelFormatEnumToMasks
   207         (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   208         SDL_SetError("Unknown display format");
   209         return NULL;
   210     }
   211 
   212     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   213     if (!renderer) {
   214         SDL_OutOfMemory();
   215         return NULL;
   216     }
   217 
   218     data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
   219     if (!data) {
   220         SW_DestroyRenderer(renderer);
   221         SDL_OutOfMemory();
   222         return NULL;
   223     }
   224     renderer->ActivateRenderer = SW_ActivateRenderer;
   225     renderer->DisplayModeChanged = SW_DisplayModeChanged;
   226     renderer->RenderFill = SW_RenderFill;
   227     renderer->RenderCopy = SW_RenderCopy;
   228     renderer->RenderPresent = SW_RenderPresent;
   229     renderer->DestroyRenderer = SW_DestroyRenderer;
   230     renderer->info.name = SW_RenderDriver.info.name;
   231     renderer->info.flags = 0;
   232     renderer->window = window->id;
   233     renderer->driverdata = data;
   234     Setup_SoftwareRenderer(renderer);
   235 
   236     if (flags & SDL_RENDERER_PRESENTFLIP2) {
   237         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
   238         n = 2;
   239     } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
   240         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
   241         n = 3;
   242     } else {
   243         renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
   244         n = 1;
   245     }
   246     data->format = displayMode->format;
   247 
   248     /* Find a render driver that we can use to display data */
   249     renderer_flags = (SDL_RENDERER_SINGLEBUFFER |
   250                       SDL_RENDERER_PRESENTDISCARD);
   251     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   252         renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
   253     }
   254     desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER");
   255     for (i = 0; i < display->num_render_drivers; ++i) {
   256         SDL_RenderDriver *driver = &display->render_drivers[i];
   257         if (driver->info.name == SW_RenderDriver.info.name) {
   258             continue;
   259         }
   260         if (desired_driver
   261             && SDL_strcasecmp(desired_driver, driver->info.name) != 0) {
   262             continue;
   263         }
   264         data->renderer = driver->CreateRenderer(window, renderer_flags);
   265         if (data->renderer) {
   266             break;
   267         }
   268     }
   269     if (i == display->num_render_drivers) {
   270         SW_DestroyRenderer(renderer);
   271         SDL_SetError("Couldn't find display render driver");
   272         return NULL;
   273     }
   274     if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
   275         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   276     }
   277 
   278     /* Create the textures we'll use for display */
   279     for (i = 0; i < n; ++i) {
   280         data->texture[i] =
   281             CreateTexture(data->renderer, data->format, window->w, window->h);
   282         if (!data->texture[i]) {
   283             SW_DestroyRenderer(renderer);
   284             return NULL;
   285         }
   286     }
   287     data->current_texture = 0;
   288 
   289     /* Create a surface we'll use for rendering */
   290     data->surface.flags = SDL_PREALLOC;
   291     data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
   292     if (!data->surface.format) {
   293         SW_DestroyRenderer(renderer);
   294         return NULL;
   295     }
   296     SDL_SetSurfacePalette(&data->surface, display->palette);
   297 
   298     /* Set up a palette watch on the display palette */
   299     if (display->palette) {
   300         SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data);
   301     }
   302 
   303     return renderer;
   304 }
   305 
   306 static int
   307 SW_ActivateRenderer(SDL_Renderer * renderer)
   308 {
   309     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   310     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   311     int i, n;
   312 
   313     if (data->renderer && data->renderer->ActivateRenderer) {
   314         if (data->renderer->ActivateRenderer(data->renderer) < 0) {
   315             return -1;
   316         }
   317     }
   318     if (data->updateSize) {
   319         /* Recreate the textures for the new window size */
   320         if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
   321             n = 2;
   322         } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
   323             n = 3;
   324         } else {
   325             n = 1;
   326         }
   327         for (i = 0; i < n; ++i) {
   328             if (data->texture[i]) {
   329                 DestroyTexture(data->renderer, data->texture[i]);
   330                 data->texture[i] = 0;
   331             }
   332         }
   333         for (i = 0; i < n; ++i) {
   334             data->texture[i] =
   335                 CreateTexture(data->renderer, data->format, window->w,
   336                               window->h);
   337             if (!data->texture[i]) {
   338                 return -1;
   339             }
   340         }
   341         data->updateSize = SDL_FALSE;
   342     }
   343     return 0;
   344 }
   345 
   346 static int
   347 SW_DisplayModeChanged(SDL_Renderer * renderer)
   348 {
   349     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   350 
   351     if (data->renderer && data->renderer->DisplayModeChanged) {
   352         if (data->renderer->DisplayModeChanged(data->renderer) < 0) {
   353             return -1;
   354         }
   355     }
   356     data->updateSize = SDL_TRUE;
   357     return 0;
   358 }
   359 
   360 static int
   361 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   362 {
   363     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   364         texture->driverdata = SDL_SW_CreateYUVTexture(texture);
   365     } else {
   366         int bpp;
   367         Uint32 Rmask, Gmask, Bmask, Amask;
   368 
   369         if (!SDL_PixelFormatEnumToMasks
   370             (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   371             SDL_SetError("Unknown texture format");
   372             return -1;
   373         }
   374 
   375         texture->driverdata =
   376             SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
   377                                  Bmask, Amask);
   378     }
   379 
   380     if (!texture->driverdata) {
   381         return -1;
   382     }
   383     return 0;
   384 }
   385 
   386 static int
   387 SW_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   388                       void **pixels, int *pitch)
   389 {
   390     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   391         return SDL_SW_QueryYUVTexturePixels((SDL_SW_YUVTexture *) texture->
   392                                             driverdata, pixels, pitch);
   393     } else {
   394         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   395 
   396         *pixels = surface->pixels;
   397         *pitch = surface->pitch;
   398         return 0;
   399     }
   400 }
   401 
   402 static int
   403 SW_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   404                      const SDL_Color * colors, int firstcolor, int ncolors)
   405 {
   406     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   407         SDL_SetError("YUV textures don't have a palette");
   408         return -1;
   409     } else {
   410         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   411 
   412         return SDL_SetPaletteColors(surface->format->palette, colors,
   413                                     firstcolor, ncolors);
   414     }
   415 }
   416 
   417 static int
   418 SW_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   419                      SDL_Color * colors, int firstcolor, int ncolors)
   420 {
   421     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   422         SDL_SetError("YUV textures don't have a palette");
   423         return -1;
   424     } else {
   425         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   426 
   427         SDL_memcpy(colors, &surface->format->palette->colors[firstcolor],
   428                    ncolors * sizeof(*colors));
   429         return 0;
   430     }
   431 }
   432 
   433 static int
   434 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   435 {
   436     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   437     return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
   438                                   texture->b);
   439 }
   440 
   441 static int
   442 SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   443 {
   444     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   445     return SDL_SetSurfaceAlphaMod(surface, texture->a);
   446 }
   447 
   448 static int
   449 SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   450 {
   451     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   452     return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
   453 }
   454 
   455 static int
   456 SW_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   457 {
   458     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   459     return SDL_SetSurfaceBlendMode(surface, texture->scaleMode);
   460 }
   461 
   462 static int
   463 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   464                  const SDL_Rect * rect, const void *pixels, int pitch)
   465 {
   466     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   467         return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *) texture->
   468                                        driverdata, rect, pixels, pitch);
   469     } else {
   470         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   471         Uint8 *src, *dst;
   472         int row;
   473         size_t length;
   474 
   475         src = (Uint8 *) pixels;
   476         dst =
   477             (Uint8 *) surface->pixels + rect->y * surface->pitch +
   478             rect->x * surface->format->BytesPerPixel;
   479         length = rect->w * surface->format->BytesPerPixel;
   480         for (row = 0; row < rect->h; ++row) {
   481             SDL_memcpy(dst, src, length);
   482             src += pitch;
   483             dst += surface->pitch;
   484         }
   485         return 0;
   486     }
   487 }
   488 
   489 static int
   490 SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   491                const SDL_Rect * rect, int markDirty, void **pixels,
   492                int *pitch)
   493 {
   494     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   495         return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *) texture->
   496                                      driverdata, rect, markDirty, pixels,
   497                                      pitch);
   498     } else {
   499         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   500 
   501         *pixels =
   502             (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
   503                       rect->x * surface->format->BytesPerPixel);
   504         *pitch = surface->pitch;
   505         return 0;
   506     }
   507 }
   508 
   509 static void
   510 SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   511 {
   512     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   513         SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
   514     }
   515 }
   516 
   517 static void
   518 SW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   519                 int numrects, const SDL_Rect * rects)
   520 {
   521 }
   522 
   523 static int
   524 SW_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
   525               const SDL_Rect * rect)
   526 {
   527     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   528     Uint32 color;
   529     SDL_Rect real_rect;
   530     int status;
   531 
   532     if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
   533         SDL_AddDirtyRect(&data->dirty, rect);
   534     }
   535 
   536     color = SDL_MapRGBA(data->surface.format, r, g, b, a);
   537 
   538     if (data->renderer->
   539         LockTexture(data->renderer, data->texture[data->current_texture],
   540                     rect, 1, &data->surface.pixels,
   541                     &data->surface.pitch) < 0) {
   542         return -1;
   543     }
   544     data->surface.w = rect->w;
   545     data->surface.h = rect->h;
   546     data->surface.clip_rect.w = rect->w;
   547     data->surface.clip_rect.h = rect->h;
   548     real_rect = data->surface.clip_rect;
   549 
   550     status = SDL_FillRect(&data->surface, &real_rect, color);
   551 
   552     data->renderer->UnlockTexture(data->renderer,
   553                                   data->texture[data->current_texture]);
   554     return status;
   555 }
   556 
   557 static int
   558 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   559               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   560 {
   561     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   562     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   563     int status;
   564 
   565     if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
   566         SDL_AddDirtyRect(&data->dirty, dstrect);
   567     }
   568 
   569     if (data->renderer->
   570         LockTexture(data->renderer, data->texture[data->current_texture],
   571                     dstrect, 1, &data->surface.pixels,
   572                     &data->surface.pitch) < 0) {
   573         return -1;
   574     }
   575 
   576     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   577         status =
   578             SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
   579                                 srcrect, data->format, dstrect->w, dstrect->h,
   580                                 data->surface.pixels, data->surface.pitch);
   581     } else {
   582         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   583         SDL_Rect real_srcrect = *srcrect;
   584         SDL_Rect real_dstrect;
   585 
   586         data->surface.w = dstrect->w;
   587         data->surface.h = dstrect->h;
   588         data->surface.clip_rect.w = dstrect->w;
   589         data->surface.clip_rect.h = dstrect->h;
   590         real_dstrect = data->surface.clip_rect;
   591 
   592         status =
   593             SDL_LowerBlit(surface, &real_srcrect, &data->surface,
   594                           &real_dstrect);
   595     }
   596     data->renderer->UnlockTexture(data->renderer,
   597                                   data->texture[data->current_texture]);
   598     return status;
   599 }
   600 
   601 static void
   602 SW_RenderPresent(SDL_Renderer * renderer)
   603 {
   604     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   605     SDL_Texture *texture = data->texture[data->current_texture];
   606 
   607     /* Send the data to the display */
   608     if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
   609         SDL_DirtyRect *dirty;
   610         for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
   611             data->renderer->RenderCopy(data->renderer, texture, &dirty->rect,
   612                                        &dirty->rect);
   613         }
   614         SDL_ClearDirtyRects(&data->dirty);
   615     } else {
   616         SDL_Rect rect;
   617         rect.x = 0;
   618         rect.y = 0;
   619         rect.w = texture->w;
   620         rect.h = texture->h;
   621         data->renderer->RenderCopy(data->renderer, texture, &rect, &rect);
   622     }
   623     data->renderer->RenderPresent(data->renderer);
   624 
   625     /* Update the flipping chain, if any */
   626     if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
   627         data->current_texture = (data->current_texture + 1) % 2;
   628     } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
   629         data->current_texture = (data->current_texture + 1) % 3;
   630     }
   631 }
   632 
   633 static void
   634 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   635 {
   636     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   637         SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
   638     } else {
   639         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   640 
   641         SDL_FreeSurface(surface);
   642     }
   643 }
   644 
   645 static void
   646 SW_DestroyRenderer(SDL_Renderer * renderer)
   647 {
   648     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   649     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   650     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   651     int i;
   652 
   653     if (data) {
   654         for (i = 0; i < SDL_arraysize(data->texture); ++i) {
   655             if (data->texture[i]) {
   656                 DestroyTexture(data->renderer, data->texture[i]);
   657             }
   658         }
   659         if (data->surface.format) {
   660             SDL_SetSurfacePalette(&data->surface, NULL);
   661             SDL_FreeFormat(data->surface.format);
   662         }
   663         if (display->palette) {
   664             SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
   665                                 data);
   666         }
   667         if (data->renderer) {
   668             data->renderer->DestroyRenderer(data->renderer);
   669         }
   670         SDL_FreeDirtyRects(&data->dirty);
   671         SDL_free(data);
   672     }
   673     SDL_free(renderer);
   674 }
   675 
   676 /* vi: set ts=4 sw=4 expandtab: */