Merge SDL-ryan-batching-renderer branch to default.
--HG-- extra : rebase_source : 83b86d35497a01be6f48055490580bbba19ccc7a extra : amend_source : faae1a04859499ede43aba3ba50fc4f62b5afbcb
This commit is contained in:
commit
9f99a9c642
38 changed files with 6953 additions and 5554 deletions
File diff suppressed because it is too large
Load diff
|
@ -39,20 +39,6 @@ typedef enum
|
|||
SDL_ScaleModeBest
|
||||
} SDL_ScaleMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} SDL_FPoint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
} SDL_FRect;
|
||||
|
||||
/* Define the SDL texture structure */
|
||||
struct SDL_Texture
|
||||
{
|
||||
|
@ -75,12 +61,63 @@ struct SDL_Texture
|
|||
int pitch;
|
||||
SDL_Rect locked_rect;
|
||||
|
||||
Uint32 last_command_generation; /* last command queue generation this texture was in. */
|
||||
|
||||
void *driverdata; /**< Driver specific texture representation */
|
||||
|
||||
SDL_Texture *prev;
|
||||
SDL_Texture *next;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_RENDERCMD_NO_OP,
|
||||
SDL_RENDERCMD_SETVIEWPORT,
|
||||
SDL_RENDERCMD_SETCLIPRECT,
|
||||
SDL_RENDERCMD_SETDRAWCOLOR,
|
||||
SDL_RENDERCMD_CLEAR,
|
||||
SDL_RENDERCMD_DRAW_POINTS,
|
||||
SDL_RENDERCMD_DRAW_LINES,
|
||||
SDL_RENDERCMD_FILL_RECTS,
|
||||
SDL_RENDERCMD_COPY,
|
||||
SDL_RENDERCMD_COPY_EX
|
||||
} SDL_RenderCommandType;
|
||||
|
||||
typedef struct SDL_RenderCommand
|
||||
{
|
||||
SDL_RenderCommandType command;
|
||||
union {
|
||||
struct {
|
||||
size_t first;
|
||||
SDL_Rect rect;
|
||||
} viewport;
|
||||
struct {
|
||||
SDL_bool enabled;
|
||||
SDL_Rect rect;
|
||||
} cliprect;
|
||||
struct {
|
||||
size_t first;
|
||||
size_t count;
|
||||
Uint8 r, g, b, a;
|
||||
SDL_BlendMode blend;
|
||||
SDL_Texture *texture;
|
||||
} draw;
|
||||
struct {
|
||||
size_t first;
|
||||
Uint8 r, g, b, a;
|
||||
} color;
|
||||
} data;
|
||||
struct SDL_RenderCommand *next;
|
||||
} SDL_RenderCommand;
|
||||
|
||||
typedef struct SDL_AllocVertGap
|
||||
{
|
||||
size_t offset;
|
||||
size_t len;
|
||||
struct SDL_AllocVertGap *next;
|
||||
} SDL_AllocVertGap;
|
||||
|
||||
|
||||
/* Define the SDL renderer structure */
|
||||
struct SDL_Renderer
|
||||
{
|
||||
|
@ -90,12 +127,20 @@ struct SDL_Renderer
|
|||
int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
|
||||
SDL_bool (*SupportsBlendMode)(SDL_Renderer * renderer, SDL_BlendMode blendMode);
|
||||
int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
int (*SetTextureColorMod) (SDL_Renderer * renderer,
|
||||
SDL_Texture * texture);
|
||||
int (*SetTextureAlphaMod) (SDL_Renderer * renderer,
|
||||
SDL_Texture * texture);
|
||||
int (*SetTextureBlendMode) (SDL_Renderer * renderer,
|
||||
SDL_Texture * texture);
|
||||
int (*QueueSetViewport) (SDL_Renderer * renderer, SDL_RenderCommand *cmd);
|
||||
int (*QueueSetDrawColor) (SDL_Renderer * renderer, SDL_RenderCommand *cmd);
|
||||
int (*QueueDrawPoints) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points,
|
||||
int count);
|
||||
int (*QueueDrawLines) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points,
|
||||
int count);
|
||||
int (*QueueFillRects) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects,
|
||||
int count);
|
||||
int (*QueueCopy) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
|
||||
int (*QueueCopyEx) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
|
||||
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
|
||||
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
|
||||
int (*RunCommandQueue) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
|
||||
int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect, const void *pixels,
|
||||
int pitch);
|
||||
|
@ -108,20 +153,6 @@ struct SDL_Renderer
|
|||
const SDL_Rect * rect, void **pixels, int *pitch);
|
||||
void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
int (*UpdateViewport) (SDL_Renderer * renderer);
|
||||
int (*UpdateClipRect) (SDL_Renderer * renderer);
|
||||
int (*RenderClear) (SDL_Renderer * renderer);
|
||||
int (*RenderDrawPoints) (SDL_Renderer * renderer, const SDL_FPoint * points,
|
||||
int count);
|
||||
int (*RenderDrawLines) (SDL_Renderer * renderer, const SDL_FPoint * points,
|
||||
int count);
|
||||
int (*RenderFillRects) (SDL_Renderer * renderer, const SDL_FRect * rects,
|
||||
int count);
|
||||
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
|
||||
int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
|
||||
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
|
||||
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||
Uint32 format, void * pixels, int pitch);
|
||||
void (*RenderPresent) (SDL_Renderer * renderer);
|
||||
|
@ -178,6 +209,26 @@ struct SDL_Renderer
|
|||
Uint8 r, g, b, a; /**< Color for drawing operations values */
|
||||
SDL_BlendMode blendMode; /**< The drawing blend mode */
|
||||
|
||||
SDL_bool always_batch;
|
||||
SDL_bool batching;
|
||||
SDL_RenderCommand *render_commands;
|
||||
SDL_RenderCommand *render_commands_tail;
|
||||
SDL_RenderCommand *render_commands_pool;
|
||||
Uint32 render_command_generation;
|
||||
Uint32 last_queued_color;
|
||||
SDL_Rect last_queued_viewport;
|
||||
SDL_Rect last_queued_cliprect;
|
||||
SDL_bool last_queued_cliprect_enabled;
|
||||
SDL_bool color_queued;
|
||||
SDL_bool viewport_queued;
|
||||
SDL_bool cliprect_queued;
|
||||
|
||||
void *vertex_data;
|
||||
size_t vertex_data_used;
|
||||
size_t vertex_data_allocation;
|
||||
SDL_AllocVertGap vertex_data_gaps;
|
||||
SDL_AllocVertGap *vertex_data_gaps_pool;
|
||||
|
||||
void *driverdata;
|
||||
};
|
||||
|
||||
|
@ -209,6 +260,11 @@ extern SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode);
|
|||
extern SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode);
|
||||
extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode);
|
||||
|
||||
/* drivers call this during their Queue*() methods to make space in a array that are used
|
||||
for a vertex buffer during RunCommandQueue(). Pointers returned here are only valid until
|
||||
the next call, because it might be in an array that gets realloc()'d. */
|
||||
extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset);
|
||||
|
||||
#endif /* SDL_sysrender_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -340,11 +340,12 @@ CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, co
|
|||
ctx->glCompileShaderARB(shader);
|
||||
ctx->glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
|
||||
if (status == 0) {
|
||||
SDL_bool isstack;
|
||||
GLint length;
|
||||
char *info;
|
||||
|
||||
ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
|
||||
info = SDL_stack_alloc(char, length+1);
|
||||
info = SDL_small_alloc(char, length+1, &isstack);
|
||||
ctx->glGetInfoLogARB(shader, length, NULL, info);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER,
|
||||
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
|
||||
|
@ -352,7 +353,7 @@ CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, co
|
|||
fprintf(stderr,
|
||||
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
|
||||
#endif
|
||||
SDL_stack_free(info);
|
||||
SDL_small_free(info, isstack);
|
||||
|
||||
return SDL_FALSE;
|
||||
} else {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
/* OpenGL shader implementation */
|
||||
|
||||
typedef enum {
|
||||
SHADER_INVALID = -1,
|
||||
SHADER_NONE,
|
||||
SHADER_SOLID,
|
||||
SHADER_RGB,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -75,6 +75,7 @@ SDL_PROC(void, glDeleteFramebuffers, (GLsizei, const GLuint *))
|
|||
SDL_PROC(GLint, glGetAttribLocation, (GLuint, const GLchar *))
|
||||
SDL_PROC(void, glGetProgramInfoLog, (GLuint, GLsizei, GLsizei*, GLchar*))
|
||||
SDL_PROC(void, glGenBuffers, (GLsizei, GLuint *))
|
||||
SDL_PROC(void, glDeleteBuffers, (GLsizei, GLuint *))
|
||||
SDL_PROC(void, glBindBuffer, (GLenum, GLuint))
|
||||
SDL_PROC(void, glBufferData, (GLenum, GLsizeiptr, const GLvoid *, GLenum))
|
||||
SDL_PROC(void, glBufferSubData, (GLenum, GLintptr, GLsizeiptr, const GLvoid *))
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -69,13 +69,13 @@ static const Uint8 GLES2_FragmentSrc_SolidSrc_[] = " \
|
|||
static const Uint8 GLES2_FragmentSrc_TextureABGRSrc_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform vec4 u_modulation; \
|
||||
uniform vec4 u_color; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
{ \
|
||||
gl_FragColor = texture2D(u_texture, v_texCoord); \
|
||||
gl_FragColor *= u_modulation; \
|
||||
gl_FragColor *= u_color; \
|
||||
} \
|
||||
";
|
||||
|
||||
|
@ -83,7 +83,7 @@ static const Uint8 GLES2_FragmentSrc_TextureABGRSrc_[] = " \
|
|||
static const Uint8 GLES2_FragmentSrc_TextureARGBSrc_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform vec4 u_modulation; \
|
||||
uniform vec4 u_color; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
|
@ -92,7 +92,7 @@ static const Uint8 GLES2_FragmentSrc_TextureARGBSrc_[] = " \
|
|||
gl_FragColor = abgr; \
|
||||
gl_FragColor.r = abgr.b; \
|
||||
gl_FragColor.b = abgr.r; \
|
||||
gl_FragColor *= u_modulation; \
|
||||
gl_FragColor *= u_color; \
|
||||
} \
|
||||
";
|
||||
|
||||
|
@ -100,7 +100,7 @@ static const Uint8 GLES2_FragmentSrc_TextureARGBSrc_[] = " \
|
|||
static const Uint8 GLES2_FragmentSrc_TextureRGBSrc_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform vec4 u_modulation; \
|
||||
uniform vec4 u_color; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
|
@ -110,7 +110,7 @@ static const Uint8 GLES2_FragmentSrc_TextureRGBSrc_[] = " \
|
|||
gl_FragColor.r = abgr.b; \
|
||||
gl_FragColor.b = abgr.r; \
|
||||
gl_FragColor.a = 1.0; \
|
||||
gl_FragColor *= u_modulation; \
|
||||
gl_FragColor *= u_color; \
|
||||
} \
|
||||
";
|
||||
|
||||
|
@ -118,7 +118,7 @@ static const Uint8 GLES2_FragmentSrc_TextureRGBSrc_[] = " \
|
|||
static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform vec4 u_modulation; \
|
||||
uniform vec4 u_color; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
|
@ -126,7 +126,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
|||
vec4 abgr = texture2D(u_texture, v_texCoord); \
|
||||
gl_FragColor = abgr; \
|
||||
gl_FragColor.a = 1.0; \
|
||||
gl_FragColor *= u_modulation; \
|
||||
gl_FragColor *= u_color; \
|
||||
} \
|
||||
";
|
||||
|
||||
|
@ -163,7 +163,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
|||
"uniform sampler2D u_texture;\n" \
|
||||
"uniform sampler2D u_texture_u;\n" \
|
||||
"uniform sampler2D u_texture_v;\n" \
|
||||
"uniform vec4 u_modulation;\n" \
|
||||
"uniform vec4 u_color;\n" \
|
||||
"varying vec2 v_texCoord;\n" \
|
||||
"\n" \
|
||||
|
||||
|
@ -185,7 +185,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
|||
"\n" \
|
||||
" // That was easy. :) \n" \
|
||||
" gl_FragColor = vec4(rgb, 1);\n" \
|
||||
" gl_FragColor *= u_modulation;\n" \
|
||||
" gl_FragColor *= u_color;\n" \
|
||||
"}" \
|
||||
|
||||
#define NV12_SHADER_BODY \
|
||||
|
@ -205,7 +205,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
|||
"\n" \
|
||||
" // That was easy. :) \n" \
|
||||
" gl_FragColor = vec4(rgb, 1);\n" \
|
||||
" gl_FragColor *= u_modulation;\n" \
|
||||
" gl_FragColor *= u_color;\n" \
|
||||
"}" \
|
||||
|
||||
#define NV21_SHADER_BODY \
|
||||
|
@ -225,7 +225,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
|||
"\n" \
|
||||
" // That was easy. :) \n" \
|
||||
" gl_FragColor = vec4(rgb, 1);\n" \
|
||||
" gl_FragColor *= u_modulation;\n" \
|
||||
" gl_FragColor *= u_color;\n" \
|
||||
"}" \
|
||||
|
||||
/* YUV to ABGR conversion */
|
||||
|
@ -284,13 +284,13 @@ static const Uint8 GLES2_FragmentSrc_TextureExternalOESSrc_[] = " \
|
|||
#extension GL_OES_EGL_image_external : require\n\
|
||||
precision mediump float; \
|
||||
uniform samplerExternalOES u_texture; \
|
||||
uniform vec4 u_modulation; \
|
||||
uniform vec4 u_color; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
{ \
|
||||
gl_FragColor = texture2D(u_texture, v_texCoord); \
|
||||
gl_FragColor *= u_modulation; \
|
||||
gl_FragColor *= u_color; \
|
||||
} \
|
||||
";
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,7 @@
|
|||
#include "../SDL_sysrender.h"
|
||||
#include "SDL_render_sw_c.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_draw.h"
|
||||
#include "SDL_blendfillrect.h"
|
||||
|
@ -36,65 +37,6 @@
|
|||
|
||||
/* SDL surface based renderer implementation */
|
||||
|
||||
static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
|
||||
static void SW_WindowEvent(SDL_Renderer * renderer,
|
||||
const SDL_WindowEvent *event);
|
||||
static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
|
||||
static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
static int SW_SetTextureColorMod(SDL_Renderer * renderer,
|
||||
SDL_Texture * texture);
|
||||
static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
|
||||
SDL_Texture * texture);
|
||||
static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
|
||||
SDL_Texture * texture);
|
||||
static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect, const void *pixels,
|
||||
int pitch);
|
||||
static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect, void **pixels, int *pitch);
|
||||
static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
static int SW_UpdateViewport(SDL_Renderer * renderer);
|
||||
static int SW_UpdateClipRect(SDL_Renderer * renderer);
|
||||
static int SW_RenderClear(SDL_Renderer * renderer);
|
||||
static int SW_RenderDrawPoints(SDL_Renderer * renderer,
|
||||
const SDL_FPoint * points, int count);
|
||||
static int SW_RenderDrawLines(SDL_Renderer * renderer,
|
||||
const SDL_FPoint * points, int count);
|
||||
static int SW_RenderFillRects(SDL_Renderer * renderer,
|
||||
const SDL_FRect * rects, int count);
|
||||
static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
|
||||
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
|
||||
const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
|
||||
static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||
Uint32 format, void * pixels, int pitch);
|
||||
static void SW_RenderPresent(SDL_Renderer * renderer);
|
||||
static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||
static void SW_DestroyRenderer(SDL_Renderer * renderer);
|
||||
|
||||
|
||||
SDL_RenderDriver SW_RenderDriver = {
|
||||
SW_CreateRenderer,
|
||||
{
|
||||
"software",
|
||||
SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
|
||||
8,
|
||||
{
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
SDL_PIXELFORMAT_RGBA8888,
|
||||
SDL_PIXELFORMAT_BGRA8888,
|
||||
SDL_PIXELFORMAT_RGB888,
|
||||
SDL_PIXELFORMAT_BGR888,
|
||||
SDL_PIXELFORMAT_RGB565,
|
||||
SDL_PIXELFORMAT_RGB555
|
||||
},
|
||||
0,
|
||||
0}
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
@ -114,82 +56,11 @@ SW_ActivateRenderer(SDL_Renderer * renderer)
|
|||
SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
|
||||
if (surface) {
|
||||
data->surface = data->window = surface;
|
||||
|
||||
SW_UpdateViewport(renderer);
|
||||
SW_UpdateClipRect(renderer);
|
||||
}
|
||||
}
|
||||
return data->surface;
|
||||
}
|
||||
|
||||
SDL_Renderer *
|
||||
SW_CreateRendererForSurface(SDL_Surface * surface)
|
||||
{
|
||||
SDL_Renderer *renderer;
|
||||
SW_RenderData *data;
|
||||
|
||||
if (!surface) {
|
||||
SDL_SetError("Can't create renderer for NULL surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
||||
if (!renderer) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SW_DestroyRenderer(renderer);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
data->surface = surface;
|
||||
data->window = surface;
|
||||
|
||||
renderer->WindowEvent = SW_WindowEvent;
|
||||
renderer->GetOutputSize = SW_GetOutputSize;
|
||||
renderer->CreateTexture = SW_CreateTexture;
|
||||
renderer->SetTextureColorMod = SW_SetTextureColorMod;
|
||||
renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
|
||||
renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
|
||||
renderer->UpdateTexture = SW_UpdateTexture;
|
||||
renderer->LockTexture = SW_LockTexture;
|
||||
renderer->UnlockTexture = SW_UnlockTexture;
|
||||
renderer->SetRenderTarget = SW_SetRenderTarget;
|
||||
renderer->UpdateViewport = SW_UpdateViewport;
|
||||
renderer->UpdateClipRect = SW_UpdateClipRect;
|
||||
renderer->RenderClear = SW_RenderClear;
|
||||
renderer->RenderDrawPoints = SW_RenderDrawPoints;
|
||||
renderer->RenderDrawLines = SW_RenderDrawLines;
|
||||
renderer->RenderFillRects = SW_RenderFillRects;
|
||||
renderer->RenderCopy = SW_RenderCopy;
|
||||
renderer->RenderCopyEx = SW_RenderCopyEx;
|
||||
renderer->RenderReadPixels = SW_RenderReadPixels;
|
||||
renderer->RenderPresent = SW_RenderPresent;
|
||||
renderer->DestroyTexture = SW_DestroyTexture;
|
||||
renderer->DestroyRenderer = SW_DestroyRenderer;
|
||||
renderer->info = SW_RenderDriver.info;
|
||||
renderer->driverdata = data;
|
||||
|
||||
SW_ActivateRenderer(renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
SDL_Renderer *
|
||||
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
surface = SDL_GetWindowSurface(window);
|
||||
if (!surface) {
|
||||
return NULL;
|
||||
}
|
||||
return SW_CreateRendererForSurface(surface);
|
||||
}
|
||||
|
||||
static void
|
||||
SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
||||
{
|
||||
|
@ -252,46 +123,6 @@ SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||
{
|
||||
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
|
||||
/* If the color mod is ever enabled (non-white), permanently disable RLE (which doesn't support
|
||||
* color mod) to avoid potentially frequent RLE encoding/decoding.
|
||||
*/
|
||||
if ((texture->r & texture->g & texture->b) != 255) {
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
}
|
||||
return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
|
||||
texture->b);
|
||||
}
|
||||
|
||||
static int
|
||||
SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||
{
|
||||
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
|
||||
/* If the texture ever has multiple alpha values (surface alpha plus alpha channel), permanently
|
||||
* disable RLE (which doesn't support this) to avoid potentially frequent RLE encoding/decoding.
|
||||
*/
|
||||
if (texture->a != 255 && surface->format->Amask) {
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
}
|
||||
return SDL_SetSurfaceAlphaMod(surface, texture->a);
|
||||
}
|
||||
|
||||
static int
|
||||
SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||
{
|
||||
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
|
||||
/* If add or mod blending are ever enabled, permanently disable RLE (which doesn't support
|
||||
* them) to avoid potentially frequent RLE encoding/decoding.
|
||||
*/
|
||||
if ((texture->blendMode == SDL_BLENDMODE_ADD || texture->blendMode == SDL_BLENDMODE_MOD)) {
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
}
|
||||
return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
|
||||
}
|
||||
|
||||
static int
|
||||
SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect, const void *pixels, int pitch)
|
||||
|
@ -350,251 +181,149 @@ SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
}
|
||||
|
||||
static int
|
||||
SW_UpdateViewport(SDL_Renderer * renderer)
|
||||
SW_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
|
||||
{
|
||||
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
|
||||
SDL_Surface *surface = data->surface;
|
||||
return 0; /* nothing to do in this backend. */
|
||||
}
|
||||
|
||||
if (!surface) {
|
||||
/* We'll update the viewport after we recreate the surface */
|
||||
return 0;
|
||||
static int
|
||||
SW_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
|
||||
{
|
||||
SDL_Point *verts = (SDL_Point *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Point), 0, &cmd->data.draw.first);
|
||||
size_t i;
|
||||
|
||||
if (!verts) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = count;
|
||||
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
const int x = renderer->viewport.x;
|
||||
const int y = renderer->viewport.y;
|
||||
for (i = 0; i < count; i++, verts++, points++) {
|
||||
verts->x = (int)(x + points->x);
|
||||
verts->y = (int)(y + points->y);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; i++, verts++, points++) {
|
||||
verts->x = (int)points->x;
|
||||
verts->y = (int)points->y;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetClipRect(data->surface, &renderer->viewport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_UpdateClipRect(SDL_Renderer * renderer)
|
||||
SW_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
|
||||
{
|
||||
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
|
||||
SDL_Surface *surface = data->surface;
|
||||
if (surface) {
|
||||
if (renderer->clipping_enabled) {
|
||||
SDL_Rect clip_rect;
|
||||
clip_rect = renderer->clip_rect;
|
||||
clip_rect.x += renderer->viewport.x;
|
||||
clip_rect.y += renderer->viewport.y;
|
||||
SDL_IntersectRect(&renderer->viewport, &clip_rect, &clip_rect);
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
} else {
|
||||
SDL_SetClipRect(surface, &renderer->viewport);
|
||||
SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
|
||||
size_t i;
|
||||
|
||||
if (!verts) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = count;
|
||||
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
const int x = renderer->viewport.x;
|
||||
const int y = renderer->viewport.y;
|
||||
|
||||
for (i = 0; i < count; i++, verts++, rects++) {
|
||||
verts->x = (int)(x + rects->x);
|
||||
verts->y = (int)(y + rects->y);
|
||||
verts->w = SDL_max((int)rects->w, 1);
|
||||
verts->h = SDL_max((int)rects->h, 1);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; i++, verts++, rects++) {
|
||||
verts->x = (int)rects->x;
|
||||
verts->y = (int)rects->y;
|
||||
verts->w = SDL_max((int)rects->w, 1);
|
||||
verts->h = SDL_max((int)rects->h, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderClear(SDL_Renderer * renderer)
|
||||
SW_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
|
||||
{
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
Uint32 color;
|
||||
SDL_Rect clip_rect;
|
||||
SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, 2 * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
|
||||
|
||||
if (!surface) {
|
||||
if (!verts) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
color = SDL_MapRGBA(surface->format,
|
||||
renderer->r, renderer->g, renderer->b, renderer->a);
|
||||
cmd->data.draw.count = 1;
|
||||
|
||||
SDL_memcpy(verts, srcrect, sizeof (SDL_Rect));
|
||||
verts++;
|
||||
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
verts->x = (int)(renderer->viewport.x + dstrect->x);
|
||||
verts->y = (int)(renderer->viewport.y + dstrect->y);
|
||||
} else {
|
||||
verts->x = (int)dstrect->x;
|
||||
verts->y = (int)dstrect->y;
|
||||
}
|
||||
verts->w = (int)dstrect->w;
|
||||
verts->h = (int)dstrect->h;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct CopyExData
|
||||
{
|
||||
SDL_Rect srcrect;
|
||||
SDL_Rect dstrect;
|
||||
double angle;
|
||||
SDL_FPoint center;
|
||||
SDL_RendererFlip flip;
|
||||
} CopyExData;
|
||||
|
||||
static int
|
||||
SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
|
||||
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
|
||||
{
|
||||
CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
|
||||
|
||||
if (!verts) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = 1;
|
||||
|
||||
SDL_memcpy(&verts->srcrect, srcrect, sizeof (SDL_Rect));
|
||||
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
verts->dstrect.x = (int)(renderer->viewport.x + dstrect->x);
|
||||
verts->dstrect.y = (int)(renderer->viewport.y + dstrect->y);
|
||||
} else {
|
||||
verts->dstrect.x = (int)dstrect->x;
|
||||
verts->dstrect.y = (int)dstrect->y;
|
||||
}
|
||||
verts->dstrect.w = (int)dstrect->w;
|
||||
verts->dstrect.h = (int)dstrect->h;
|
||||
verts->angle = angle;
|
||||
SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
|
||||
verts->flip = flip;
|
||||
|
||||
/* By definition the clear ignores the clip rect */
|
||||
clip_rect = surface->clip_rect;
|
||||
SDL_SetClipRect(surface, NULL);
|
||||
SDL_FillRect(surface, NULL, color);
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
|
||||
int count)
|
||||
{
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
SDL_Point *final_points;
|
||||
int i, status;
|
||||
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final_points = SDL_stack_alloc(SDL_Point, count);
|
||||
if (!final_points) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
int x = renderer->viewport.x;
|
||||
int y = renderer->viewport.y;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
final_points[i].x = (int)(x + points[i].x);
|
||||
final_points[i].y = (int)(y + points[i].y);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; ++i) {
|
||||
final_points[i].x = (int)points[i].x;
|
||||
final_points[i].y = (int)points[i].y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw the points! */
|
||||
if (renderer->blendMode == SDL_BLENDMODE_NONE) {
|
||||
Uint32 color = SDL_MapRGBA(surface->format,
|
||||
renderer->r, renderer->g, renderer->b,
|
||||
renderer->a);
|
||||
|
||||
status = SDL_DrawPoints(surface, final_points, count, color);
|
||||
} else {
|
||||
status = SDL_BlendPoints(surface, final_points, count,
|
||||
renderer->blendMode,
|
||||
renderer->r, renderer->g, renderer->b,
|
||||
renderer->a);
|
||||
}
|
||||
SDL_stack_free(final_points);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
|
||||
int count)
|
||||
{
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
SDL_Point *final_points;
|
||||
int i, status;
|
||||
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final_points = SDL_stack_alloc(SDL_Point, count);
|
||||
if (!final_points) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
int x = renderer->viewport.x;
|
||||
int y = renderer->viewport.y;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
final_points[i].x = (int)(x + points[i].x);
|
||||
final_points[i].y = (int)(y + points[i].y);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; ++i) {
|
||||
final_points[i].x = (int)points[i].x;
|
||||
final_points[i].y = (int)points[i].y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw the lines! */
|
||||
if (renderer->blendMode == SDL_BLENDMODE_NONE) {
|
||||
Uint32 color = SDL_MapRGBA(surface->format,
|
||||
renderer->r, renderer->g, renderer->b,
|
||||
renderer->a);
|
||||
|
||||
status = SDL_DrawLines(surface, final_points, count, color);
|
||||
} else {
|
||||
status = SDL_BlendLines(surface, final_points, count,
|
||||
renderer->blendMode,
|
||||
renderer->r, renderer->g, renderer->b,
|
||||
renderer->a);
|
||||
}
|
||||
SDL_stack_free(final_points);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
|
||||
{
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
SDL_Rect *final_rects;
|
||||
int i, status;
|
||||
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final_rects = SDL_stack_alloc(SDL_Rect, count);
|
||||
if (!final_rects) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
int x = renderer->viewport.x;
|
||||
int y = renderer->viewport.y;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
final_rects[i].x = (int)(x + rects[i].x);
|
||||
final_rects[i].y = (int)(y + rects[i].y);
|
||||
final_rects[i].w = SDL_max((int)rects[i].w, 1);
|
||||
final_rects[i].h = SDL_max((int)rects[i].h, 1);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; ++i) {
|
||||
final_rects[i].x = (int)rects[i].x;
|
||||
final_rects[i].y = (int)rects[i].y;
|
||||
final_rects[i].w = SDL_max((int)rects[i].w, 1);
|
||||
final_rects[i].h = SDL_max((int)rects[i].h, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderer->blendMode == SDL_BLENDMODE_NONE) {
|
||||
Uint32 color = SDL_MapRGBA(surface->format,
|
||||
renderer->r, renderer->g, renderer->b,
|
||||
renderer->a);
|
||||
status = SDL_FillRects(surface, final_rects, count, color);
|
||||
} else {
|
||||
status = SDL_BlendFillRects(surface, final_rects, count,
|
||||
renderer->blendMode,
|
||||
renderer->r, renderer->g, renderer->b,
|
||||
renderer->a);
|
||||
}
|
||||
SDL_stack_free(final_rects);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
|
||||
{
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
|
||||
SDL_Rect final_rect;
|
||||
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
final_rect.x = (int)(renderer->viewport.x + dstrect->x);
|
||||
final_rect.y = (int)(renderer->viewport.y + dstrect->y);
|
||||
} else {
|
||||
final_rect.x = (int)dstrect->x;
|
||||
final_rect.y = (int)dstrect->y;
|
||||
}
|
||||
final_rect.w = (int)dstrect->w;
|
||||
final_rect.h = (int)dstrect->h;
|
||||
|
||||
if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {
|
||||
return SDL_BlitSurface(src, srcrect, surface, &final_rect);
|
||||
} else {
|
||||
/* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
|
||||
* to avoid potentially frequent RLE encoding/decoding.
|
||||
*/
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
return SDL_BlitScaled(src, srcrect, surface, &final_rect);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
|
||||
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_Rect * final_rect,
|
||||
const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
|
||||
{
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
|
||||
SDL_Rect final_rect, tmp_rect;
|
||||
SDL_Rect tmp_rect;
|
||||
SDL_Surface *src_clone, *src_rotated, *src_scaled;
|
||||
SDL_Surface *mask = NULL, *mask_rotated = NULL;
|
||||
int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
|
||||
|
@ -609,19 +338,10 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (renderer->viewport.x || renderer->viewport.y) {
|
||||
final_rect.x = (int)(renderer->viewport.x + dstrect->x);
|
||||
final_rect.y = (int)(renderer->viewport.y + dstrect->y);
|
||||
} else {
|
||||
final_rect.x = (int)dstrect->x;
|
||||
final_rect.y = (int)dstrect->y;
|
||||
}
|
||||
final_rect.w = (int)dstrect->w;
|
||||
final_rect.h = (int)dstrect->h;
|
||||
|
||||
tmp_rect = final_rect;
|
||||
tmp_rect.x = 0;
|
||||
tmp_rect.y = 0;
|
||||
tmp_rect.w = final_rect->w;
|
||||
tmp_rect.h = final_rect->h;
|
||||
|
||||
/* It is possible to encounter an RLE encoded surface here and locking it is
|
||||
* necessary because this code is going to access the pixel buffer directly.
|
||||
|
@ -653,7 +373,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
}
|
||||
|
||||
/* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
|
||||
if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) {
|
||||
if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) {
|
||||
blitRequired = SDL_TRUE;
|
||||
}
|
||||
|
||||
|
@ -678,7 +398,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
* to clear the pixels in the destination surface. The other steps are explained below.
|
||||
*/
|
||||
if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
|
||||
mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
|
||||
mask = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
|
||||
if (mask == NULL) {
|
||||
retval = -1;
|
||||
|
@ -692,7 +412,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
*/
|
||||
if (!retval && (blitRequired || applyModulation)) {
|
||||
SDL_Rect scale_rect = tmp_rect;
|
||||
src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
|
||||
src_scaled = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
|
||||
if (src_scaled == NULL) {
|
||||
retval = -1;
|
||||
|
@ -723,32 +443,32 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
}
|
||||
if (!retval) {
|
||||
/* 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 + (int)center->x;
|
||||
abscentery = final_rect.y + (int)center->y;
|
||||
abscenterx = final_rect->x + (int)center->x;
|
||||
abscentery = final_rect->y + (int)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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
|
@ -824,6 +544,170 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
PrepTextureForCopy(const SDL_RenderCommand *cmd)
|
||||
{
|
||||
const Uint8 r = cmd->data.draw.r;
|
||||
const Uint8 g = cmd->data.draw.g;
|
||||
const Uint8 b = cmd->data.draw.b;
|
||||
const Uint8 a = cmd->data.draw.a;
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
|
||||
|
||||
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
SDL_SetSurfaceColorMod(surface, r, g, b);
|
||||
}
|
||||
|
||||
if ((texture->modMode & SDL_TEXTUREMODULATE_ALPHA) && surface->format->Amask) {
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
SDL_SetSurfaceAlphaMod(surface, a);
|
||||
}
|
||||
|
||||
if ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD)) {
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
}
|
||||
SDL_SetSurfaceBlendMode(surface, blend);
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
||||
{
|
||||
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
const SDL_Rect *viewport = NULL;
|
||||
const SDL_Rect *cliprect = NULL;
|
||||
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (cmd) {
|
||||
switch (cmd->command) {
|
||||
case SDL_RENDERCMD_SETDRAWCOLOR: {
|
||||
break; /* Not used in this backend. */
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_SETVIEWPORT: {
|
||||
viewport = &cmd->data.viewport.rect;
|
||||
SDL_SetClipRect(data->surface, viewport);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_SETCLIPRECT: {
|
||||
SDL_assert(viewport != NULL);
|
||||
cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
|
||||
if (cliprect) {
|
||||
SDL_Rect clip_rect = { cliprect->x + viewport->x, cliprect->y + viewport->y, cliprect->w, cliprect->h };
|
||||
SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
} else {
|
||||
SDL_SetClipRect(surface, viewport);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_CLEAR: {
|
||||
const Uint8 r = cmd->data.color.r;
|
||||
const Uint8 g = cmd->data.color.g;
|
||||
const Uint8 b = cmd->data.color.b;
|
||||
const Uint8 a = cmd->data.color.a;
|
||||
const SDL_Rect clip_rect = surface->clip_rect;
|
||||
/* By definition the clear ignores the clip rect */
|
||||
SDL_SetClipRect(surface, NULL);
|
||||
SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS: {
|
||||
const Uint8 r = cmd->data.draw.r;
|
||||
const Uint8 g = cmd->data.draw.g;
|
||||
const Uint8 b = cmd->data.draw.b;
|
||||
const Uint8 a = cmd->data.draw.a;
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
if (blend == SDL_BLENDMODE_NONE) {
|
||||
SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
} else {
|
||||
SDL_BlendPoints(surface, verts, count, blend, r, g, b, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_LINES: {
|
||||
const Uint8 r = cmd->data.draw.r;
|
||||
const Uint8 g = cmd->data.draw.g;
|
||||
const Uint8 b = cmd->data.draw.b;
|
||||
const Uint8 a = cmd->data.draw.a;
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
if (blend == SDL_BLENDMODE_NONE) {
|
||||
SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
} else {
|
||||
SDL_BlendLines(surface, verts, count, blend, r, g, b, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_FILL_RECTS: {
|
||||
const Uint8 r = cmd->data.draw.r;
|
||||
const Uint8 g = cmd->data.draw.g;
|
||||
const Uint8 b = cmd->data.draw.b;
|
||||
const Uint8 a = cmd->data.draw.a;
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
if (blend == SDL_BLENDMODE_NONE) {
|
||||
SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
} else {
|
||||
SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_COPY: {
|
||||
SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_Rect *srcrect = verts;
|
||||
SDL_Rect *dstrect = verts + 1;
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
|
||||
|
||||
PrepTextureForCopy(cmd);
|
||||
|
||||
if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
|
||||
SDL_BlitSurface(src, srcrect, surface, dstrect);
|
||||
} else {
|
||||
/* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
|
||||
* to avoid potentially frequent RLE encoding/decoding.
|
||||
*/
|
||||
SDL_SetSurfaceRLE(surface, 0);
|
||||
SDL_BlitScaled(src, srcrect, surface, dstrect);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_COPY_EX: {
|
||||
const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
PrepTextureForCopy(cmd);
|
||||
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect,
|
||||
©data->dstrect, copydata->angle, ©data->center, copydata->flip);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_NO_OP:
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||
Uint32 format, void * pixels, int pitch)
|
||||
|
@ -882,6 +766,91 @@ SW_DestroyRenderer(SDL_Renderer * renderer)
|
|||
SDL_free(renderer);
|
||||
}
|
||||
|
||||
SDL_Renderer *
|
||||
SW_CreateRendererForSurface(SDL_Surface * surface)
|
||||
{
|
||||
SDL_Renderer *renderer;
|
||||
SW_RenderData *data;
|
||||
|
||||
if (!surface) {
|
||||
SDL_SetError("Can't create renderer for NULL surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
||||
if (!renderer) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SW_DestroyRenderer(renderer);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
data->surface = surface;
|
||||
data->window = surface;
|
||||
|
||||
renderer->WindowEvent = SW_WindowEvent;
|
||||
renderer->GetOutputSize = SW_GetOutputSize;
|
||||
renderer->CreateTexture = SW_CreateTexture;
|
||||
renderer->UpdateTexture = SW_UpdateTexture;
|
||||
renderer->LockTexture = SW_LockTexture;
|
||||
renderer->UnlockTexture = SW_UnlockTexture;
|
||||
renderer->SetRenderTarget = SW_SetRenderTarget;
|
||||
renderer->QueueSetViewport = SW_QueueSetViewport;
|
||||
renderer->QueueSetDrawColor = SW_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
|
||||
renderer->QueueDrawPoints = SW_QueueDrawPoints;
|
||||
renderer->QueueDrawLines = SW_QueueDrawPoints; /* lines and points queue vertices the same way. */
|
||||
renderer->QueueFillRects = SW_QueueFillRects;
|
||||
renderer->QueueCopy = SW_QueueCopy;
|
||||
renderer->QueueCopyEx = SW_QueueCopyEx;
|
||||
renderer->RunCommandQueue = SW_RunCommandQueue;
|
||||
renderer->RenderReadPixels = SW_RenderReadPixels;
|
||||
renderer->RenderPresent = SW_RenderPresent;
|
||||
renderer->DestroyTexture = SW_DestroyTexture;
|
||||
renderer->DestroyRenderer = SW_DestroyRenderer;
|
||||
renderer->info = SW_RenderDriver.info;
|
||||
renderer->driverdata = data;
|
||||
|
||||
SW_ActivateRenderer(renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
SDL_Renderer *
|
||||
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
surface = SDL_GetWindowSurface(window);
|
||||
if (!surface) {
|
||||
return NULL;
|
||||
}
|
||||
return SW_CreateRendererForSurface(surface);
|
||||
}
|
||||
|
||||
SDL_RenderDriver SW_RenderDriver = {
|
||||
SW_CreateRenderer,
|
||||
{
|
||||
"software",
|
||||
SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
|
||||
8,
|
||||
{
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
SDL_PIXELFORMAT_RGBA8888,
|
||||
SDL_PIXELFORMAT_BGRA8888,
|
||||
SDL_PIXELFORMAT_RGB888,
|
||||
SDL_PIXELFORMAT_BGR888,
|
||||
SDL_PIXELFORMAT_RGB565,
|
||||
SDL_PIXELFORMAT_RGB555
|
||||
},
|
||||
0,
|
||||
0}
|
||||
};
|
||||
|
||||
#endif /* !SDL_RENDER_DISABLED */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue