diff -r 31519ae88ab6 -r c70acae5f548 include/SDL_render.h --- a/include/SDL_render.h Wed Sep 21 11:50:51 2011 -0300 +++ b/include/SDL_render.h Wed Sep 21 11:49:05 2011 -0300 @@ -562,6 +562,25 @@ const SDL_Rect * srcrect, 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 srcquad A pointer to the source quad, or NULL for the entire + * texture. + * \param dstquad A pointer to the destination quad, 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 center of rotation (if NULL, rotation will be done aroud dstrect.w/2, dstrect.h/2) + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyRotate(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_Rect * dstrect, + const double angle, + const SDL_Point *center); /** * \fn SDL_bool SDL_RenderTargetSupported(SDL_Renderer *renderer) diff -r 31519ae88ab6 -r c70acae5f548 src/render/SDL_render.c --- a/src/render/SDL_render.c Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/SDL_render.c Wed Sep 21 11:49:05 2011 -0300 @@ -1076,6 +1076,47 @@ &real_dstrect); } + +int +SDL_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center) +{ + SDL_Window *window; + SDL_Rect real_srcrect; + + 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->RenderCopyRotate) { + SDL_SetError("Renderer does not support RenderCopyRotate"); + 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; + } + } + + if (texture->native) { + texture = texture->native; + } + + return renderer->RenderCopyRotate(renderer, texture, &real_srcrect, + dstrect, angle, center); +} + int SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch) diff -r 31519ae88ab6 -r c70acae5f548 src/render/SDL_sysrender.h --- a/src/render/SDL_sysrender.h Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/SDL_sysrender.h Wed Sep 21 11:49:05 2011 -0300 @@ -87,6 +87,9 @@ int count); int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); + int (*RenderCopyRotate) (SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcquad, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center); int (*SetTargetTexture) (SDL_Renderer * renderer, SDL_Texture * texture); int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch); diff -r 31519ae88ab6 -r c70acae5f548 src/render/direct3d/SDL_render_d3d.c --- a/src/render/direct3d/SDL_render_d3d.c Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/direct3d/SDL_render_d3d.c Wed Sep 21 11:49:05 2011 -0300 @@ -35,6 +35,90 @@ #include #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 /////////////////////////////////////////////////////////////////////////// // ID3DXBuffer: @@ -109,6 +193,9 @@ const SDL_Rect * rects, int count); static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); +static int D3D_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point * center); static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch); static int D3D_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture); @@ -142,6 +229,8 @@ IDirect3DSurface9 *defaultRenderTarget; IDirect3DSurface9 *currentRenderTarget; Uint32 NumSimultaneousRTs; + void* d3dxDLL; + ID3DXMatrixStack *matrixStack; } D3D_RenderData; typedef struct @@ -348,6 +437,7 @@ int w, h; SDL_DisplayMode fullscreen_mode; D3DMATRIX matrix; + int d3dxVersion; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { @@ -376,8 +466,29 @@ SDL_UnloadObject(data->d3dDLL); data->d3dDLL = NULL; } + + char d3dxDLLFile[50]; + for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) { + sprintf(d3dxDLLFile, "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(data); SDL_SetError("Unable to create Direct3D interface"); @@ -395,6 +506,7 @@ renderer->RenderDrawLines = D3D_RenderDrawLines; renderer->RenderFillRects = D3D_RenderFillRects; renderer->RenderCopy = D3D_RenderCopy; + renderer->RenderCopyRotate = D3D_RenderCopyRotate; renderer->RenderReadPixels = D3D_RenderReadPixels; renderer->SetTargetTexture = D3D_SetTargetTexture; renderer->RenderPresent = D3D_RenderPresent; @@ -1130,6 +1242,124 @@ 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; + } + }*/ + return 0; +} + + +static int +D3D_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point * center) +{ + 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; + } + + if (center != NULL) { + centerx = (float)center->x; + centery = (float)center->y; + } + else { + // Center in the middle of the rectangle + centerx = (float) dstrect->w / 2.0; + centery = (float) dstrect->h / 2.0; + } + + minx = (float) -centerx - 0.5f; + miny = (float) -centery - 0.5f; + maxx = (float) dstrect->w - centerx - 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)) { @@ -1151,6 +1381,11 @@ 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; } diff -r 31519ae88ab6 -r c70acae5f548 src/render/opengl/SDL_glfuncs.h --- a/src/render/opengl/SDL_glfuncs.h Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/opengl/SDL_glfuncs.h Wed Sep 21 11:49:05 2011 -0300 @@ -279,14 +279,14 @@ SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte * mask)) SDL_PROC_UNUSED(void, glPopAttrib, (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, glPrioritizeTextures, (GLsizei n, const GLuint * textures, const GLclampf * priorities)) SDL_PROC_UNUSED(void, glPushAttrib, (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, glRasterPos2d, (GLdouble x, GLdouble y)) SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble * v)) @@ -331,7 +331,7 @@ (GLshort x1, GLshort y1, GLshort x2, GLshort y2)) SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2)) SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode)) -SDL_PROC_UNUSED(void, glRotated, +SDL_PROC(void, glRotated, (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)) SDL_PROC_UNUSED(void, glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) @@ -419,7 +419,7 @@ GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels)) 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, glVertex2dv, (const GLdouble * v)) SDL_PROC(void, glVertex2f, (GLfloat x, GLfloat y)) diff -r 31519ae88ab6 -r c70acae5f548 src/render/opengl/SDL_render_gl.c --- a/src/render/opengl/SDL_render_gl.c Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/opengl/SDL_render_gl.c Wed Sep 21 11:49:05 2011 -0300 @@ -64,6 +64,9 @@ const SDL_Rect * rects, int count); static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); +static int GL_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center); static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 pixel_format, void * pixels, int pitch); static int GL_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture); @@ -309,6 +312,7 @@ renderer->RenderDrawLines = GL_RenderDrawLines; renderer->RenderFillRects = GL_RenderFillRects; renderer->RenderCopy = GL_RenderCopy; + renderer->RenderCopyRotate = GL_RenderCopyRotate; renderer->SetTargetTexture = GL_SetTargetTexture; renderer->RenderReadPixels = GL_RenderReadPixels; renderer->RenderPresent = GL_RenderPresent; @@ -1037,6 +1041,92 @@ } static int +GL_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center) +{ + 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); + } + + + if (center != NULL) { + centerx = (GLfloat)center->x; + centery = (GLfloat)center->y; + } + else { + // Center in the middle of the rectangle + centerx = (GLfloat) dstrect->w / 2.0; + centery = (GLfloat) dstrect->h / 2.0; + } + + minx = -centerx; + miny = -centery; + maxx = (GLfloat) dstrect->w - centerx; + 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 position, rotate + 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 GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 pixel_format, void * pixels, int pitch) { diff -r 31519ae88ab6 -r c70acae5f548 src/render/opengles/SDL_render_gles.c --- a/src/render/opengles/SDL_render_gles.c Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/opengles/SDL_render_gles.c Wed Sep 21 11:49:05 2011 -0300 @@ -64,6 +64,9 @@ static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); +static int GLES_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center); static void GLES_RenderPresent(SDL_Renderer * renderer); static void GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); @@ -305,6 +308,7 @@ renderer->RenderDrawLines = GLES_RenderDrawLines; renderer->RenderFillRects = GLES_RenderFillRects; renderer->RenderCopy = GLES_RenderCopy; + renderer->RenderCopyRotate = GLES_RenderCopyRotate; renderer->RenderPresent = GLES_RenderPresent; renderer->DestroyTexture = GLES_DestroyTexture; renderer->DestroyRenderer = GLES_DestroyRenderer; @@ -857,6 +861,92 @@ return 0; } +static int +GLES_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center) +{ + + 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; + + if (angle == 0.0) return GLES_RenderCopy(renderer, texture, srcrect, dstrect); + + GLES_ActivateRenderer(renderer); + + glEnable(GL_TEXTURE_2D); + + 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); + + if (center != NULL) { + centerx = (GLfloat)center->x; + centery = (GLfloat)center->y; + } else { + // Center in the middle of the rectangle + centerx = (GLfloat) dstrect->w / 2.0; + centery = (GLfloat) dstrect->h / 2.0; + } + // Rotate and translate + glPushMatrix(); + glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0); + glRotatef((GLfloat)angle, (GLfloat)0.0, (GLfloat)0.0, (GLfloat)1.0); + + minx = -centerx; + miny = -centery; + maxx = dstrect->w - centerx; + 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; + glVertexPointer(2, GL_SHORT, 0, vertices); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glPopMatrix(); + glDisable(GL_TEXTURE_2D); + + return 0; +} + static void GLES_RenderPresent(SDL_Renderer * renderer) { diff -r 31519ae88ab6 -r c70acae5f548 src/render/opengles2/SDL_render_gles2.c --- a/src/render/opengles2/SDL_render_gles2.c Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/opengles2/SDL_render_gles2.c Wed Sep 21 11:49:05 2011 -0300 @@ -106,7 +106,9 @@ typedef enum { GLES2_ATTRIBUTE_POSITION = 0, - GLES2_ATTRIBUTE_TEXCOORD = 1 + GLES2_ATTRIBUTE_TEXCOORD = 1, + GLES2_ATTRIBUTE_ANGLE = 2, + GLES2_ATTRIBUTE_CENTER = 3, } GLES2_Attribute; typedef enum @@ -536,6 +538,8 @@ glAttachShader(entry->id, fragment->id); glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position"); glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord"); + glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle"); + glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center"); glLinkProgram(entry->id); glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful); if (glGetError() != GL_NO_ERROR || !linkSuccessful) @@ -835,6 +839,9 @@ static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect *rects, int count); static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect); +static int GLES2_RenderCopyRotate(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_Point *center); static void GLES2_RenderPresent(SDL_Renderer *renderer); @@ -1031,6 +1038,15 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect) { + SDL_Point center = {0,0}; + return GLES2_RenderCopyRotate(renderer, texture, srcrect, dstrect, 0, ¢er); +} + + +static int +GLES2_RenderCopyRotate(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, + const SDL_Rect *dstrect, const double angle, const SDL_Point *center) +{ GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata; GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; GLES2_ImageSource sourceType; @@ -1039,8 +1055,31 @@ GLfloat texCoords[8]; GLuint locTexture; GLuint locModulation; + GLfloat translate[8]; + GLfloat fAngle[4]; GLES2_ActivateRenderer(renderer); + + if (angle != 0) { + glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER); + glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE); + fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)angle; + /* Calculate the center of rotation */ + if (center != NULL) { + 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); + + } + else { + // Center in the middle of the rectangle + translate[0] = translate[2] = translate[4] = translate[6] = (GLfloat) (dstrect->w / 2.0 + dstrect->x); + translate[1] = translate[3] = translate[5] = translate[7] = (GLfloat) (dstrect->h / 2.0 + dstrect->y); + } + } + else { + glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER); + glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE); + } /* Activate an appropriate shader and set the projection matrix */ blendMode = texture->blendMode; @@ -1090,7 +1129,11 @@ vertices[6] = (GLfloat)(dstrect->x + dstrect->w); vertices[7] = (GLfloat)(dstrect->y + dstrect->h); } + glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle); + glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate); 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; @@ -1294,6 +1337,7 @@ renderer->RenderDrawLines = &GLES2_RenderDrawLines; renderer->RenderFillRects = &GLES2_RenderFillRects; renderer->RenderCopy = &GLES2_RenderCopy; + renderer->RenderCopyRotate = &GLES2_RenderCopyRotate; renderer->RenderPresent = &GLES2_RenderPresent; renderer->DestroyTexture = &GLES2_DestroyTexture; renderer->DestroyRenderer = &GLES2_DestroyRenderer; diff -r 31519ae88ab6 -r c70acae5f548 src/render/opengles2/SDL_shaders_gles2.c --- a/src/render/opengles2/SDL_shaders_gles2.c Wed Sep 21 11:50:51 2011 -0300 +++ b/src/render/opengles2/SDL_shaders_gles2.c Wed Sep 21 11:49:05 2011 -0300 @@ -33,14 +33,21 @@ static const Uint8 GLES2_VertexSrc_Default_[] = " \ uniform mat4 u_projection; \ - attribute vec4 a_position; \ + attribute vec2 a_position; \ attribute vec2 a_texCoord; \ + attribute float a_angle; \ + attribute vec2 a_center; \ varying vec2 v_texCoord; \ \ 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; \ - gl_Position = u_projection * a_position; \ + gl_Position = u_projection * vec4(position, 0.0, 1.0);\ gl_PointSize = 1.0; \ } \ ";