cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_render_sw.c (23409B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#if !SDL_RENDER_DISABLED
     24
     25#include "../SDL_sysrender.h"
     26#include "SDL_render_sw_c.h"
     27#include "SDL_hints.h"
     28
     29#include "SDL_draw.h"
     30#include "SDL_blendfillrect.h"
     31#include "SDL_blendline.h"
     32#include "SDL_blendpoint.h"
     33#include "SDL_drawline.h"
     34#include "SDL_drawpoint.h"
     35#include "SDL_rotate.h"
     36
     37/* SDL surface based renderer implementation */
     38
     39static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
     40static void SW_WindowEvent(SDL_Renderer * renderer,
     41                           const SDL_WindowEvent *event);
     42static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
     43static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
     44static int SW_SetTextureColorMod(SDL_Renderer * renderer,
     45                                 SDL_Texture * texture);
     46static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
     47                                 SDL_Texture * texture);
     48static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
     49                                  SDL_Texture * texture);
     50static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
     51                            const SDL_Rect * rect, const void *pixels,
     52                            int pitch);
     53static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
     54                          const SDL_Rect * rect, void **pixels, int *pitch);
     55static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
     56static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
     57static int SW_UpdateViewport(SDL_Renderer * renderer);
     58static int SW_UpdateClipRect(SDL_Renderer * renderer);
     59static int SW_RenderClear(SDL_Renderer * renderer);
     60static int SW_RenderDrawPoints(SDL_Renderer * renderer,
     61                               const SDL_FPoint * points, int count);
     62static int SW_RenderDrawLines(SDL_Renderer * renderer,
     63                              const SDL_FPoint * points, int count);
     64static int SW_RenderFillRects(SDL_Renderer * renderer,
     65                              const SDL_FRect * rects, int count);
     66static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     67                         const SDL_Rect * srcrect, const SDL_FRect * dstrect);
     68static 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);
     71static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
     72                               Uint32 format, void * pixels, int pitch);
     73static void SW_RenderPresent(SDL_Renderer * renderer);
     74static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
     75static void SW_DestroyRenderer(SDL_Renderer * renderer);
     76
     77
     78SDL_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
     98typedef struct
     99{
    100    SDL_Surface *surface;
    101    SDL_Surface *window;
    102} SW_RenderData;
    103
    104
    105static SDL_Surface *
    106SW_ActivateRenderer(SDL_Renderer * renderer)
    107{
    108    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    109
    110    if (!data->surface) {
    111        data->surface = data->window;
    112    }
    113    if (!data->surface) {
    114        SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
    115        if (surface) {
    116            data->surface = data->window = surface;
    117
    118            SW_UpdateViewport(renderer);
    119            SW_UpdateClipRect(renderer);
    120        }
    121    }
    122    return data->surface;
    123}
    124
    125SDL_Renderer *
    126SW_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
    181SDL_Renderer *
    182SW_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}
    192
    193static void
    194SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
    195{
    196    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    197
    198    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
    199        data->surface = NULL;
    200        data->window = NULL;
    201    }
    202}
    203
    204static int
    205SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
    206{
    207    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    208
    209    if (surface) {
    210        if (w) {
    211            *w = surface->w;
    212        }
    213        if (h) {
    214            *h = surface->h;
    215        }
    216        return 0;
    217    } else {
    218        SDL_SetError("Software renderer doesn't have an output surface");
    219        return -1;
    220    }
    221}
    222
    223static int
    224SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    225{
    226    int bpp;
    227    Uint32 Rmask, Gmask, Bmask, Amask;
    228
    229    if (!SDL_PixelFormatEnumToMasks
    230        (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
    231        return SDL_SetError("Unknown texture format");
    232    }
    233
    234    texture->driverdata =
    235        SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
    236                             Bmask, Amask);
    237    SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
    238                           texture->b);
    239    SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
    240    SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
    241
    242    if (texture->access == SDL_TEXTUREACCESS_STATIC) {
    243        SDL_SetSurfaceRLE(texture->driverdata, 1);
    244    }
    245
    246    if (!texture->driverdata) {
    247        return -1;
    248    }
    249    return 0;
    250}
    251
    252static int
    253SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
    254{
    255    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
    256    return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
    257                                  texture->b);
    258}
    259
    260static int
    261SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
    262{
    263    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
    264    return SDL_SetSurfaceAlphaMod(surface, texture->a);
    265}
    266
    267static int
    268SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
    269{
    270    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
    271    return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
    272}
    273
    274static int
    275SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    276                 const SDL_Rect * rect, const void *pixels, int pitch)
    277{
    278    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
    279    Uint8 *src, *dst;
    280    int row;
    281    size_t length;
    282
    283    if(SDL_MUSTLOCK(surface))
    284        SDL_LockSurface(surface);
    285    src = (Uint8 *) pixels;
    286    dst = (Uint8 *) surface->pixels +
    287                        rect->y * surface->pitch +
    288                        rect->x * surface->format->BytesPerPixel;
    289    length = rect->w * surface->format->BytesPerPixel;
    290    for (row = 0; row < rect->h; ++row) {
    291        SDL_memcpy(dst, src, length);
    292        src += pitch;
    293        dst += surface->pitch;
    294    }
    295    if(SDL_MUSTLOCK(surface))
    296        SDL_UnlockSurface(surface);
    297    return 0;
    298}
    299
    300static int
    301SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    302               const SDL_Rect * rect, void **pixels, int *pitch)
    303{
    304    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
    305
    306    *pixels =
    307        (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
    308                  rect->x * surface->format->BytesPerPixel);
    309    *pitch = surface->pitch;
    310    return 0;
    311}
    312
    313static void
    314SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    315{
    316}
    317
    318static int
    319SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
    320{
    321    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    322
    323    if (texture ) {
    324        data->surface = (SDL_Surface *) texture->driverdata;
    325    } else {
    326        data->surface = data->window;
    327    }
    328    return 0;
    329}
    330
    331static int
    332SW_UpdateViewport(SDL_Renderer * renderer)
    333{
    334    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    335    SDL_Surface *surface = data->surface;
    336
    337    if (!surface) {
    338        /* We'll update the viewport after we recreate the surface */
    339        return 0;
    340    }
    341
    342    SDL_SetClipRect(data->surface, &renderer->viewport);
    343    return 0;
    344}
    345
    346static int
    347SW_UpdateClipRect(SDL_Renderer * renderer)
    348{
    349    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    350    SDL_Surface *surface = data->surface;
    351    if (surface) {
    352        if (renderer->clipping_enabled) {
    353            SDL_SetClipRect(surface, &renderer->clip_rect);
    354        } else {
    355            SDL_SetClipRect(surface, NULL);
    356        }
    357    }
    358    return 0;
    359}
    360
    361static int
    362SW_RenderClear(SDL_Renderer * renderer)
    363{
    364    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    365    Uint32 color;
    366    SDL_Rect clip_rect;
    367
    368    if (!surface) {
    369        return -1;
    370    }
    371
    372    color = SDL_MapRGBA(surface->format,
    373                        renderer->r, renderer->g, renderer->b, renderer->a);
    374
    375    /* By definition the clear ignores the clip rect */
    376    clip_rect = surface->clip_rect;
    377    SDL_SetClipRect(surface, NULL);
    378    SDL_FillRect(surface, NULL, color);
    379    SDL_SetClipRect(surface, &clip_rect);
    380    return 0;
    381}
    382
    383static int
    384SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
    385                    int count)
    386{
    387    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    388    SDL_Point *final_points;
    389    int i, status;
    390
    391    if (!surface) {
    392        return -1;
    393    }
    394
    395    final_points = SDL_stack_alloc(SDL_Point, count);
    396    if (!final_points) {
    397        return SDL_OutOfMemory();
    398    }
    399    if (renderer->viewport.x || renderer->viewport.y) {
    400        int x = renderer->viewport.x;
    401        int y = renderer->viewport.y;
    402
    403        for (i = 0; i < count; ++i) {
    404            final_points[i].x = (int)(x + points[i].x);
    405            final_points[i].y = (int)(y + points[i].y);
    406        }
    407    } else {
    408        for (i = 0; i < count; ++i) {
    409            final_points[i].x = (int)points[i].x;
    410            final_points[i].y = (int)points[i].y;
    411        }
    412    }
    413
    414    /* Draw the points! */
    415    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
    416        Uint32 color = SDL_MapRGBA(surface->format,
    417                                   renderer->r, renderer->g, renderer->b,
    418                                   renderer->a);
    419
    420        status = SDL_DrawPoints(surface, final_points, count, color);
    421    } else {
    422        status = SDL_BlendPoints(surface, final_points, count,
    423                                renderer->blendMode,
    424                                renderer->r, renderer->g, renderer->b,
    425                                renderer->a);
    426    }
    427    SDL_stack_free(final_points);
    428
    429    return status;
    430}
    431
    432static int
    433SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
    434                   int count)
    435{
    436    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    437    SDL_Point *final_points;
    438    int i, status;
    439
    440    if (!surface) {
    441        return -1;
    442    }
    443
    444    final_points = SDL_stack_alloc(SDL_Point, count);
    445    if (!final_points) {
    446        return SDL_OutOfMemory();
    447    }
    448    if (renderer->viewport.x || renderer->viewport.y) {
    449        int x = renderer->viewport.x;
    450        int y = renderer->viewport.y;
    451
    452        for (i = 0; i < count; ++i) {
    453            final_points[i].x = (int)(x + points[i].x);
    454            final_points[i].y = (int)(y + points[i].y);
    455        }
    456    } else {
    457        for (i = 0; i < count; ++i) {
    458            final_points[i].x = (int)points[i].x;
    459            final_points[i].y = (int)points[i].y;
    460        }
    461    }
    462
    463    /* Draw the lines! */
    464    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
    465        Uint32 color = SDL_MapRGBA(surface->format,
    466                                   renderer->r, renderer->g, renderer->b,
    467                                   renderer->a);
    468
    469        status = SDL_DrawLines(surface, final_points, count, color);
    470    } else {
    471        status = SDL_BlendLines(surface, final_points, count,
    472                                renderer->blendMode,
    473                                renderer->r, renderer->g, renderer->b,
    474                                renderer->a);
    475    }
    476    SDL_stack_free(final_points);
    477
    478    return status;
    479}
    480
    481static int
    482SW_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
    483{
    484    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    485    SDL_Rect *final_rects;
    486    int i, status;
    487
    488    if (!surface) {
    489        return -1;
    490    }
    491
    492    final_rects = SDL_stack_alloc(SDL_Rect, count);
    493    if (!final_rects) {
    494        return SDL_OutOfMemory();
    495    }
    496    if (renderer->viewport.x || renderer->viewport.y) {
    497        int x = renderer->viewport.x;
    498        int y = renderer->viewport.y;
    499
    500        for (i = 0; i < count; ++i) {
    501            final_rects[i].x = (int)(x + rects[i].x);
    502            final_rects[i].y = (int)(y + rects[i].y);
    503            final_rects[i].w = SDL_max((int)rects[i].w, 1);
    504            final_rects[i].h = SDL_max((int)rects[i].h, 1);
    505        }
    506    } else {
    507        for (i = 0; i < count; ++i) {
    508            final_rects[i].x = (int)rects[i].x;
    509            final_rects[i].y = (int)rects[i].y;
    510            final_rects[i].w = SDL_max((int)rects[i].w, 1);
    511            final_rects[i].h = SDL_max((int)rects[i].h, 1);
    512        }
    513    }
    514
    515    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
    516        Uint32 color = SDL_MapRGBA(surface->format,
    517                                   renderer->r, renderer->g, renderer->b,
    518                                   renderer->a);
    519        status = SDL_FillRects(surface, final_rects, count, color);
    520    } else {
    521        status = SDL_BlendFillRects(surface, final_rects, count,
    522                                    renderer->blendMode,
    523                                    renderer->r, renderer->g, renderer->b,
    524                                    renderer->a);
    525    }
    526    SDL_stack_free(final_rects);
    527
    528    return status;
    529}
    530
    531static int
    532SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    533              const SDL_Rect * srcrect, const SDL_FRect * dstrect)
    534{
    535    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    536    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
    537    SDL_Rect final_rect;
    538
    539    if (!surface) {
    540        return -1;
    541    }
    542
    543    if (renderer->viewport.x || renderer->viewport.y) {
    544        final_rect.x = (int)(renderer->viewport.x + dstrect->x);
    545        final_rect.y = (int)(renderer->viewport.y + dstrect->y);
    546    } else {
    547        final_rect.x = (int)dstrect->x;
    548        final_rect.y = (int)dstrect->y;
    549    }
    550    final_rect.w = (int)dstrect->w;
    551    final_rect.h = (int)dstrect->h;
    552
    553    if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {
    554        return SDL_BlitSurface(src, srcrect, surface, &final_rect);
    555    } else {
    556        return SDL_BlitScaled(src, srcrect, surface, &final_rect);
    557    }
    558}
    559
    560static int
    561GetScaleQuality(void)
    562{
    563    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
    564
    565    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
    566        return 0;
    567    } else {
    568        return 1;
    569    }
    570}
    571
    572static int
    573SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    574                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
    575                const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
    576{
    577    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    578    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
    579    SDL_Rect final_rect, tmp_rect;
    580    SDL_Surface *surface_rotated, *surface_scaled;
    581    Uint32 colorkey;
    582    int retval, dstwidth, dstheight, abscenterx, abscentery;
    583    double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
    584
    585    if (!surface) {
    586        return -1;
    587    }
    588
    589    if (renderer->viewport.x || renderer->viewport.y) {
    590        final_rect.x = (int)(renderer->viewport.x + dstrect->x);
    591        final_rect.y = (int)(renderer->viewport.y + dstrect->y);
    592    } else {
    593        final_rect.x = (int)dstrect->x;
    594        final_rect.y = (int)dstrect->y;
    595    }
    596    final_rect.w = (int)dstrect->w;
    597    final_rect.h = (int)dstrect->h;
    598
    599    surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel,
    600                                          src->format->Rmask, src->format->Gmask,
    601                                          src->format->Bmask, src->format->Amask );
    602    if (surface_scaled) {
    603        SDL_GetColorKey(src, &colorkey);
    604        SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey);
    605        tmp_rect = final_rect;
    606        tmp_rect.x = 0;
    607        tmp_rect.y = 0;
    608
    609        retval = SDL_BlitScaled(src, srcrect, surface_scaled, &tmp_rect);
    610        if (!retval) {
    611            SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, -angle, &dstwidth, &dstheight, &cangle, &sangle);
    612            surface_rotated = SDLgfx_rotateSurface(surface_scaled, -angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
    613            if(surface_rotated) {
    614                /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
    615                abscenterx = final_rect.x + (int)center->x;
    616                abscentery = final_rect.y + (int)center->y;
    617                /* Compensate the angle inversion to match the behaviour of the other backends */
    618                sangle = -sangle;
    619
    620                /* Top Left */
    621                px = final_rect.x - abscenterx;
    622                py = final_rect.y - abscentery;
    623                p1x = px * cangle - py * sangle + abscenterx;
    624                p1y = px * sangle + py * cangle + abscentery;
    625
    626                /* Top Right */
    627                px = final_rect.x + final_rect.w - abscenterx;
    628                py = final_rect.y - abscentery;
    629                p2x = px * cangle - py * sangle + abscenterx;
    630                p2y = px * sangle + py * cangle + abscentery;
    631
    632                /* Bottom Left */
    633                px = final_rect.x - abscenterx;
    634                py = final_rect.y + final_rect.h - abscentery;
    635                p3x = px * cangle - py * sangle + abscenterx;
    636                p3y = px * sangle + py * cangle + abscentery;
    637
    638                /* Bottom Right */
    639                px = final_rect.x + final_rect.w - abscenterx;
    640                py = final_rect.y + final_rect.h - abscentery;
    641                p4x = px * cangle - py * sangle + abscenterx;
    642                p4y = px * sangle + py * cangle + abscentery;
    643
    644                tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
    645                tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
    646                tmp_rect.w = dstwidth;
    647                tmp_rect.h = dstheight;
    648
    649                retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect);
    650                SDL_FreeSurface(surface_scaled);
    651                SDL_FreeSurface(surface_rotated);
    652                return retval;
    653            }
    654        }
    655        return retval;
    656    }
    657
    658    return -1;
    659}
    660
    661static int
    662SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    663                    Uint32 format, void * pixels, int pitch)
    664{
    665    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    666    Uint32 src_format;
    667    void *src_pixels;
    668    SDL_Rect final_rect;
    669
    670    if (!surface) {
    671        return -1;
    672    }
    673
    674    if (renderer->viewport.x || renderer->viewport.y) {
    675        final_rect.x = renderer->viewport.x + rect->x;
    676        final_rect.y = renderer->viewport.y + rect->y;
    677        final_rect.w = rect->w;
    678        final_rect.h = rect->h;
    679        rect = &final_rect;
    680    }
    681
    682    if (rect->x < 0 || rect->x+rect->w > surface->w ||
    683        rect->y < 0 || rect->y+rect->h > surface->h) {
    684        return SDL_SetError("Tried to read outside of surface bounds");
    685    }
    686
    687    src_format = surface->format->format;
    688    src_pixels = (void*)((Uint8 *) surface->pixels +
    689                    rect->y * surface->pitch +
    690                    rect->x * surface->format->BytesPerPixel);
    691
    692    return SDL_ConvertPixels(rect->w, rect->h,
    693                             src_format, src_pixels, surface->pitch,
    694                             format, pixels, pitch);
    695}
    696
    697static void
    698SW_RenderPresent(SDL_Renderer * renderer)
    699{
    700    SDL_Window *window = renderer->window;
    701
    702    if (window) {
    703        SDL_UpdateWindowSurface(window);
    704    }
    705}
    706
    707static void
    708SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    709{
    710    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
    711
    712    SDL_FreeSurface(surface);
    713}
    714
    715static void
    716SW_DestroyRenderer(SDL_Renderer * renderer)
    717{
    718    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    719
    720    SDL_free(data);
    721    SDL_free(renderer);
    722}
    723
    724#endif /* !SDL_RENDER_DISABLED */
    725
    726/* vi: set ts=4 sw=4 expandtab: */