RenderCopyEx,rotation and flipping for all hardware/software backends (#1308)
authorGabriel Jacobo <gabomdq@gmail.com>
Fri, 01 Jun 2012 19:51:08 -0300
changeset 63206077a1310907
parent 6319 698c98b83cbb
child 6321 71fa3d8976a3
RenderCopyEx,rotation and flipping for all hardware/software backends (#1308)
include/SDL_render.h
src/render/SDL_render.c
src/render/SDL_sysrender.h
src/render/direct3d/SDL_render_d3d.c
src/render/opengl/SDL_glfuncs.h
src/render/opengl/SDL_render_gl.c
src/render/opengles/SDL_render_gles.c
src/render/opengles2/SDL_render_gles2.c
src/render/opengles2/SDL_shaders_gles2.c
src/render/software/SDL_render_sw.c
src/render/software/SDL_rotate.c
src/render/software/SDL_rotate.h
test/Makefile.in
test/testrendercopyex.c
     1.1 --- a/include/SDL_render.h	Fri Jun 01 19:42:15 2012 -0300
     1.2 +++ b/include/SDL_render.h	Fri Jun 01 19:51:08 2012 -0300
     1.3 @@ -105,6 +105,16 @@
     1.4  } SDL_TextureModulate;
     1.5  
     1.6  /**
     1.7 + *  \brief Flip constants for SDL_RenderCopyEx
     1.8 + */
     1.9 +typedef enum
    1.10 +{
    1.11 +    SDL_FLIP_NONE = 0x00000000,     /**< Do not flip */
    1.12 +    SDL_FLIP_HORIZONTAL = 0x00000001,    /**< flip horizontally */
    1.13 +    SDL_FLIP_VERTICAL = 0x00000002     /**< flip vertically */
    1.14 +} SDL_RendererFlip;
    1.15 +
    1.16 +/**
    1.17   *  \brief A structure representing rendering state
    1.18   */
    1.19  struct SDL_Renderer;
    1.20 @@ -599,6 +609,27 @@
    1.21                                             const SDL_Rect * srcrect,
    1.22                                             const SDL_Rect * dstrect);
    1.23  
    1.24 +/**
    1.25 + *  \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center 
    1.26 + *
    1.27 + *  \param texture The source texture.
    1.28 + *  \param srcrect   A pointer to the source rectangle, or NULL for the entire
    1.29 + *                   texture.
    1.30 + *  \param dstrect   A pointer to the destination rectangle, or NULL for the
    1.31 + *                   entire rendering target.
    1.32 + *  \param angle    An angle in degrees that indicates the rotation that will be applied to dstrect
    1.33 + *  \param center   A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done aroud dstrect.w/2, dstrect.h/2)
    1.34 + *  \param flip     A SFL_Flip value stating which flipping actions should be performed on the texture
    1.35 + * 
    1.36 + *  \return 0 on success, or -1 on error
    1.37 + */
    1.38 +extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
    1.39 +                                           SDL_Texture * texture,
    1.40 +                                           const SDL_Rect * srcrect,
    1.41 +                                           const SDL_Rect * dstrect,
    1.42 +                                           const double angle,
    1.43 +                                           const SDL_Point *center,
    1.44 +                                           const SDL_RendererFlip flip);
    1.45  
    1.46  /**
    1.47   *  \brief Read pixels from the current rendering target.
     2.1 --- a/src/render/SDL_render.c	Fri Jun 01 19:42:15 2012 -0300
     2.2 +++ b/src/render/SDL_render.c	Fri Jun 01 19:51:08 2012 -0300
     2.3 @@ -1231,6 +1231,62 @@
     2.4                                  &real_dstrect);
     2.5  }
     2.6  
     2.7 +
     2.8 +int
     2.9 +SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    2.10 +               const SDL_Rect * srcrect, const SDL_Rect * dstrect,
    2.11 +               const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
    2.12 +{
    2.13 +    SDL_Window *window;
    2.14 +    SDL_Rect real_srcrect, real_dstrect;
    2.15 +    SDL_Point real_center;
    2.16 +
    2.17 +    CHECK_RENDERER_MAGIC(renderer, -1);
    2.18 +    CHECK_TEXTURE_MAGIC(texture, -1);
    2.19 +
    2.20 +    if (renderer != texture->renderer) {
    2.21 +        SDL_SetError("Texture was not created with this renderer");
    2.22 +        return -1;
    2.23 +    }
    2.24 +    if (!renderer->RenderCopyEx) {
    2.25 +        SDL_SetError("Renderer does not support RenderCopyEx");
    2.26 +        return -1;
    2.27 +    }
    2.28 +    
    2.29 +    window = renderer->window;
    2.30 +
    2.31 +    real_srcrect.x = 0;
    2.32 +    real_srcrect.y = 0;
    2.33 +    real_srcrect.w = texture->w;
    2.34 +    real_srcrect.h = texture->h;
    2.35 +    if (srcrect) {
    2.36 +        if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
    2.37 +            return 0;
    2.38 +        }
    2.39 +    }
    2.40 +
    2.41 +    /* We don't intersect the dstrect with the viewport as RenderCopy does because of potential rotation clipping issues... TODO: should we? */
    2.42 +    if (dstrect) real_dstrect = *dstrect;
    2.43 +    else {
    2.44 +        real_srcrect.x = 0;
    2.45 +        real_srcrect.y = 0;
    2.46 +        real_srcrect.w = renderer->viewport.w;
    2.47 +        real_srcrect.h = renderer->viewport.h;
    2.48 +    }
    2.49 +
    2.50 +    if (texture->native) {
    2.51 +        texture = texture->native;
    2.52 +    }
    2.53 +
    2.54 +    if(center) real_center = *center;
    2.55 +    else {
    2.56 +        real_center.x = real_dstrect.w/2;
    2.57 +        real_center.y = real_dstrect.h/2;
    2.58 +    }
    2.59 +
    2.60 +    return renderer->RenderCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
    2.61 +}
    2.62 +
    2.63  int
    2.64  SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    2.65                       Uint32 format, void * pixels, int pitch)
     3.1 --- a/src/render/SDL_sysrender.h	Fri Jun 01 19:42:15 2012 -0300
     3.2 +++ b/src/render/SDL_sysrender.h	Fri Jun 01 19:51:08 2012 -0300
     3.3 @@ -88,6 +88,9 @@
     3.4                              int count);
     3.5      int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
     3.6                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     3.7 +    int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,
     3.8 +                       const SDL_Rect * srcquad, const SDL_Rect * dstrect,
     3.9 +                       const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
    3.10      int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
    3.11                               Uint32 format, void * pixels, int pitch);
    3.12      void (*RenderPresent) (SDL_Renderer * renderer);
     4.1 --- a/src/render/direct3d/SDL_render_d3d.c	Fri Jun 01 19:42:15 2012 -0300
     4.2 +++ b/src/render/direct3d/SDL_render_d3d.c	Fri Jun 01 19:51:08 2012 -0300
     4.3 @@ -29,12 +29,97 @@
     4.4  #include "SDL_loadso.h"
     4.5  #include "SDL_syswm.h"
     4.6  #include "../SDL_sysrender.h"
     4.7 +#include "stdio.h"
     4.8  
     4.9  #if SDL_VIDEO_RENDER_D3D
    4.10  #define D3D_DEBUG_INFO
    4.11  #include <d3d9.h>
    4.12  #endif
    4.13  
    4.14 +
    4.15 +typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK;
    4.16 +typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX;
    4.17 +typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3;
    4.18 +
    4.19 +DEFINE_GUID(IID_ID3DXMatrixStack,
    4.20 +0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85);
    4.21 +
    4.22 +#undef INTERFACE
    4.23 +#define INTERFACE ID3DXMatrixStack
    4.24 +
    4.25 +DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown)
    4.26 +{
    4.27 +    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
    4.28 +    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
    4.29 +    STDMETHOD_(ULONG,Release)(THIS) PURE;
    4.30 +    STDMETHOD(Pop)(THIS) PURE;
    4.31 +    STDMETHOD(Push)(THIS) PURE;
    4.32 +    STDMETHOD(LoadIdentity)(THIS) PURE;
    4.33 +    STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
    4.34 +    STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
    4.35 +    STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE;
    4.36 +    STDMETHOD(RotateAxis)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
    4.37 +    STDMETHOD(RotateAxisLocal)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
    4.38 +    STDMETHOD(RotateYawPitchRoll)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
    4.39 +    STDMETHOD(RotateYawPitchRollLocal)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
    4.40 +    STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
    4.41 +    STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
    4.42 +    STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE;
    4.43 +    STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
    4.44 +    STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE;
    4.45 +};
    4.46 +
    4.47 +#undef INTERFACE
    4.48 +
    4.49 +#if !defined(__cplusplus) || defined(CINTERFACE)
    4.50 +#define ID3DXMatrixStack_QueryInterface(p,a,b)            (p)->lpVtbl->QueryInterface(p,a,b)
    4.51 +#define ID3DXMatrixStack_AddRef(p)                        (p)->lpVtbl->AddRef(p)
    4.52 +#define ID3DXMatrixStack_Release(p)                       (p)->lpVtbl->Release(p)
    4.53 +#define ID3DXMatrixStack_Pop(p)                           (p)->lpVtbl->Pop(p)
    4.54 +#define ID3DXMatrixStack_Push(p)                          (p)->lpVtbl->Push(p)
    4.55 +#define ID3DXMatrixStack_LoadIdentity(p)                  (p)->lpVtbl->LoadIdentity(p)
    4.56 +#define ID3DXMatrixStack_LoadMatrix(p,a)                  (p)->lpVtbl->LoadMatrix(p,a)
    4.57 +#define ID3DXMatrixStack_MultMatrix(p,a)                  (p)->lpVtbl->MultMatrix(p,a)
    4.58 +#define ID3DXMatrixStack_MultMatrixLocal(p,a)             (p)->lpVtbl->MultMatrixLocal(p,a)
    4.59 +#define ID3DXMatrixStack_RotateAxis(p,a,b)                (p)->lpVtbl->RotateAxis(p,a,b)
    4.60 +#define ID3DXMatrixStack_RotateAxisLocal(p,a,b)           (p)->lpVtbl->RotateAxisLocal(p,a,b)
    4.61 +#define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c)      (p)->lpVtbl->RotateYawPitchRoll(p,a,b,c)
    4.62 +#define ID3DXMatrixStack_RotateYawPitchRollLocal(p,a,b,c) (p)->lpVtbl->RotateYawPitchRollLocal(p,a,b,c)
    4.63 +#define ID3DXMatrixStack_Scale(p,a,b,c)                   (p)->lpVtbl->Scale(p,a,b,c)
    4.64 +#define ID3DXMatrixStack_ScaleLocal(p,a,b,c)              (p)->lpVtbl->ScaleLocal(p,a,b,c)
    4.65 +#define ID3DXMatrixStack_Translate(p,a,b,c)               (p)->lpVtbl->Translate(p,a,b,c)
    4.66 +#define ID3DXMatrixStack_TranslateLocal(p,a,b,c)          (p)->lpVtbl->TranslateLocal(p,a,b,c)
    4.67 +#define ID3DXMatrixStack_GetTop(p)                        (p)->lpVtbl->GetTop(p)
    4.68 +#else
    4.69 +#define ID3DXMatrixStack_QueryInterface(p,a,b)            (p)->QueryInterface(a,b)
    4.70 +#define ID3DXMatrixStack_AddRef(p)                        (p)->AddRef()
    4.71 +#define ID3DXMatrixStack_Release(p)                       (p)->Release()
    4.72 +#define ID3DXMatrixStack_Pop(p)    (p)->Pop()
    4.73 +#define ID3DXMatrixStack_Push(p)    (p)->Push()
    4.74 +#define ID3DXMatrixStack_LoadIdentity(p)    (p)->LoadIdentity()
    4.75 +#define ID3DXMatrixStack_LoadMatrix(p,a)    (p)->LoadMatrix(a)
    4.76 +#define ID3DXMatrixStack_MultMatrix(p,a)    (p)->MultMatrix(a)
    4.77 +#define ID3DXMatrixStack_MultMatrixLocal(p,a)    (p)->MultMatrixLocal(a)
    4.78 +#define ID3DXMatrixStack_RotateAxis(p,a,b)    (p)->RotateAxis(a,b)
    4.79 +#define ID3DXMatrixStack_RotateAxisLocal(p,a,b)    (p)->RotateAxisLocal(a,b)
    4.80 +#define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c)    (p)->RotateYawPitchRollLocal(a,b,c)
    4.81 +#define ID3DXMatrixStack_Scale(p,a,b,c)    (p)->Scale(a,b,c)
    4.82 +#define ID3DXMatrixStack_ScaleLocal(p,a,b,c)    (p)->ScaleLocal(a,b,c)
    4.83 +#define ID3DXMatrixStack_Translate(p,a,b,c)    (p)->Translate(a,b,c)
    4.84 +#define ID3DXMatrixStack_TranslateLocal(p,a,b,c)    (p)->TranslateLocal(a,b,c)
    4.85 +#define ID3DXMatrixStack_GetTop(p)    (p)->GetTop()
    4.86 +#endif
    4.87 +
    4.88 +#ifdef __cplusplus
    4.89 +extern "C" {
    4.90 +#endif
    4.91 +
    4.92 +HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, LPD3DXMATRIXSTACK* ppstack);
    4.93 +
    4.94 +#ifdef __cplusplus
    4.95 +}
    4.96 +#endif
    4.97 +
    4.98  #ifdef ASSEMBLE_SHADER
    4.99  ///////////////////////////////////////////////////////////////////////////
   4.100  // ID3DXBuffer:
   4.101 @@ -110,6 +195,9 @@
   4.102                                 const SDL_Rect * rects, int count);
   4.103  static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   4.104                            const SDL_Rect * srcrect, const SDL_Rect * dstrect);
   4.105 +static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   4.106 +                          const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   4.107 +                          const double angle, const SDL_Point * center, const SDL_RendererFlip flip);
   4.108  static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   4.109                                  Uint32 format, void * pixels, int pitch);
   4.110  static void D3D_RenderPresent(SDL_Renderer * renderer);
   4.111 @@ -141,6 +229,8 @@
   4.112      D3DTEXTUREFILTERTYPE scaleMode;
   4.113      IDirect3DSurface9 *defaultRenderTarget;
   4.114      IDirect3DSurface9 *currentRenderTarget;
   4.115 +    void* d3dxDLL;
   4.116 +    ID3DXMatrixStack *matrixStack;
   4.117  } D3D_RenderData;
   4.118  
   4.119  typedef struct
   4.120 @@ -347,6 +437,8 @@
   4.121      int w, h;
   4.122      SDL_DisplayMode fullscreen_mode;
   4.123      D3DMATRIX matrix;
   4.124 +    int d3dxVersion;
   4.125 +	char d3dxDLLFile[50];
   4.126  
   4.127      renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   4.128      if (!renderer) {
   4.129 @@ -375,8 +467,28 @@
   4.130              SDL_UnloadObject(data->d3dDLL);
   4.131              data->d3dDLL = NULL;
   4.132          }
   4.133 +
   4.134 +        for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) {
   4.135 +            SDL_snprintf(d3dxDLLFile, 49, "D3DX9_%02d.dll", d3dxVersion);
   4.136 +            data->d3dxDLL = SDL_LoadObject(d3dxDLLFile);
   4.137 +            if (data->d3dxDLL) {
   4.138 +                HRESULT (WINAPI *D3DXCreateMatrixStack) (DWORD Flags, LPD3DXMATRIXSTACK*  ppStack);
   4.139 +                D3DXCreateMatrixStack = (HRESULT (WINAPI *) (DWORD, LPD3DXMATRIXSTACK*)) SDL_LoadFunction(data->d3dxDLL, "D3DXCreateMatrixStack");
   4.140 +                if (D3DXCreateMatrixStack) {
   4.141 +                    D3DXCreateMatrixStack(0, &data->matrixStack);
   4.142 +                    break;
   4.143 +                }
   4.144 +            }
   4.145 +        }
   4.146 +
   4.147 +        if (!data->matrixStack) {
   4.148 +            if (data->d3dxDLL) SDL_UnloadObject(data->d3dxDLL);
   4.149 +        }
   4.150      }
   4.151 -    if (!data->d3d) {
   4.152 +
   4.153 +
   4.154 +    
   4.155 +    if (!data->d3d || !data->matrixStack) {
   4.156          SDL_free(renderer);
   4.157          SDL_free(data);
   4.158          SDL_SetError("Unable to create Direct3D interface");
   4.159 @@ -395,6 +507,7 @@
   4.160      renderer->RenderDrawLines = D3D_RenderDrawLines;
   4.161      renderer->RenderFillRects = D3D_RenderFillRects;
   4.162      renderer->RenderCopy = D3D_RenderCopy;
   4.163 +    renderer->RenderCopyEx = D3D_RenderCopyEx;
   4.164      renderer->RenderReadPixels = D3D_RenderReadPixels;
   4.165      renderer->RenderPresent = D3D_RenderPresent;
   4.166      renderer->DestroyTexture = D3D_DestroyTexture;
   4.167 @@ -1126,6 +1239,135 @@
   4.168      return 0;
   4.169  }
   4.170  
   4.171 +
   4.172 +static int
   4.173 +D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   4.174 +               const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   4.175 +               const double angle, const SDL_Point * center, const SDL_RendererFlip flip)
   4.176 +{
   4.177 +    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   4.178 +    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
   4.179 +    LPDIRECT3DPIXELSHADER9 shader = NULL;
   4.180 +    float minx, miny, maxx, maxy;
   4.181 +    float minu, maxu, minv, maxv;
   4.182 +    float centerx, centery;
   4.183 +    DWORD color;
   4.184 +    Vertex vertices[4];
   4.185 +    HRESULT result;
   4.186 +
   4.187 +    if (D3D_ActivateRenderer(renderer) < 0) {
   4.188 +        return -1;
   4.189 +    }
   4.190 +
   4.191 +    centerx = (float)center->x;
   4.192 +    centery = (float)center->y;
   4.193 +
   4.194 +    if (flip & SDL_FLIP_HORIZONTAL) {
   4.195 +        minx = (float) dstrect->w - centerx - 0.5f;
   4.196 +        maxx = (float) -centerx - 0.5f;
   4.197 +    }
   4.198 +    else {
   4.199 +        minx = (float) -centerx - 0.5f;
   4.200 +        maxx = (float) dstrect->w - centerx - 0.5f;
   4.201 +    }
   4.202 +
   4.203 +    if (flip & SDL_FLIP_VERTICAL) {
   4.204 +        miny = (float) dstrect->h - centery - 0.5f;
   4.205 +        maxy = (float) -centery - 0.5f;
   4.206 +    }
   4.207 +    else {
   4.208 +        miny = (float) -centery - 0.5f;
   4.209 +        maxy = (float) dstrect->h - centery - 0.5f;
   4.210 +    }
   4.211 +
   4.212 +    minu = (float) srcrect->x / texture->w;
   4.213 +    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
   4.214 +    minv = (float) srcrect->y / texture->h;
   4.215 +    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
   4.216 +
   4.217 +    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
   4.218 +
   4.219 +    vertices[0].x = minx;
   4.220 +    vertices[0].y = miny;
   4.221 +    vertices[0].z = 0.0f;
   4.222 +    vertices[0].color = color;
   4.223 +    vertices[0].u = minu;
   4.224 +    vertices[0].v = minv;
   4.225 +
   4.226 +    vertices[1].x = maxx;
   4.227 +    vertices[1].y = miny;
   4.228 +    vertices[1].z = 0.0f;
   4.229 +    vertices[1].color = color;
   4.230 +    vertices[1].u = maxu;
   4.231 +    vertices[1].v = minv;
   4.232 +
   4.233 +    vertices[2].x = maxx;
   4.234 +    vertices[2].y = maxy;
   4.235 +    vertices[2].z = 0.0f;
   4.236 +    vertices[2].color = color;
   4.237 +    vertices[2].u = maxu;
   4.238 +    vertices[2].v = maxv;
   4.239 +
   4.240 +    vertices[3].x = minx;
   4.241 +    vertices[3].y = maxy;
   4.242 +    vertices[3].z = 0.0f;
   4.243 +    vertices[3].color = color;
   4.244 +    vertices[3].u = minu;
   4.245 +    vertices[3].v = maxv;
   4.246 +
   4.247 +    D3D_SetBlendMode(data, texture->blendMode);
   4.248 +
   4.249 +    // Rotate and translate
   4.250 +    ID3DXMatrixStack_Push(data->matrixStack);
   4.251 +    ID3DXMatrixStack_LoadIdentity(data->matrixStack);
   4.252 +    ID3DXMatrixStack_RotateYawPitchRoll(data->matrixStack, 0.0, 0.0, M_PI * (float) angle / 180.0f);
   4.253 +    ID3DXMatrixStack_Translate(data->matrixStack, (float)dstrect->x + centerx, (float)dstrect->y + centery, (float)0.0);
   4.254 +    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
   4.255 +
   4.256 +    if (texturedata->scaleMode != data->scaleMode) {
   4.257 +        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
   4.258 +                                         texturedata->scaleMode);
   4.259 +        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
   4.260 +                                         texturedata->scaleMode);
   4.261 +        data->scaleMode = texturedata->scaleMode;
   4.262 +    }
   4.263 +
   4.264 +    result =
   4.265 +        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
   4.266 +                                    texturedata->texture);
   4.267 +    if (FAILED(result)) {
   4.268 +        D3D_SetError("SetTexture()", result);
   4.269 +        return -1;
   4.270 +    }
   4.271 +    if (shader) {
   4.272 +        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
   4.273 +        if (FAILED(result)) {
   4.274 +            D3D_SetError("SetShader()", result);
   4.275 +            return -1;
   4.276 +        }
   4.277 +    }
   4.278 +    result =
   4.279 +        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
   4.280 +                                         vertices, sizeof(*vertices));
   4.281 +    if (FAILED(result)) {
   4.282 +        D3D_SetError("DrawPrimitiveUP()", result);
   4.283 +        return -1;
   4.284 +    }
   4.285 +    if (shader) {
   4.286 +        result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
   4.287 +        if (FAILED(result)) {
   4.288 +            D3D_SetError("SetShader()", result);
   4.289 +            return -1;
   4.290 +        }
   4.291 +    }
   4.292 +    ID3DXMatrixStack_Pop(data->matrixStack);
   4.293 +    ID3DXMatrixStack_Push(data->matrixStack);
   4.294 +    ID3DXMatrixStack_LoadIdentity(data->matrixStack);
   4.295 +    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
   4.296 +    ID3DXMatrixStack_Pop(data->matrixStack);
   4.297 +    return 0;
   4.298 +}
   4.299 +
   4.300  static int
   4.301  D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   4.302                       Uint32 format, void * pixels, int pitch)
     5.1 --- a/src/render/opengl/SDL_glfuncs.h	Fri Jun 01 19:42:15 2012 -0300
     5.2 +++ b/src/render/opengl/SDL_glfuncs.h	Fri Jun 01 19:51:08 2012 -0300
     5.3 @@ -279,14 +279,14 @@
     5.4  SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte * mask))
     5.5  SDL_PROC_UNUSED(void, glPopAttrib, (void))
     5.6  SDL_PROC_UNUSED(void, glPopClientAttrib, (void))
     5.7 -SDL_PROC_UNUSED(void, glPopMatrix, (void))
     5.8 +SDL_PROC(void, glPopMatrix, (void))
     5.9  SDL_PROC_UNUSED(void, glPopName, (void))
    5.10  SDL_PROC_UNUSED(void, glPrioritizeTextures,
    5.11                  (GLsizei n, const GLuint * textures,
    5.12                   const GLclampf * priorities))
    5.13  SDL_PROC_UNUSED(void, glPushAttrib, (GLbitfield mask))
    5.14  SDL_PROC_UNUSED(void, glPushClientAttrib, (GLbitfield mask))
    5.15 -SDL_PROC_UNUSED(void, glPushMatrix, (void))
    5.16 +SDL_PROC(void, glPushMatrix, (void))
    5.17  SDL_PROC_UNUSED(void, glPushName, (GLuint name))
    5.18  SDL_PROC_UNUSED(void, glRasterPos2d, (GLdouble x, GLdouble y))
    5.19  SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble * v))
    5.20 @@ -331,7 +331,7 @@
    5.21                  (GLshort x1, GLshort y1, GLshort x2, GLshort y2))
    5.22  SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2))
    5.23  SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
    5.24 -SDL_PROC_UNUSED(void, glRotated,
    5.25 +SDL_PROC(void, glRotated,
    5.26                  (GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
    5.27  SDL_PROC_UNUSED(void, glRotatef,
    5.28                  (GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
    5.29 @@ -419,7 +419,7 @@
    5.30            GLsizei width, GLsizei height, GLenum format, GLenum type,
    5.31            const GLvoid * pixels))
    5.32  SDL_PROC_UNUSED(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
    5.33 -SDL_PROC_UNUSED(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
    5.34 +SDL_PROC(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
    5.35  SDL_PROC_UNUSED(void, glVertex2d, (GLdouble x, GLdouble y))
    5.36  SDL_PROC_UNUSED(void, glVertex2dv, (const GLdouble * v))
    5.37  SDL_PROC(void, glVertex2f, (GLfloat x, GLfloat y))
     6.1 --- a/src/render/opengl/SDL_render_gl.c	Fri Jun 01 19:42:15 2012 -0300
     6.2 +++ b/src/render/opengl/SDL_render_gl.c	Fri Jun 01 19:51:08 2012 -0300
     6.3 @@ -65,6 +65,9 @@
     6.4                                const SDL_Rect * rects, int count);
     6.5  static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     6.6                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     6.7 +static int GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
     6.8 +                         const SDL_Rect * srcrect, const SDL_Rect * dstrect,
     6.9 +                         const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
    6.10  static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    6.11                                 Uint32 pixel_format, void * pixels, int pitch);
    6.12  static void GL_RenderPresent(SDL_Renderer * renderer);
    6.13 @@ -314,6 +317,7 @@
    6.14      renderer->RenderDrawLines = GL_RenderDrawLines;
    6.15      renderer->RenderFillRects = GL_RenderFillRects;
    6.16      renderer->RenderCopy = GL_RenderCopy;
    6.17 +    renderer->RenderCopyEx = GL_RenderCopyEx;
    6.18      renderer->RenderReadPixels = GL_RenderReadPixels;
    6.19      renderer->RenderPresent = GL_RenderPresent;
    6.20      renderer->DestroyTexture = GL_DestroyTexture;
    6.21 @@ -1019,6 +1023,96 @@
    6.22  }
    6.23  
    6.24  static int
    6.25 +GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    6.26 +              const SDL_Rect * srcrect, const SDL_Rect * dstrect,
    6.27 +              const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
    6.28 +{
    6.29 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    6.30 +    GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
    6.31 +    GLfloat minx, miny, maxx, maxy;
    6.32 +    GLfloat centerx, centery;
    6.33 +    GLfloat minu, maxu, minv, maxv;
    6.34 +    GL_ActivateRenderer(renderer);
    6.35 +
    6.36 +    data->glEnable(texturedata->type);
    6.37 +    if (texturedata->yuv) {
    6.38 +        data->glActiveTextureARB(GL_TEXTURE2_ARB);
    6.39 +        data->glBindTexture(texturedata->type, texturedata->vtexture);
    6.40 +
    6.41 +        data->glActiveTextureARB(GL_TEXTURE1_ARB);
    6.42 +        data->glBindTexture(texturedata->type, texturedata->utexture);
    6.43 +
    6.44 +        data->glActiveTextureARB(GL_TEXTURE0_ARB);
    6.45 +    }
    6.46 +    data->glBindTexture(texturedata->type, texturedata->texture);
    6.47 +
    6.48 +    if (texture->modMode) {
    6.49 +        GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
    6.50 +    } else {
    6.51 +        GL_SetColor(data, 255, 255, 255, 255);
    6.52 +    }
    6.53 +
    6.54 +    GL_SetBlendMode(data, texture->blendMode);
    6.55 +
    6.56 +    if (texturedata->yuv) {
    6.57 +        GL_SetShader(data, SHADER_YV12);
    6.58 +    } else {
    6.59 +        GL_SetShader(data, SHADER_RGB);
    6.60 +    }
    6.61 +
    6.62 +    centerx = (GLfloat)center->x;
    6.63 +    centery = (GLfloat)center->y;
    6.64 +
    6.65 +    if (flip & SDL_FLIP_HORIZONTAL) {
    6.66 +        minx = (GLfloat) dstrect->w - centerx;
    6.67 +        maxx = -centerx;
    6.68 +    }
    6.69 +    else {
    6.70 +        minx = -centerx;
    6.71 +        maxx = (GLfloat) dstrect->w - centerx;
    6.72 +    }
    6.73 +
    6.74 +    if (flip & SDL_FLIP_VERTICAL) {
    6.75 +        miny = (GLfloat) dstrect->h - centery;
    6.76 +        maxy = -centery;
    6.77 +    }
    6.78 +    else {
    6.79 +        miny = -centery;
    6.80 +        maxy = (GLfloat) dstrect->h - centery;
    6.81 +    }
    6.82 +
    6.83 +    minu = (GLfloat) srcrect->x / texture->w;
    6.84 +    minu *= texturedata->texw;
    6.85 +    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
    6.86 +    maxu *= texturedata->texw;
    6.87 +    minv = (GLfloat) srcrect->y / texture->h;
    6.88 +    minv *= texturedata->texh;
    6.89 +    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
    6.90 +    maxv *= texturedata->texh;
    6.91 +
    6.92 +    // Translate to flip, rotate, translate to position
    6.93 +    data->glPushMatrix();
    6.94 +    data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);    
    6.95 +    data->glRotated(angle, (GLdouble)0.0, (GLdouble)0.0, (GLdouble)1.0);
    6.96 +    
    6.97 +    data->glBegin(GL_TRIANGLE_STRIP);
    6.98 +    data->glTexCoord2f(minu, minv);
    6.99 +    data->glVertex2f(minx, miny);
   6.100 +    data->glTexCoord2f(maxu, minv);
   6.101 +    data->glVertex2f(maxx, miny);
   6.102 +    data->glTexCoord2f(minu, maxv);
   6.103 +    data->glVertex2f(minx, maxy);
   6.104 +    data->glTexCoord2f(maxu, maxv);
   6.105 +    data->glVertex2f(maxx, maxy);
   6.106 +    data->glEnd();
   6.107 +    data->glPopMatrix();
   6.108 +    
   6.109 +    data->glDisable(texturedata->type);
   6.110 +
   6.111 +    return 0;
   6.112 +}
   6.113 +
   6.114 +static int
   6.115  GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   6.116                      Uint32 pixel_format, void * pixels, int pitch)
   6.117  {
     7.1 --- a/src/render/opengles/SDL_render_gles.c	Fri Jun 01 19:42:15 2012 -0300
     7.2 +++ b/src/render/opengles/SDL_render_gles.c	Fri Jun 01 19:51:08 2012 -0300
     7.3 @@ -71,6 +71,9 @@
     7.4                             const SDL_Rect * dstrect);
     7.5  static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
     7.6                      Uint32 pixel_format, void * pixels, int pitch);
     7.7 +static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
     7.8 +                         const SDL_Rect * srcrect, const SDL_Rect * dstrect,
     7.9 +                         const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
    7.10  static void GLES_RenderPresent(SDL_Renderer * renderer);
    7.11  static void GLES_DestroyTexture(SDL_Renderer * renderer,
    7.12                                  SDL_Texture * texture);
    7.13 @@ -304,6 +307,7 @@
    7.14      renderer->RenderFillRects = GLES_RenderFillRects;
    7.15      renderer->RenderCopy = GLES_RenderCopy;
    7.16      renderer->RenderReadPixels = GLES_RenderReadPixels;
    7.17 +    renderer->RenderCopyEx = GLES_RenderCopyEx;
    7.18      renderer->RenderPresent = GLES_RenderPresent;
    7.19      renderer->DestroyTexture = GLES_DestroyTexture;
    7.20      renderer->DestroyRenderer = GLES_DestroyRenderer;
    7.21 @@ -958,6 +962,98 @@
    7.22      return status;
    7.23  }
    7.24  
    7.25 +static int
    7.26 +GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    7.27 +                const SDL_Rect * srcrect, const SDL_Rect * dstrect,
    7.28 +                const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
    7.29 +{
    7.30 +
    7.31 +    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
    7.32 +    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
    7.33 +    int minx, miny, maxx, maxy;
    7.34 +    GLfloat minu, maxu, minv, maxv;
    7.35 +    GLfloat centerx, centery;
    7.36 +    
    7.37 +    GLES_ActivateRenderer(renderer);
    7.38 +
    7.39 +    data->glEnable(GL_TEXTURE_2D);
    7.40 +
    7.41 +    data->glBindTexture(texturedata->type, texturedata->texture);
    7.42 +
    7.43 +    if (texture->modMode) {
    7.44 +        GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
    7.45 +    } else {
    7.46 +        GLES_SetColor(data, 255, 255, 255, 255);
    7.47 +    }
    7.48 +
    7.49 +    GLES_SetBlendMode(data, texture->blendMode);
    7.50 +
    7.51 +    GLES_SetTexCoords(data, SDL_TRUE);
    7.52 +
    7.53 +    centerx = (GLfloat)center->x;
    7.54 +    centery = (GLfloat)center->y;
    7.55 +
    7.56 +    // Rotate and translate
    7.57 +    data->glPushMatrix();
    7.58 +    data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);
    7.59 +    data->glRotatef((GLfloat)angle, (GLfloat)0.0, (GLfloat)0.0, (GLfloat)1.0);
    7.60 +
    7.61 +    if (flip & SDL_FLIP_HORIZONTAL) {
    7.62 +        minx = (GLfloat) dstrect->w - centerx;
    7.63 +        maxx = -centerx;
    7.64 +    }
    7.65 +    else {
    7.66 +        minx = -centerx;
    7.67 +        maxx = dstrect->w - centerx;
    7.68 +    }
    7.69 +
    7.70 +    if (flip & SDL_FLIP_VERTICAL) {
    7.71 +        miny = dstrect->h - centery;
    7.72 +        maxy = -centery;
    7.73 +    }
    7.74 +    else {
    7.75 +        miny = -centery;
    7.76 +        maxy = dstrect->h - centery;
    7.77 +    }
    7.78 +
    7.79 +    minu = (GLfloat) srcrect->x / texture->w;
    7.80 +    minu *= texturedata->texw;
    7.81 +    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
    7.82 +    maxu *= texturedata->texw;
    7.83 +    minv = (GLfloat) srcrect->y / texture->h;
    7.84 +    minv *= texturedata->texh;
    7.85 +    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
    7.86 +    maxv *= texturedata->texh;
    7.87 +
    7.88 +    GLshort vertices[8];
    7.89 +    GLfloat texCoords[8];
    7.90 +
    7.91 +    vertices[0] = minx;
    7.92 +    vertices[1] = miny;
    7.93 +    vertices[2] = maxx;
    7.94 +    vertices[3] = miny;
    7.95 +    vertices[4] = minx;
    7.96 +    vertices[5] = maxy;
    7.97 +    vertices[6] = maxx;
    7.98 +    vertices[7] = maxy;
    7.99 +
   7.100 +    texCoords[0] = minu;
   7.101 +    texCoords[1] = minv;
   7.102 +    texCoords[2] = maxu;
   7.103 +    texCoords[3] = minv;
   7.104 +    texCoords[4] = minu;
   7.105 +    texCoords[5] = maxv;
   7.106 +    texCoords[6] = maxu;
   7.107 +    texCoords[7] = maxv;
   7.108 +    data->glVertexPointer(2, GL_SHORT, 0, vertices);
   7.109 +    data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   7.110 +    data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   7.111 +    data->glPopMatrix();
   7.112 +    data->glDisable(GL_TEXTURE_2D);
   7.113 +
   7.114 +    return 0;
   7.115 +}
   7.116 +
   7.117  static void
   7.118  GLES_RenderPresent(SDL_Renderer * renderer)
   7.119  {
     8.1 --- a/src/render/opengles2/SDL_render_gles2.c	Fri Jun 01 19:42:15 2012 -0300
     8.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Fri Jun 01 19:51:08 2012 -0300
     8.3 @@ -112,7 +112,9 @@
     8.4  typedef enum
     8.5  {
     8.6      GLES2_ATTRIBUTE_POSITION = 0,
     8.7 -    GLES2_ATTRIBUTE_TEXCOORD = 1
     8.8 +    GLES2_ATTRIBUTE_TEXCOORD = 1,
     8.9 +    GLES2_ATTRIBUTE_ANGLE = 2,
    8.10 +    GLES2_ATTRIBUTE_CENTER = 3,
    8.11  } GLES2_Attribute;
    8.12  
    8.13  typedef enum
    8.14 @@ -628,6 +630,8 @@
    8.15      rdata->glAttachShader(entry->id, fragment->id);
    8.16      rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
    8.17      rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
    8.18 +    rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
    8.19 +    rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
    8.20      rdata->glLinkProgram(entry->id);
    8.21      rdata->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
    8.22      if (rdata->glGetError() != GL_NO_ERROR || !linkSuccessful)
    8.23 @@ -940,6 +944,9 @@
    8.24                              const SDL_Rect *dstrect);
    8.25  static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    8.26                      Uint32 pixel_format, void * pixels, int pitch);
    8.27 +static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    8.28 +                         const SDL_Rect * srcrect, const SDL_Rect * dstrect,
    8.29 +                         const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
    8.30  static void GLES2_RenderPresent(SDL_Renderer *renderer);
    8.31  
    8.32  
    8.33 @@ -1241,6 +1248,175 @@
    8.34      /* Select the target texture */
    8.35      locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
    8.36      rdata->glGetError();
    8.37 +	rdata->glActiveTexture(GL_TEXTURE0);
    8.38 +    rdata->glBindTexture(tdata->texture_type, tdata->texture);
    8.39 +    rdata->glUniform1i(locTexture, 0);
    8.40 +
    8.41 +    /* Configure color modulation */
    8.42 +    locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
    8.43 +    rdata->glUniform4f(locModulation,
    8.44 +                texture->r * inv255f,
    8.45 +                texture->g * inv255f,
    8.46 +                texture->b * inv255f,
    8.47 +                texture->a * inv255f);
    8.48 +
    8.49 +    /* Configure texture blending */
    8.50 +    GLES2_SetBlendMode(rdata, blendMode);
    8.51 +
    8.52 +    GLES2_SetTexCoords(rdata, SDL_TRUE);
    8.53 +
    8.54 +    /* Emit the textured quad */
    8.55 +    if (renderer->target) {
    8.56 +        // Flip the texture vertically to compensate for the inversion it'll be subjected to later when it's rendered to the screen
    8.57 +        vertices[0] = (GLfloat)dstrect->x;
    8.58 +        vertices[1] = (GLfloat)renderer->viewport.h-dstrect->y;
    8.59 +        vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
    8.60 +        vertices[3] = (GLfloat)renderer->viewport.h-dstrect->y;
    8.61 +        vertices[4] = (GLfloat)dstrect->x;
    8.62 +        vertices[5] = (GLfloat)renderer->viewport.h-(dstrect->y + dstrect->h);
    8.63 +        vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
    8.64 +        vertices[7] = (GLfloat)renderer->viewport.h-(dstrect->y + dstrect->h);
    8.65 +    }
    8.66 +    else {
    8.67 +        vertices[0] = (GLfloat)dstrect->x;
    8.68 +        vertices[1] = (GLfloat)dstrect->y;
    8.69 +        vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
    8.70 +        vertices[3] = (GLfloat)dstrect->y;
    8.71 +        vertices[4] = (GLfloat)dstrect->x;
    8.72 +        vertices[5] = (GLfloat)(dstrect->y + dstrect->h);
    8.73 +        vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
    8.74 +        vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
    8.75 +    }
    8.76 +    rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    8.77 +    texCoords[0] = srcrect->x / (GLfloat)texture->w;
    8.78 +    texCoords[1] = srcrect->y / (GLfloat)texture->h;
    8.79 +    texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
    8.80 +    texCoords[3] = srcrect->y / (GLfloat)texture->h;
    8.81 +    texCoords[4] = srcrect->x / (GLfloat)texture->w;
    8.82 +    texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
    8.83 +    texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
    8.84 +    texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
    8.85 +    rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    8.86 +    rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    8.87 +    if (rdata->glGetError() != GL_NO_ERROR)
    8.88 +    {
    8.89 +        SDL_SetError("Failed to render texture");
    8.90 +        return -1;
    8.91 +    }
    8.92 +    return 0;
    8.93 +}
    8.94 +
    8.95 +static int
    8.96 +GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
    8.97 +                 const SDL_Rect *dstrect, const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
    8.98 +{
    8.99 +    GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
   8.100 +    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   8.101 +    GLES2_ImageSource sourceType;
   8.102 +    SDL_BlendMode blendMode;
   8.103 +    GLfloat vertices[8];
   8.104 +    GLfloat texCoords[8];
   8.105 +    GLuint locTexture;
   8.106 +    GLuint locModulation;
   8.107 +    GLfloat translate[8];
   8.108 +    GLfloat fAngle[4];
   8.109 +    GLfloat tmp;
   8.110 +
   8.111 +    GLES2_ActivateRenderer(renderer);
   8.112 +    
   8.113 +    rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
   8.114 +    rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
   8.115 +    fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)angle;
   8.116 +    /* Calculate the center of rotation */
   8.117 +    translate[0] = translate[2] = translate[4] = translate[6] = (GLfloat)(center->x + dstrect->x);
   8.118 +    translate[1] = translate[3] = translate[5] = translate[7] = (GLfloat)(center->y + dstrect->y);
   8.119 +
   8.120 +    /* Activate an appropriate shader and set the projection matrix */
   8.121 +    blendMode = texture->blendMode;
   8.122 +    if (renderer->target) {
   8.123 +        /* Check if we need to do color mapping between the source and render target textures */
   8.124 +        if (renderer->target->format != texture->format) {
   8.125 +            switch (texture->format)
   8.126 +            {
   8.127 +            case SDL_PIXELFORMAT_ABGR8888:
   8.128 +                switch (renderer->target->format)
   8.129 +                {
   8.130 +                    case SDL_PIXELFORMAT_ARGB8888:
   8.131 +                    case SDL_PIXELFORMAT_RGB888:
   8.132 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   8.133 +                        break;
   8.134 +                    case SDL_PIXELFORMAT_BGR888:
   8.135 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   8.136 +                        break;
   8.137 +                }
   8.138 +                break;
   8.139 +            case SDL_PIXELFORMAT_ARGB8888:
   8.140 +                switch (renderer->target->format)
   8.141 +                {
   8.142 +                    case SDL_PIXELFORMAT_ABGR8888:
   8.143 +                    case SDL_PIXELFORMAT_BGR888:
   8.144 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   8.145 +                        break;
   8.146 +                    case SDL_PIXELFORMAT_RGB888:
   8.147 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   8.148 +                        break;
   8.149 +                }
   8.150 +                break;
   8.151 +            case SDL_PIXELFORMAT_BGR888:
   8.152 +                switch (renderer->target->format)
   8.153 +                {
   8.154 +                    case SDL_PIXELFORMAT_ABGR8888:
   8.155 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
   8.156 +                        break;
   8.157 +                    case SDL_PIXELFORMAT_ARGB8888:
   8.158 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
   8.159 +                        break;
   8.160 +                    case SDL_PIXELFORMAT_RGB888:
   8.161 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   8.162 +                        break;
   8.163 +                }
   8.164 +                break;
   8.165 +            case SDL_PIXELFORMAT_RGB888:
   8.166 +                switch (renderer->target->format)
   8.167 +                {
   8.168 +                    case SDL_PIXELFORMAT_ABGR8888:
   8.169 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   8.170 +                        break;
   8.171 +                    case SDL_PIXELFORMAT_ARGB8888:
   8.172 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
   8.173 +                        break;
   8.174 +                    case SDL_PIXELFORMAT_BGR888:
   8.175 +                        sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   8.176 +                        break;
   8.177 +                }
   8.178 +                break;
   8.179 +            }
   8.180 +        }
   8.181 +        else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;   // Texture formats match, use the non color mapping shader (even if the formats are not ABGR)
   8.182 +    }
   8.183 +    else {
   8.184 +        switch (texture->format)
   8.185 +        {
   8.186 +            case SDL_PIXELFORMAT_ABGR8888:
   8.187 +                sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   8.188 +                break;
   8.189 +            case SDL_PIXELFORMAT_ARGB8888:
   8.190 +                sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   8.191 +                break;
   8.192 +            case SDL_PIXELFORMAT_BGR888:
   8.193 +                sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
   8.194 +                break;
   8.195 +            case SDL_PIXELFORMAT_RGB888:
   8.196 +                sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
   8.197 +                break;
   8.198 +        }
   8.199 +    }
   8.200 +    if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
   8.201 +        return -1;
   8.202 +
   8.203 +    /* Select the target texture */
   8.204 +    locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
   8.205 +    rdata->glGetError();
   8.206      rdata->glActiveTexture(GL_TEXTURE0);
   8.207      rdata->glBindTexture(tdata->texture_type, tdata->texture);
   8.208      rdata->glUniform1i(locTexture, 0);
   8.209 @@ -1280,6 +1456,19 @@
   8.210          vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
   8.211          vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
   8.212      }
   8.213 +    if (flip & SDL_FLIP_HORIZONTAL) {
   8.214 +        tmp = vertices[0];
   8.215 +        vertices[0] = vertices[4] = vertices[2];
   8.216 +        vertices[2] = vertices[6] = tmp;
   8.217 +    }
   8.218 +    if (flip & SDL_FLIP_VERTICAL) {
   8.219 +        tmp = vertices[1];
   8.220 +        vertices[1] = vertices[3] = vertices[5];
   8.221 +        vertices[5] = vertices[7] = tmp;
   8.222 +    }
   8.223 +    
   8.224 +    rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
   8.225 +    rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
   8.226      rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   8.227  
   8.228      texCoords[0] = srcrect->x / (GLfloat)texture->w;
   8.229 @@ -1292,6 +1481,8 @@
   8.230      texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
   8.231      rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
   8.232      rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   8.233 +    rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
   8.234 +    rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
   8.235      if (rdata->glGetError() != GL_NO_ERROR)
   8.236      {
   8.237          SDL_SetError("Failed to render texture");
   8.238 @@ -1504,6 +1695,7 @@
   8.239      renderer->RenderFillRects     = &GLES2_RenderFillRects;
   8.240      renderer->RenderCopy          = &GLES2_RenderCopy;
   8.241      renderer->RenderReadPixels    = &GLES2_RenderReadPixels;
   8.242 +    renderer->RenderCopyEx        = &GLES2_RenderCopyEx;
   8.243      renderer->RenderPresent       = &GLES2_RenderPresent;
   8.244      renderer->DestroyTexture      = &GLES2_DestroyTexture;
   8.245      renderer->DestroyRenderer     = &GLES2_DestroyRenderer;
     9.1 --- a/src/render/opengles2/SDL_shaders_gles2.c	Fri Jun 01 19:42:15 2012 -0300
     9.2 +++ b/src/render/opengles2/SDL_shaders_gles2.c	Fri Jun 01 19:51:08 2012 -0300
     9.3 @@ -33,14 +33,21 @@
     9.4  
     9.5  static const Uint8 GLES2_VertexSrc_Default_[] = " \
     9.6      uniform mat4 u_projection; \
     9.7 -    attribute vec4 a_position; \
     9.8 +    attribute vec2 a_position; \
     9.9      attribute vec2 a_texCoord; \
    9.10 +    attribute float a_angle; \
    9.11 +    attribute vec2 a_center; \
    9.12      varying vec2 v_texCoord; \
    9.13      \
    9.14      void main() \
    9.15      { \
    9.16 +        float angle = radians(a_angle); \
    9.17 +        float c = cos(angle); \
    9.18 +        float s = sin(angle); \
    9.19 +        mat2 rotationMatrix = mat2(c, -s, s, c); \
    9.20 +        vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
    9.21          v_texCoord = a_texCoord; \
    9.22 -        gl_Position = u_projection * a_position; \
    9.23 +        gl_Position = u_projection * vec4(position, 0.0, 1.0);\
    9.24          gl_PointSize = 1.0; \
    9.25      } \
    9.26  ";
    10.1 --- a/src/render/software/SDL_render_sw.c	Fri Jun 01 19:42:15 2012 -0300
    10.2 +++ b/src/render/software/SDL_render_sw.c	Fri Jun 01 19:51:08 2012 -0300
    10.3 @@ -24,6 +24,7 @@
    10.4  
    10.5  #include "../SDL_sysrender.h"
    10.6  #include "SDL_render_sw_c.h"
    10.7 +#include "SDL_hints.h"
    10.8  
    10.9  #include "SDL_draw.h"
   10.10  #include "SDL_blendfillrect.h"
   10.11 @@ -31,7 +32,7 @@
   10.12  #include "SDL_blendpoint.h"
   10.13  #include "SDL_drawline.h"
   10.14  #include "SDL_drawpoint.h"
   10.15 -
   10.16 +#include "SDL_rotate.h"
   10.17  
   10.18  /* SDL surface based renderer implementation */
   10.19  
   10.20 @@ -62,6 +63,9 @@
   10.21                                const SDL_Rect * rects, int count);
   10.22  static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   10.23                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
   10.24 +static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   10.25 +                          const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   10.26 +                          const double angle, const SDL_Point * center, const SDL_RendererFlip flip);
   10.27  static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   10.28                                 Uint32 format, void * pixels, int pitch);
   10.29  static void SW_RenderPresent(SDL_Renderer * renderer);
   10.30 @@ -152,6 +156,7 @@
   10.31      renderer->RenderDrawLines = SW_RenderDrawLines;
   10.32      renderer->RenderFillRects = SW_RenderFillRects;
   10.33      renderer->RenderCopy = SW_RenderCopy;
   10.34 +    renderer->RenderCopyEx = SW_RenderCopyEx;
   10.35      renderer->RenderReadPixels = SW_RenderReadPixels;
   10.36      renderer->RenderPresent = SW_RenderPresent;
   10.37      renderer->DestroyTexture = SW_DestroyTexture;
   10.38 @@ -496,6 +501,102 @@
   10.39  }
   10.40  
   10.41  static int
   10.42 +GetScaleQuality(void)
   10.43 +{
   10.44 +    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
   10.45 +
   10.46 +    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
   10.47 +        return 0;
   10.48 +    } else {
   10.49 +        return 1;
   10.50 +    }
   10.51 +}
   10.52 +
   10.53 +static int
   10.54 +SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   10.55 +                const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   10.56 +                const double angle, const SDL_Point * center, const SDL_RendererFlip flip)
   10.57 +{
   10.58 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
   10.59 +    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
   10.60 +    SDL_Rect final_rect = *dstrect, tmp_rect;
   10.61 +    SDL_Surface *surface_rotated, *surface_scaled;
   10.62 +    SDL_Point final_rect_center;
   10.63 +    Uint32 colorkey;
   10.64 +    int retval, dstwidth, dstheight, abscenterx, abscentery;
   10.65 +    double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
   10.66 +
   10.67 +    if (!surface) {
   10.68 +        return -1;
   10.69 +    }
   10.70 +
   10.71 +    if (renderer->viewport.x || renderer->viewport.y) {
   10.72 +        final_rect.x += renderer->viewport.x;
   10.73 +        final_rect.y += renderer->viewport.y;
   10.74 +    }
   10.75 +
   10.76 +    surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel,
   10.77 +                                          src->format->Rmask, src->format->Gmask,
   10.78 +                                          src->format->Bmask, src->format->Amask );
   10.79 +    SDL_GetColorKey(src, &colorkey);
   10.80 +    SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey);
   10.81 +    tmp_rect = final_rect;
   10.82 +    tmp_rect.x = 0;
   10.83 +    tmp_rect.y = 0;
   10.84 +    if (surface_scaled) {
   10.85 +        retval = SDL_BlitScaled(src, srcrect, surface_scaled, &tmp_rect);
   10.86 +        if (!retval) {
   10.87 +            _rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, -angle, &dstwidth, &dstheight, &cangle, &sangle);
   10.88 +            surface_rotated = _rotateSurface(surface_scaled, -angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
   10.89 +            if(surface_rotated) {
   10.90 +                /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
   10.91 +                abscenterx = final_rect.x + center->x;
   10.92 +                abscentery = final_rect.y + center->y;
   10.93 +                /* Compensate the angle inversion to match the behaviour of the other backends */
   10.94 +                sangle = -sangle;
   10.95 +
   10.96 +                /* Top Left */
   10.97 +                px = final_rect.x - abscenterx;
   10.98 +                py = final_rect.y - abscentery;
   10.99 +                p1x = px * cangle - py * sangle + abscenterx;
  10.100 +                p1y = px * sangle + py * cangle + abscentery;
  10.101 +
  10.102 +                /* Top Right */
  10.103 +                px = final_rect.x + final_rect.w - abscenterx;
  10.104 +                py = final_rect.y - abscentery;
  10.105 +                p2x = px * cangle - py * sangle + abscenterx;
  10.106 +                p2y = px * sangle + py * cangle + abscentery;
  10.107 +
  10.108 +                /* Bottom Left */
  10.109 +                px = final_rect.x - abscenterx;
  10.110 +                py = final_rect.y + final_rect.h - abscentery;
  10.111 +                p3x = px * cangle - py * sangle + abscenterx;
  10.112 +                p3y = px * sangle + py * cangle + abscentery;
  10.113 +
  10.114 +                /* Bottom Right */
  10.115 +                px = final_rect.x + final_rect.w - abscenterx;
  10.116 +                py = final_rect.y + final_rect.h - abscentery;
  10.117 +                p4x = px * cangle - py * sangle + abscenterx;
  10.118 +                p4y = px * sangle + py * cangle + abscentery;
  10.119 +
  10.120 +                tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
  10.121 +                tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
  10.122 +                tmp_rect.w = dstwidth;
  10.123 +                tmp_rect.h = dstheight;
  10.124 +
  10.125 +                retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect);
  10.126 +                SDL_FreeSurface(surface_scaled);
  10.127 +                SDL_FreeSurface(surface_rotated);
  10.128 +                return retval;
  10.129 +            }
  10.130 +        }
  10.131 +        return retval;
  10.132 +    }
  10.133 +
  10.134 +    return -1;
  10.135 +}
  10.136 +
  10.137 +static int
  10.138  SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  10.139                      Uint32 format, void * pixels, int pitch)
  10.140  {
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/render/software/SDL_rotate.c	Fri Jun 01 19:51:08 2012 -0300
    11.3 @@ -0,0 +1,500 @@
    11.4 +/*
    11.5 +
    11.6 +SDL_rotate.c: rotates 32bit or 8bit surfaces
    11.7 +
    11.8 +Shamelessly stolen from SDL_gfx by Andreas Schiffler. Original copyright follows:
    11.9 +
   11.10 +Copyright (C) 2001-2011  Andreas Schiffler
   11.11 +
   11.12 +This software is provided 'as-is', without any express or implied
   11.13 +warranty. In no event will the authors be held liable for any damages
   11.14 +arising from the use of this software.
   11.15 +
   11.16 +Permission is granted to anyone to use this software for any purpose,
   11.17 +including commercial applications, and to alter it and redistribute it
   11.18 +freely, subject to the following restrictions:
   11.19 +
   11.20 +   1. The origin of this software must not be misrepresented; you must not
   11.21 +   claim that you wrote the original software. If you use this software
   11.22 +   in a product, an acknowledgment in the product documentation would be
   11.23 +   appreciated but is not required.
   11.24 +
   11.25 +   2. Altered source versions must be plainly marked as such, and must not be
   11.26 +   misrepresented as being the original software.
   11.27 +
   11.28 +   3. This notice may not be removed or altered from any source
   11.29 +   distribution.
   11.30 +
   11.31 +Andreas Schiffler -- aschiffler at ferzkopp dot net
   11.32 +
   11.33 +*/
   11.34 +
   11.35 +#ifdef WIN32
   11.36 +#include <windows.h>
   11.37 +#endif
   11.38 +
   11.39 +#include <stdlib.h>
   11.40 +#include <string.h>
   11.41 +
   11.42 +#include "SDL.h"
   11.43 +#include "SDL_rotate.h"
   11.44 +
   11.45 +/* ---- Internally used structures */
   11.46 +
   11.47 +/*!
   11.48 +\brief A 32 bit RGBA pixel.
   11.49 +*/
   11.50 +typedef struct tColorRGBA {
   11.51 +    Uint8 r;
   11.52 +    Uint8 g;
   11.53 +    Uint8 b;
   11.54 +    Uint8 a;
   11.55 +} tColorRGBA;
   11.56 +
   11.57 +/*!
   11.58 +\brief A 8bit Y/palette pixel.
   11.59 +*/
   11.60 +typedef struct tColorY {
   11.61 +    Uint8 y;
   11.62 +} tColorY;
   11.63 +
   11.64 +/*!
   11.65 +\brief Returns maximum of two numbers a and b.
   11.66 +*/
   11.67 +#define MAX(a,b)    (((a) > (b)) ? (a) : (b))
   11.68 +
   11.69 +/*!
   11.70 +\brief Number of guard rows added to destination surfaces.
   11.71 +
   11.72 +This is a simple but effective workaround for observed issues.
   11.73 +These rows allocate extra memory and are then hidden from the surface.
   11.74 +Rows are added to the end of destination surfaces when they are allocated.
   11.75 +This catches any potential overflows which seem to happen with
   11.76 +just the right src image dimensions and scale/rotation and can lead
   11.77 +to a situation where the program can segfault.
   11.78 +*/
   11.79 +#define GUARD_ROWS (2)
   11.80 +
   11.81 +/*!
   11.82 +\brief Lower limit of absolute zoom factor or rotation degrees.
   11.83 +*/
   11.84 +#define VALUE_LIMIT 0.001
   11.85 +
   11.86 +/*!
   11.87 +\brief Returns colorkey info for a surface
   11.88 +*/
   11.89 +Uint32 _colorkey(SDL_Surface *src)
   11.90 +{
   11.91 +    Uint32 key = 0;
   11.92 +    SDL_GetColorKey(src, &key);
   11.93 +    return key;
   11.94 +}
   11.95 +
   11.96 +
   11.97 +/*!
   11.98 +\brief Internal target surface sizing function for rotations with trig result return.
   11.99 +
  11.100 +\param width The source surface width.
  11.101 +\param height The source surface height.
  11.102 +\param angle The angle to rotate in degrees.
  11.103 +\param dstwidth The calculated width of the destination surface.
  11.104 +\param dstheight The calculated height of the destination surface.
  11.105 +\param cangle The sine of the angle
  11.106 +\param sangle The cosine of the angle
  11.107 +
  11.108 +*/
  11.109 +void _rotozoomSurfaceSizeTrig(int width, int height, double angle,
  11.110 +                              int *dstwidth, int *dstheight,
  11.111 +                              double *cangle, double *sangle)
  11.112 +{
  11.113 +    double x, y, cx, cy, sx, sy;
  11.114 +    double radangle;
  11.115 +    int dstwidthhalf, dstheighthalf;
  11.116 +
  11.117 +    /*
  11.118 +    * Determine destination width and height by rotating a centered source box
  11.119 +    */
  11.120 +    radangle = angle * (M_PI / 180.0);
  11.121 +    *sangle = SDL_sin(radangle);
  11.122 +    *cangle = SDL_cos(radangle);
  11.123 +    x = (double)(width / 2);
  11.124 +    y = (double)(height / 2);
  11.125 +    cx = *cangle * x;
  11.126 +    cy = *cangle * y;
  11.127 +    sx = *sangle * x;
  11.128 +    sy = *sangle * y;
  11.129 +
  11.130 +    dstwidthhalf = MAX((int)
  11.131 +        SDL_ceil(MAX(MAX(MAX(SDL_fabs(cx + sy), SDL_fabs(cx - sy)), SDL_fabs(-cx + sy)), SDL_fabs(-cx - sy))), 1);
  11.132 +    dstheighthalf = MAX((int)
  11.133 +        SDL_ceil(MAX(MAX(MAX(SDL_fabs(sx + cy), SDL_fabs(sx - cy)), SDL_fabs(-sx + cy)), SDL_fabs(-sx - cy))), 1);
  11.134 +    *dstwidth = 2 * dstwidthhalf;
  11.135 +    *dstheight = 2 * dstheighthalf;
  11.136 +}
  11.137 +
  11.138 +
  11.139 +/*!
  11.140 +\brief Internal 32 bit rotozoomer with optional anti-aliasing.
  11.141 +
  11.142 +Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
  11.143 +parameters by scanning the destination surface and applying optionally anti-aliasing
  11.144 +by bilinear interpolation.
  11.145 +Assumes src and dst surfaces are of 32 bit depth.
  11.146 +Assumes dst surface was allocated with the correct dimensions.
  11.147 +
  11.148 +\param src Source surface.
  11.149 +\param dst Destination surface.
  11.150 +\param cx Horizontal center coordinate.
  11.151 +\param cy Vertical center coordinate.
  11.152 +\param isin Integer version of sine of angle.
  11.153 +\param icos Integer version of cosine of angle.
  11.154 +\param flipx Flag indicating horizontal mirroring should be applied.
  11.155 +\param flipy Flag indicating vertical mirroring should be applied.
  11.156 +\param smooth Flag indicating anti-aliasing should be used.
  11.157 +*/
  11.158 +void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
  11.159 +{
  11.160 +    int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
  11.161 +    tColorRGBA c00, c01, c10, c11, cswap;
  11.162 +    tColorRGBA *pc, *sp;
  11.163 +    int gap;
  11.164 +
  11.165 +    /*
  11.166 +    * Variable setup
  11.167 +    */
  11.168 +    xd = ((src->w - dst->w) << 15);
  11.169 +    yd = ((src->h - dst->h) << 15);
  11.170 +    ax = (cx << 16) - (icos * cx);
  11.171 +    ay = (cy << 16) - (isin * cx);
  11.172 +    sw = src->w - 1;
  11.173 +    sh = src->h - 1;
  11.174 +    pc = (tColorRGBA*) dst->pixels;
  11.175 +    gap = dst->pitch - dst->w * 4;
  11.176 +
  11.177 +    /*
  11.178 +    * Switch between interpolating and non-interpolating code
  11.179 +    */
  11.180 +    if (smooth) {
  11.181 +        for (y = 0; y < dst->h; y++) {
  11.182 +            dy = cy - y;
  11.183 +            sdx = (ax + (isin * dy)) + xd;
  11.184 +            sdy = (ay - (icos * dy)) + yd;
  11.185 +            for (x = 0; x < dst->w; x++) {
  11.186 +                dx = (sdx >> 16);
  11.187 +                dy = (sdy >> 16);
  11.188 +                if (flipx) dx = sw - dx;
  11.189 +                if (flipy) dy = sh - dy;
  11.190 +                if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
  11.191 +                    sp = (tColorRGBA *)src->pixels;;
  11.192 +                    sp += ((src->pitch/4) * dy);
  11.193 +                    sp += dx;
  11.194 +                    c00 = *sp;
  11.195 +                    sp += 1;
  11.196 +                    c01 = *sp;
  11.197 +                    sp += (src->pitch/4);
  11.198 +                    c11 = *sp;
  11.199 +                    sp -= 1;
  11.200 +                    c10 = *sp;
  11.201 +                    if (flipx) {
  11.202 +                        cswap = c00; c00=c01; c01=cswap;
  11.203 +                        cswap = c10; c10=c11; c11=cswap;
  11.204 +                    }
  11.205 +                    if (flipy) {
  11.206 +                        cswap = c00; c00=c10; c10=cswap;
  11.207 +                        cswap = c01; c01=c11; c11=cswap;
  11.208 +                    }
  11.209 +                    /*
  11.210 +                    * Interpolate colors
  11.211 +                    */
  11.212 +                    ex = (sdx & 0xffff);
  11.213 +                    ey = (sdy & 0xffff);
  11.214 +                    t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
  11.215 +                    t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
  11.216 +                    pc->r = (((t2 - t1) * ey) >> 16) + t1;
  11.217 +                    t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
  11.218 +                    t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
  11.219 +                    pc->g = (((t2 - t1) * ey) >> 16) + t1;
  11.220 +                    t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
  11.221 +                    t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
  11.222 +                    pc->b = (((t2 - t1) * ey) >> 16) + t1;
  11.223 +                    t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
  11.224 +                    t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
  11.225 +                    pc->a = (((t2 - t1) * ey) >> 16) + t1;
  11.226 +                }
  11.227 +                sdx += icos;
  11.228 +                sdy += isin;
  11.229 +                pc++;
  11.230 +            }
  11.231 +            pc = (tColorRGBA *) ((Uint8 *) pc + gap);
  11.232 +        }
  11.233 +    } else {
  11.234 +        for (y = 0; y < dst->h; y++) {
  11.235 +            dy = cy - y;
  11.236 +            sdx = (ax + (isin * dy)) + xd;
  11.237 +            sdy = (ay - (icos * dy)) + yd;
  11.238 +            for (x = 0; x < dst->w; x++) {
  11.239 +                dx = (short) (sdx >> 16);
  11.240 +                dy = (short) (sdy >> 16);
  11.241 +                if (flipx) dx = (src->w-1)-dx;
  11.242 +                if (flipy) dy = (src->h-1)-dy;
  11.243 +                if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
  11.244 +                    sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  11.245 +                    sp += dx;
  11.246 +                    *pc = *sp;
  11.247 +                }
  11.248 +                sdx += icos;
  11.249 +                sdy += isin;
  11.250 +                pc++;
  11.251 +            }
  11.252 +            pc = (tColorRGBA *) ((Uint8 *) pc + gap);
  11.253 +        }
  11.254 +    }
  11.255 +}
  11.256 +
  11.257 +/*!
  11.258 +
  11.259 +\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
  11.260 +
  11.261 +Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
  11.262 +parameters by scanning the destination surface.
  11.263 +Assumes src and dst surfaces are of 8 bit depth.
  11.264 +Assumes dst surface was allocated with the correct dimensions.
  11.265 +
  11.266 +\param src Source surface.
  11.267 +\param dst Destination surface.
  11.268 +\param cx Horizontal center coordinate.
  11.269 +\param cy Vertical center coordinate.
  11.270 +\param isin Integer version of sine of angle.
  11.271 +\param icos Integer version of cosine of angle.
  11.272 +\param flipx Flag indicating horizontal mirroring should be applied.
  11.273 +\param flipy Flag indicating vertical mirroring should be applied.
  11.274 +*/
  11.275 +void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
  11.276 +{
  11.277 +    int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
  11.278 +    tColorY *pc, *sp;
  11.279 +    int gap;
  11.280 +
  11.281 +    /*
  11.282 +    * Variable setup
  11.283 +    */
  11.284 +    xd = ((src->w - dst->w) << 15);
  11.285 +    yd = ((src->h - dst->h) << 15);
  11.286 +    ax = (cx << 16) - (icos * cx);
  11.287 +    ay = (cy << 16) - (isin * cx);
  11.288 +    sw = src->w - 1;
  11.289 +    sh = src->h - 1;
  11.290 +    pc = (tColorY*) dst->pixels;
  11.291 +    gap = dst->pitch - dst->w;
  11.292 +    /*
  11.293 +    * Clear surface to colorkey
  11.294 +    */
  11.295 +    SDL_memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
  11.296 +    /*
  11.297 +    * Iterate through destination surface
  11.298 +    */
  11.299 +    for (y = 0; y < dst->h; y++) {
  11.300 +        dy = cy - y;
  11.301 +        sdx = (ax + (isin * dy)) + xd;
  11.302 +        sdy = (ay - (icos * dy)) + yd;
  11.303 +        for (x = 0; x < dst->w; x++) {
  11.304 +            dx = (short) (sdx >> 16);
  11.305 +            dy = (short) (sdy >> 16);
  11.306 +            if (flipx) dx = (src->w-1)-dx;
  11.307 +            if (flipy) dy = (src->h-1)-dy;
  11.308 +            if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
  11.309 +                sp = (tColorY *) (src->pixels);
  11.310 +                sp += (src->pitch * dy + dx);
  11.311 +                *pc = *sp;
  11.312 +            }
  11.313 +            sdx += icos;
  11.314 +            sdy += isin;
  11.315 +            pc++;
  11.316 +        }
  11.317 +        pc += gap;
  11.318 +    }
  11.319 +}
  11.320 +
  11.321 +
  11.322 +
  11.323 +
  11.324 +/*!
  11.325 +\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing.
  11.326 +
  11.327 +Rotates a 32bit or 8bit 'src' surface to newly created 'dst' surface.
  11.328 +'angle' is the rotation in degrees, 'centerx' and 'centery' the rotation center. If 'smooth' is set
  11.329 +then the destination 32bit surface is anti-aliased. If the surface is not 8bit
  11.330 +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
  11.331 +
  11.332 +\param src The surface to rotozoom.
  11.333 +\param angle The angle to rotate in degrees.
  11.334 +\param centerx The horizontal coordinate of the center of rotation
  11.335 +\param zoomy The vertical coordinate of the center of rotation
  11.336 +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable.
  11.337 +\param flipx Set to 1 to flip the image horizontally
  11.338 +\param flipy Set to 1 to flip the image vertically
  11.339 +\param dstwidth The destination surface width
  11.340 +\param dstheight The destination surface height
  11.341 +\param cangle The angle cosine
  11.342 +\param sangle The angle sine
  11.343 +\return The new rotated surface.
  11.344 +
  11.345 +*/
  11.346 +
  11.347 +SDL_Surface *_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery, int smooth, int flipx, int flipy, int dstwidth, int dstheight, double cangle, double sangle)
  11.348 +{
  11.349 +    SDL_Surface *rz_src;
  11.350 +    SDL_Surface *rz_dst;
  11.351 +    int is32bit;
  11.352 +    int i, src_converted;
  11.353 +    Uint8 r,g,b;
  11.354 +    Uint32 colorkey = 0;
  11.355 +    int colorKeyAvailable = 0;
  11.356 +    double sangleinv, cangleinv;
  11.357 +
  11.358 +    /*
  11.359 +    * Sanity check
  11.360 +    */
  11.361 +    if (src == NULL)
  11.362 +        return (NULL);
  11.363 +
  11.364 +    if (src->flags & SDL_TRUE/*SDL_SRCCOLORKEY*/)
  11.365 +    {
  11.366 +        colorkey = _colorkey(src);
  11.367 +        SDL_GetRGB(colorkey, src->format, &r, &g, &b);
  11.368 +        colorKeyAvailable = 1;
  11.369 +    }
  11.370 +    /*
  11.371 +    * Determine if source surface is 32bit or 8bit
  11.372 +    */
  11.373 +    is32bit = (src->format->BitsPerPixel == 32);
  11.374 +    if ((is32bit) || (src->format->BitsPerPixel == 8)) {
  11.375 +        /*
  11.376 +        * Use source surface 'as is'
  11.377 +        */
  11.378 +        rz_src = src;
  11.379 +        src_converted = 0;
  11.380 +    } else {
  11.381 +        /*
  11.382 +        * New source surface is 32bit with a defined RGBA ordering
  11.383 +        */
  11.384 +        rz_src =
  11.385 +            SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
  11.386 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN
  11.387 +            0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
  11.388 +#else
  11.389 +            0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
  11.390 +#endif
  11.391 +            );
  11.392 +        if(colorKeyAvailable)
  11.393 +            SDL_SetColorKey(src, 0, 0);
  11.394 +
  11.395 +        SDL_BlitSurface(src, NULL, rz_src, NULL);
  11.396 +
  11.397 +        if(colorKeyAvailable)
  11.398 +            SDL_SetColorKey(src, SDL_TRUE /*SDL_SRCCOLORKEY*/, colorkey);
  11.399 +        src_converted = 1;
  11.400 +        is32bit = 1;
  11.401 +    }
  11.402 +
  11.403 +
  11.404 +    /* Determine target size */
  11.405 +    //_rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, &dstwidth, &dstheight, &cangle, &sangle);
  11.406 +
  11.407 +    /*
  11.408 +    * Calculate target factors from sin/cos and zoom
  11.409 +    */
  11.410 +    sangleinv = sangle*65536.0;
  11.411 +    cangleinv = cangle*65536.0;
  11.412 +
  11.413 +    /*
  11.414 +    * Alloc space to completely contain the rotated surface
  11.415 +    */
  11.416 +    rz_dst = NULL;
  11.417 +    if (is32bit) {
  11.418 +        /*
  11.419 +        * Target surface is 32bit with source RGBA/ABGR ordering
  11.420 +        */
  11.421 +        rz_dst =
  11.422 +            SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
  11.423 +            rz_src->format->Rmask, rz_src->format->Gmask,
  11.424 +            rz_src->format->Bmask, rz_src->format->Amask);
  11.425 +    } else {
  11.426 +        /*
  11.427 +        * Target surface is 8bit
  11.428 +        */
  11.429 +        rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
  11.430 +    }
  11.431 +
  11.432 +    /* Check target */
  11.433 +    if (rz_dst == NULL)
  11.434 +        return NULL;
  11.435 +
  11.436 +    /* Adjust for guard rows */
  11.437 +    rz_dst->h = dstheight;
  11.438 +
  11.439 +    if (colorKeyAvailable == 1){
  11.440 +        colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
  11.441 +
  11.442 +        SDL_FillRect(rz_dst, NULL, colorkey );
  11.443 +    }
  11.444 +
  11.445 +    /*
  11.446 +    * Lock source surface
  11.447 +    */
  11.448 +    if (SDL_MUSTLOCK(rz_src)) {
  11.449 +        SDL_LockSurface(rz_src);
  11.450 +    }
  11.451 +
  11.452 +    /*
  11.453 +    * Check which kind of surface we have
  11.454 +    */
  11.455 +    if (is32bit) {
  11.456 +        /*
  11.457 +        * Call the 32bit transformation routine to do the rotation (using alpha)
  11.458 +        */
  11.459 +        _transformSurfaceRGBA(rz_src, rz_dst, centerx, centery,
  11.460 +            (int) (sangleinv), (int) (cangleinv),
  11.461 +            flipx, flipy,
  11.462 +            smooth);
  11.463 +        /*
  11.464 +        * Turn on source-alpha support
  11.465 +        */
  11.466 +        //SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
  11.467 +        SDL_SetColorKey(rz_dst, /*SDL_SRCCOLORKEY*/ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
  11.468 +    } else {
  11.469 +        /*
  11.470 +        * Copy palette and colorkey info
  11.471 +        */
  11.472 +        for (i = 0; i < rz_src->format->palette->ncolors; i++) {
  11.473 +            rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
  11.474 +        }
  11.475 +        rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
  11.476 +        /*
  11.477 +        * Call the 8bit transformation routine to do the rotation
  11.478 +        */
  11.479 +        transformSurfaceY(rz_src, rz_dst, centerx, centery,
  11.480 +            (int) (sangleinv), (int) (cangleinv),
  11.481 +            flipx, flipy);
  11.482 +        SDL_SetColorKey(rz_dst, /*SDL_SRCCOLORKEY*/ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
  11.483 +    }
  11.484 +    /*
  11.485 +    * Unlock source surface
  11.486 +    */
  11.487 +    if (SDL_MUSTLOCK(rz_src)) {
  11.488 +        SDL_UnlockSurface(rz_src);
  11.489 +    }
  11.490 +
  11.491 +    /*
  11.492 +    * Cleanup temp surface
  11.493 +    */
  11.494 +    if (src_converted) {
  11.495 +        SDL_FreeSurface(rz_src);
  11.496 +    }
  11.497 +
  11.498 +    /*
  11.499 +    * Return destination surface
  11.500 +    */
  11.501 +    return (rz_dst);
  11.502 +}
  11.503 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/render/software/SDL_rotate.h	Fri Jun 01 19:51:08 2012 -0300
    12.3 @@ -0,0 +1,6 @@
    12.4 +#ifndef MIN
    12.5 +#define MIN(a,b)    (((a) < (b)) ? (a) : (b))
    12.6 +#endif
    12.7 +
    12.8 +extern SDL_Surface *_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery, int smooth, int flipx, int flipy, int dstwidth, int dstheight, double cangle, double sangle);
    12.9 +extern void _rotozoomSurfaceSizeTrig(int width, int height, double angle, int *dstwidth, int *dstheight, double *cangle, double *sangle);
   12.10 \ No newline at end of file
    13.1 --- a/test/Makefile.in	Fri Jun 01 19:42:15 2012 -0300
    13.2 +++ b/test/Makefile.in	Fri Jun 01 19:51:08 2012 -0300
    13.3 @@ -45,6 +45,7 @@
    13.4  	testver$(EXE) \
    13.5  	testwm2$(EXE) \
    13.6  	torturethread$(EXE) \
    13.7 +	testrendercopyex$(EXE) \
    13.8  
    13.9  all: Makefile $(TARGETS)
   13.10  
   13.11 @@ -171,6 +172,9 @@
   13.12  torturethread$(EXE): $(srcdir)/torturethread.c
   13.13  	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
   13.14  
   13.15 +testrendercopyex$(EXE): $(srcdir)/testrendercopyex.c $(srcdir)/common.c
   13.16 +	$(CC) -o $@ $(srcdir)/testrendercopyex.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @MATHLIB@
   13.17 +	
   13.18  clean:
   13.19  	rm -f $(TARGETS)
   13.20  
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/testrendercopyex.c	Fri Jun 01 19:51:08 2012 -0300
    14.3 @@ -0,0 +1,208 @@
    14.4 +/*
    14.5 +  Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
    14.6 +
    14.7 +  This software is provided 'as-is', without any express or implied
    14.8 +  warranty.  In no event will the authors be held liable for any damages
    14.9 +  arising from the use of this software.
   14.10 +
   14.11 +  Permission is granted to anyone to use this software for any purpose,
   14.12 +  including commercial applications, and to alter it and redistribute it
   14.13 +  freely.
   14.14 +*/
   14.15 +/* Simple program:  Move N sprites around on the screen as fast as possible */
   14.16 +
   14.17 +#include <stdlib.h>
   14.18 +#include <stdio.h>
   14.19 +#include <time.h>
   14.20 +
   14.21 +#include "SDL.h"
   14.22 +#include "common.h"
   14.23 +
   14.24 +#define WINDOW_WIDTH    640
   14.25 +#define WINDOW_HEIGHT   480
   14.26 +
   14.27 +static CommonState *state;
   14.28 +
   14.29 +typedef struct {
   14.30 +    SDL_Window *window;
   14.31 +    SDL_Renderer *renderer;
   14.32 +    SDL_Texture *background;
   14.33 +    SDL_Texture *sprite;
   14.34 +    SDL_Rect sprite_rect;
   14.35 +    int scale_direction;
   14.36 +} DrawState;
   14.37 +
   14.38 +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   14.39 +static void
   14.40 +quit(int rc)
   14.41 +{
   14.42 +    CommonQuit(state);
   14.43 +    exit(rc);
   14.44 +}
   14.45 +
   14.46 +SDL_Texture *
   14.47 +LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
   14.48 +{
   14.49 +    SDL_Surface *temp;
   14.50 +    SDL_Texture *texture;
   14.51 +
   14.52 +    /* Load the sprite image */
   14.53 +    temp = SDL_LoadBMP(file);
   14.54 +    if (temp == NULL) {
   14.55 +        fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
   14.56 +        return NULL;
   14.57 +    }
   14.58 +
   14.59 +    /* Set transparent pixel as the pixel at (0,0) */
   14.60 +    if (transparent) {
   14.61 +        if (temp->format->palette) {
   14.62 +            SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
   14.63 +        } else {
   14.64 +            switch (temp->format->BitsPerPixel) {
   14.65 +            case 15:
   14.66 +                SDL_SetColorKey(temp, SDL_TRUE,
   14.67 +                                (*(Uint16 *) temp->pixels) & 0x00007FFF);
   14.68 +                break;
   14.69 +            case 16:
   14.70 +                SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
   14.71 +                break;
   14.72 +            case 24:
   14.73 +                SDL_SetColorKey(temp, SDL_TRUE,
   14.74 +                                (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
   14.75 +                break;
   14.76 +            case 32:
   14.77 +                SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
   14.78 +                break;
   14.79 +            }
   14.80 +        }
   14.81 +    }
   14.82 +
   14.83 +    /* Create textures from the image */
   14.84 +    texture = SDL_CreateTextureFromSurface(renderer, temp);
   14.85 +    if (!texture) {
   14.86 +        fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
   14.87 +        SDL_FreeSurface(temp);
   14.88 +        return NULL;
   14.89 +    }
   14.90 +    SDL_FreeSurface(temp);
   14.91 +
   14.92 +    /* We're ready to roll. :) */
   14.93 +    return texture;
   14.94 +}
   14.95 +
   14.96 +void
   14.97 +Draw(DrawState *s)
   14.98 +{
   14.99 +    SDL_Rect viewport;
  14.100 +    SDL_Texture *target;
  14.101 +    SDL_Point *center=NULL;
  14.102 +    SDL_Point origin = {0,0};
  14.103 +
  14.104 +    SDL_RenderGetViewport(s->renderer, &viewport);
  14.105 +
  14.106 +    target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
  14.107 +    SDL_SetRenderTarget(s->renderer, target);
  14.108 +
  14.109 +    /* Draw the background */
  14.110 +    SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
  14.111 +
  14.112 +    /* Scale and draw the sprite */
  14.113 +    s->sprite_rect.w += s->scale_direction;
  14.114 +    s->sprite_rect.h += s->scale_direction;
  14.115 +    if (s->scale_direction > 0) {
  14.116 +        center = &origin;
  14.117 +        if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
  14.118 +            s->scale_direction = -1;
  14.119 +        }
  14.120 +    } else {
  14.121 +        if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
  14.122 +            s->scale_direction = 1;
  14.123 +        }
  14.124 +    }
  14.125 +    s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
  14.126 +    s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
  14.127 +
  14.128 +    SDL_RenderCopyEx(s->renderer, s->sprite, NULL, &s->sprite_rect, (double)s->sprite_rect.w, center, s->scale_direction);
  14.129 +
  14.130 +    SDL_SetRenderTarget(s->renderer, NULL);
  14.131 +    SDL_RenderCopy(s->renderer, target, NULL, NULL);
  14.132 +    SDL_DestroyTexture(target);
  14.133 +
  14.134 +    /* Update the screen! */
  14.135 +    SDL_RenderPresent(s->renderer);
  14.136 +    //SDL_Delay(10);
  14.137 +}
  14.138 +
  14.139 +int
  14.140 +main(int argc, char *argv[])
  14.141 +{
  14.142 +    DrawState *drawstates;
  14.143 +    int i, done;
  14.144 +    SDL_Event event;
  14.145 +    int frames;
  14.146 +    Uint32 then, now;
  14.147 +
  14.148 +    /* Initialize test framework */
  14.149 +    state = CommonCreateState(argv, SDL_INIT_VIDEO);
  14.150 +    if (!state) {
  14.151 +        return 1;
  14.152 +    }
  14.153 +    for (i = 1; i < argc;) {
  14.154 +        int consumed;
  14.155 +
  14.156 +        consumed = CommonArg(state, i);
  14.157 +        if (consumed == 0) {
  14.158 +            fprintf(stderr, "Usage: %s %s\n", argv[0], CommonUsage(state));
  14.159 +            return 1;
  14.160 +        }
  14.161 +        i += consumed;
  14.162 +    }
  14.163 +    if (!CommonInit(state)) {
  14.164 +        quit(2);
  14.165 +    }
  14.166 +
  14.167 +    drawstates = SDL_stack_alloc(DrawState, state->num_windows);
  14.168 +    for (i = 0; i < state->num_windows; ++i) {
  14.169 +        DrawState *drawstate = &drawstates[i];
  14.170 +
  14.171 +        drawstate->window = state->windows[i];
  14.172 +        drawstate->renderer = state->renderers[i];
  14.173 +        drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
  14.174 +        drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp", SDL_FALSE);
  14.175 +        if (!drawstate->sprite || !drawstate->background) {
  14.176 +            quit(2);
  14.177 +        }
  14.178 +        SDL_QueryTexture(drawstate->sprite, NULL, NULL,
  14.179 +                         &drawstate->sprite_rect.w, &drawstate->sprite_rect.h);
  14.180 +        drawstate->scale_direction = 1;
  14.181 +    }
  14.182 +
  14.183 +    /* Main render loop */
  14.184 +    frames = 0;
  14.185 +    then = SDL_GetTicks();
  14.186 +    done = 0;
  14.187 +    while (!done) {
  14.188 +        /* Check for events */
  14.189 +        ++frames;
  14.190 +        while (SDL_PollEvent(&event)) {
  14.191 +            CommonEvent(state, &event, &done);
  14.192 +        }
  14.193 +        for (i = 0; i < state->num_windows; ++i) {
  14.194 +            Draw(&drawstates[i]);
  14.195 +        }
  14.196 +    }
  14.197 +
  14.198 +    /* Print out some timing information */
  14.199 +    now = SDL_GetTicks();
  14.200 +    if (now > then) {
  14.201 +        double fps = ((double) frames * 1000) / (now - then);
  14.202 +        printf("%2.2f frames per second\n", fps);
  14.203 +    }
  14.204 +
  14.205 +    SDL_stack_free(drawstates);
  14.206 +
  14.207 +    quit(0);
  14.208 +    return 0;
  14.209 +}
  14.210 +
  14.211 +/* vi: set ts=4 sw=4 expandtab: */