src/render/software/SDL_render_sw.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 05 Feb 2011 12:01:11 -0800
changeset 5195 bb45ecd958d8
parent 5166 src/render/software/SDL_renderer_sw.c@4d39eeaad00b
child 5224 2178ffe17222
permissions -rw-r--r--
Renamed files for consistency
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 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_sysrender.h"
    25 #include "../../video/SDL_pixels_c.h"
    26 
    27 #include "SDL_draw.h"
    28 #include "SDL_blendfillrect.h"
    29 #include "SDL_blendline.h"
    30 #include "SDL_blendpoint.h"
    31 #include "SDL_drawline.h"
    32 #include "SDL_drawpoint.h"
    33 
    34 
    35 /* SDL surface based renderer implementation */
    36 
    37 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
    38 static void SW_WindowEvent(SDL_Renderer * renderer,
    39                            const SDL_WindowEvent *event);
    40 static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    41 static int SW_SetTextureColorMod(SDL_Renderer * renderer,
    42                                  SDL_Texture * texture);
    43 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
    44                                  SDL_Texture * texture);
    45 static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
    46                                   SDL_Texture * texture);
    47 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    48                             const SDL_Rect * rect, const void *pixels,
    49                             int pitch);
    50 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    51                           const SDL_Rect * rect, void **pixels, int *pitch);
    52 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    53 static int SW_RenderDrawPoints(SDL_Renderer * renderer,
    54                                const SDL_Point * points, int count);
    55 static int SW_RenderDrawLines(SDL_Renderer * renderer,
    56                               const SDL_Point * points, int count);
    57 static int SW_RenderFillRects(SDL_Renderer * renderer,
    58                               const SDL_Rect ** rects, int count);
    59 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    60                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
    61 static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    62                                Uint32 format, void * pixels, int pitch);
    63 static void SW_RenderPresent(SDL_Renderer * renderer);
    64 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    65 static void SW_DestroyRenderer(SDL_Renderer * renderer);
    66 
    67 
    68 SDL_RenderDriver SW_RenderDriver = {
    69     SW_CreateRenderer,
    70     {
    71      "software",
    72      0,
    73      8,
    74      {
    75       SDL_PIXELFORMAT_RGB555,
    76       SDL_PIXELFORMAT_RGB565,
    77       SDL_PIXELFORMAT_RGB888,
    78       SDL_PIXELFORMAT_BGR888,
    79       SDL_PIXELFORMAT_ARGB8888,
    80       SDL_PIXELFORMAT_RGBA8888,
    81       SDL_PIXELFORMAT_ABGR8888,
    82       SDL_PIXELFORMAT_BGRA8888
    83      },
    84      0,
    85      0}
    86 };
    87 
    88 typedef struct
    89 {
    90     SDL_bool updateSize;
    91     SDL_Surface *surface;
    92 } SW_RenderData;
    93 
    94 
    95 SDL_Renderer *
    96 SW_CreateRendererForSurface(SDL_Surface * surface)
    97 {
    98     SDL_Renderer *renderer;
    99     SW_RenderData *data;
   100 
   101     if (!surface) {
   102         SDL_SetError("Can't create renderer for NULL surface");
   103         return NULL;
   104     }
   105 
   106     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   107     if (!renderer) {
   108         SDL_OutOfMemory();
   109         return NULL;
   110     }
   111 
   112     data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
   113     if (!data) {
   114         SW_DestroyRenderer(renderer);
   115         SDL_OutOfMemory();
   116         return NULL;
   117     }
   118     data->surface = surface;
   119 
   120     renderer->WindowEvent = SW_WindowEvent;
   121     renderer->CreateTexture = SW_CreateTexture;
   122     renderer->SetTextureColorMod = SW_SetTextureColorMod;
   123     renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
   124     renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
   125     renderer->UpdateTexture = SW_UpdateTexture;
   126     renderer->LockTexture = SW_LockTexture;
   127     renderer->UnlockTexture = SW_UnlockTexture;
   128     renderer->DestroyTexture = SW_DestroyTexture;
   129     renderer->RenderDrawPoints = SW_RenderDrawPoints;
   130     renderer->RenderDrawLines = SW_RenderDrawLines;
   131     renderer->RenderFillRects = SW_RenderFillRects;
   132     renderer->RenderCopy = SW_RenderCopy;
   133     renderer->RenderReadPixels = SW_RenderReadPixels;
   134     renderer->RenderPresent = SW_RenderPresent;
   135     renderer->DestroyRenderer = SW_DestroyRenderer;
   136     renderer->info = SW_RenderDriver.info;
   137     renderer->driverdata = data;
   138 
   139     return renderer;
   140 }
   141 
   142 SDL_Renderer *
   143 SW_CreateRenderer(SDL_Window * window, Uint32 flags)
   144 {
   145     SDL_Surface *surface;
   146 
   147     surface = SDL_GetWindowSurface(window);
   148     if (!surface) {
   149         return NULL;
   150     }
   151     return SW_CreateRendererForSurface(surface);
   152 }
   153 
   154 static SDL_Surface *
   155 SW_ActivateRenderer(SDL_Renderer * renderer)
   156 {
   157     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   158     SDL_Window *window = renderer->window;
   159 
   160     if (data->updateSize) {
   161         data->surface = SDL_GetWindowSurface(window);
   162         data->updateSize = SDL_FALSE;
   163     }
   164     return data->surface;
   165 }
   166 
   167 static void
   168 SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   169 {
   170     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   171 
   172     if (event->event == SDL_WINDOWEVENT_RESIZED) {
   173         data->updateSize = SDL_TRUE;
   174     }
   175 }
   176 
   177 static int
   178 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   179 {
   180     int bpp;
   181     Uint32 Rmask, Gmask, Bmask, Amask;
   182 
   183     if (!SDL_PixelFormatEnumToMasks
   184         (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   185         SDL_SetError("Unknown texture format");
   186         return -1;
   187     }
   188 
   189     texture->driverdata =
   190         SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
   191                              Bmask, Amask);
   192     SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
   193                            texture->b);
   194     SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
   195     SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
   196 
   197     if (texture->access == SDL_TEXTUREACCESS_STATIC) {
   198         SDL_SetSurfaceRLE(texture->driverdata, 1);
   199     }
   200 
   201     if (!texture->driverdata) {
   202         return -1;
   203     }
   204     return 0;
   205 }
   206 
   207 static int
   208 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   209 {
   210     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   211     return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
   212                                   texture->b);
   213 }
   214 
   215 static int
   216 SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   217 {
   218     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   219     return SDL_SetSurfaceAlphaMod(surface, texture->a);
   220 }
   221 
   222 static int
   223 SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   224 {
   225     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   226     return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
   227 }
   228 
   229 static int
   230 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   231                  const SDL_Rect * rect, const void *pixels, int pitch)
   232 {
   233     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   234     Uint8 *src, *dst;
   235     int row;
   236     size_t length;
   237 
   238     src = (Uint8 *) pixels;
   239     dst = (Uint8 *) surface->pixels +
   240                         rect->y * surface->pitch +
   241                         rect->x * surface->format->BytesPerPixel;
   242     length = rect->w * surface->format->BytesPerPixel;
   243     for (row = 0; row < rect->h; ++row) {
   244         SDL_memcpy(dst, src, length);
   245         src += pitch;
   246         dst += surface->pitch;
   247     }
   248     return 0;
   249 }
   250 
   251 static int
   252 SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   253                const SDL_Rect * rect, void **pixels, int *pitch)
   254 {
   255     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   256 
   257     *pixels =
   258         (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
   259                   rect->x * surface->format->BytesPerPixel);
   260     *pitch = surface->pitch;
   261     return 0;
   262 }
   263 
   264 static void
   265 SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   266 {
   267 }
   268 
   269 static int
   270 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
   271                     int count)
   272 {
   273     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   274 
   275     if (!surface) {
   276         return -1;
   277     }
   278 
   279     /* Draw the points! */
   280     if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   281         Uint32 color = SDL_MapRGBA(surface->format,
   282                                    renderer->r, renderer->g, renderer->b,
   283                                    renderer->a);
   284 
   285         return SDL_DrawPoints(surface, points, count, color);
   286     } else {
   287         return SDL_BlendPoints(surface, points, count,
   288                                renderer->blendMode,
   289                                renderer->r, renderer->g, renderer->b,
   290                                renderer->a);
   291     }
   292 }
   293 
   294 static int
   295 SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
   296                    int count)
   297 {
   298     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   299 
   300     if (!surface) {
   301         return -1;
   302     }
   303 
   304     /* Draw the lines! */
   305     if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   306         Uint32 color = SDL_MapRGBA(surface->format,
   307                                    renderer->r, renderer->g, renderer->b,
   308                                    renderer->a);
   309 
   310         return SDL_DrawLines(surface, points, count, color);
   311     } else {
   312         return SDL_BlendLines(surface, points, count,
   313                               renderer->blendMode,
   314                               renderer->r, renderer->g, renderer->b,
   315                               renderer->a);
   316     }
   317 }
   318 
   319 static int
   320 SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
   321                    int count)
   322 {
   323     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   324 
   325     if (!surface) {
   326         return -1;
   327     }
   328 
   329     if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   330         Uint32 color = SDL_MapRGBA(surface->format,
   331                                    renderer->r, renderer->g, renderer->b,
   332                                    renderer->a);
   333         return SDL_FillRects(surface, rects, count, color);
   334     } else {
   335         return SDL_BlendFillRects(surface, rects, count,
   336                                      renderer->blendMode,
   337                                      renderer->r, renderer->g, renderer->b,
   338                                      renderer->a);
   339     }
   340 }
   341 
   342 static int
   343 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   344               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   345 {
   346     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   347     SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   348     SDL_Rect final_rect = *dstrect;
   349 
   350     if (!surface) {
   351         return -1;
   352     }
   353     return SDL_BlitSurface(src, srcrect, surface, &final_rect);
   354 }
   355 
   356 static int
   357 SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   358                     Uint32 format, void * pixels, int pitch)
   359 {
   360     SDL_Surface *surface = SW_ActivateRenderer(renderer);
   361     Uint32 src_format;
   362     void *src_pixels;
   363 
   364     if (!surface) {
   365         return -1;
   366     }
   367 
   368     if (rect->x < 0 || rect->x+rect->w > surface->w ||
   369         rect->y < 0 || rect->y+rect->h > surface->h) {
   370         SDL_SetError("Tried to read outside of surface bounds");
   371         return -1;
   372     }
   373 
   374     src_format = SDL_MasksToPixelFormatEnum(
   375                     surface->format->BitsPerPixel,
   376                     surface->format->Rmask, surface->format->Gmask,
   377                     surface->format->Bmask, surface->format->Amask);
   378 
   379     src_pixels = (void*)((Uint8 *) surface->pixels +
   380                     rect->y * surface->pitch +
   381                     rect->x * surface->format->BytesPerPixel);
   382 
   383     return SDL_ConvertPixels(rect->w, rect->h,
   384                              src_format, src_pixels, surface->pitch,
   385                              format, pixels, pitch);
   386 }
   387 
   388 static void
   389 SW_RenderPresent(SDL_Renderer * renderer)
   390 {
   391     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   392     SDL_Window *window = renderer->window;
   393 
   394     if (window) {
   395         SDL_UpdateWindowSurface(window);
   396     }
   397 }
   398 
   399 static void
   400 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   401 {
   402     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   403 
   404     SDL_FreeSurface(surface);
   405 }
   406 
   407 static void
   408 SW_DestroyRenderer(SDL_Renderer * renderer)
   409 {
   410     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   411 
   412     if (data) {
   413         SDL_free(data);
   414     }
   415     SDL_free(renderer);
   416 }
   417 
   418 /* vi: set ts=4 sw=4 expandtab: */