src/render/software/SDL_render_sw.c
changeset 5195 bb45ecd958d8
parent 5166 4d39eeaad00b
child 5224 2178ffe17222
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/render/software/SDL_render_sw.c	Sat Feb 05 12:01:11 2011 -0800
     1.3 @@ -0,0 +1,418 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2010 Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Lesser General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Lesser General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Lesser General Public
    1.19 +    License along with this library; if not, write to the Free Software
    1.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +*/
    1.25 +#include "SDL_config.h"
    1.26 +
    1.27 +#include "../SDL_sysrender.h"
    1.28 +#include "../../video/SDL_pixels_c.h"
    1.29 +
    1.30 +#include "SDL_draw.h"
    1.31 +#include "SDL_blendfillrect.h"
    1.32 +#include "SDL_blendline.h"
    1.33 +#include "SDL_blendpoint.h"
    1.34 +#include "SDL_drawline.h"
    1.35 +#include "SDL_drawpoint.h"
    1.36 +
    1.37 +
    1.38 +/* SDL surface based renderer implementation */
    1.39 +
    1.40 +static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
    1.41 +static void SW_WindowEvent(SDL_Renderer * renderer,
    1.42 +                           const SDL_WindowEvent *event);
    1.43 +static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.44 +static int SW_SetTextureColorMod(SDL_Renderer * renderer,
    1.45 +                                 SDL_Texture * texture);
    1.46 +static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
    1.47 +                                 SDL_Texture * texture);
    1.48 +static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
    1.49 +                                  SDL_Texture * texture);
    1.50 +static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.51 +                            const SDL_Rect * rect, const void *pixels,
    1.52 +                            int pitch);
    1.53 +static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.54 +                          const SDL_Rect * rect, void **pixels, int *pitch);
    1.55 +static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.56 +static int SW_RenderDrawPoints(SDL_Renderer * renderer,
    1.57 +                               const SDL_Point * points, int count);
    1.58 +static int SW_RenderDrawLines(SDL_Renderer * renderer,
    1.59 +                              const SDL_Point * points, int count);
    1.60 +static int SW_RenderFillRects(SDL_Renderer * renderer,
    1.61 +                              const SDL_Rect ** rects, int count);
    1.62 +static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    1.63 +                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
    1.64 +static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    1.65 +                               Uint32 format, void * pixels, int pitch);
    1.66 +static void SW_RenderPresent(SDL_Renderer * renderer);
    1.67 +static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.68 +static void SW_DestroyRenderer(SDL_Renderer * renderer);
    1.69 +
    1.70 +
    1.71 +SDL_RenderDriver SW_RenderDriver = {
    1.72 +    SW_CreateRenderer,
    1.73 +    {
    1.74 +     "software",
    1.75 +     0,
    1.76 +     8,
    1.77 +     {
    1.78 +      SDL_PIXELFORMAT_RGB555,
    1.79 +      SDL_PIXELFORMAT_RGB565,
    1.80 +      SDL_PIXELFORMAT_RGB888,
    1.81 +      SDL_PIXELFORMAT_BGR888,
    1.82 +      SDL_PIXELFORMAT_ARGB8888,
    1.83 +      SDL_PIXELFORMAT_RGBA8888,
    1.84 +      SDL_PIXELFORMAT_ABGR8888,
    1.85 +      SDL_PIXELFORMAT_BGRA8888
    1.86 +     },
    1.87 +     0,
    1.88 +     0}
    1.89 +};
    1.90 +
    1.91 +typedef struct
    1.92 +{
    1.93 +    SDL_bool updateSize;
    1.94 +    SDL_Surface *surface;
    1.95 +} SW_RenderData;
    1.96 +
    1.97 +
    1.98 +SDL_Renderer *
    1.99 +SW_CreateRendererForSurface(SDL_Surface * surface)
   1.100 +{
   1.101 +    SDL_Renderer *renderer;
   1.102 +    SW_RenderData *data;
   1.103 +
   1.104 +    if (!surface) {
   1.105 +        SDL_SetError("Can't create renderer for NULL surface");
   1.106 +        return NULL;
   1.107 +    }
   1.108 +
   1.109 +    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   1.110 +    if (!renderer) {
   1.111 +        SDL_OutOfMemory();
   1.112 +        return NULL;
   1.113 +    }
   1.114 +
   1.115 +    data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
   1.116 +    if (!data) {
   1.117 +        SW_DestroyRenderer(renderer);
   1.118 +        SDL_OutOfMemory();
   1.119 +        return NULL;
   1.120 +    }
   1.121 +    data->surface = surface;
   1.122 +
   1.123 +    renderer->WindowEvent = SW_WindowEvent;
   1.124 +    renderer->CreateTexture = SW_CreateTexture;
   1.125 +    renderer->SetTextureColorMod = SW_SetTextureColorMod;
   1.126 +    renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
   1.127 +    renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
   1.128 +    renderer->UpdateTexture = SW_UpdateTexture;
   1.129 +    renderer->LockTexture = SW_LockTexture;
   1.130 +    renderer->UnlockTexture = SW_UnlockTexture;
   1.131 +    renderer->DestroyTexture = SW_DestroyTexture;
   1.132 +    renderer->RenderDrawPoints = SW_RenderDrawPoints;
   1.133 +    renderer->RenderDrawLines = SW_RenderDrawLines;
   1.134 +    renderer->RenderFillRects = SW_RenderFillRects;
   1.135 +    renderer->RenderCopy = SW_RenderCopy;
   1.136 +    renderer->RenderReadPixels = SW_RenderReadPixels;
   1.137 +    renderer->RenderPresent = SW_RenderPresent;
   1.138 +    renderer->DestroyRenderer = SW_DestroyRenderer;
   1.139 +    renderer->info = SW_RenderDriver.info;
   1.140 +    renderer->driverdata = data;
   1.141 +
   1.142 +    return renderer;
   1.143 +}
   1.144 +
   1.145 +SDL_Renderer *
   1.146 +SW_CreateRenderer(SDL_Window * window, Uint32 flags)
   1.147 +{
   1.148 +    SDL_Surface *surface;
   1.149 +
   1.150 +    surface = SDL_GetWindowSurface(window);
   1.151 +    if (!surface) {
   1.152 +        return NULL;
   1.153 +    }
   1.154 +    return SW_CreateRendererForSurface(surface);
   1.155 +}
   1.156 +
   1.157 +static SDL_Surface *
   1.158 +SW_ActivateRenderer(SDL_Renderer * renderer)
   1.159 +{
   1.160 +    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.161 +    SDL_Window *window = renderer->window;
   1.162 +
   1.163 +    if (data->updateSize) {
   1.164 +        data->surface = SDL_GetWindowSurface(window);
   1.165 +        data->updateSize = SDL_FALSE;
   1.166 +    }
   1.167 +    return data->surface;
   1.168 +}
   1.169 +
   1.170 +static void
   1.171 +SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   1.172 +{
   1.173 +    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.174 +
   1.175 +    if (event->event == SDL_WINDOWEVENT_RESIZED) {
   1.176 +        data->updateSize = SDL_TRUE;
   1.177 +    }
   1.178 +}
   1.179 +
   1.180 +static int
   1.181 +SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.182 +{
   1.183 +    int bpp;
   1.184 +    Uint32 Rmask, Gmask, Bmask, Amask;
   1.185 +
   1.186 +    if (!SDL_PixelFormatEnumToMasks
   1.187 +        (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   1.188 +        SDL_SetError("Unknown texture format");
   1.189 +        return -1;
   1.190 +    }
   1.191 +
   1.192 +    texture->driverdata =
   1.193 +        SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
   1.194 +                             Bmask, Amask);
   1.195 +    SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
   1.196 +                           texture->b);
   1.197 +    SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
   1.198 +    SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
   1.199 +
   1.200 +    if (texture->access == SDL_TEXTUREACCESS_STATIC) {
   1.201 +        SDL_SetSurfaceRLE(texture->driverdata, 1);
   1.202 +    }
   1.203 +
   1.204 +    if (!texture->driverdata) {
   1.205 +        return -1;
   1.206 +    }
   1.207 +    return 0;
   1.208 +}
   1.209 +
   1.210 +static int
   1.211 +SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   1.212 +{
   1.213 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.214 +    return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
   1.215 +                                  texture->b);
   1.216 +}
   1.217 +
   1.218 +static int
   1.219 +SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   1.220 +{
   1.221 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.222 +    return SDL_SetSurfaceAlphaMod(surface, texture->a);
   1.223 +}
   1.224 +
   1.225 +static int
   1.226 +SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   1.227 +{
   1.228 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.229 +    return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
   1.230 +}
   1.231 +
   1.232 +static int
   1.233 +SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.234 +                 const SDL_Rect * rect, const void *pixels, int pitch)
   1.235 +{
   1.236 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.237 +    Uint8 *src, *dst;
   1.238 +    int row;
   1.239 +    size_t length;
   1.240 +
   1.241 +    src = (Uint8 *) pixels;
   1.242 +    dst = (Uint8 *) surface->pixels +
   1.243 +                        rect->y * surface->pitch +
   1.244 +                        rect->x * surface->format->BytesPerPixel;
   1.245 +    length = rect->w * surface->format->BytesPerPixel;
   1.246 +    for (row = 0; row < rect->h; ++row) {
   1.247 +        SDL_memcpy(dst, src, length);
   1.248 +        src += pitch;
   1.249 +        dst += surface->pitch;
   1.250 +    }
   1.251 +    return 0;
   1.252 +}
   1.253 +
   1.254 +static int
   1.255 +SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.256 +               const SDL_Rect * rect, void **pixels, int *pitch)
   1.257 +{
   1.258 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.259 +
   1.260 +    *pixels =
   1.261 +        (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
   1.262 +                  rect->x * surface->format->BytesPerPixel);
   1.263 +    *pitch = surface->pitch;
   1.264 +    return 0;
   1.265 +}
   1.266 +
   1.267 +static void
   1.268 +SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.269 +{
   1.270 +}
   1.271 +
   1.272 +static int
   1.273 +SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
   1.274 +                    int count)
   1.275 +{
   1.276 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.277 +
   1.278 +    if (!surface) {
   1.279 +        return -1;
   1.280 +    }
   1.281 +
   1.282 +    /* Draw the points! */
   1.283 +    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   1.284 +        Uint32 color = SDL_MapRGBA(surface->format,
   1.285 +                                   renderer->r, renderer->g, renderer->b,
   1.286 +                                   renderer->a);
   1.287 +
   1.288 +        return SDL_DrawPoints(surface, points, count, color);
   1.289 +    } else {
   1.290 +        return SDL_BlendPoints(surface, points, count,
   1.291 +                               renderer->blendMode,
   1.292 +                               renderer->r, renderer->g, renderer->b,
   1.293 +                               renderer->a);
   1.294 +    }
   1.295 +}
   1.296 +
   1.297 +static int
   1.298 +SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
   1.299 +                   int count)
   1.300 +{
   1.301 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.302 +
   1.303 +    if (!surface) {
   1.304 +        return -1;
   1.305 +    }
   1.306 +
   1.307 +    /* Draw the lines! */
   1.308 +    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   1.309 +        Uint32 color = SDL_MapRGBA(surface->format,
   1.310 +                                   renderer->r, renderer->g, renderer->b,
   1.311 +                                   renderer->a);
   1.312 +
   1.313 +        return SDL_DrawLines(surface, points, count, color);
   1.314 +    } else {
   1.315 +        return SDL_BlendLines(surface, points, count,
   1.316 +                              renderer->blendMode,
   1.317 +                              renderer->r, renderer->g, renderer->b,
   1.318 +                              renderer->a);
   1.319 +    }
   1.320 +}
   1.321 +
   1.322 +static int
   1.323 +SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
   1.324 +                   int count)
   1.325 +{
   1.326 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.327 +
   1.328 +    if (!surface) {
   1.329 +        return -1;
   1.330 +    }
   1.331 +
   1.332 +    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
   1.333 +        Uint32 color = SDL_MapRGBA(surface->format,
   1.334 +                                   renderer->r, renderer->g, renderer->b,
   1.335 +                                   renderer->a);
   1.336 +        return SDL_FillRects(surface, rects, count, color);
   1.337 +    } else {
   1.338 +        return SDL_BlendFillRects(surface, rects, count,
   1.339 +                                     renderer->blendMode,
   1.340 +                                     renderer->r, renderer->g, renderer->b,
   1.341 +                                     renderer->a);
   1.342 +    }
   1.343 +}
   1.344 +
   1.345 +static int
   1.346 +SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   1.347 +              const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   1.348 +{
   1.349 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.350 +    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   1.351 +    SDL_Rect final_rect = *dstrect;
   1.352 +
   1.353 +    if (!surface) {
   1.354 +        return -1;
   1.355 +    }
   1.356 +    return SDL_BlitSurface(src, srcrect, surface, &final_rect);
   1.357 +}
   1.358 +
   1.359 +static int
   1.360 +SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1.361 +                    Uint32 format, void * pixels, int pitch)
   1.362 +{
   1.363 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   1.364 +    Uint32 src_format;
   1.365 +    void *src_pixels;
   1.366 +
   1.367 +    if (!surface) {
   1.368 +        return -1;
   1.369 +    }
   1.370 +
   1.371 +    if (rect->x < 0 || rect->x+rect->w > surface->w ||
   1.372 +        rect->y < 0 || rect->y+rect->h > surface->h) {
   1.373 +        SDL_SetError("Tried to read outside of surface bounds");
   1.374 +        return -1;
   1.375 +    }
   1.376 +
   1.377 +    src_format = SDL_MasksToPixelFormatEnum(
   1.378 +                    surface->format->BitsPerPixel,
   1.379 +                    surface->format->Rmask, surface->format->Gmask,
   1.380 +                    surface->format->Bmask, surface->format->Amask);
   1.381 +
   1.382 +    src_pixels = (void*)((Uint8 *) surface->pixels +
   1.383 +                    rect->y * surface->pitch +
   1.384 +                    rect->x * surface->format->BytesPerPixel);
   1.385 +
   1.386 +    return SDL_ConvertPixels(rect->w, rect->h,
   1.387 +                             src_format, src_pixels, surface->pitch,
   1.388 +                             format, pixels, pitch);
   1.389 +}
   1.390 +
   1.391 +static void
   1.392 +SW_RenderPresent(SDL_Renderer * renderer)
   1.393 +{
   1.394 +    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.395 +    SDL_Window *window = renderer->window;
   1.396 +
   1.397 +    if (window) {
   1.398 +        SDL_UpdateWindowSurface(window);
   1.399 +    }
   1.400 +}
   1.401 +
   1.402 +static void
   1.403 +SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.404 +{
   1.405 +    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   1.406 +
   1.407 +    SDL_FreeSurface(surface);
   1.408 +}
   1.409 +
   1.410 +static void
   1.411 +SW_DestroyRenderer(SDL_Renderer * renderer)
   1.412 +{
   1.413 +    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
   1.414 +
   1.415 +    if (data) {
   1.416 +        SDL_free(data);
   1.417 +    }
   1.418 +    SDL_free(renderer);
   1.419 +}
   1.420 +
   1.421 +/* vi: set ts=4 sw=4 expandtab: */