RenderCopyEx,rotation and flipping for all hardware/software backends (#1308)
This commit is contained in:
parent
5791b11bc4
commit
17bdcc6e8e
14 changed files with 1550 additions and 10 deletions
|
@ -104,6 +104,16 @@ typedef enum
|
||||||
SDL_TEXTUREMODULATE_ALPHA = 0x00000002 /**< srcA = srcA * alpha */
|
SDL_TEXTUREMODULATE_ALPHA = 0x00000002 /**< srcA = srcA * alpha */
|
||||||
} SDL_TextureModulate;
|
} SDL_TextureModulate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Flip constants for SDL_RenderCopyEx
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SDL_FLIP_NONE = 0x00000000, /**< Do not flip */
|
||||||
|
SDL_FLIP_HORIZONTAL = 0x00000001, /**< flip horizontally */
|
||||||
|
SDL_FLIP_VERTICAL = 0x00000002 /**< flip vertically */
|
||||||
|
} SDL_RendererFlip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A structure representing rendering state
|
* \brief A structure representing rendering state
|
||||||
*/
|
*/
|
||||||
|
@ -599,6 +609,27 @@ extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
|
||||||
const SDL_Rect * srcrect,
|
const SDL_Rect * srcrect,
|
||||||
const SDL_Rect * dstrect);
|
const SDL_Rect * dstrect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center
|
||||||
|
*
|
||||||
|
* \param texture The source texture.
|
||||||
|
* \param srcrect A pointer to the source rectangle, or NULL for the entire
|
||||||
|
* texture.
|
||||||
|
* \param dstrect A pointer to the destination rectangle, or NULL for the
|
||||||
|
* entire rendering target.
|
||||||
|
* \param angle An angle in degrees that indicates the rotation that will be applied to dstrect
|
||||||
|
* \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)
|
||||||
|
* \param flip A SFL_Flip value stating which flipping actions should be performed on the texture
|
||||||
|
*
|
||||||
|
* \return 0 on success, or -1 on error
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
|
||||||
|
SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect,
|
||||||
|
const SDL_Rect * dstrect,
|
||||||
|
const double angle,
|
||||||
|
const SDL_Point *center,
|
||||||
|
const SDL_RendererFlip flip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read pixels from the current rendering target.
|
* \brief Read pixels from the current rendering target.
|
||||||
|
|
|
@ -1231,6 +1231,62 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
&real_dstrect);
|
&real_dstrect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
|
||||||
|
{
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_Rect real_srcrect, real_dstrect;
|
||||||
|
SDL_Point real_center;
|
||||||
|
|
||||||
|
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||||
|
CHECK_TEXTURE_MAGIC(texture, -1);
|
||||||
|
|
||||||
|
if (renderer != texture->renderer) {
|
||||||
|
SDL_SetError("Texture was not created with this renderer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!renderer->RenderCopyEx) {
|
||||||
|
SDL_SetError("Renderer does not support RenderCopyEx");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = renderer->window;
|
||||||
|
|
||||||
|
real_srcrect.x = 0;
|
||||||
|
real_srcrect.y = 0;
|
||||||
|
real_srcrect.w = texture->w;
|
||||||
|
real_srcrect.h = texture->h;
|
||||||
|
if (srcrect) {
|
||||||
|
if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't intersect the dstrect with the viewport as RenderCopy does because of potential rotation clipping issues... TODO: should we? */
|
||||||
|
if (dstrect) real_dstrect = *dstrect;
|
||||||
|
else {
|
||||||
|
real_srcrect.x = 0;
|
||||||
|
real_srcrect.y = 0;
|
||||||
|
real_srcrect.w = renderer->viewport.w;
|
||||||
|
real_srcrect.h = renderer->viewport.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture->native) {
|
||||||
|
texture = texture->native;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(center) real_center = *center;
|
||||||
|
else {
|
||||||
|
real_center.x = real_dstrect.w/2;
|
||||||
|
real_center.y = real_dstrect.h/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderer->RenderCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch)
|
Uint32 format, void * pixels, int pitch)
|
||||||
|
|
|
@ -88,6 +88,9 @@ struct SDL_Renderer
|
||||||
int count);
|
int count);
|
||||||
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
|
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
|
int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcquad, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
|
||||||
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch);
|
Uint32 format, void * pixels, int pitch);
|
||||||
void (*RenderPresent) (SDL_Renderer * renderer);
|
void (*RenderPresent) (SDL_Renderer * renderer);
|
||||||
|
|
|
@ -29,12 +29,97 @@
|
||||||
#include "SDL_loadso.h"
|
#include "SDL_loadso.h"
|
||||||
#include "SDL_syswm.h"
|
#include "SDL_syswm.h"
|
||||||
#include "../SDL_sysrender.h"
|
#include "../SDL_sysrender.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
#if SDL_VIDEO_RENDER_D3D
|
#if SDL_VIDEO_RENDER_D3D
|
||||||
#define D3D_DEBUG_INFO
|
#define D3D_DEBUG_INFO
|
||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK;
|
||||||
|
typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX;
|
||||||
|
typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3;
|
||||||
|
|
||||||
|
DEFINE_GUID(IID_ID3DXMatrixStack,
|
||||||
|
0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85);
|
||||||
|
|
||||||
|
#undef INTERFACE
|
||||||
|
#define INTERFACE ID3DXMatrixStack
|
||||||
|
|
||||||
|
DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown)
|
||||||
|
{
|
||||||
|
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
|
||||||
|
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
||||||
|
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
||||||
|
STDMETHOD(Pop)(THIS) PURE;
|
||||||
|
STDMETHOD(Push)(THIS) PURE;
|
||||||
|
STDMETHOD(LoadIdentity)(THIS) PURE;
|
||||||
|
STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
|
||||||
|
STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
|
||||||
|
STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE;
|
||||||
|
STDMETHOD(RotateAxis)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
|
||||||
|
STDMETHOD(RotateAxisLocal)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
|
||||||
|
STDMETHOD(RotateYawPitchRoll)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
|
||||||
|
STDMETHOD(RotateYawPitchRollLocal)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
|
||||||
|
STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
|
||||||
|
STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
|
||||||
|
STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE;
|
||||||
|
STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
|
||||||
|
STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef INTERFACE
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) || defined(CINTERFACE)
|
||||||
|
#define ID3DXMatrixStack_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||||
|
#define ID3DXMatrixStack_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||||
|
#define ID3DXMatrixStack_Release(p) (p)->lpVtbl->Release(p)
|
||||||
|
#define ID3DXMatrixStack_Pop(p) (p)->lpVtbl->Pop(p)
|
||||||
|
#define ID3DXMatrixStack_Push(p) (p)->lpVtbl->Push(p)
|
||||||
|
#define ID3DXMatrixStack_LoadIdentity(p) (p)->lpVtbl->LoadIdentity(p)
|
||||||
|
#define ID3DXMatrixStack_LoadMatrix(p,a) (p)->lpVtbl->LoadMatrix(p,a)
|
||||||
|
#define ID3DXMatrixStack_MultMatrix(p,a) (p)->lpVtbl->MultMatrix(p,a)
|
||||||
|
#define ID3DXMatrixStack_MultMatrixLocal(p,a) (p)->lpVtbl->MultMatrixLocal(p,a)
|
||||||
|
#define ID3DXMatrixStack_RotateAxis(p,a,b) (p)->lpVtbl->RotateAxis(p,a,b)
|
||||||
|
#define ID3DXMatrixStack_RotateAxisLocal(p,a,b) (p)->lpVtbl->RotateAxisLocal(p,a,b)
|
||||||
|
#define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c) (p)->lpVtbl->RotateYawPitchRoll(p,a,b,c)
|
||||||
|
#define ID3DXMatrixStack_RotateYawPitchRollLocal(p,a,b,c) (p)->lpVtbl->RotateYawPitchRollLocal(p,a,b,c)
|
||||||
|
#define ID3DXMatrixStack_Scale(p,a,b,c) (p)->lpVtbl->Scale(p,a,b,c)
|
||||||
|
#define ID3DXMatrixStack_ScaleLocal(p,a,b,c) (p)->lpVtbl->ScaleLocal(p,a,b,c)
|
||||||
|
#define ID3DXMatrixStack_Translate(p,a,b,c) (p)->lpVtbl->Translate(p,a,b,c)
|
||||||
|
#define ID3DXMatrixStack_TranslateLocal(p,a,b,c) (p)->lpVtbl->TranslateLocal(p,a,b,c)
|
||||||
|
#define ID3DXMatrixStack_GetTop(p) (p)->lpVtbl->GetTop(p)
|
||||||
|
#else
|
||||||
|
#define ID3DXMatrixStack_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
|
||||||
|
#define ID3DXMatrixStack_AddRef(p) (p)->AddRef()
|
||||||
|
#define ID3DXMatrixStack_Release(p) (p)->Release()
|
||||||
|
#define ID3DXMatrixStack_Pop(p) (p)->Pop()
|
||||||
|
#define ID3DXMatrixStack_Push(p) (p)->Push()
|
||||||
|
#define ID3DXMatrixStack_LoadIdentity(p) (p)->LoadIdentity()
|
||||||
|
#define ID3DXMatrixStack_LoadMatrix(p,a) (p)->LoadMatrix(a)
|
||||||
|
#define ID3DXMatrixStack_MultMatrix(p,a) (p)->MultMatrix(a)
|
||||||
|
#define ID3DXMatrixStack_MultMatrixLocal(p,a) (p)->MultMatrixLocal(a)
|
||||||
|
#define ID3DXMatrixStack_RotateAxis(p,a,b) (p)->RotateAxis(a,b)
|
||||||
|
#define ID3DXMatrixStack_RotateAxisLocal(p,a,b) (p)->RotateAxisLocal(a,b)
|
||||||
|
#define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c) (p)->RotateYawPitchRollLocal(a,b,c)
|
||||||
|
#define ID3DXMatrixStack_Scale(p,a,b,c) (p)->Scale(a,b,c)
|
||||||
|
#define ID3DXMatrixStack_ScaleLocal(p,a,b,c) (p)->ScaleLocal(a,b,c)
|
||||||
|
#define ID3DXMatrixStack_Translate(p,a,b,c) (p)->Translate(a,b,c)
|
||||||
|
#define ID3DXMatrixStack_TranslateLocal(p,a,b,c) (p)->TranslateLocal(a,b,c)
|
||||||
|
#define ID3DXMatrixStack_GetTop(p) (p)->GetTop()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, LPD3DXMATRIXSTACK* ppstack);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ASSEMBLE_SHADER
|
#ifdef ASSEMBLE_SHADER
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// ID3DXBuffer:
|
// ID3DXBuffer:
|
||||||
|
@ -110,6 +195,9 @@ static int D3D_RenderFillRects(SDL_Renderer * renderer,
|
||||||
const SDL_Rect * rects, int count);
|
const SDL_Rect * rects, int count);
|
||||||
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
|
static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point * center, const SDL_RendererFlip flip);
|
||||||
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch);
|
Uint32 format, void * pixels, int pitch);
|
||||||
static void D3D_RenderPresent(SDL_Renderer * renderer);
|
static void D3D_RenderPresent(SDL_Renderer * renderer);
|
||||||
|
@ -141,6 +229,8 @@ typedef struct
|
||||||
D3DTEXTUREFILTERTYPE scaleMode;
|
D3DTEXTUREFILTERTYPE scaleMode;
|
||||||
IDirect3DSurface9 *defaultRenderTarget;
|
IDirect3DSurface9 *defaultRenderTarget;
|
||||||
IDirect3DSurface9 *currentRenderTarget;
|
IDirect3DSurface9 *currentRenderTarget;
|
||||||
|
void* d3dxDLL;
|
||||||
|
ID3DXMatrixStack *matrixStack;
|
||||||
} D3D_RenderData;
|
} D3D_RenderData;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -347,6 +437,8 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
int w, h;
|
int w, h;
|
||||||
SDL_DisplayMode fullscreen_mode;
|
SDL_DisplayMode fullscreen_mode;
|
||||||
D3DMATRIX matrix;
|
D3DMATRIX matrix;
|
||||||
|
int d3dxVersion;
|
||||||
|
char d3dxDLLFile[50];
|
||||||
|
|
||||||
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
|
@ -375,8 +467,28 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
SDL_UnloadObject(data->d3dDLL);
|
SDL_UnloadObject(data->d3dDLL);
|
||||||
data->d3dDLL = NULL;
|
data->d3dDLL = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) {
|
||||||
|
SDL_snprintf(d3dxDLLFile, 49, "D3DX9_%02d.dll", d3dxVersion);
|
||||||
|
data->d3dxDLL = SDL_LoadObject(d3dxDLLFile);
|
||||||
|
if (data->d3dxDLL) {
|
||||||
|
HRESULT (WINAPI *D3DXCreateMatrixStack) (DWORD Flags, LPD3DXMATRIXSTACK* ppStack);
|
||||||
|
D3DXCreateMatrixStack = (HRESULT (WINAPI *) (DWORD, LPD3DXMATRIXSTACK*)) SDL_LoadFunction(data->d3dxDLL, "D3DXCreateMatrixStack");
|
||||||
|
if (D3DXCreateMatrixStack) {
|
||||||
|
D3DXCreateMatrixStack(0, &data->matrixStack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data->matrixStack) {
|
||||||
|
if (data->d3dxDLL) SDL_UnloadObject(data->d3dxDLL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!data->d3d) {
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!data->d3d || !data->matrixStack) {
|
||||||
SDL_free(renderer);
|
SDL_free(renderer);
|
||||||
SDL_free(data);
|
SDL_free(data);
|
||||||
SDL_SetError("Unable to create Direct3D interface");
|
SDL_SetError("Unable to create Direct3D interface");
|
||||||
|
@ -395,6 +507,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->RenderDrawLines = D3D_RenderDrawLines;
|
renderer->RenderDrawLines = D3D_RenderDrawLines;
|
||||||
renderer->RenderFillRects = D3D_RenderFillRects;
|
renderer->RenderFillRects = D3D_RenderFillRects;
|
||||||
renderer->RenderCopy = D3D_RenderCopy;
|
renderer->RenderCopy = D3D_RenderCopy;
|
||||||
|
renderer->RenderCopyEx = D3D_RenderCopyEx;
|
||||||
renderer->RenderReadPixels = D3D_RenderReadPixels;
|
renderer->RenderReadPixels = D3D_RenderReadPixels;
|
||||||
renderer->RenderPresent = D3D_RenderPresent;
|
renderer->RenderPresent = D3D_RenderPresent;
|
||||||
renderer->DestroyTexture = D3D_DestroyTexture;
|
renderer->DestroyTexture = D3D_DestroyTexture;
|
||||||
|
@ -1126,6 +1239,135 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point * center, const SDL_RendererFlip flip)
|
||||||
|
{
|
||||||
|
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
|
||||||
|
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
|
||||||
|
LPDIRECT3DPIXELSHADER9 shader = NULL;
|
||||||
|
float minx, miny, maxx, maxy;
|
||||||
|
float minu, maxu, minv, maxv;
|
||||||
|
float centerx, centery;
|
||||||
|
DWORD color;
|
||||||
|
Vertex vertices[4];
|
||||||
|
HRESULT result;
|
||||||
|
|
||||||
|
if (D3D_ActivateRenderer(renderer) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
centerx = (float)center->x;
|
||||||
|
centery = (float)center->y;
|
||||||
|
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL) {
|
||||||
|
minx = (float) dstrect->w - centerx - 0.5f;
|
||||||
|
maxx = (float) -centerx - 0.5f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
minx = (float) -centerx - 0.5f;
|
||||||
|
maxx = (float) dstrect->w - centerx - 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flip & SDL_FLIP_VERTICAL) {
|
||||||
|
miny = (float) dstrect->h - centery - 0.5f;
|
||||||
|
maxy = (float) -centery - 0.5f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miny = (float) -centery - 0.5f;
|
||||||
|
maxy = (float) dstrect->h - centery - 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
minu = (float) srcrect->x / texture->w;
|
||||||
|
maxu = (float) (srcrect->x + srcrect->w) / texture->w;
|
||||||
|
minv = (float) srcrect->y / texture->h;
|
||||||
|
maxv = (float) (srcrect->y + srcrect->h) / texture->h;
|
||||||
|
|
||||||
|
color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
|
||||||
|
|
||||||
|
vertices[0].x = minx;
|
||||||
|
vertices[0].y = miny;
|
||||||
|
vertices[0].z = 0.0f;
|
||||||
|
vertices[0].color = color;
|
||||||
|
vertices[0].u = minu;
|
||||||
|
vertices[0].v = minv;
|
||||||
|
|
||||||
|
vertices[1].x = maxx;
|
||||||
|
vertices[1].y = miny;
|
||||||
|
vertices[1].z = 0.0f;
|
||||||
|
vertices[1].color = color;
|
||||||
|
vertices[1].u = maxu;
|
||||||
|
vertices[1].v = minv;
|
||||||
|
|
||||||
|
vertices[2].x = maxx;
|
||||||
|
vertices[2].y = maxy;
|
||||||
|
vertices[2].z = 0.0f;
|
||||||
|
vertices[2].color = color;
|
||||||
|
vertices[2].u = maxu;
|
||||||
|
vertices[2].v = maxv;
|
||||||
|
|
||||||
|
vertices[3].x = minx;
|
||||||
|
vertices[3].y = maxy;
|
||||||
|
vertices[3].z = 0.0f;
|
||||||
|
vertices[3].color = color;
|
||||||
|
vertices[3].u = minu;
|
||||||
|
vertices[3].v = maxv;
|
||||||
|
|
||||||
|
D3D_SetBlendMode(data, texture->blendMode);
|
||||||
|
|
||||||
|
// Rotate and translate
|
||||||
|
ID3DXMatrixStack_Push(data->matrixStack);
|
||||||
|
ID3DXMatrixStack_LoadIdentity(data->matrixStack);
|
||||||
|
ID3DXMatrixStack_RotateYawPitchRoll(data->matrixStack, 0.0, 0.0, M_PI * (float) angle / 180.0f);
|
||||||
|
ID3DXMatrixStack_Translate(data->matrixStack, (float)dstrect->x + centerx, (float)dstrect->y + centery, (float)0.0);
|
||||||
|
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
|
||||||
|
|
||||||
|
if (texturedata->scaleMode != data->scaleMode) {
|
||||||
|
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
|
||||||
|
texturedata->scaleMode);
|
||||||
|
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
|
||||||
|
texturedata->scaleMode);
|
||||||
|
data->scaleMode = texturedata->scaleMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
result =
|
||||||
|
IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
|
||||||
|
texturedata->texture);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
D3D_SetError("SetTexture()", result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (shader) {
|
||||||
|
result = IDirect3DDevice9_SetPixelShader(data->device, shader);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
D3D_SetError("SetShader()", result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result =
|
||||||
|
IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
|
||||||
|
vertices, sizeof(*vertices));
|
||||||
|
if (FAILED(result)) {
|
||||||
|
D3D_SetError("DrawPrimitiveUP()", result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (shader) {
|
||||||
|
result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
D3D_SetError("SetShader()", result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ID3DXMatrixStack_Pop(data->matrixStack);
|
||||||
|
ID3DXMatrixStack_Push(data->matrixStack);
|
||||||
|
ID3DXMatrixStack_LoadIdentity(data->matrixStack);
|
||||||
|
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
|
||||||
|
ID3DXMatrixStack_Pop(data->matrixStack);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch)
|
Uint32 format, void * pixels, int pitch)
|
||||||
|
|
|
@ -279,14 +279,14 @@ SDL_PROC_UNUSED(void, glPolygonOffset, (GLfloat factor, GLfloat units))
|
||||||
SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte * mask))
|
SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte * mask))
|
||||||
SDL_PROC_UNUSED(void, glPopAttrib, (void))
|
SDL_PROC_UNUSED(void, glPopAttrib, (void))
|
||||||
SDL_PROC_UNUSED(void, glPopClientAttrib, (void))
|
SDL_PROC_UNUSED(void, glPopClientAttrib, (void))
|
||||||
SDL_PROC_UNUSED(void, glPopMatrix, (void))
|
SDL_PROC(void, glPopMatrix, (void))
|
||||||
SDL_PROC_UNUSED(void, glPopName, (void))
|
SDL_PROC_UNUSED(void, glPopName, (void))
|
||||||
SDL_PROC_UNUSED(void, glPrioritizeTextures,
|
SDL_PROC_UNUSED(void, glPrioritizeTextures,
|
||||||
(GLsizei n, const GLuint * textures,
|
(GLsizei n, const GLuint * textures,
|
||||||
const GLclampf * priorities))
|
const GLclampf * priorities))
|
||||||
SDL_PROC_UNUSED(void, glPushAttrib, (GLbitfield mask))
|
SDL_PROC_UNUSED(void, glPushAttrib, (GLbitfield mask))
|
||||||
SDL_PROC_UNUSED(void, glPushClientAttrib, (GLbitfield mask))
|
SDL_PROC_UNUSED(void, glPushClientAttrib, (GLbitfield mask))
|
||||||
SDL_PROC_UNUSED(void, glPushMatrix, (void))
|
SDL_PROC(void, glPushMatrix, (void))
|
||||||
SDL_PROC_UNUSED(void, glPushName, (GLuint name))
|
SDL_PROC_UNUSED(void, glPushName, (GLuint name))
|
||||||
SDL_PROC_UNUSED(void, glRasterPos2d, (GLdouble x, GLdouble y))
|
SDL_PROC_UNUSED(void, glRasterPos2d, (GLdouble x, GLdouble y))
|
||||||
SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble * v))
|
SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble * v))
|
||||||
|
@ -331,7 +331,7 @@ SDL_PROC_UNUSED(void, glRects,
|
||||||
(GLshort x1, GLshort y1, GLshort x2, GLshort y2))
|
(GLshort x1, GLshort y1, GLshort x2, GLshort y2))
|
||||||
SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2))
|
SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2))
|
||||||
SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
|
SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
|
||||||
SDL_PROC_UNUSED(void, glRotated,
|
SDL_PROC(void, glRotated,
|
||||||
(GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
|
(GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
|
||||||
SDL_PROC_UNUSED(void, glRotatef,
|
SDL_PROC_UNUSED(void, glRotatef,
|
||||||
(GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
|
(GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
|
||||||
|
@ -419,7 +419,7 @@ SDL_PROC(void, glTexSubImage2D,
|
||||||
GLsizei width, GLsizei height, GLenum format, GLenum type,
|
GLsizei width, GLsizei height, GLenum format, GLenum type,
|
||||||
const GLvoid * pixels))
|
const GLvoid * pixels))
|
||||||
SDL_PROC_UNUSED(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
|
SDL_PROC_UNUSED(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
|
||||||
SDL_PROC_UNUSED(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
|
SDL_PROC(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
|
||||||
SDL_PROC_UNUSED(void, glVertex2d, (GLdouble x, GLdouble y))
|
SDL_PROC_UNUSED(void, glVertex2d, (GLdouble x, GLdouble y))
|
||||||
SDL_PROC_UNUSED(void, glVertex2dv, (const GLdouble * v))
|
SDL_PROC_UNUSED(void, glVertex2dv, (const GLdouble * v))
|
||||||
SDL_PROC(void, glVertex2f, (GLfloat x, GLfloat y))
|
SDL_PROC(void, glVertex2f, (GLfloat x, GLfloat y))
|
||||||
|
|
|
@ -65,6 +65,9 @@ static int GL_RenderFillRects(SDL_Renderer * renderer,
|
||||||
const SDL_Rect * rects, int count);
|
const SDL_Rect * rects, int count);
|
||||||
static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
|
static int GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
|
||||||
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch);
|
Uint32 pixel_format, void * pixels, int pitch);
|
||||||
static void GL_RenderPresent(SDL_Renderer * renderer);
|
static void GL_RenderPresent(SDL_Renderer * renderer);
|
||||||
|
@ -314,6 +317,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->RenderDrawLines = GL_RenderDrawLines;
|
renderer->RenderDrawLines = GL_RenderDrawLines;
|
||||||
renderer->RenderFillRects = GL_RenderFillRects;
|
renderer->RenderFillRects = GL_RenderFillRects;
|
||||||
renderer->RenderCopy = GL_RenderCopy;
|
renderer->RenderCopy = GL_RenderCopy;
|
||||||
|
renderer->RenderCopyEx = GL_RenderCopyEx;
|
||||||
renderer->RenderReadPixels = GL_RenderReadPixels;
|
renderer->RenderReadPixels = GL_RenderReadPixels;
|
||||||
renderer->RenderPresent = GL_RenderPresent;
|
renderer->RenderPresent = GL_RenderPresent;
|
||||||
renderer->DestroyTexture = GL_DestroyTexture;
|
renderer->DestroyTexture = GL_DestroyTexture;
|
||||||
|
@ -1018,6 +1022,96 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
|
||||||
|
{
|
||||||
|
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
||||||
|
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
||||||
|
GLfloat minx, miny, maxx, maxy;
|
||||||
|
GLfloat centerx, centery;
|
||||||
|
GLfloat minu, maxu, minv, maxv;
|
||||||
|
GL_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
data->glEnable(texturedata->type);
|
||||||
|
if (texturedata->yuv) {
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE2_ARB);
|
||||||
|
data->glBindTexture(texturedata->type, texturedata->vtexture);
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||||
|
data->glBindTexture(texturedata->type, texturedata->utexture);
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||||
|
}
|
||||||
|
data->glBindTexture(texturedata->type, texturedata->texture);
|
||||||
|
|
||||||
|
if (texture->modMode) {
|
||||||
|
GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
|
||||||
|
} else {
|
||||||
|
GL_SetColor(data, 255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_SetBlendMode(data, texture->blendMode);
|
||||||
|
|
||||||
|
if (texturedata->yuv) {
|
||||||
|
GL_SetShader(data, SHADER_YV12);
|
||||||
|
} else {
|
||||||
|
GL_SetShader(data, SHADER_RGB);
|
||||||
|
}
|
||||||
|
|
||||||
|
centerx = (GLfloat)center->x;
|
||||||
|
centery = (GLfloat)center->y;
|
||||||
|
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL) {
|
||||||
|
minx = (GLfloat) dstrect->w - centerx;
|
||||||
|
maxx = -centerx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
minx = -centerx;
|
||||||
|
maxx = (GLfloat) dstrect->w - centerx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flip & SDL_FLIP_VERTICAL) {
|
||||||
|
miny = (GLfloat) dstrect->h - centery;
|
||||||
|
maxy = -centery;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miny = -centery;
|
||||||
|
maxy = (GLfloat) dstrect->h - centery;
|
||||||
|
}
|
||||||
|
|
||||||
|
minu = (GLfloat) srcrect->x / texture->w;
|
||||||
|
minu *= texturedata->texw;
|
||||||
|
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
|
||||||
|
maxu *= texturedata->texw;
|
||||||
|
minv = (GLfloat) srcrect->y / texture->h;
|
||||||
|
minv *= texturedata->texh;
|
||||||
|
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
|
||||||
|
maxv *= texturedata->texh;
|
||||||
|
|
||||||
|
// Translate to flip, rotate, translate to position
|
||||||
|
data->glPushMatrix();
|
||||||
|
data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);
|
||||||
|
data->glRotated(angle, (GLdouble)0.0, (GLdouble)0.0, (GLdouble)1.0);
|
||||||
|
|
||||||
|
data->glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
data->glTexCoord2f(minu, minv);
|
||||||
|
data->glVertex2f(minx, miny);
|
||||||
|
data->glTexCoord2f(maxu, minv);
|
||||||
|
data->glVertex2f(maxx, miny);
|
||||||
|
data->glTexCoord2f(minu, maxv);
|
||||||
|
data->glVertex2f(minx, maxy);
|
||||||
|
data->glTexCoord2f(maxu, maxv);
|
||||||
|
data->glVertex2f(maxx, maxy);
|
||||||
|
data->glEnd();
|
||||||
|
data->glPopMatrix();
|
||||||
|
|
||||||
|
data->glDisable(texturedata->type);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch)
|
Uint32 pixel_format, void * pixels, int pitch)
|
||||||
|
|
|
@ -71,6 +71,9 @@ static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * dstrect);
|
const SDL_Rect * dstrect);
|
||||||
static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch);
|
Uint32 pixel_format, void * pixels, int pitch);
|
||||||
|
static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
|
||||||
static void GLES_RenderPresent(SDL_Renderer * renderer);
|
static void GLES_RenderPresent(SDL_Renderer * renderer);
|
||||||
static void GLES_DestroyTexture(SDL_Renderer * renderer,
|
static void GLES_DestroyTexture(SDL_Renderer * renderer,
|
||||||
SDL_Texture * texture);
|
SDL_Texture * texture);
|
||||||
|
@ -304,6 +307,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->RenderFillRects = GLES_RenderFillRects;
|
renderer->RenderFillRects = GLES_RenderFillRects;
|
||||||
renderer->RenderCopy = GLES_RenderCopy;
|
renderer->RenderCopy = GLES_RenderCopy;
|
||||||
renderer->RenderReadPixels = GLES_RenderReadPixels;
|
renderer->RenderReadPixels = GLES_RenderReadPixels;
|
||||||
|
renderer->RenderCopyEx = GLES_RenderCopyEx;
|
||||||
renderer->RenderPresent = GLES_RenderPresent;
|
renderer->RenderPresent = GLES_RenderPresent;
|
||||||
renderer->DestroyTexture = GLES_DestroyTexture;
|
renderer->DestroyTexture = GLES_DestroyTexture;
|
||||||
renderer->DestroyRenderer = GLES_DestroyRenderer;
|
renderer->DestroyRenderer = GLES_DestroyRenderer;
|
||||||
|
@ -958,6 +962,98 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
|
||||||
|
GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
|
||||||
|
int minx, miny, maxx, maxy;
|
||||||
|
GLfloat minu, maxu, minv, maxv;
|
||||||
|
GLfloat centerx, centery;
|
||||||
|
|
||||||
|
GLES_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
data->glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
data->glBindTexture(texturedata->type, texturedata->texture);
|
||||||
|
|
||||||
|
if (texture->modMode) {
|
||||||
|
GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
|
||||||
|
} else {
|
||||||
|
GLES_SetColor(data, 255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLES_SetBlendMode(data, texture->blendMode);
|
||||||
|
|
||||||
|
GLES_SetTexCoords(data, SDL_TRUE);
|
||||||
|
|
||||||
|
centerx = (GLfloat)center->x;
|
||||||
|
centery = (GLfloat)center->y;
|
||||||
|
|
||||||
|
// Rotate and translate
|
||||||
|
data->glPushMatrix();
|
||||||
|
data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);
|
||||||
|
data->glRotatef((GLfloat)angle, (GLfloat)0.0, (GLfloat)0.0, (GLfloat)1.0);
|
||||||
|
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL) {
|
||||||
|
minx = (GLfloat) dstrect->w - centerx;
|
||||||
|
maxx = -centerx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
minx = -centerx;
|
||||||
|
maxx = dstrect->w - centerx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flip & SDL_FLIP_VERTICAL) {
|
||||||
|
miny = dstrect->h - centery;
|
||||||
|
maxy = -centery;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miny = -centery;
|
||||||
|
maxy = dstrect->h - centery;
|
||||||
|
}
|
||||||
|
|
||||||
|
minu = (GLfloat) srcrect->x / texture->w;
|
||||||
|
minu *= texturedata->texw;
|
||||||
|
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
|
||||||
|
maxu *= texturedata->texw;
|
||||||
|
minv = (GLfloat) srcrect->y / texture->h;
|
||||||
|
minv *= texturedata->texh;
|
||||||
|
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
|
||||||
|
maxv *= texturedata->texh;
|
||||||
|
|
||||||
|
GLshort vertices[8];
|
||||||
|
GLfloat texCoords[8];
|
||||||
|
|
||||||
|
vertices[0] = minx;
|
||||||
|
vertices[1] = miny;
|
||||||
|
vertices[2] = maxx;
|
||||||
|
vertices[3] = miny;
|
||||||
|
vertices[4] = minx;
|
||||||
|
vertices[5] = maxy;
|
||||||
|
vertices[6] = maxx;
|
||||||
|
vertices[7] = maxy;
|
||||||
|
|
||||||
|
texCoords[0] = minu;
|
||||||
|
texCoords[1] = minv;
|
||||||
|
texCoords[2] = maxu;
|
||||||
|
texCoords[3] = minv;
|
||||||
|
texCoords[4] = minu;
|
||||||
|
texCoords[5] = maxv;
|
||||||
|
texCoords[6] = maxu;
|
||||||
|
texCoords[7] = maxv;
|
||||||
|
data->glVertexPointer(2, GL_SHORT, 0, vertices);
|
||||||
|
data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
|
||||||
|
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
data->glPopMatrix();
|
||||||
|
data->glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
GLES_RenderPresent(SDL_Renderer * renderer)
|
GLES_RenderPresent(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,7 +112,9 @@ typedef struct GLES2_ProgramCache
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GLES2_ATTRIBUTE_POSITION = 0,
|
GLES2_ATTRIBUTE_POSITION = 0,
|
||||||
GLES2_ATTRIBUTE_TEXCOORD = 1
|
GLES2_ATTRIBUTE_TEXCOORD = 1,
|
||||||
|
GLES2_ATTRIBUTE_ANGLE = 2,
|
||||||
|
GLES2_ATTRIBUTE_CENTER = 3,
|
||||||
} GLES2_Attribute;
|
} GLES2_Attribute;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -628,6 +630,8 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
|
||||||
rdata->glAttachShader(entry->id, fragment->id);
|
rdata->glAttachShader(entry->id, fragment->id);
|
||||||
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
|
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
|
||||||
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
|
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
|
||||||
|
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
|
||||||
|
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
|
||||||
rdata->glLinkProgram(entry->id);
|
rdata->glLinkProgram(entry->id);
|
||||||
rdata->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
|
rdata->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
|
||||||
if (rdata->glGetError() != GL_NO_ERROR || !linkSuccessful)
|
if (rdata->glGetError() != GL_NO_ERROR || !linkSuccessful)
|
||||||
|
@ -940,6 +944,9 @@ static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const
|
||||||
const SDL_Rect *dstrect);
|
const SDL_Rect *dstrect);
|
||||||
static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch);
|
Uint32 pixel_format, void * pixels, int pitch);
|
||||||
|
static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
|
||||||
static void GLES2_RenderPresent(SDL_Renderer *renderer);
|
static void GLES2_RenderPresent(SDL_Renderer *renderer);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1241,7 +1248,7 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
/* Select the target texture */
|
/* Select the target texture */
|
||||||
locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
|
locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
|
||||||
rdata->glGetError();
|
rdata->glGetError();
|
||||||
rdata->glActiveTexture(GL_TEXTURE0);
|
rdata->glActiveTexture(GL_TEXTURE0);
|
||||||
rdata->glBindTexture(tdata->texture_type, tdata->texture);
|
rdata->glBindTexture(tdata->texture_type, tdata->texture);
|
||||||
rdata->glUniform1i(locTexture, 0);
|
rdata->glUniform1i(locTexture, 0);
|
||||||
|
|
||||||
|
@ -1281,6 +1288,188 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
|
vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
|
||||||
}
|
}
|
||||||
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||||
|
texCoords[0] = srcrect->x / (GLfloat)texture->w;
|
||||||
|
texCoords[1] = srcrect->y / (GLfloat)texture->h;
|
||||||
|
texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
|
texCoords[3] = srcrect->y / (GLfloat)texture->h;
|
||||||
|
texCoords[4] = srcrect->x / (GLfloat)texture->w;
|
||||||
|
texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
|
texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
|
texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
|
||||||
|
rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
if (rdata->glGetError() != GL_NO_ERROR)
|
||||||
|
{
|
||||||
|
SDL_SetError("Failed to render texture");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
|
||||||
|
const SDL_Rect *dstrect, const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
|
||||||
|
{
|
||||||
|
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
|
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||||
|
GLES2_ImageSource sourceType;
|
||||||
|
SDL_BlendMode blendMode;
|
||||||
|
GLfloat vertices[8];
|
||||||
|
GLfloat texCoords[8];
|
||||||
|
GLuint locTexture;
|
||||||
|
GLuint locModulation;
|
||||||
|
GLfloat translate[8];
|
||||||
|
GLfloat fAngle[4];
|
||||||
|
GLfloat tmp;
|
||||||
|
|
||||||
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
|
||||||
|
rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
|
||||||
|
fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)angle;
|
||||||
|
/* Calculate the center of rotation */
|
||||||
|
translate[0] = translate[2] = translate[4] = translate[6] = (GLfloat)(center->x + dstrect->x);
|
||||||
|
translate[1] = translate[3] = translate[5] = translate[7] = (GLfloat)(center->y + dstrect->y);
|
||||||
|
|
||||||
|
/* Activate an appropriate shader and set the projection matrix */
|
||||||
|
blendMode = texture->blendMode;
|
||||||
|
if (renderer->target) {
|
||||||
|
/* Check if we need to do color mapping between the source and render target textures */
|
||||||
|
if (renderer->target->format != texture->format) {
|
||||||
|
switch (texture->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
switch (renderer->target->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
switch (renderer->target->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
switch (renderer->target->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
switch (renderer->target->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; // Texture formats match, use the non color mapping shader (even if the formats are not ABGR)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (texture->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Select the target texture */
|
||||||
|
locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
|
||||||
|
rdata->glGetError();
|
||||||
|
rdata->glActiveTexture(GL_TEXTURE0);
|
||||||
|
rdata->glBindTexture(tdata->texture_type, tdata->texture);
|
||||||
|
rdata->glUniform1i(locTexture, 0);
|
||||||
|
|
||||||
|
/* Configure color modulation */
|
||||||
|
locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
|
||||||
|
rdata->glUniform4f(locModulation,
|
||||||
|
texture->r * inv255f,
|
||||||
|
texture->g * inv255f,
|
||||||
|
texture->b * inv255f,
|
||||||
|
texture->a * inv255f);
|
||||||
|
|
||||||
|
/* Configure texture blending */
|
||||||
|
GLES2_SetBlendMode(rdata, blendMode);
|
||||||
|
|
||||||
|
GLES2_SetTexCoords(rdata, SDL_TRUE);
|
||||||
|
|
||||||
|
/* Emit the textured quad */
|
||||||
|
if (renderer->target) {
|
||||||
|
// Flip the texture vertically to compensate for the inversion it'll be subjected to later when it's rendered to the screen
|
||||||
|
vertices[0] = (GLfloat)dstrect->x;
|
||||||
|
vertices[1] = (GLfloat)renderer->viewport.h-dstrect->y;
|
||||||
|
vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[3] = (GLfloat)renderer->viewport.h-dstrect->y;
|
||||||
|
vertices[4] = (GLfloat)dstrect->x;
|
||||||
|
vertices[5] = (GLfloat)renderer->viewport.h-(dstrect->y + dstrect->h);
|
||||||
|
vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[7] = (GLfloat)renderer->viewport.h-(dstrect->y + dstrect->h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertices[0] = (GLfloat)dstrect->x;
|
||||||
|
vertices[1] = (GLfloat)dstrect->y;
|
||||||
|
vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[3] = (GLfloat)dstrect->y;
|
||||||
|
vertices[4] = (GLfloat)dstrect->x;
|
||||||
|
vertices[5] = (GLfloat)(dstrect->y + dstrect->h);
|
||||||
|
vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
|
||||||
|
}
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL) {
|
||||||
|
tmp = vertices[0];
|
||||||
|
vertices[0] = vertices[4] = vertices[2];
|
||||||
|
vertices[2] = vertices[6] = tmp;
|
||||||
|
}
|
||||||
|
if (flip & SDL_FLIP_VERTICAL) {
|
||||||
|
tmp = vertices[1];
|
||||||
|
vertices[1] = vertices[3] = vertices[5];
|
||||||
|
vertices[5] = vertices[7] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
|
||||||
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
|
||||||
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||||
|
|
||||||
texCoords[0] = srcrect->x / (GLfloat)texture->w;
|
texCoords[0] = srcrect->x / (GLfloat)texture->w;
|
||||||
texCoords[1] = srcrect->y / (GLfloat)texture->h;
|
texCoords[1] = srcrect->y / (GLfloat)texture->h;
|
||||||
|
@ -1292,6 +1481,8 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
|
||||||
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
|
||||||
rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
|
||||||
|
rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
|
||||||
if (rdata->glGetError() != GL_NO_ERROR)
|
if (rdata->glGetError() != GL_NO_ERROR)
|
||||||
{
|
{
|
||||||
SDL_SetError("Failed to render texture");
|
SDL_SetError("Failed to render texture");
|
||||||
|
@ -1504,6 +1695,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
renderer->RenderFillRects = &GLES2_RenderFillRects;
|
renderer->RenderFillRects = &GLES2_RenderFillRects;
|
||||||
renderer->RenderCopy = &GLES2_RenderCopy;
|
renderer->RenderCopy = &GLES2_RenderCopy;
|
||||||
renderer->RenderReadPixels = &GLES2_RenderReadPixels;
|
renderer->RenderReadPixels = &GLES2_RenderReadPixels;
|
||||||
|
renderer->RenderCopyEx = &GLES2_RenderCopyEx;
|
||||||
renderer->RenderPresent = &GLES2_RenderPresent;
|
renderer->RenderPresent = &GLES2_RenderPresent;
|
||||||
renderer->DestroyTexture = &GLES2_DestroyTexture;
|
renderer->DestroyTexture = &GLES2_DestroyTexture;
|
||||||
renderer->DestroyRenderer = &GLES2_DestroyRenderer;
|
renderer->DestroyRenderer = &GLES2_DestroyRenderer;
|
||||||
|
|
|
@ -33,14 +33,21 @@
|
||||||
|
|
||||||
static const Uint8 GLES2_VertexSrc_Default_[] = " \
|
static const Uint8 GLES2_VertexSrc_Default_[] = " \
|
||||||
uniform mat4 u_projection; \
|
uniform mat4 u_projection; \
|
||||||
attribute vec4 a_position; \
|
attribute vec2 a_position; \
|
||||||
attribute vec2 a_texCoord; \
|
attribute vec2 a_texCoord; \
|
||||||
|
attribute float a_angle; \
|
||||||
|
attribute vec2 a_center; \
|
||||||
varying vec2 v_texCoord; \
|
varying vec2 v_texCoord; \
|
||||||
\
|
\
|
||||||
void main() \
|
void main() \
|
||||||
{ \
|
{ \
|
||||||
|
float angle = radians(a_angle); \
|
||||||
|
float c = cos(angle); \
|
||||||
|
float s = sin(angle); \
|
||||||
|
mat2 rotationMatrix = mat2(c, -s, s, c); \
|
||||||
|
vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
|
||||||
v_texCoord = a_texCoord; \
|
v_texCoord = a_texCoord; \
|
||||||
gl_Position = u_projection * a_position; \
|
gl_Position = u_projection * vec4(position, 0.0, 1.0);\
|
||||||
gl_PointSize = 1.0; \
|
gl_PointSize = 1.0; \
|
||||||
} \
|
} \
|
||||||
";
|
";
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "../SDL_sysrender.h"
|
#include "../SDL_sysrender.h"
|
||||||
#include "SDL_render_sw_c.h"
|
#include "SDL_render_sw_c.h"
|
||||||
|
#include "SDL_hints.h"
|
||||||
|
|
||||||
#include "SDL_draw.h"
|
#include "SDL_draw.h"
|
||||||
#include "SDL_blendfillrect.h"
|
#include "SDL_blendfillrect.h"
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
#include "SDL_blendpoint.h"
|
#include "SDL_blendpoint.h"
|
||||||
#include "SDL_drawline.h"
|
#include "SDL_drawline.h"
|
||||||
#include "SDL_drawpoint.h"
|
#include "SDL_drawpoint.h"
|
||||||
|
#include "SDL_rotate.h"
|
||||||
|
|
||||||
/* SDL surface based renderer implementation */
|
/* SDL surface based renderer implementation */
|
||||||
|
|
||||||
|
@ -62,6 +63,9 @@ static int SW_RenderFillRects(SDL_Renderer * renderer,
|
||||||
const SDL_Rect * rects, int count);
|
const SDL_Rect * rects, int count);
|
||||||
static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
|
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point * center, const SDL_RendererFlip flip);
|
||||||
static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch);
|
Uint32 format, void * pixels, int pitch);
|
||||||
static void SW_RenderPresent(SDL_Renderer * renderer);
|
static void SW_RenderPresent(SDL_Renderer * renderer);
|
||||||
|
@ -152,6 +156,7 @@ SW_CreateRendererForSurface(SDL_Surface * surface)
|
||||||
renderer->RenderDrawLines = SW_RenderDrawLines;
|
renderer->RenderDrawLines = SW_RenderDrawLines;
|
||||||
renderer->RenderFillRects = SW_RenderFillRects;
|
renderer->RenderFillRects = SW_RenderFillRects;
|
||||||
renderer->RenderCopy = SW_RenderCopy;
|
renderer->RenderCopy = SW_RenderCopy;
|
||||||
|
renderer->RenderCopyEx = SW_RenderCopyEx;
|
||||||
renderer->RenderReadPixels = SW_RenderReadPixels;
|
renderer->RenderReadPixels = SW_RenderReadPixels;
|
||||||
renderer->RenderPresent = SW_RenderPresent;
|
renderer->RenderPresent = SW_RenderPresent;
|
||||||
renderer->DestroyTexture = SW_DestroyTexture;
|
renderer->DestroyTexture = SW_DestroyTexture;
|
||||||
|
@ -495,6 +500,102 @@ SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GetScaleQuality(void)
|
||||||
|
{
|
||||||
|
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
|
||||||
|
|
||||||
|
if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect,
|
||||||
|
const double angle, const SDL_Point * center, const SDL_RendererFlip flip)
|
||||||
|
{
|
||||||
|
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||||
|
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
|
||||||
|
SDL_Rect final_rect = *dstrect, tmp_rect;
|
||||||
|
SDL_Surface *surface_rotated, *surface_scaled;
|
||||||
|
SDL_Point final_rect_center;
|
||||||
|
Uint32 colorkey;
|
||||||
|
int retval, dstwidth, dstheight, abscenterx, abscentery;
|
||||||
|
double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
|
||||||
|
|
||||||
|
if (!surface) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer->viewport.x || renderer->viewport.y) {
|
||||||
|
final_rect.x += renderer->viewport.x;
|
||||||
|
final_rect.y += renderer->viewport.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel,
|
||||||
|
src->format->Rmask, src->format->Gmask,
|
||||||
|
src->format->Bmask, src->format->Amask );
|
||||||
|
SDL_GetColorKey(src, &colorkey);
|
||||||
|
SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey);
|
||||||
|
tmp_rect = final_rect;
|
||||||
|
tmp_rect.x = 0;
|
||||||
|
tmp_rect.y = 0;
|
||||||
|
if (surface_scaled) {
|
||||||
|
retval = SDL_BlitScaled(src, srcrect, surface_scaled, &tmp_rect);
|
||||||
|
if (!retval) {
|
||||||
|
_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, -angle, &dstwidth, &dstheight, &cangle, &sangle);
|
||||||
|
surface_rotated = _rotateSurface(surface_scaled, -angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
|
||||||
|
if(surface_rotated) {
|
||||||
|
/* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
|
||||||
|
abscenterx = final_rect.x + center->x;
|
||||||
|
abscentery = final_rect.y + center->y;
|
||||||
|
/* Compensate the angle inversion to match the behaviour of the other backends */
|
||||||
|
sangle = -sangle;
|
||||||
|
|
||||||
|
/* Top Left */
|
||||||
|
px = final_rect.x - abscenterx;
|
||||||
|
py = final_rect.y - abscentery;
|
||||||
|
p1x = px * cangle - py * sangle + abscenterx;
|
||||||
|
p1y = px * sangle + py * cangle + abscentery;
|
||||||
|
|
||||||
|
/* Top Right */
|
||||||
|
px = final_rect.x + final_rect.w - abscenterx;
|
||||||
|
py = final_rect.y - abscentery;
|
||||||
|
p2x = px * cangle - py * sangle + abscenterx;
|
||||||
|
p2y = px * sangle + py * cangle + abscentery;
|
||||||
|
|
||||||
|
/* Bottom Left */
|
||||||
|
px = final_rect.x - abscenterx;
|
||||||
|
py = final_rect.y + final_rect.h - abscentery;
|
||||||
|
p3x = px * cangle - py * sangle + abscenterx;
|
||||||
|
p3y = px * sangle + py * cangle + abscentery;
|
||||||
|
|
||||||
|
/* Bottom Right */
|
||||||
|
px = final_rect.x + final_rect.w - abscenterx;
|
||||||
|
py = final_rect.y + final_rect.h - abscentery;
|
||||||
|
p4x = px * cangle - py * sangle + abscenterx;
|
||||||
|
p4y = px * sangle + py * cangle + abscentery;
|
||||||
|
|
||||||
|
tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
|
||||||
|
tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
|
||||||
|
tmp_rect.w = dstwidth;
|
||||||
|
tmp_rect.h = dstheight;
|
||||||
|
|
||||||
|
retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect);
|
||||||
|
SDL_FreeSurface(surface_scaled);
|
||||||
|
SDL_FreeSurface(surface_rotated);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch)
|
Uint32 format, void * pixels, int pitch)
|
||||||
|
|
500
src/render/software/SDL_rotate.c
Normal file
500
src/render/software/SDL_rotate.c
Normal file
|
@ -0,0 +1,500 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
SDL_rotate.c: rotates 32bit or 8bit surfaces
|
||||||
|
|
||||||
|
Shamelessly stolen from SDL_gfx by Andreas Schiffler. Original copyright follows:
|
||||||
|
|
||||||
|
Copyright (C) 2001-2011 Andreas Schiffler
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
Andreas Schiffler -- aschiffler at ferzkopp dot net
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
#include "SDL_rotate.h"
|
||||||
|
|
||||||
|
/* ---- Internally used structures */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief A 32 bit RGBA pixel.
|
||||||
|
*/
|
||||||
|
typedef struct tColorRGBA {
|
||||||
|
Uint8 r;
|
||||||
|
Uint8 g;
|
||||||
|
Uint8 b;
|
||||||
|
Uint8 a;
|
||||||
|
} tColorRGBA;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief A 8bit Y/palette pixel.
|
||||||
|
*/
|
||||||
|
typedef struct tColorY {
|
||||||
|
Uint8 y;
|
||||||
|
} tColorY;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Returns maximum of two numbers a and b.
|
||||||
|
*/
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Number of guard rows added to destination surfaces.
|
||||||
|
|
||||||
|
This is a simple but effective workaround for observed issues.
|
||||||
|
These rows allocate extra memory and are then hidden from the surface.
|
||||||
|
Rows are added to the end of destination surfaces when they are allocated.
|
||||||
|
This catches any potential overflows which seem to happen with
|
||||||
|
just the right src image dimensions and scale/rotation and can lead
|
||||||
|
to a situation where the program can segfault.
|
||||||
|
*/
|
||||||
|
#define GUARD_ROWS (2)
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Lower limit of absolute zoom factor or rotation degrees.
|
||||||
|
*/
|
||||||
|
#define VALUE_LIMIT 0.001
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Returns colorkey info for a surface
|
||||||
|
*/
|
||||||
|
Uint32 _colorkey(SDL_Surface *src)
|
||||||
|
{
|
||||||
|
Uint32 key = 0;
|
||||||
|
SDL_GetColorKey(src, &key);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Internal target surface sizing function for rotations with trig result return.
|
||||||
|
|
||||||
|
\param width The source surface width.
|
||||||
|
\param height The source surface height.
|
||||||
|
\param angle The angle to rotate in degrees.
|
||||||
|
\param dstwidth The calculated width of the destination surface.
|
||||||
|
\param dstheight The calculated height of the destination surface.
|
||||||
|
\param cangle The sine of the angle
|
||||||
|
\param sangle The cosine of the angle
|
||||||
|
|
||||||
|
*/
|
||||||
|
void _rotozoomSurfaceSizeTrig(int width, int height, double angle,
|
||||||
|
int *dstwidth, int *dstheight,
|
||||||
|
double *cangle, double *sangle)
|
||||||
|
{
|
||||||
|
double x, y, cx, cy, sx, sy;
|
||||||
|
double radangle;
|
||||||
|
int dstwidthhalf, dstheighthalf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine destination width and height by rotating a centered source box
|
||||||
|
*/
|
||||||
|
radangle = angle * (M_PI / 180.0);
|
||||||
|
*sangle = SDL_sin(radangle);
|
||||||
|
*cangle = SDL_cos(radangle);
|
||||||
|
x = (double)(width / 2);
|
||||||
|
y = (double)(height / 2);
|
||||||
|
cx = *cangle * x;
|
||||||
|
cy = *cangle * y;
|
||||||
|
sx = *sangle * x;
|
||||||
|
sy = *sangle * y;
|
||||||
|
|
||||||
|
dstwidthhalf = MAX((int)
|
||||||
|
SDL_ceil(MAX(MAX(MAX(SDL_fabs(cx + sy), SDL_fabs(cx - sy)), SDL_fabs(-cx + sy)), SDL_fabs(-cx - sy))), 1);
|
||||||
|
dstheighthalf = MAX((int)
|
||||||
|
SDL_ceil(MAX(MAX(MAX(SDL_fabs(sx + cy), SDL_fabs(sx - cy)), SDL_fabs(-sx + cy)), SDL_fabs(-sx - cy))), 1);
|
||||||
|
*dstwidth = 2 * dstwidthhalf;
|
||||||
|
*dstheight = 2 * dstheighthalf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Internal 32 bit rotozoomer with optional anti-aliasing.
|
||||||
|
|
||||||
|
Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
|
||||||
|
parameters by scanning the destination surface and applying optionally anti-aliasing
|
||||||
|
by bilinear interpolation.
|
||||||
|
Assumes src and dst surfaces are of 32 bit depth.
|
||||||
|
Assumes dst surface was allocated with the correct dimensions.
|
||||||
|
|
||||||
|
\param src Source surface.
|
||||||
|
\param dst Destination surface.
|
||||||
|
\param cx Horizontal center coordinate.
|
||||||
|
\param cy Vertical center coordinate.
|
||||||
|
\param isin Integer version of sine of angle.
|
||||||
|
\param icos Integer version of cosine of angle.
|
||||||
|
\param flipx Flag indicating horizontal mirroring should be applied.
|
||||||
|
\param flipy Flag indicating vertical mirroring should be applied.
|
||||||
|
\param smooth Flag indicating anti-aliasing should be used.
|
||||||
|
*/
|
||||||
|
void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
|
||||||
|
{
|
||||||
|
int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
|
||||||
|
tColorRGBA c00, c01, c10, c11, cswap;
|
||||||
|
tColorRGBA *pc, *sp;
|
||||||
|
int gap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variable setup
|
||||||
|
*/
|
||||||
|
xd = ((src->w - dst->w) << 15);
|
||||||
|
yd = ((src->h - dst->h) << 15);
|
||||||
|
ax = (cx << 16) - (icos * cx);
|
||||||
|
ay = (cy << 16) - (isin * cx);
|
||||||
|
sw = src->w - 1;
|
||||||
|
sh = src->h - 1;
|
||||||
|
pc = (tColorRGBA*) dst->pixels;
|
||||||
|
gap = dst->pitch - dst->w * 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch between interpolating and non-interpolating code
|
||||||
|
*/
|
||||||
|
if (smooth) {
|
||||||
|
for (y = 0; y < dst->h; y++) {
|
||||||
|
dy = cy - y;
|
||||||
|
sdx = (ax + (isin * dy)) + xd;
|
||||||
|
sdy = (ay - (icos * dy)) + yd;
|
||||||
|
for (x = 0; x < dst->w; x++) {
|
||||||
|
dx = (sdx >> 16);
|
||||||
|
dy = (sdy >> 16);
|
||||||
|
if (flipx) dx = sw - dx;
|
||||||
|
if (flipy) dy = sh - dy;
|
||||||
|
if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
|
||||||
|
sp = (tColorRGBA *)src->pixels;;
|
||||||
|
sp += ((src->pitch/4) * dy);
|
||||||
|
sp += dx;
|
||||||
|
c00 = *sp;
|
||||||
|
sp += 1;
|
||||||
|
c01 = *sp;
|
||||||
|
sp += (src->pitch/4);
|
||||||
|
c11 = *sp;
|
||||||
|
sp -= 1;
|
||||||
|
c10 = *sp;
|
||||||
|
if (flipx) {
|
||||||
|
cswap = c00; c00=c01; c01=cswap;
|
||||||
|
cswap = c10; c10=c11; c11=cswap;
|
||||||
|
}
|
||||||
|
if (flipy) {
|
||||||
|
cswap = c00; c00=c10; c10=cswap;
|
||||||
|
cswap = c01; c01=c11; c11=cswap;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Interpolate colors
|
||||||
|
*/
|
||||||
|
ex = (sdx & 0xffff);
|
||||||
|
ey = (sdy & 0xffff);
|
||||||
|
t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
|
||||||
|
t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
|
||||||
|
pc->r = (((t2 - t1) * ey) >> 16) + t1;
|
||||||
|
t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
|
||||||
|
t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
|
||||||
|
pc->g = (((t2 - t1) * ey) >> 16) + t1;
|
||||||
|
t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
|
||||||
|
t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
|
||||||
|
pc->b = (((t2 - t1) * ey) >> 16) + t1;
|
||||||
|
t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
|
||||||
|
t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
|
||||||
|
pc->a = (((t2 - t1) * ey) >> 16) + t1;
|
||||||
|
}
|
||||||
|
sdx += icos;
|
||||||
|
sdy += isin;
|
||||||
|
pc++;
|
||||||
|
}
|
||||||
|
pc = (tColorRGBA *) ((Uint8 *) pc + gap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (y = 0; y < dst->h; y++) {
|
||||||
|
dy = cy - y;
|
||||||
|
sdx = (ax + (isin * dy)) + xd;
|
||||||
|
sdy = (ay - (icos * dy)) + yd;
|
||||||
|
for (x = 0; x < dst->w; x++) {
|
||||||
|
dx = (short) (sdx >> 16);
|
||||||
|
dy = (short) (sdy >> 16);
|
||||||
|
if (flipx) dx = (src->w-1)-dx;
|
||||||
|
if (flipy) dy = (src->h-1)-dy;
|
||||||
|
if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
|
||||||
|
sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
|
||||||
|
sp += dx;
|
||||||
|
*pc = *sp;
|
||||||
|
}
|
||||||
|
sdx += icos;
|
||||||
|
sdy += isin;
|
||||||
|
pc++;
|
||||||
|
}
|
||||||
|
pc = (tColorRGBA *) ((Uint8 *) pc + gap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
|
||||||
|
|
||||||
|
Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
|
||||||
|
parameters by scanning the destination surface.
|
||||||
|
Assumes src and dst surfaces are of 8 bit depth.
|
||||||
|
Assumes dst surface was allocated with the correct dimensions.
|
||||||
|
|
||||||
|
\param src Source surface.
|
||||||
|
\param dst Destination surface.
|
||||||
|
\param cx Horizontal center coordinate.
|
||||||
|
\param cy Vertical center coordinate.
|
||||||
|
\param isin Integer version of sine of angle.
|
||||||
|
\param icos Integer version of cosine of angle.
|
||||||
|
\param flipx Flag indicating horizontal mirroring should be applied.
|
||||||
|
\param flipy Flag indicating vertical mirroring should be applied.
|
||||||
|
*/
|
||||||
|
void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
|
||||||
|
{
|
||||||
|
int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
|
||||||
|
tColorY *pc, *sp;
|
||||||
|
int gap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variable setup
|
||||||
|
*/
|
||||||
|
xd = ((src->w - dst->w) << 15);
|
||||||
|
yd = ((src->h - dst->h) << 15);
|
||||||
|
ax = (cx << 16) - (icos * cx);
|
||||||
|
ay = (cy << 16) - (isin * cx);
|
||||||
|
sw = src->w - 1;
|
||||||
|
sh = src->h - 1;
|
||||||
|
pc = (tColorY*) dst->pixels;
|
||||||
|
gap = dst->pitch - dst->w;
|
||||||
|
/*
|
||||||
|
* Clear surface to colorkey
|
||||||
|
*/
|
||||||
|
SDL_memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
|
||||||
|
/*
|
||||||
|
* Iterate through destination surface
|
||||||
|
*/
|
||||||
|
for (y = 0; y < dst->h; y++) {
|
||||||
|
dy = cy - y;
|
||||||
|
sdx = (ax + (isin * dy)) + xd;
|
||||||
|
sdy = (ay - (icos * dy)) + yd;
|
||||||
|
for (x = 0; x < dst->w; x++) {
|
||||||
|
dx = (short) (sdx >> 16);
|
||||||
|
dy = (short) (sdy >> 16);
|
||||||
|
if (flipx) dx = (src->w-1)-dx;
|
||||||
|
if (flipy) dy = (src->h-1)-dy;
|
||||||
|
if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
|
||||||
|
sp = (tColorY *) (src->pixels);
|
||||||
|
sp += (src->pitch * dy + dx);
|
||||||
|
*pc = *sp;
|
||||||
|
}
|
||||||
|
sdx += icos;
|
||||||
|
sdy += isin;
|
||||||
|
pc++;
|
||||||
|
}
|
||||||
|
pc += gap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing.
|
||||||
|
|
||||||
|
Rotates a 32bit or 8bit 'src' surface to newly created 'dst' surface.
|
||||||
|
'angle' is the rotation in degrees, 'centerx' and 'centery' the rotation center. If 'smooth' is set
|
||||||
|
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
|
||||||
|
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
|
||||||
|
|
||||||
|
\param src The surface to rotozoom.
|
||||||
|
\param angle The angle to rotate in degrees.
|
||||||
|
\param centerx The horizontal coordinate of the center of rotation
|
||||||
|
\param zoomy The vertical coordinate of the center of rotation
|
||||||
|
\param smooth Antialiasing flag; set to SMOOTHING_ON to enable.
|
||||||
|
\param flipx Set to 1 to flip the image horizontally
|
||||||
|
\param flipy Set to 1 to flip the image vertically
|
||||||
|
\param dstwidth The destination surface width
|
||||||
|
\param dstheight The destination surface height
|
||||||
|
\param cangle The angle cosine
|
||||||
|
\param sangle The angle sine
|
||||||
|
\return The new rotated surface.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
SDL_Surface *rz_src;
|
||||||
|
SDL_Surface *rz_dst;
|
||||||
|
int is32bit;
|
||||||
|
int i, src_converted;
|
||||||
|
Uint8 r,g,b;
|
||||||
|
Uint32 colorkey = 0;
|
||||||
|
int colorKeyAvailable = 0;
|
||||||
|
double sangleinv, cangleinv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity check
|
||||||
|
*/
|
||||||
|
if (src == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
if (src->flags & SDL_TRUE/*SDL_SRCCOLORKEY*/)
|
||||||
|
{
|
||||||
|
colorkey = _colorkey(src);
|
||||||
|
SDL_GetRGB(colorkey, src->format, &r, &g, &b);
|
||||||
|
colorKeyAvailable = 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Determine if source surface is 32bit or 8bit
|
||||||
|
*/
|
||||||
|
is32bit = (src->format->BitsPerPixel == 32);
|
||||||
|
if ((is32bit) || (src->format->BitsPerPixel == 8)) {
|
||||||
|
/*
|
||||||
|
* Use source surface 'as is'
|
||||||
|
*/
|
||||||
|
rz_src = src;
|
||||||
|
src_converted = 0;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* New source surface is 32bit with a defined RGBA ordering
|
||||||
|
*/
|
||||||
|
rz_src =
|
||||||
|
SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
|
||||||
|
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||||
|
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
|
||||||
|
#else
|
||||||
|
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
if(colorKeyAvailable)
|
||||||
|
SDL_SetColorKey(src, 0, 0);
|
||||||
|
|
||||||
|
SDL_BlitSurface(src, NULL, rz_src, NULL);
|
||||||
|
|
||||||
|
if(colorKeyAvailable)
|
||||||
|
SDL_SetColorKey(src, SDL_TRUE /*SDL_SRCCOLORKEY*/, colorkey);
|
||||||
|
src_converted = 1;
|
||||||
|
is32bit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine target size */
|
||||||
|
//_rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, &dstwidth, &dstheight, &cangle, &sangle);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate target factors from sin/cos and zoom
|
||||||
|
*/
|
||||||
|
sangleinv = sangle*65536.0;
|
||||||
|
cangleinv = cangle*65536.0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alloc space to completely contain the rotated surface
|
||||||
|
*/
|
||||||
|
rz_dst = NULL;
|
||||||
|
if (is32bit) {
|
||||||
|
/*
|
||||||
|
* Target surface is 32bit with source RGBA/ABGR ordering
|
||||||
|
*/
|
||||||
|
rz_dst =
|
||||||
|
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
|
||||||
|
rz_src->format->Rmask, rz_src->format->Gmask,
|
||||||
|
rz_src->format->Bmask, rz_src->format->Amask);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Target surface is 8bit
|
||||||
|
*/
|
||||||
|
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check target */
|
||||||
|
if (rz_dst == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Adjust for guard rows */
|
||||||
|
rz_dst->h = dstheight;
|
||||||
|
|
||||||
|
if (colorKeyAvailable == 1){
|
||||||
|
colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
|
||||||
|
|
||||||
|
SDL_FillRect(rz_dst, NULL, colorkey );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lock source surface
|
||||||
|
*/
|
||||||
|
if (SDL_MUSTLOCK(rz_src)) {
|
||||||
|
SDL_LockSurface(rz_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check which kind of surface we have
|
||||||
|
*/
|
||||||
|
if (is32bit) {
|
||||||
|
/*
|
||||||
|
* Call the 32bit transformation routine to do the rotation (using alpha)
|
||||||
|
*/
|
||||||
|
_transformSurfaceRGBA(rz_src, rz_dst, centerx, centery,
|
||||||
|
(int) (sangleinv), (int) (cangleinv),
|
||||||
|
flipx, flipy,
|
||||||
|
smooth);
|
||||||
|
/*
|
||||||
|
* Turn on source-alpha support
|
||||||
|
*/
|
||||||
|
//SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
|
||||||
|
SDL_SetColorKey(rz_dst, /*SDL_SRCCOLORKEY*/ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Copy palette and colorkey info
|
||||||
|
*/
|
||||||
|
for (i = 0; i < rz_src->format->palette->ncolors; i++) {
|
||||||
|
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
|
||||||
|
}
|
||||||
|
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
|
||||||
|
/*
|
||||||
|
* Call the 8bit transformation routine to do the rotation
|
||||||
|
*/
|
||||||
|
transformSurfaceY(rz_src, rz_dst, centerx, centery,
|
||||||
|
(int) (sangleinv), (int) (cangleinv),
|
||||||
|
flipx, flipy);
|
||||||
|
SDL_SetColorKey(rz_dst, /*SDL_SRCCOLORKEY*/ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Unlock source surface
|
||||||
|
*/
|
||||||
|
if (SDL_MUSTLOCK(rz_src)) {
|
||||||
|
SDL_UnlockSurface(rz_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cleanup temp surface
|
||||||
|
*/
|
||||||
|
if (src_converted) {
|
||||||
|
SDL_FreeSurface(rz_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return destination surface
|
||||||
|
*/
|
||||||
|
return (rz_dst);
|
||||||
|
}
|
||||||
|
|
6
src/render/software/SDL_rotate.h
Normal file
6
src/render/software/SDL_rotate.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
extern void _rotozoomSurfaceSizeTrig(int width, int height, double angle, int *dstwidth, int *dstheight, double *cangle, double *sangle);
|
|
@ -45,6 +45,7 @@ TARGETS = \
|
||||||
testver$(EXE) \
|
testver$(EXE) \
|
||||||
testwm2$(EXE) \
|
testwm2$(EXE) \
|
||||||
torturethread$(EXE) \
|
torturethread$(EXE) \
|
||||||
|
testrendercopyex$(EXE) \
|
||||||
|
|
||||||
all: Makefile $(TARGETS)
|
all: Makefile $(TARGETS)
|
||||||
|
|
||||||
|
@ -171,6 +172,9 @@ testwm2$(EXE): $(srcdir)/testwm2.c $(srcdir)/common.c
|
||||||
torturethread$(EXE): $(srcdir)/torturethread.c
|
torturethread$(EXE): $(srcdir)/torturethread.c
|
||||||
$(CC) -o $@ $? $(CFLAGS) $(LIBS)
|
$(CC) -o $@ $? $(CFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
testrendercopyex$(EXE): $(srcdir)/testrendercopyex.c $(srcdir)/common.c
|
||||||
|
$(CC) -o $@ $(srcdir)/testrendercopyex.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @MATHLIB@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGETS)
|
rm -f $(TARGETS)
|
||||||
|
|
||||||
|
|
208
test/testrendercopyex.c
Normal file
208
test/testrendercopyex.c
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely.
|
||||||
|
*/
|
||||||
|
/* Simple program: Move N sprites around on the screen as fast as possible */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define WINDOW_WIDTH 640
|
||||||
|
#define WINDOW_HEIGHT 480
|
||||||
|
|
||||||
|
static CommonState *state;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
SDL_Texture *background;
|
||||||
|
SDL_Texture *sprite;
|
||||||
|
SDL_Rect sprite_rect;
|
||||||
|
int scale_direction;
|
||||||
|
} DrawState;
|
||||||
|
|
||||||
|
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
|
||||||
|
static void
|
||||||
|
quit(int rc)
|
||||||
|
{
|
||||||
|
CommonQuit(state);
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *
|
||||||
|
LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
|
||||||
|
{
|
||||||
|
SDL_Surface *temp;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
|
||||||
|
/* Load the sprite image */
|
||||||
|
temp = SDL_LoadBMP(file);
|
||||||
|
if (temp == NULL) {
|
||||||
|
fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set transparent pixel as the pixel at (0,0) */
|
||||||
|
if (transparent) {
|
||||||
|
if (temp->format->palette) {
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
|
||||||
|
} else {
|
||||||
|
switch (temp->format->BitsPerPixel) {
|
||||||
|
case 15:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE,
|
||||||
|
(*(Uint16 *) temp->pixels) & 0x00007FFF);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE,
|
||||||
|
(*(Uint32 *) temp->pixels) & 0x00FFFFFF);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create textures from the image */
|
||||||
|
texture = SDL_CreateTextureFromSurface(renderer, temp);
|
||||||
|
if (!texture) {
|
||||||
|
fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
|
||||||
|
SDL_FreeSurface(temp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(temp);
|
||||||
|
|
||||||
|
/* We're ready to roll. :) */
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Draw(DrawState *s)
|
||||||
|
{
|
||||||
|
SDL_Rect viewport;
|
||||||
|
SDL_Texture *target;
|
||||||
|
SDL_Point *center=NULL;
|
||||||
|
SDL_Point origin = {0,0};
|
||||||
|
|
||||||
|
SDL_RenderGetViewport(s->renderer, &viewport);
|
||||||
|
|
||||||
|
target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
|
||||||
|
SDL_SetRenderTarget(s->renderer, target);
|
||||||
|
|
||||||
|
/* Draw the background */
|
||||||
|
SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
|
||||||
|
|
||||||
|
/* Scale and draw the sprite */
|
||||||
|
s->sprite_rect.w += s->scale_direction;
|
||||||
|
s->sprite_rect.h += s->scale_direction;
|
||||||
|
if (s->scale_direction > 0) {
|
||||||
|
center = &origin;
|
||||||
|
if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
|
||||||
|
s->scale_direction = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
|
||||||
|
s->scale_direction = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
|
||||||
|
s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
|
||||||
|
|
||||||
|
SDL_RenderCopyEx(s->renderer, s->sprite, NULL, &s->sprite_rect, (double)s->sprite_rect.w, center, s->scale_direction);
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(s->renderer, NULL);
|
||||||
|
SDL_RenderCopy(s->renderer, target, NULL, NULL);
|
||||||
|
SDL_DestroyTexture(target);
|
||||||
|
|
||||||
|
/* Update the screen! */
|
||||||
|
SDL_RenderPresent(s->renderer);
|
||||||
|
//SDL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
DrawState *drawstates;
|
||||||
|
int i, done;
|
||||||
|
SDL_Event event;
|
||||||
|
int frames;
|
||||||
|
Uint32 then, now;
|
||||||
|
|
||||||
|
/* Initialize test framework */
|
||||||
|
state = CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||||
|
if (!state) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = 1; i < argc;) {
|
||||||
|
int consumed;
|
||||||
|
|
||||||
|
consumed = CommonArg(state, i);
|
||||||
|
if (consumed == 0) {
|
||||||
|
fprintf(stderr, "Usage: %s %s\n", argv[0], CommonUsage(state));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
i += consumed;
|
||||||
|
}
|
||||||
|
if (!CommonInit(state)) {
|
||||||
|
quit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawstates = SDL_stack_alloc(DrawState, state->num_windows);
|
||||||
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
|
DrawState *drawstate = &drawstates[i];
|
||||||
|
|
||||||
|
drawstate->window = state->windows[i];
|
||||||
|
drawstate->renderer = state->renderers[i];
|
||||||
|
drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
|
||||||
|
drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp", SDL_FALSE);
|
||||||
|
if (!drawstate->sprite || !drawstate->background) {
|
||||||
|
quit(2);
|
||||||
|
}
|
||||||
|
SDL_QueryTexture(drawstate->sprite, NULL, NULL,
|
||||||
|
&drawstate->sprite_rect.w, &drawstate->sprite_rect.h);
|
||||||
|
drawstate->scale_direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main render loop */
|
||||||
|
frames = 0;
|
||||||
|
then = SDL_GetTicks();
|
||||||
|
done = 0;
|
||||||
|
while (!done) {
|
||||||
|
/* Check for events */
|
||||||
|
++frames;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
CommonEvent(state, &event, &done);
|
||||||
|
}
|
||||||
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
|
Draw(&drawstates[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print out some timing information */
|
||||||
|
now = SDL_GetTicks();
|
||||||
|
if (now > then) {
|
||||||
|
double fps = ((double) frames * 1000) / (now - then);
|
||||||
|
printf("%2.2f frames per second\n", fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_stack_free(drawstates);
|
||||||
|
|
||||||
|
quit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
Loading…
Add table
Add a link
Reference in a new issue