SDL_render.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 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, 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.
*/
#include "../SDL_internal.h"
/* The SDL 2D rendering system */
#include "SDL_assert.h"
#include "SDL_hints.h"
#include "SDL_log.h"
#include "SDL_render.h"
#include "SDL_sysrender.h"
#include "software/SDL_render_sw_c.h"
#if defined(__ANDROID__)
# include "../core/android/SDL_android.h"
#endif
#define SDL_WINDOWRENDERDATA "_SDL_WindowRenderData"
#define CHECK_RENDERER_MAGIC(renderer, retval) \
SDL_assert(renderer && renderer->magic == &renderer_magic); \
if (!renderer || renderer->magic != &renderer_magic) { \
SDL_SetError("Invalid renderer"); \
return retval; \
}
#define CHECK_TEXTURE_MAGIC(texture, retval) \
SDL_assert(texture && texture->magic == &texture_magic); \
if (!texture || texture->magic != &texture_magic) { \
SDL_SetError("Invalid texture"); \
return retval; \
}
/* Predefined blend modes */
#define SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation, \
srcAlphaFactor, dstAlphaFactor, alphaOperation) \
(SDL_BlendMode)(((Uint32)colorOperation << 0) | \
((Uint32)srcColorFactor << 4) | \
((Uint32)dstColorFactor << 8) | \
((Uint32)alphaOperation << 16) | \
((Uint32)srcAlphaFactor << 20) | \
((Uint32)dstAlphaFactor << 24))
#define SDL_BLENDMODE_NONE_FULL \
SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD, \
SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD)
#define SDL_BLENDMODE_BLEND_FULL \
SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, \
SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD)
#define SDL_BLENDMODE_ADD_FULL \
SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD, \
SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
#define SDL_BLENDMODE_MOD_FULL \
SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR, SDL_BLENDOPERATION_ADD, \
SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
#if !SDL_RENDER_DISABLED
static const SDL_RenderDriver *render_drivers[] = {
#if SDL_VIDEO_RENDER_D3D
&D3D_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_D3D11
&D3D11_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_METAL
&METAL_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_OGL
&GL_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_OGL_ES2
&GLES2_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_OGL_ES
&GLES_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_DIRECTFB
&DirectFB_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_PSP
&PSP_RenderDriver,
#endif
&SW_RenderDriver
};
#endif /* !SDL_RENDER_DISABLED */
static char renderer_magic;
static char texture_magic;
static SDL_INLINE void
DebugLogRenderCommands(const SDL_RenderCommand *cmd)
{
#if 0
unsigned int i = 1;
SDL_Log("Render commands to flush:");
while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_NO_OP:
SDL_Log(" %u. no-op", i++);
break;
case SDL_RENDERCMD_SETVIEWPORT:
SDL_Log(" %u. set viewport (first=%u, rect={(%d, %d), %dx%d})", i++,
(unsigned int) cmd->data.viewport.first,
cmd->data.viewport.rect.x, cmd->data.viewport.rect.y,
cmd->data.viewport.rect.w, cmd->data.viewport.rect.h);
break;
case SDL_RENDERCMD_SETCLIPRECT:
SDL_Log(" %u. set cliprect (enabled=%s, rect={(%d, %d), %dx%d})", i++,
cmd->data.cliprect.enabled ? "true" : "false",
cmd->data.cliprect.rect.x, cmd->data.cliprect.rect.y,
cmd->data.cliprect.rect.w, cmd->data.cliprect.rect.h);
break;
case SDL_RENDERCMD_SETDRAWCOLOR:
SDL_Log(" %u. set draw color (first=%u, r=%d, g=%d, b=%d, a=%d)", i++,
(unsigned int) cmd->data.color.first,
(int) cmd->data.color.r, (int) cmd->data.color.g,
(int) cmd->data.color.b, (int) cmd->data.color.a);
break;
case SDL_RENDERCMD_CLEAR:
SDL_Log(" %u. clear (first=%u, r=%d, g=%d, b=%d, a=%d)", i++,
(unsigned int) cmd->data.color.first,
(int) cmd->data.color.r, (int) cmd->data.color.g,
(int) cmd->data.color.b, (int) cmd->data.color.a);
break;
case SDL_RENDERCMD_DRAW_POINTS:
SDL_Log(" %u. draw points (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.r, (int) cmd->data.draw.g,
(int) cmd->data.draw.b, (int) cmd->data.draw.a,
(int) cmd->data.draw.blend);
break;
case SDL_RENDERCMD_DRAW_LINES:
SDL_Log(" %u. draw lines (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.r, (int) cmd->data.draw.g,
(int) cmd->data.draw.b, (int) cmd->data.draw.a,
(int) cmd->data.draw.blend);
break;
case SDL_RENDERCMD_FILL_RECTS:
SDL_Log(" %u. fill rects (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.r, (int) cmd->data.draw.g,
(int) cmd->data.draw.b, (int) cmd->data.draw.a,
(int) cmd->data.draw.blend);
break;
case SDL_RENDERCMD_COPY:
SDL_Log(" %u. copy (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.r, (int) cmd->data.draw.g,
(int) cmd->data.draw.b, (int) cmd->data.draw.a,
(int) cmd->data.draw.blend, cmd->data.draw.texture);
break;
case SDL_RENDERCMD_COPY_EX:
SDL_Log(" %u. copyex (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.r, (int) cmd->data.draw.g,
(int) cmd->data.draw.b, (int) cmd->data.draw.a,
(int) cmd->data.draw.blend, cmd->data.draw.texture);
break;
}
cmd = cmd->next;
}
#endif
}
static int
FlushRenderCommands(SDL_Renderer *renderer)
{
SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps;
SDL_AllocVertGap *gap = prevgap;
int retval;
SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL));
if (renderer->render_commands == NULL) { /* nothing to do! */
SDL_assert(renderer->vertex_data_used == 0);
return 0;
}
DebugLogRenderCommands(renderer->render_commands);
retval = renderer->RunCommandQueue(renderer, renderer->render_commands, renderer->vertex_data, renderer->vertex_data_used);
while (gap) {
prevgap = gap;
gap = gap->next;
}
prevgap->next = renderer->vertex_data_gaps_pool;
renderer->vertex_data_gaps_pool = renderer->vertex_data_gaps.next;
renderer->vertex_data_gaps.next = NULL;
/* Move the whole render command queue to the unused pool so we can reuse them next time. */
if (renderer->render_commands_tail != NULL) {
renderer->render_commands_tail->next = renderer->render_commands_pool;
renderer->render_commands_pool = renderer->render_commands;
renderer->render_commands_tail = NULL;
renderer->render_commands = NULL;
}
renderer->vertex_data_used = 0;
renderer->render_command_generation++;
renderer->color_queued = SDL_FALSE;
renderer->viewport_queued = SDL_FALSE;
renderer->cliprect_queued = SDL_FALSE;
return retval;
}
static int
FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
{
SDL_Renderer *renderer = texture->renderer;
if (texture->last_command_generation == renderer->render_command_generation) {
/* the current command queue depends on this texture, flush the queue now before it changes */
return FlushRenderCommands(renderer);
}
return 0;
}
static SDL_INLINE int
FlushRenderCommandsIfNotBatching(SDL_Renderer *renderer)
{
return renderer->batching ? 0 : FlushRenderCommands(renderer);
}
int
SDL_RenderFlush(SDL_Renderer * renderer)
{
return FlushRenderCommands(renderer);
}
static SDL_AllocVertGap *
AllocateVertexGap(SDL_Renderer *renderer)
{
SDL_AllocVertGap *retval = renderer->vertex_data_gaps_pool;
if (retval) {
renderer->vertex_data_gaps_pool = retval->next;
retval->next = NULL;
} else {
retval = (SDL_AllocVertGap *) SDL_malloc(sizeof (SDL_AllocVertGap));
if (!retval) {
SDL_OutOfMemory();
}
}
return retval;
}
void *
SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
{
const size_t needed = renderer->vertex_data_used + numbytes + alignment;
size_t aligner, aligned;
void *retval;
SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps;
SDL_AllocVertGap *gap = prevgap->next;
while (gap) {
const size_t gapoffset = gap->offset;
aligner = (alignment && ((gap->offset % alignment) != 0)) ? (alignment - (gap->offset % alignment)) : 0;
aligned = gapoffset + aligner;
/* Can we use this gap? */
if ((aligner < gap->len) && ((gap->len - aligner) >= numbytes)) {
/* we either finished this gap off, trimmed the left, trimmed the right, or split it into two gaps. */
if (gap->len == numbytes) { /* finished it off, remove it */
SDL_assert(aligned == gapoffset);
prevgap->next = gap->next;
gap->next = renderer->vertex_data_gaps_pool;
renderer->vertex_data_gaps_pool = gap;
} else if (aligned == gapoffset) { /* trimmed the left */
gap->offset += numbytes;
gap->len -= numbytes;
} else if (((aligned - gapoffset) + numbytes) == gap->len) { /* trimmed the right */
gap->len -= numbytes;
} else { /* split into two gaps */
SDL_AllocVertGap *newgap = AllocateVertexGap(renderer);
if (!newgap) {
return NULL;
}
newgap->offset = aligned + numbytes;
newgap->len = gap->len - (aligner + numbytes);
newgap->next = gap->next;
// gap->offset doesn't change.
gap->len = aligner;
gap->next = newgap;
}
if (offset) {
*offset = aligned;
}
return ((Uint8 *) renderer->vertex_data) + aligned;
}
/* Try the next gap */
prevgap = gap;
gap = gap->next;
}
/* no gaps with enough space; get a new piece of the vertex buffer */
while (needed > renderer->vertex_data_allocation) {
const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 1024;
const size_t newsize = current_allocation * 2;
void *ptr = SDL_realloc(renderer->vertex_data, newsize);
if (ptr == NULL) {
SDL_OutOfMemory();
return NULL;
}
renderer->vertex_data = ptr;
renderer->vertex_data_allocation = newsize;
}
aligner = (alignment && ((renderer->vertex_data_used % alignment) != 0)) ? (alignment - (renderer->vertex_data_used % alignment)) : 0;
aligned = renderer->vertex_data_used + aligner;
retval = ((Uint8 *) renderer->vertex_data) + aligned;
if (offset) {
*offset = aligned;
}
if (aligner) { /* made a new gap... */
SDL_AllocVertGap *newgap = AllocateVertexGap(renderer);
if (newgap) { /* just let it slide as lost space if malloc fails. */
newgap->offset = renderer->vertex_data_used;
newgap->len = aligner;
newgap->next = NULL;
prevgap->next = newgap;
}
}
renderer->vertex_data_used += aligner + numbytes;
return retval;
}
static SDL_RenderCommand *
AllocateRenderCommand(SDL_Renderer *renderer)
{
SDL_RenderCommand *retval = NULL;
/* !!! FIXME: are there threading limitations in SDL's render API? If not, we need to mutex this. */
retval = renderer->render_commands_pool;
if (retval != NULL) {
renderer->render_commands_pool = retval->next;
retval->next = NULL;
} else {
retval = SDL_calloc(1, sizeof (*retval));
if (!retval) {
SDL_OutOfMemory();
return NULL;
}
}
SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL));
if (renderer->render_commands_tail != NULL) {
renderer->render_commands_tail->next = retval;
} else {
renderer->render_commands = retval;
}
renderer->render_commands_tail = retval;
return retval;
}
static int
QueueCmdSetViewport(SDL_Renderer *renderer)
{
int retval = 0;
if (!renderer->viewport_queued || (SDL_memcmp(&renderer->viewport, &renderer->last_queued_viewport, sizeof (SDL_Rect)) != 0)) {
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
retval = -1;
if (cmd != NULL) {
cmd->command = SDL_RENDERCMD_SETVIEWPORT;
cmd->data.viewport.first = 0; /* render backend will fill this in. */
SDL_memcpy(&cmd->data.viewport.rect, &renderer->viewport, sizeof (renderer->viewport));
retval = renderer->QueueSetViewport(renderer, cmd);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
} else {
SDL_memcpy(&renderer->last_queued_viewport, &renderer->viewport, sizeof (SDL_Rect));
renderer->viewport_queued = SDL_TRUE;
}
}
}
return retval;
}
static int
QueueCmdSetClipRect(SDL_Renderer *renderer)
{
int retval = 0;
if ((!renderer->cliprect_queued) ||
(renderer->clipping_enabled != renderer->last_queued_cliprect_enabled) ||
(SDL_memcmp(&renderer->clip_rect, &renderer->last_queued_cliprect, sizeof (SDL_Rect)) != 0)) {
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
if (cmd == NULL) {
retval = -1;
} else {
cmd->command = SDL_RENDERCMD_SETCLIPRECT;
cmd->data.cliprect.enabled = renderer->clipping_enabled;
SDL_memcpy(&cmd->data.cliprect.rect, &renderer->clip_rect, sizeof (cmd->data.cliprect.rect));
SDL_memcpy(&renderer->last_queued_cliprect, &renderer->clip_rect, sizeof (SDL_Rect));
renderer->last_queued_cliprect_enabled = renderer->clipping_enabled;
renderer->cliprect_queued = SDL_TRUE;
}
}
return retval;
}
static int
QueueCmdSetDrawColor(SDL_Renderer *renderer, const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a)
{
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
int retval = 0;
if (!renderer->color_queued || (color != renderer->last_queued_color)) {
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
retval = -1;
if (cmd != NULL) {
cmd->command = SDL_RENDERCMD_SETDRAWCOLOR;
cmd->data.color.first = 0; /* render backend will fill this in. */
cmd->data.color.r = r;
cmd->data.color.g = g;
cmd->data.color.b = b;
cmd->data.color.a = a;
retval = renderer->QueueSetDrawColor(renderer, cmd);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
} else {
renderer->last_queued_color = color;
renderer->color_queued = SDL_TRUE;
}
}
}
return retval;
}
static int
QueueCmdClear(SDL_Renderer *renderer)
{
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
if (cmd == NULL) {
return -1;
}
cmd->command = SDL_RENDERCMD_CLEAR;
cmd->data.color.first = 0;
cmd->data.color.r = renderer->r;
cmd->data.color.g = renderer->g;
cmd->data.color.b = renderer->b;
cmd->data.color.a = renderer->a;
return 0;
}
static int
PrepQueueCmdDraw(SDL_Renderer *renderer, const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a)
{
int retval = 0;
if (retval == 0) {
retval = QueueCmdSetDrawColor(renderer, r, g, b, a);
}
if (retval == 0) {
retval = QueueCmdSetViewport(renderer);
}
if (retval == 0) {
retval = QueueCmdSetClipRect(renderer);
}
return retval;
}
static SDL_RenderCommand *
PrepQueueCmdDrawSolid(SDL_Renderer *renderer, const SDL_RenderCommandType cmdtype)
{
/* !!! FIXME: drop this draw if viewport w or h is zero. */
SDL_RenderCommand *cmd = NULL;
if (PrepQueueCmdDraw(renderer, renderer->r, renderer->g, renderer->b, renderer->a) == 0) {
cmd = AllocateRenderCommand(renderer);
if (cmd != NULL) {
cmd->command = cmdtype;
cmd->data.draw.first = 0; /* render backend will fill this in. */
cmd->data.draw.count = 0; /* render backend will fill this in. */
cmd->data.draw.r = renderer->r;
cmd->data.draw.g = renderer->g;
cmd->data.draw.b = renderer->b;
cmd->data.draw.a = renderer->a;
cmd->data.draw.blend = renderer->blendMode;
cmd->data.draw.texture = NULL; /* no texture. */
}
}
return cmd;
}
static int
QueueCmdDrawPoints(SDL_Renderer *renderer, const SDL_FPoint * points, const int count)
{
SDL_RenderCommand *cmd = PrepQueueCmdDrawSolid(renderer, SDL_RENDERCMD_DRAW_POINTS);
int retval = -1;
if (cmd != NULL) {
retval = renderer->QueueDrawPoints(renderer, cmd, points, count);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
}
return retval;
}
static int
QueueCmdDrawLines(SDL_Renderer *renderer, const SDL_FPoint * points, const int count)
{
SDL_RenderCommand *cmd = PrepQueueCmdDrawSolid(renderer, SDL_RENDERCMD_DRAW_LINES);
int retval = -1;
if (cmd != NULL) {
retval = renderer->QueueDrawLines(renderer, cmd, points, count);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
}
return retval;
}
static int
QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect * rects, const int count)
{
SDL_RenderCommand *cmd = PrepQueueCmdDrawSolid(renderer, SDL_RENDERCMD_FILL_RECTS);
int retval = -1;
if (cmd != NULL) {
retval = renderer->QueueFillRects(renderer, cmd, rects, count);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
}
return retval;
}
static SDL_RenderCommand *
PrepQueueCmdDrawTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_RenderCommandType cmdtype)
{
/* !!! FIXME: drop this draw if viewport w or h is zero. */
SDL_RenderCommand *cmd = NULL;
if (PrepQueueCmdDraw(renderer, texture->r, texture->g, texture->b, texture->a) == 0) {
cmd = AllocateRenderCommand(renderer);
if (cmd != NULL) {
cmd->command = cmdtype;
cmd->data.draw.first = 0; /* render backend will fill this in. */
cmd->data.draw.count = 0; /* render backend will fill this in. */
cmd->data.draw.r = texture->r;
cmd->data.draw.g = texture->g;
cmd->data.draw.b = texture->b;
cmd->data.draw.a = texture->a;
cmd->data.draw.blend = texture->blendMode;
cmd->data.draw.texture = texture;
}
}
return cmd;
}
static int
QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
SDL_RenderCommand *cmd = PrepQueueCmdDrawTexture(renderer, texture, SDL_RENDERCMD_COPY);
int retval = -1;
if (cmd != NULL) {
retval = renderer->QueueCopy(renderer, cmd, texture, srcrect, dstrect);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
}
return retval;
}
static int
QueueCmdCopyEx(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)
{
SDL_RenderCommand *cmd = PrepQueueCmdDrawTexture(renderer, texture, SDL_RENDERCMD_COPY_EX);
int retval = -1;
SDL_assert(renderer->QueueCopyEx != NULL); /* should have caught at higher level. */
if (cmd != NULL) {
retval = renderer->QueueCopyEx(renderer, cmd, texture, srcquad, dstrect, angle, center, flip);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
}
return retval;
}
static int UpdateLogicalSize(SDL_Renderer *renderer);
int
SDL_GetNumRenderDrivers(void)
{
#if !SDL_RENDER_DISABLED
return SDL_arraysize(render_drivers);
#else
return 0;
#endif
}
int
SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
{
#if !SDL_RENDER_DISABLED
if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
return SDL_SetError("index must be in the range of 0 - %d",
SDL_GetNumRenderDrivers() - 1);
}
*info = render_drivers[index]->info;
return 0;
#else
return SDL_SetError("SDL not built with rendering support");
#endif
}
static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_Rect *viewport, SDL_FPoint *scale)
{
SDL_LockMutex(renderer->target_mutex);
*logical_w = renderer->target ? renderer->logical_w_backup : renderer->logical_w;
*logical_h = renderer->target ? renderer->logical_h_backup : renderer->logical_h;
*viewport = renderer->target ? renderer->viewport_backup : renderer->viewport;
*scale = renderer->target ? renderer->scale_backup : renderer->scale;
SDL_UnlockMutex(renderer->target_mutex);
}
static int SDLCALL
SDL_RendererEventWatch(void *userdata, SDL_Event *event)
{
SDL_Renderer *renderer = (SDL_Renderer *)userdata;
if (event->type == SDL_WINDOWEVENT) {
SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
if (window == renderer->window) {
if (renderer->WindowEvent) {
renderer->WindowEvent(renderer, &event->window);
}
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
/* Make sure we're operating on the default render target */
SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
if (saved_target) {
SDL_SetRenderTarget(renderer, NULL);
}
if (renderer->logical_w) {
UpdateLogicalSize(renderer);
} else {
/* Window was resized, reset viewport */
int w, h;
if (renderer->GetOutputSize) {
renderer->GetOutputSize(renderer, &w, &h);
} else {
SDL_GetWindowSize(renderer->window, &w, &h);
}
if (renderer->target) {
renderer->viewport_backup.x = 0;
renderer->viewport_backup.y = 0;
renderer->viewport_backup.w = w;
renderer->viewport_backup.h = h;
} else {
renderer->viewport.x = 0;
renderer->viewport.y = 0;
renderer->viewport.w = w;
renderer->viewport.h = h;
QueueCmdSetViewport(renderer);
FlushRenderCommandsIfNotBatching(renderer);
}
}
if (saved_target) {
SDL_SetRenderTarget(renderer, saved_target);
}
} else if (event->window.event == SDL_WINDOWEVENT_HIDDEN) {
renderer->hidden = SDL_TRUE;
} else if (event->window.event == SDL_WINDOWEVENT_SHOWN) {
if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)) {
renderer->hidden = SDL_FALSE;
}
} else if (event->window.event == SDL_WINDOWEVENT_MINIMIZED) {
renderer->hidden = SDL_TRUE;
} else if (event->window.event == SDL_WINDOWEVENT_RESTORED ||
event->window.event == SDL_WINDOWEVENT_MAXIMIZED) {
if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
renderer->hidden = SDL_FALSE;
}
}
}
} else if (event->type == SDL_MOUSEMOTION) {
SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID);
if (window == renderer->window) {
int logical_w, logical_h;
SDL_Rect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
event->motion.x -= (int)(viewport.x * renderer->dpi_scale.x);
event->motion.y -= (int)(viewport.y * renderer->dpi_scale.y);
event->motion.x = (int)(event->motion.x / (scale.x * renderer->dpi_scale.x));
event->motion.y = (int)(event->motion.y / (scale.y * renderer->dpi_scale.y));
if (event->motion.xrel > 0) {
event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
} else if (event->motion.xrel < 0) {
event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
}
if (event->motion.yrel > 0) {
event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
} else if (event->motion.yrel < 0) {
event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
}
}
}
} else if (event->type == SDL_MOUSEBUTTONDOWN ||
event->type == SDL_MOUSEBUTTONUP) {
SDL_Window *window = SDL_GetWindowFromID(event->button.windowID);
if (window == renderer->window) {
int logical_w, logical_h;
SDL_Rect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
event->button.x -= (int)(viewport.x * renderer->dpi_scale.x);
event->button.y -= (int)(viewport.y * renderer->dpi_scale.y);
event->button.x = (int)(event->button.x / (scale.x * renderer->dpi_scale.x));
event->button.y = (int)(event->button.y / (scale.y * renderer->dpi_scale.y));
}
}
} else if (event->type == SDL_FINGERDOWN ||
event->type == SDL_FINGERUP ||
event->type == SDL_FINGERMOTION) {
int logical_w, logical_h;
SDL_Rect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
int w = 1;
int h = 1;
SDL_GetRendererOutputSize(renderer, &w, &h);
event->tfinger.x *= (w - 1);
event->tfinger.y *= (h - 1);
event->tfinger.x -= (viewport.x * renderer->dpi_scale.x);
event->tfinger.y -= (viewport.y * renderer->dpi_scale.y);
event->tfinger.x = (event->tfinger.x / (scale.x * renderer->dpi_scale.x));
event->tfinger.y = (event->tfinger.y / (scale.y * renderer->dpi_scale.y));
if (logical_w > 1) {
event->tfinger.x = event->tfinger.x / (logical_w - 1);
} else {
event->tfinger.x = 0.5f;
}
if (logical_h > 1) {
event->tfinger.y = event->tfinger.y / (logical_h - 1);
} else {
event->tfinger.y = 0.5f;
}
}
}
return 0;
}
int
SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags,
SDL_Window **window, SDL_Renderer **renderer)
{
*window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
width, height, window_flags);
if (!*window) {
*renderer = NULL;
return -1;
}
*renderer = SDL_CreateRenderer(*window, -1, 0);
if (!*renderer) {
return -1;
}
return 0;
}
static SDL_INLINE
void VerifyDrawQueueFunctions(const SDL_Renderer *renderer)
{
/* all of these functions are required to be implemented, even as no-ops, so we don't
have to check that they aren't NULL over and over. */
SDL_assert(renderer->QueueSetViewport != NULL);
SDL_assert(renderer->QueueSetDrawColor != NULL);
SDL_assert(renderer->QueueDrawPoints != NULL);
SDL_assert(renderer->QueueDrawLines != NULL);
SDL_assert(renderer->QueueFillRects != NULL);
SDL_assert(renderer->QueueCopy != NULL);
SDL_assert(renderer->RunCommandQueue != NULL);
}
SDL_Renderer *
SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
{
#if !SDL_RENDER_DISABLED
SDL_Renderer *renderer = NULL;
int n = SDL_GetNumRenderDrivers();
SDL_bool batching = SDL_TRUE;
const char *hint;
#if defined(__ANDROID__)
Android_ActivityMutex_Lock_Running();
#endif
if (!window) {
SDL_SetError("Invalid window");
goto error;
}
if (SDL_GetRenderer(window)) {
SDL_SetError("Renderer already associated with window");
goto error;
}
if (SDL_GetHint(SDL_HINT_RENDER_VSYNC)) {
if (SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)) {
flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
}
if (index < 0) {
hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
if (hint) {
for (index = 0; index < n; ++index) {
const SDL_RenderDriver *driver = render_drivers[index];
if (SDL_strcasecmp(hint, driver->info.name) == 0) {
/* Create a new renderer instance */
renderer = driver->CreateRenderer(window, flags);
if (renderer) {
batching = SDL_FALSE;
}
break;
}
}
}
if (!renderer) {
for (index = 0; index < n; ++index) {
const SDL_RenderDriver *driver = render_drivers[index];
if ((driver->info.flags & flags) == flags) {
/* Create a new renderer instance */
renderer = driver->CreateRenderer(window, flags);
if (renderer) {
/* Yay, we got one! */
break;
}
}
}
}
if (index == n) {
SDL_SetError("Couldn't find matching render driver");
goto error;
}
} else {
if (index >= SDL_GetNumRenderDrivers()) {
SDL_SetError("index must be -1 or in the range of 0 - %d",
SDL_GetNumRenderDrivers() - 1);
goto error;
}
/* Create a new renderer instance */
renderer = render_drivers[index]->CreateRenderer(window, flags);
batching = SDL_FALSE;
}
if (!renderer) {
goto error;
}
VerifyDrawQueueFunctions(renderer);
/* let app/user override batching decisions. */
if (renderer->always_batch) {
batching = SDL_TRUE;
} else if (SDL_GetHint(SDL_HINT_RENDER_BATCHING)) {
batching = SDL_GetHintBoolean(SDL_HINT_RENDER_BATCHING, SDL_TRUE);
}
renderer->batching = batching;
renderer->magic = &renderer_magic;
renderer->window = window;
renderer->target_mutex = SDL_CreateMutex();
renderer->scale.x = 1.0f;
renderer->scale.y = 1.0f;
renderer->dpi_scale.x = 1.0f;
renderer->dpi_scale.y = 1.0f;
/* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */
renderer->render_command_generation = 1;
if (window && renderer->GetOutputSize) {
int window_w, window_h;
int output_w, output_h;
if (renderer->GetOutputSize(renderer, &output_w, &output_h) == 0) {
SDL_GetWindowSize(renderer->window, &window_w, &window_h);
renderer->dpi_scale.x = (float)window_w / output_w;
renderer->dpi_scale.y = (float)window_h / output_h;
}
}
if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {
renderer->hidden = SDL_TRUE;
} else {
renderer->hidden = SDL_FALSE;
}
SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer);
SDL_RenderSetViewport(renderer, NULL);
SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
"Created renderer: %s", renderer->info.name);
#if defined(__ANDROID__)
Android_ActivityMutex_Unlock();
#endif
return renderer;
error:
#if defined(__ANDROID__)
Android_ActivityMutex_Unlock();
#endif
return NULL;
#else
SDL_SetError("SDL not built with rendering support");
return NULL;
#endif
}
SDL_Renderer *
SDL_CreateSoftwareRenderer(SDL_Surface * surface)
{
#if !SDL_RENDER_DISABLED
SDL_Renderer *renderer;
renderer = SW_CreateRendererForSurface(surface);
if (renderer) {
VerifyDrawQueueFunctions(renderer);
renderer->magic = &renderer_magic;
renderer->target_mutex = SDL_CreateMutex();
renderer->scale.x = 1.0f;
renderer->scale.y = 1.0f;
/* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */
renderer->render_command_generation = 1;
SDL_RenderSetViewport(renderer, NULL);
}
return renderer;
#else
SDL_SetError("SDL not built with rendering support");
return NULL;
#endif /* !SDL_RENDER_DISABLED */
}
SDL_Renderer *
SDL_GetRenderer(SDL_Window * window)
{
return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA);
}
int
SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
{
CHECK_RENDERER_MAGIC(renderer, -1);
*info = renderer->info;
return 0;
}
int
SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
CHECK_RENDERER_MAGIC(renderer, -1);
if (renderer->target) {
return SDL_QueryTexture(renderer->target, NULL, NULL, w, h);
} else if (renderer->GetOutputSize) {
return renderer->GetOutputSize(renderer, w, h);
} else if (renderer->window) {
SDL_GetWindowSize(renderer->window, w, h);
return 0;
} else {
SDL_assert(0 && "This should never happen");
return SDL_SetError("Renderer doesn't support querying output size");
}
}
static SDL_bool
IsSupportedBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
{
switch (blendMode)
{
/* These are required to be supported by all renderers */
case SDL_BLENDMODE_NONE:
case SDL_BLENDMODE_BLEND:
case SDL_BLENDMODE_ADD:
case SDL_BLENDMODE_MOD:
return SDL_TRUE;
default:
return renderer->SupportsBlendMode && renderer->SupportsBlendMode(renderer, blendMode);
}
}
static SDL_bool
IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
{
Uint32 i;
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
if (renderer->info.texture_formats[i] == format) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static Uint32
GetClosestSupportedFormat(SDL_Renderer * renderer, Uint32 format)
{
Uint32 i;
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
/* Look for an exact match */
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
if (renderer->info.texture_formats[i] == format) {
return renderer->info.texture_formats[i];
}
}
} else {
SDL_bool hasAlpha = SDL_ISPIXELFORMAT_ALPHA(format);
/* We just want to match the first format that has the same channels */
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == hasAlpha) {
return renderer->info.texture_formats[i];
}
}
}
return renderer->info.texture_formats[0];
}
static SDL_ScaleMode SDL_GetScaleMode(void)
{
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
if (!hint || SDL_strcasecmp(hint, "nearest") == 0) {
return SDL_ScaleModeNearest;
} else if (SDL_strcasecmp(hint, "linear") == 0) {
return SDL_ScaleModeLinear;
} else if (SDL_strcasecmp(hint, "best") == 0) {
return SDL_ScaleModeBest;
} else {
return (SDL_ScaleMode)SDL_atoi(hint);
}
}
SDL_Texture *
SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
{
SDL_Texture *texture;
CHECK_RENDERER_MAGIC(renderer, NULL);
if (!format) {
format = renderer->info.texture_formats[0];
}
if (SDL_BYTESPERPIXEL(format) == 0) {
SDL_SetError("Invalid texture format");
return NULL;
}
if (SDL_ISPIXELFORMAT_INDEXED(format)) {
SDL_SetError("Palettized textures are not supported");
return NULL;
}
if (w <= 0 || h <= 0) {
SDL_SetError("Texture dimensions can't be 0");
return NULL;
}
if ((renderer->info.max_texture_width && w > renderer->info.max_texture_width) ||
(renderer->info.max_texture_height && h > renderer->info.max_texture_height)) {
SDL_SetError("Texture dimensions are limited to %dx%d", renderer->info.max_texture_width, renderer->info.max_texture_height);
return NULL;
}
texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
if (!texture) {
SDL_OutOfMemory();
return NULL;
}
texture->magic = &texture_magic;
texture->format = format;
texture->access = access;
texture->w = w;
texture->h = h;
texture->r = 255;
texture->g = 255;
texture->b = 255;
texture->a = 255;
texture->scaleMode = SDL_GetScaleMode();
texture->renderer = renderer;
texture->next = renderer->textures;
if (renderer->textures) {
renderer->textures->prev = texture;
}
renderer->textures = texture;
if (IsSupportedFormat(renderer, format)) {
if (renderer->CreateTexture(renderer, texture) < 0) {
SDL_DestroyTexture(texture);
return NULL;
}
} else {
texture->native = SDL_CreateTexture(renderer,
GetClosestSupportedFormat(renderer, format),
access, w, h);
if (!texture->native) {
SDL_DestroyTexture(texture);
return NULL;
}
/* Swap textures to have texture before texture->native in the list */
texture->native->next = texture->next;
if (texture->native->next) {
texture->native->next->prev = texture->native;
}
texture->prev = texture->native->prev;
if (texture->prev) {
texture->prev->next = texture;
}
texture->native->prev = texture;
texture->next = texture->native;
renderer->textures = texture;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
texture->yuv = SDL_SW_CreateYUVTexture(format, w, h);
if (!texture->yuv) {
SDL_DestroyTexture(texture);
return NULL;
}
} else if (access == SDL_TEXTUREACCESS_STREAMING) {
/* The pitch is 4 byte aligned */
texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
texture->pixels = SDL_calloc(1, texture->pitch * h);
if (!texture->pixels) {
SDL_DestroyTexture(texture);
return NULL;
}
}
}
return texture;
}
SDL_Texture *
SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
{
const SDL_PixelFormat *fmt;
SDL_bool needAlpha;
SDL_bool direct_update;
int i;
Uint32 format = SDL_PIXELFORMAT_UNKNOWN;
SDL_Texture *texture;
CHECK_RENDERER_MAGIC(renderer, NULL);
if (!surface) {
SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
return NULL;
}
/* See what the best texture format is */
fmt = surface->format;
if (fmt->Amask || SDL_HasColorKey(surface)) {
needAlpha = SDL_TRUE;
} else {
needAlpha = SDL_FALSE;
}
/* If Palette contains alpha values, promotes to alpha format */
if (fmt->palette) {
for (i = 0; i < fmt->palette->ncolors; i++) {
Uint8 alpha_value = fmt->palette->colors[i].a;
if (alpha_value != 0 || alpha_value != SDL_ALPHA_OPAQUE) {
needAlpha = SDL_TRUE;
break;
}
}
}
/* Try to have the best pixel format for the texture */
/* No alpha, but a colorkey => promote to alpha */
if (!fmt->Amask && SDL_HasColorKey(surface)) {
if (fmt->format == SDL_PIXELFORMAT_RGB888) {
for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ARGB8888) {
format = SDL_PIXELFORMAT_ARGB8888;
break;
}
}
} else if (fmt->format == SDL_PIXELFORMAT_BGR888) {
for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ABGR8888) {
format = SDL_PIXELFORMAT_ABGR8888;
break;
}
}
}
} else {
/* Exact match would be fine */
for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
if (renderer->info.texture_formats[i] == fmt->format) {
format = fmt->format;
break;
}
}
}
/* Fallback, choose a valid pixel format */
if (format == SDL_PIXELFORMAT_UNKNOWN) {
format = renderer->info.texture_formats[0];
for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
format = renderer->info.texture_formats[i];
break;
}
}
}
texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
surface->w, surface->h);
if (!texture) {
return NULL;
}
if (format == surface->format->format) {
if (surface->format->Amask && SDL_HasColorKey(surface)) {
/* Surface and Renderer formats are identicals.
* Intermediate conversion is needed to convert color key to alpha (SDL_ConvertColorkeyToAlpha()). */
direct_update = SDL_FALSE;
} else {
/* Update Texture directly */
direct_update = SDL_TRUE;
}
} else {
/* Surface and Renderer formats are differents, it needs an intermediate conversion. */
direct_update = SDL_FALSE;
}
if (direct_update) {
if (SDL_MUSTLOCK(surface)) {
SDL_LockSurface(surface);
SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
SDL_UnlockSurface(surface);
} else {
SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
}
} else {
SDL_PixelFormat *dst_fmt;
SDL_Surface *temp = NULL;
/* Set up a destination surface for the texture update */
dst_fmt = SDL_AllocFormat(format);
if (!dst_fmt) {
SDL_DestroyTexture(texture);
return NULL;
}
temp = SDL_ConvertSurface(surface, dst_fmt, 0);
SDL_FreeFormat(dst_fmt);
if (temp) {
SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
SDL_FreeSurface(temp);
} else {
SDL_DestroyTexture(texture);
return NULL;
}
}
{
Uint8 r, g, b, a;
SDL_BlendMode blendMode;
SDL_GetSurfaceColorMod(surface, &r, &g, &b);
SDL_SetTextureColorMod(texture, r, g, b);
SDL_GetSurfaceAlphaMod(surface, &a);
SDL_SetTextureAlphaMod(texture, a);
if (SDL_HasColorKey(surface)) {
/* We converted to a texture with alpha format */
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
} else {
SDL_GetSurfaceBlendMode(surface, &blendMode);
SDL_SetTextureBlendMode(texture, blendMode);
}
}
return texture;
}
int
SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access,
int *w, int *h)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (format) {
*format = texture->format;
}
if (access) {
*access = texture->access;
}
if (w) {
*w = texture->w;
}
if (h) {
*h = texture->h;
}
return 0;
}
int
SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (r < 255 || g < 255 || b < 255) {
texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
} else {
texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
}
texture->r = r;
texture->g = g;
texture->b = b;
if (texture->native) {
return SDL_SetTextureColorMod(texture->native, r, g, b);
}
return 0;
}
int
SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g,
Uint8 * b)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (r) {
*r = texture->r;
}
if (g) {
*g = texture->g;
}
if (b) {
*b = texture->b;
}
return 0;
}
int
SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (alpha < 255) {
texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
} else {
texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
}
texture->a = alpha;
if (texture->native) {
return SDL_SetTextureAlphaMod(texture->native, alpha);
}
return 0;
}
int
SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (alpha) {
*alpha = texture->a;
}
return 0;
}
int
SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
if (!IsSupportedBlendMode(renderer, blendMode)) {
return SDL_Unsupported();
}
texture->blendMode = blendMode;
if (texture->native) {
return SDL_SetTextureBlendMode(texture->native, blendMode);
}
return 0;
}
int
SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (blendMode) {
*blendMode = texture->blendMode;
}
return 0;
}
static int
SDL_UpdateTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
const void *pixels, int pitch)
{
SDL_Texture *native = texture->native;
SDL_Rect full_rect;
if (SDL_SW_UpdateYUVTexture(texture->yuv, rect, pixels, pitch) < 0) {
return -1;
}
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
/* We can lock the texture and copy to it */
void *native_pixels = NULL;
int native_pitch = 0;
if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
return -1;
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, native_pixels, native_pitch);
SDL_UnlockTexture(native);
} else {
/* Use a temporary buffer for updating */
const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
const size_t alloclen = rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (!temp_pixels) {
return SDL_OutOfMemory();
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, temp_pixels, temp_pitch);
SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
SDL_free(temp_pixels);
}
}
return 0;
}
static int
SDL_UpdateTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
const void *pixels, int pitch)
{
SDL_Texture *native = texture->native;
if (!rect->w || !rect->h) {
return 0; /* nothing to do. */
}
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
/* We can lock the texture and copy to it */
void *native_pixels = NULL;
int native_pitch = 0;
if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
return -1;
}
SDL_ConvertPixels(rect->w, rect->h,
texture->format, pixels, pitch,
native->format, native_pixels, native_pitch);
SDL_UnlockTexture(native);
} else {
/* Use a temporary buffer for updating */
const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
const size_t alloclen = rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (!temp_pixels) {
return SDL_OutOfMemory();
}
SDL_ConvertPixels(rect->w, rect->h,
texture->format, pixels, pitch,
native->format, temp_pixels, temp_pitch);
SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
SDL_free(temp_pixels);
}
}
return 0;
}
int
SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
const void *pixels, int pitch)
{
SDL_Rect full_rect;
CHECK_TEXTURE_MAGIC(texture, -1);
if (!pixels) {
return SDL_InvalidParamError("pixels");
}
if (!pitch) {
return SDL_InvalidParamError("pitch");
}
if (!rect) {
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
}
if ((rect->w == 0) || (rect->h == 0)) {
return 0; /* nothing to do. */
} else if (texture->yuv) {
return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);
} else if (texture->native) {
return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
} else {
SDL_Renderer *renderer = texture->renderer;
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
return -1;
}
return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
}
}
static int
SDL_UpdateTextureYUVPlanar(SDL_Texture * texture, const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch)
{
SDL_Texture *native = texture->native;
SDL_Rect full_rect;
if (SDL_SW_UpdateYUVTexturePlanar(texture->yuv, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch) < 0) {
return -1;
}
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
if (!rect->w || !rect->h) {
return 0; /* nothing to do. */
}
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
/* We can lock the texture and copy to it */
void *native_pixels = NULL;
int native_pitch = 0;
if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
return -1;
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, native_pixels, native_pitch);
SDL_UnlockTexture(native);
} else {
/* Use a temporary buffer for updating */
const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
const size_t alloclen = rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (!temp_pixels) {
return SDL_OutOfMemory();
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, temp_pixels, temp_pitch);
SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
SDL_free(temp_pixels);
}
}
return 0;
}
int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch)
{
SDL_Renderer *renderer;
SDL_Rect full_rect;
CHECK_TEXTURE_MAGIC(texture, -1);
if (!Yplane) {
return SDL_InvalidParamError("Yplane");
}
if (!Ypitch) {
return SDL_InvalidParamError("Ypitch");
}
if (!Uplane) {
return SDL_InvalidParamError("Uplane");
}
if (!Upitch) {
return SDL_InvalidParamError("Upitch");
}
if (!Vplane) {
return SDL_InvalidParamError("Vplane");
}
if (!Vpitch) {
return SDL_InvalidParamError("Vpitch");
}
if (texture->format != SDL_PIXELFORMAT_YV12 &&
texture->format != SDL_PIXELFORMAT_IYUV) {
return SDL_SetError("Texture format must by YV12 or IYUV");
}
if (!rect) {
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
}
if (!rect->w || !rect->h) {
return 0; /* nothing to do. */
}
if (texture->yuv) {
return SDL_UpdateTextureYUVPlanar(texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
} else {
SDL_assert(!texture->native);
renderer = texture->renderer;
SDL_assert(renderer->UpdateTextureYUV);
if (renderer->UpdateTextureYUV) {
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
return -1;
}
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
} else {
return SDL_Unsupported();
}
}
}
static int
SDL_LockTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
void **pixels, int *pitch)
{
return SDL_SW_LockYUVTexture(texture->yuv, rect, pixels, pitch);
}
static int
SDL_LockTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
void **pixels, int *pitch)
{
texture->locked_rect = *rect;
*pixels = (void *) ((Uint8 *) texture->pixels +
rect->y * texture->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = texture->pitch;
return 0;
}
int
SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
void **pixels, int *pitch)
{
SDL_Rect full_rect;
CHECK_TEXTURE_MAGIC(texture, -1);
if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
return SDL_SetError("SDL_LockTexture(): texture must be streaming");
}
if (!rect) {
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
}
if (texture->yuv) {
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
return -1;
}
return SDL_LockTextureYUV(texture, rect, pixels, pitch);
} else if (texture->native) {
/* Calls a real SDL_LockTexture/SDL_UnlockTexture on unlock, flushing then. */
return SDL_LockTextureNative(texture, rect, pixels, pitch);
} else {
SDL_Renderer *renderer = texture->renderer;
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
return -1;
}
return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
}
}
static void
SDL_UnlockTextureYUV(SDL_Texture * texture)
{
SDL_Texture *native = texture->native;
void *native_pixels = NULL;
int native_pitch = 0;
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = texture->w;
rect.h = texture->h;
if (SDL_LockTexture(native, &rect, &native_pixels, &native_pitch) < 0) {
return;
}
SDL_SW_CopyYUVToRGB(texture->yuv, &rect, native->format,
rect.w, rect.h, native_pixels, native_pitch);
SDL_UnlockTexture(native);
}
static void
SDL_UnlockTextureNative(SDL_Texture * texture)
{
SDL_Texture *native = texture->native;
void *native_pixels = NULL;
int native_pitch = 0;
const SDL_Rect *rect = &texture->locked_rect;
const void* pixels = (void *) ((Uint8 *) texture->pixels +
rect->y * texture->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
int pitch = texture->pitch;
if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
return;
}
SDL_ConvertPixels(rect->w, rect->h,
texture->format, pixels, pitch,
native->format, native_pixels, native_pitch);
SDL_UnlockTexture(native);
}
void
SDL_UnlockTexture(SDL_Texture * texture)
{
CHECK_TEXTURE_MAGIC(texture, );
if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
return;
}
if (texture->yuv) {
SDL_UnlockTextureYUV(texture);
} else if (texture->native) {
SDL_UnlockTextureNative(texture);
} else {
SDL_Renderer *renderer = texture->renderer;
renderer->UnlockTexture(renderer, texture);
}
}
SDL_bool
SDL_RenderTargetSupported(SDL_Renderer *renderer)
{
if (!renderer || !renderer->SetRenderTarget) {
return SDL_FALSE;
}
return (renderer->info.flags & SDL_RENDERER_TARGETTEXTURE) != 0;
}
int
SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
if (!SDL_RenderTargetSupported(renderer)) {
return SDL_Unsupported();
}
if (texture == renderer->target) {
/* Nothing to do! */
return 0;
}
FlushRenderCommands(renderer); /* time to send everything to the GPU! */
/* texture == NULL is valid and means reset the target to the window */
if (texture) {
CHECK_TEXTURE_MAGIC(texture, -1);
if (renderer != texture->renderer) {
return SDL_SetError("Texture was not created with this renderer");
}
if (texture->access != SDL_TEXTUREACCESS_TARGET) {
return SDL_SetError("Texture not created with SDL_TEXTUREACCESS_TARGET");
}
if (texture->native) {
/* Always render to the native texture */
texture = texture->native;
}
}
SDL_LockMutex(renderer->target_mutex);
if (texture && !renderer->target) {
/* Make a backup of the viewport */
renderer->viewport_backup = renderer->viewport;
renderer->clip_rect_backup = renderer->clip_rect;
renderer->clipping_enabled_backup = renderer->clipping_enabled;
renderer->scale_backup = renderer->scale;
renderer->logical_w_backup = renderer->logical_w;
renderer->logical_h_backup = renderer->logical_h;
}
renderer->target = texture;
if (renderer->SetRenderTarget(renderer, texture) < 0) {
SDL_UnlockMutex(renderer->target_mutex);
return -1;
}
if (texture) {
renderer->viewport.x = 0;
renderer->viewport.y = 0;
renderer->viewport.w = texture->w;
renderer->viewport.h = texture->h;
SDL_zero(renderer->clip_rect);
renderer->clipping_enabled = SDL_FALSE;
renderer->scale.x = 1.0f;
renderer->scale.y = 1.0f;
renderer->logical_w = texture->w;
renderer->logical_h = texture->h;
} else {
renderer->viewport = renderer->viewport_backup;
renderer->clip_rect = renderer->clip_rect_backup;
renderer->clipping_enabled = renderer->clipping_enabled_backup;
renderer->scale = renderer->scale_backup;
renderer->logical_w = renderer->logical_w_backup;
renderer->logical_h = renderer->logical_h_backup;
}
SDL_UnlockMutex(renderer->target_mutex);
if (QueueCmdSetViewport(renderer) < 0) {
return -1;
}
if (QueueCmdSetClipRect(renderer) < 0) {
return -1;
}
/* All set! */
return FlushRenderCommandsIfNotBatching(renderer);
}
SDL_Texture *
SDL_GetRenderTarget(SDL_Renderer *renderer)
{
return renderer->target;
}
static int
UpdateLogicalSize(SDL_Renderer *renderer)
{
int w = 1, h = 1;
float want_aspect;
float real_aspect;
float scale;
SDL_Rect viewport;
/* 0 is for letterbox, 1 is for overscan */
int scale_policy = 0;
const char *hint;
if (!renderer->logical_w || !renderer->logical_h) {
return 0;
}
if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
return -1;
}
hint = SDL_GetHint(SDL_HINT_RENDER_LOGICAL_SIZE_MODE);
if (hint && (*hint == '1' || SDL_strcasecmp(hint, "overscan") == 0)) {
#if SDL_VIDEO_RENDER_D3D
SDL_bool overscan_supported = SDL_TRUE;
/* Unfortunately, Direct3D 9 doesn't support negative viewport numbers
which the overscan implementation relies on.
*/
if (SDL_strcasecmp(SDL_GetCurrentVideoDriver(), "direct3d") == 0) {
overscan_supported = SDL_FALSE;
}
if (overscan_supported) {
scale_policy = 1;
}
#else
scale_policy = 1;
#endif
}
want_aspect = (float)renderer->logical_w / renderer->logical_h;
real_aspect = (float)w / h;
/* Clear the scale because we're setting viewport in output coordinates */
SDL_RenderSetScale(renderer, 1.0f, 1.0f);
if (renderer->integer_scale) {
if (want_aspect > real_aspect) {
scale = (float)(w / renderer->logical_w);
} else {
scale = (float)(h / renderer->logical_h);
}
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
viewport.x = (w - viewport.w) / 2;
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
viewport.y = (h - viewport.h) / 2;
SDL_RenderSetViewport(renderer, &viewport);
} else if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
/* The aspect ratios are the same, just scale appropriately */
scale = (float)w / renderer->logical_w;
SDL_RenderSetViewport(renderer, NULL);
} else if (want_aspect > real_aspect) {
if (scale_policy == 1) {
/* We want a wider aspect ratio than is available -
zoom so logical height matches the real height
and the width will grow off the screen
*/
scale = (float)h / renderer->logical_h;
viewport.y = 0;
viewport.h = h;
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
viewport.x = (w - viewport.w) / 2;
SDL_RenderSetViewport(renderer, &viewport);
} else {
/* We want a wider aspect ratio than is available - letterbox it */
scale = (float)w / renderer->logical_w;
viewport.x = 0;
viewport.w = w;
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
viewport.y = (h - viewport.h) / 2;
SDL_RenderSetViewport(renderer, &viewport);
}
} else {
if (scale_policy == 1) {
/* We want a narrower aspect ratio than is available -
zoom so logical width matches the real width
and the height will grow off the screen
*/
scale = (float)w / renderer->logical_w;
viewport.x = 0;
viewport.w = w;
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
viewport.y = (h - viewport.h) / 2;
SDL_RenderSetViewport(renderer, &viewport);
} else {
/* We want a narrower aspect ratio than is available - use side-bars */
scale = (float)h / renderer->logical_h;
viewport.y = 0;
viewport.h = h;
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
viewport.x = (w - viewport.w) / 2;
SDL_RenderSetViewport(renderer, &viewport);
}
}
/* Set the new scale */
SDL_RenderSetScale(renderer, scale, scale);
return 0;
}
int
SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h)
{
CHECK_RENDERER_MAGIC(renderer, -1);
if (!w || !h) {
/* Clear any previous logical resolution */
renderer->logical_w = 0;
renderer->logical_h = 0;
SDL_RenderSetViewport(renderer, NULL);
SDL_RenderSetScale(renderer, 1.0f, 1.0f);
return 0;
}
renderer->logical_w = w;
renderer->logical_h = h;
return UpdateLogicalSize(renderer);
}
void
SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h)
{
CHECK_RENDERER_MAGIC(renderer, );
if (w) {
*w = renderer->logical_w;
}
if (h) {
*h = renderer->logical_h;
}
}
int
SDL_RenderSetIntegerScale(SDL_Renderer * renderer, SDL_bool enable)
{
CHECK_RENDERER_MAGIC(renderer, -1);
renderer->integer_scale = enable;
return UpdateLogicalSize(renderer);
}
SDL_bool
SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, SDL_FALSE);
return renderer->integer_scale;
}
int
SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
{
int retval;
CHECK_RENDERER_MAGIC(renderer, -1);
if (rect) {
renderer->viewport.x = (int)SDL_floor(rect->x * renderer->scale.x);
renderer->viewport.y = (int)SDL_floor(rect->y * renderer->scale.y);
renderer->viewport.w = (int)SDL_ceil(rect->w * renderer->scale.x);
renderer->viewport.h = (int)SDL_ceil(rect->h * renderer->scale.y);
} else {
renderer->viewport.x = 0;
renderer->viewport.y = 0;
if (SDL_GetRendererOutputSize(renderer, &renderer->viewport.w, &renderer->viewport.h) < 0) {
return -1;
}
}
retval = QueueCmdSetViewport(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
void
SDL_RenderGetViewport(SDL_Renderer * renderer, SDL_Rect * rect)
{
CHECK_RENDERER_MAGIC(renderer, );
if (rect) {
rect->x = (int)(renderer->viewport.x / renderer->scale.x);
rect->y = (int)(renderer->viewport.y / renderer->scale.y);
rect->w = (int)(renderer->viewport.w / renderer->scale.x);
rect->h = (int)(renderer->viewport.h / renderer->scale.y);
}
}
int
SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
{
int retval;
CHECK_RENDERER_MAGIC(renderer, -1)
if (rect) {
renderer->clipping_enabled = SDL_TRUE;
renderer->clip_rect.x = (int)SDL_floor(rect->x * renderer->scale.x);
renderer->clip_rect.y = (int)SDL_floor(rect->y * renderer->scale.y);
renderer->clip_rect.w = (int)SDL_ceil(rect->w * renderer->scale.x);
renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y);
} else {
renderer->clipping_enabled = SDL_FALSE;
SDL_zero(renderer->clip_rect);
}
retval = QueueCmdSetClipRect(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
void
SDL_RenderGetClipRect(SDL_Renderer * renderer, SDL_Rect * rect)
{
CHECK_RENDERER_MAGIC(renderer, )
if (rect) {
rect->x = (int)(renderer->clip_rect.x / renderer->scale.x);
rect->y = (int)(renderer->clip_rect.y / renderer->scale.y);
rect->w = (int)(renderer->clip_rect.w / renderer->scale.x);
rect->h = (int)(renderer->clip_rect.h / renderer->scale.y);
}
}
SDL_bool
SDL_RenderIsClipEnabled(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, SDL_FALSE)
return renderer->clipping_enabled;
}
int
SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
{
CHECK_RENDERER_MAGIC(renderer, -1);
renderer->scale.x = scaleX;
renderer->scale.y = scaleY;
return 0;
}
void
SDL_RenderGetScale(SDL_Renderer * renderer, float *scaleX, float *scaleY)
{
CHECK_RENDERER_MAGIC(renderer, );
if (scaleX) {
*scaleX = renderer->scale.x;
}
if (scaleY) {
*scaleY = renderer->scale.y;
}
}
int
SDL_SetRenderDrawColor(SDL_Renderer * renderer,
Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
CHECK_RENDERER_MAGIC(renderer, -1);
renderer->r = r;
renderer->g = g;
renderer->b = b;
renderer->a = a;
return 0;
}
int
SDL_GetRenderDrawColor(SDL_Renderer * renderer,
Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
{
CHECK_RENDERER_MAGIC(renderer, -1);
if (r) {
*r = renderer->r;
}
if (g) {
*g = renderer->g;
}
if (b) {
*b = renderer->b;
}
if (a) {
*a = renderer->a;
}
return 0;
}
int
SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
{
CHECK_RENDERER_MAGIC(renderer, -1);
if (!IsSupportedBlendMode(renderer, blendMode)) {
return SDL_Unsupported();
}
renderer->blendMode = blendMode;
return 0;
}
int
SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode *blendMode)
{
CHECK_RENDERER_MAGIC(renderer, -1);
*blendMode = renderer->blendMode;
return 0;
}
int
SDL_RenderClear(SDL_Renderer * renderer)
{
int retval;
CHECK_RENDERER_MAGIC(renderer, -1);
retval = QueueCmdClear(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
/* !!! FIXME: delete all the duplicate code for the integer versions in 2.1,
!!! FIXME: making the floating point versions the only available APIs. */
int
SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
{
SDL_FPoint fpoint;
fpoint.x = (float) x;
fpoint.y = (float) y;
return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
}
int
SDL_RenderDrawPointF(SDL_Renderer * renderer, float x, float y)
{
SDL_FPoint fpoint;
fpoint.x = x;
fpoint.y = y;
return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
}
static int
RenderDrawPointsWithRects(SDL_Renderer * renderer,
const SDL_Point * points, const int count)
{
int retval = -1;
SDL_bool isstack;
SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
int i;
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
frects[i].x = points[i].x * renderer->scale.x;
frects[i].y = points[i].y * renderer->scale.y;
frects[i].w = renderer->scale.x;
frects[i].h = renderer->scale.y;
}
retval = QueueCmdFillRects(renderer, frects, count);
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawPoints(SDL_Renderer * renderer,
const SDL_Point * points, int count)
{
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!points) {
return SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
return RenderDrawPointsWithRects(renderer, points, count);
}
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
fpoints[i].x = points[i].x * renderer->scale.x;
fpoints[i].y = points[i].y * renderer->scale.y;
}
retval = QueueCmdDrawPoints(renderer, fpoints, count);
SDL_small_free(fpoints, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
static int
RenderDrawPointsWithRectsF(SDL_Renderer * renderer,
const SDL_FPoint * fpoints, const int count)
{
int retval = -1;
SDL_bool isstack;
SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
int i;
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
frects[i].x = fpoints[i].x * renderer->scale.x;
frects[i].y = fpoints[i].y * renderer->scale.y;
frects[i].w = renderer->scale.x;
frects[i].h = renderer->scale.y;
}
retval = QueueCmdFillRects(renderer, frects, count);
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawPointsF(SDL_Renderer * renderer,
const SDL_FPoint * points, int count)
{
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!points) {
return SDL_SetError("SDL_RenderDrawFPoints(): Passed NULL points");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
return RenderDrawPointsWithRectsF(renderer, points, count);
}
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
fpoints[i].x = points[i].x * renderer->scale.x;
fpoints[i].y = points[i].y * renderer->scale.y;
}
retval = QueueCmdDrawPoints(renderer, fpoints, count);
SDL_small_free(fpoints, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
{
SDL_FPoint points[2];
points[0].x = (float) x1;
points[0].y = (float) y1;
points[1].x = (float) x2;
points[1].y = (float) y2;
return SDL_RenderDrawLinesF(renderer, points, 2);
}
int
SDL_RenderDrawLineF(SDL_Renderer * renderer, float x1, float y1, float x2, float y2)
{
SDL_FPoint points[2];
points[0].x = x1;
points[0].y = y1;
points[1].x = x2;
points[1].y = y2;
return SDL_RenderDrawLinesF(renderer, points, 2);
}
static int
RenderDrawLinesWithRects(SDL_Renderer * renderer,
const SDL_Point * points, const int count)
{
SDL_FRect *frect;
SDL_FRect *frects;
SDL_FPoint fpoints[2];
int i, nrects = 0;
int retval = 0;
SDL_bool isstack;
frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count-1; ++i) {
if (points[i].x == points[i+1].x) {
const int minY = SDL_min(points[i].y, points[i+1].y);
const int maxY = SDL_max(points[i].y, points[i+1].y);
frect = &frects[nrects++];
frect->x = points[i].x * renderer->scale.x;
frect->y = minY * renderer->scale.y;
frect->w = renderer->scale.x;
frect->h = (maxY - minY + 1) * renderer->scale.y;
} else if (points[i].y == points[i+1].y) {
const int minX = SDL_min(points[i].x, points[i+1].x);
const int maxX = SDL_max(points[i].x, points[i+1].x);
frect = &frects[nrects++];
frect->x = minX * renderer->scale.x;
frect->y = points[i].y * renderer->scale.y;
frect->w = (maxX - minX + 1) * renderer->scale.x;
frect->h = renderer->scale.y;
} else {
/* FIXME: We can't use a rect for this line... */
fpoints[0].x = points[i].x * renderer->scale.x;
fpoints[0].y = points[i].y * renderer->scale.y;
fpoints[1].x = points[i+1].x * renderer->scale.x;
fpoints[1].y = points[i+1].y * renderer->scale.y;
retval += QueueCmdDrawLines(renderer, fpoints, 2);
}
}
retval += QueueCmdFillRects(renderer, frects, nrects);
SDL_small_free(frects, isstack);
if (retval < 0) {
retval = -1;
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
static int
RenderDrawLinesWithRectsF(SDL_Renderer * renderer,
const SDL_FPoint * points, const int count)
{
SDL_FRect *frect;
SDL_FRect *frects;
SDL_FPoint fpoints[2];
int i, nrects = 0;
int retval = 0;
SDL_bool isstack;
frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count-1; ++i) {
if (points[i].x == points[i+1].x) {
const int minY = (int)SDL_min(points[i].y, points[i+1].y);
const int maxY = (int)SDL_max(points[i].y, points[i+1].y);
frect = &frects[nrects++];
frect->x = points[i].x * renderer->scale.x;
frect->y = minY * renderer->scale.y;
frect->w = renderer->scale.x;
frect->h = (maxY - minY + 1) * renderer->scale.y;
} else if (points[i].y == points[i+1].y) {
const int minX = (int)SDL_min(points[i].x, points[i+1].x);
const int maxX = (int)SDL_max(points[i].x, points[i+1].x);
frect = &frects[nrects++];
frect->x = minX * renderer->scale.x;
frect->y = points[i].y * renderer->scale.y;
frect->w = (maxX - minX + 1) * renderer->scale.x;
frect->h = renderer->scale.y;
} else {
/* FIXME: We can't use a rect for this line... */
fpoints[0].x = points[i].x * renderer->scale.x;
fpoints[0].y = points[i].y * renderer->scale.y;
fpoints[1].x = points[i+1].x * renderer->scale.x;
fpoints[1].y = points[i+1].y * renderer->scale.y;
retval += QueueCmdDrawLines(renderer, fpoints, 2);
}
}
retval += QueueCmdFillRects(renderer, frects, nrects);
SDL_small_free(frects, isstack);
if (retval < 0) {
retval = -1;
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawLines(SDL_Renderer * renderer,
const SDL_Point * points, int count)
{
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!points) {
return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
}
if (count < 2) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
return RenderDrawLinesWithRects(renderer, points, count);
}
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
fpoints[i].x = points[i].x * renderer->scale.x;
fpoints[i].y = points[i].y * renderer->scale.y;
}
retval = QueueCmdDrawLines(renderer, fpoints, count);
SDL_small_free(fpoints, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawLinesF(SDL_Renderer * renderer,
const SDL_FPoint * points, int count)
{
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!points) {
return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
}
if (count < 2) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
return RenderDrawLinesWithRectsF(renderer, points, count);
}
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
fpoints[i].x = points[i].x * renderer->scale.x;
fpoints[i].y = points[i].y * renderer->scale.y;
}
retval = QueueCmdDrawLines(renderer, fpoints, count);
SDL_small_free(fpoints, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
{
SDL_FRect frect;
SDL_FRect *prect = NULL;
if (rect) {
frect.x = (float) rect->x;
frect.y = (float) rect->y;
frect.w = (float) rect->w;
frect.h = (float) rect->h;
prect = &frect;
}
return SDL_RenderDrawRectF(renderer, prect);
}
int
SDL_RenderDrawRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
{
SDL_FRect frect;
SDL_FPoint points[5];
CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */
if (!rect) {
SDL_Rect r;
SDL_RenderGetViewport(renderer, &r);
frect.x = 0.0f;
frect.y = 0.0f;
frect.w = (float) r.w;
frect.h = (float) r.h;
rect = &frect;
}
points[0].x = rect->x;
points[0].y = rect->y;
points[1].x = rect->x+rect->w-1;
points[1].y = rect->y;
points[2].x = rect->x+rect->w-1;
points[2].y = rect->y+rect->h-1;
points[3].x = rect->x;
points[3].y = rect->y+rect->h-1;
points[4].x = rect->x;
points[4].y = rect->y;
return SDL_RenderDrawLinesF(renderer, points, 5);
}
int
SDL_RenderDrawRects(SDL_Renderer * renderer,
const SDL_Rect * rects, int count)
{
int i;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!rects) {
return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
for (i = 0; i < count; ++i) {
if (SDL_RenderDrawRect(renderer, &rects[i]) < 0) {
return -1;
}
}
return 0;
}
int
SDL_RenderDrawRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects, int count)
{
int i;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!rects) {
return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
for (i = 0; i < count; ++i) {
if (SDL_RenderDrawRectF(renderer, &rects[i]) < 0) {
return -1;
}
}
return 0;
}
int
SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
{
SDL_FRect frect;
CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */
if (rect) {
frect.x = (float) rect->x;
frect.y = (float) rect->y;
frect.w = (float) rect->w;
frect.h = (float) rect->h;
} else {
SDL_Rect r;
SDL_zero(r);
SDL_RenderGetViewport(renderer, &r);
frect.x = 0.0f;
frect.y = 0.0f;
frect.w = (float) r.w;
frect.h = (float) r.h;
}
return SDL_RenderFillRectsF(renderer, &frect, 1);
}
int
SDL_RenderFillRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
{
SDL_FRect frect;
CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */
if (!rect) {
SDL_Rect r;
SDL_zero(r);
SDL_RenderGetViewport(renderer, &r);
frect.x = 0.0f;
frect.y = 0.0f;
frect.w = (float) r.w;
frect.h = (float) r.h;
rect = &frect;
}
return SDL_RenderFillRectsF(renderer, rect, 1);
}
int
SDL_RenderFillRects(SDL_Renderer * renderer,
const SDL_Rect * rects, int count)
{
SDL_FRect *frects;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!rects) {
return SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
frects[i].x = rects[i].x * renderer->scale.x;
frects[i].y = rects[i].y * renderer->scale.y;
frects[i].w = rects[i].w * renderer->scale.x;
frects[i].h = rects[i].h * renderer->scale.y;
}
retval = QueueCmdFillRects(renderer, frects, count);
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderFillRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects, int count)
{
SDL_FRect *frects;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!rects) {
return SDL_SetError("SDL_RenderFillFRects(): Passed NULL rects");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
frects[i].x = rects[i].x * renderer->scale.x;
frects[i].y = rects[i].y * renderer->scale.y;
frects[i].w = rects[i].w * renderer->scale.x;
frects[i].h = rects[i].h * renderer->scale.y;
}
retval = QueueCmdFillRects(renderer, frects, count);
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
{
return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
}
/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
static SDL_bool
SDL_HasIntersectionF(const SDL_FRect * A, const SDL_FRect * B)
{
float Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_FRectEmpty(A) || SDL_FRectEmpty(B)) {
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
return SDL_TRUE;
}
int
SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{
SDL_FRect dstfrect;
SDL_FRect *pdstfrect = NULL;
if (dstrect) {
dstfrect.x = (float) dstrect->x;
dstfrect.y = (float) dstrect->y;
dstfrect.w = (float) dstrect->w;
dstfrect.h = (float) dstrect->h;
pdstfrect = &dstfrect;
}
return SDL_RenderCopyF(renderer, texture, srcrect, pdstfrect);
}
int
SDL_RenderCopyF(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
SDL_Rect real_srcrect;
SDL_FRect real_dstrect;
SDL_Rect r;
int retval;
CHECK_RENDERER_MAGIC(renderer, -1);
CHECK_TEXTURE_MAGIC(texture, -1);
if (renderer != texture->renderer) {
return SDL_SetError("Texture was not created with this renderer");
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
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;
}
}
SDL_zero(r);
SDL_RenderGetViewport(renderer, &r);
real_dstrect.x = 0.0f;
real_dstrect.y = 0.0f;
real_dstrect.w = (float) r.w;
real_dstrect.h = (float) r.h;
if (dstrect) {
if (!SDL_HasIntersectionF(dstrect, &real_dstrect)) {
return 0;
}
real_dstrect = *dstrect;
}
if (texture->native) {
texture = texture->native;
}
real_dstrect.x *= renderer->scale.x;
real_dstrect.y *= renderer->scale.y;
real_dstrect.w *= renderer->scale.x;
real_dstrect.h *= renderer->scale.y;
texture->last_command_generation = renderer->render_command_generation;
retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
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_FRect dstfrect;
SDL_FRect *pdstfrect = NULL;
SDL_FPoint fcenter;
SDL_FPoint *pfcenter = NULL;
if (dstrect) {
dstfrect.x = (float) dstrect->x;
dstfrect.y = (float) dstrect->y;
dstfrect.w = (float) dstrect->w;
dstfrect.h = (float) dstrect->h;
pdstfrect = &dstfrect;
}
if (center) {
fcenter.x = (float) center->x;
fcenter.y = (float) center->y;
pfcenter = &fcenter;
}
return SDL_RenderCopyExF(renderer, texture, srcrect, pdstfrect, angle, pfcenter, flip);
}
int
SDL_RenderCopyExF(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)
{
SDL_Rect real_srcrect;
SDL_FRect real_dstrect;
SDL_FPoint real_center;
int retval;
if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */
return SDL_RenderCopyF(renderer, texture, srcrect, dstrect);
}
CHECK_RENDERER_MAGIC(renderer, -1);
CHECK_TEXTURE_MAGIC(texture, -1);
if (renderer != texture->renderer) {
return SDL_SetError("Texture was not created with this renderer");
}
if (!renderer->QueueCopyEx) {
return SDL_SetError("Renderer does not support RenderCopyEx");
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
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 {
SDL_Rect r;
SDL_zero(r);
SDL_RenderGetViewport(renderer, &r);
real_dstrect.x = 0.0f;
real_dstrect.y = 0.0f;
real_dstrect.w = (float) r.w;
real_dstrect.h = (float) r.h;
}
if (texture->native) {
texture = texture->native;
}
if (center) {
real_center = *center;
} else {
real_center.x = real_dstrect.w / 2.0f;
real_center.y = real_dstrect.h / 2.0f;
}
real_dstrect.x *= renderer->scale.x;
real_dstrect.y *= renderer->scale.y;
real_dstrect.w *= renderer->scale.x;
real_dstrect.h *= renderer->scale.y;
real_center.x *= renderer->scale.x;
real_center.y *= renderer->scale.y;
texture->last_command_generation = renderer->render_command_generation;
retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
{
SDL_Rect real_rect;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!renderer->RenderReadPixels) {
return SDL_Unsupported();
}
FlushRenderCommands(renderer); /* we need to render before we read the results. */
if (!format) {
format = SDL_GetWindowPixelFormat(renderer->window);
}
real_rect.x = renderer->viewport.x;
real_rect.y = renderer->viewport.y;
real_rect.w = renderer->viewport.w;
real_rect.h = renderer->viewport.h;
if (rect) {
if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
return 0;
}
if (real_rect.y > rect->y) {
pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
}
if (real_rect.x > rect->x) {
int bpp = SDL_BYTESPERPIXEL(format);
pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
}
}
return renderer->RenderReadPixels(renderer, &real_rect,
format, pixels, pitch);
}
void
SDL_RenderPresent(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, );
FlushRenderCommands(renderer); /* time to send everything to the GPU! */
/* Don't present while we're hidden */
if (renderer->hidden) {
return;
}
renderer->RenderPresent(renderer);
}
void
SDL_DestroyTexture(SDL_Texture * texture)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, );
renderer = texture->renderer;
if (texture == renderer->target) {
SDL_SetRenderTarget(renderer, NULL); /* implies command queue flush */
} else {
FlushRenderCommandsIfTextureNeeded(texture);
}
texture->magic = NULL;
if (texture->next) {
texture->next->prev = texture->prev;
}
if (texture->prev) {
texture->prev->next = texture->next;
} else {
renderer->textures = texture->next;
}
if (texture->native) {
SDL_DestroyTexture(texture->native);
}
if (texture->yuv) {
SDL_SW_DestroyYUVTexture(texture->yuv);
}
SDL_free(texture->pixels);
renderer->DestroyTexture(renderer, texture);
SDL_free(texture);
}
void
SDL_DestroyRenderer(SDL_Renderer * renderer)
{
SDL_RenderCommand *cmd;
SDL_AllocVertGap *gap;
SDL_AllocVertGap *nextgap;
CHECK_RENDERER_MAGIC(renderer, );
SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
if (renderer->render_commands_tail != NULL) {
renderer->render_commands_tail->next = renderer->render_commands_pool;
cmd = renderer->render_commands;
} else {
cmd = renderer->render_commands_pool;
}
renderer->render_commands_pool = NULL;
renderer->render_commands_tail = NULL;
renderer->render_commands = NULL;
while (cmd != NULL) {
SDL_RenderCommand *next = cmd->next;
SDL_free(cmd);
cmd = next;
}
SDL_free(renderer->vertex_data);
for (gap = renderer->vertex_data_gaps.next; gap; gap = nextgap) {
nextgap = gap->next;
SDL_free(gap);
}
for (gap = renderer->vertex_data_gaps_pool; gap; gap = nextgap) {
nextgap = gap->next;
SDL_free(gap);
}
/* Free existing textures for this renderer */
while (renderer->textures) {
SDL_Texture *tex = renderer->textures; (void) tex;
SDL_DestroyTexture(renderer->textures);
SDL_assert(tex != renderer->textures); /* satisfy static analysis. */
}
if (renderer->window) {
SDL_SetWindowData(renderer->window, SDL_WINDOWRENDERDATA, NULL);
}
/* It's no longer magical... */
renderer->magic = NULL;
/* Free the target mutex */
SDL_DestroyMutex(renderer->target_mutex);
renderer->target_mutex = NULL;
/* Free the renderer instance */
renderer->DestroyRenderer(renderer);
}
int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
if (texture->native) {
return SDL_GL_BindTexture(texture->native, texw, texh);
} else if (renderer && renderer->GL_BindTexture) {
FlushRenderCommandsIfTextureNeeded(texture); /* in case the app is going to mess with it. */
return renderer->GL_BindTexture(renderer, texture, texw, texh);
} else {
return SDL_Unsupported();
}
}
int SDL_GL_UnbindTexture(SDL_Texture *texture)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
if (texture->native) {
return SDL_GL_UnbindTexture(texture->native);
} else if (renderer && renderer->GL_UnbindTexture) {
FlushRenderCommandsIfTextureNeeded(texture); /* in case the app messed with it. */
return renderer->GL_UnbindTexture(renderer, texture);
}
return SDL_Unsupported();
}
void *
SDL_RenderGetMetalLayer(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, NULL);
if (renderer->GetMetalLayer) {
FlushRenderCommands(renderer); /* in case the app is going to mess with it. */
return renderer->GetMetalLayer(renderer);
}
return NULL;
}
void *
SDL_RenderGetMetalCommandEncoder(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, NULL);
if (renderer->GetMetalCommandEncoder) {
FlushRenderCommands(renderer); /* in case the app is going to mess with it. */
return renderer->GetMetalCommandEncoder(renderer);
}
return NULL;
}
static SDL_BlendMode
SDL_GetShortBlendMode(SDL_BlendMode blendMode)
{
if (blendMode == SDL_BLENDMODE_NONE_FULL) {
return SDL_BLENDMODE_NONE;
}
if (blendMode == SDL_BLENDMODE_BLEND_FULL) {
return SDL_BLENDMODE_BLEND;
}
if (blendMode == SDL_BLENDMODE_ADD_FULL) {
return SDL_BLENDMODE_ADD;
}
if (blendMode == SDL_BLENDMODE_MOD_FULL) {
return SDL_BLENDMODE_MOD;
}
return blendMode;
}
static SDL_BlendMode
SDL_GetLongBlendMode(SDL_BlendMode blendMode)
{
if (blendMode == SDL_BLENDMODE_NONE) {
return SDL_BLENDMODE_NONE_FULL;
}
if (blendMode == SDL_BLENDMODE_BLEND) {
return SDL_BLENDMODE_BLEND_FULL;
}
if (blendMode == SDL_BLENDMODE_ADD) {
return SDL_BLENDMODE_ADD_FULL;
}
if (blendMode == SDL_BLENDMODE_MOD) {
return SDL_BLENDMODE_MOD_FULL;
}
return blendMode;
}
SDL_BlendMode
SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, SDL_BlendFactor dstColorFactor,
SDL_BlendOperation colorOperation,
SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor,
SDL_BlendOperation alphaOperation)
{
SDL_BlendMode blendMode = SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation,
srcAlphaFactor, dstAlphaFactor, alphaOperation);
return SDL_GetShortBlendMode(blendMode);
}
SDL_BlendFactor
SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
{
blendMode = SDL_GetLongBlendMode(blendMode);
return (SDL_BlendFactor)(((Uint32)blendMode >> 4) & 0xF);
}
SDL_BlendFactor
SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
{
blendMode = SDL_GetLongBlendMode(blendMode);
return (SDL_BlendFactor)(((Uint32)blendMode >> 8) & 0xF);
}
SDL_BlendOperation
SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
{
blendMode = SDL_GetLongBlendMode(blendMode);
return (SDL_BlendOperation)(((Uint32)blendMode >> 0) & 0xF);
}
SDL_BlendFactor
SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
{
blendMode = SDL_GetLongBlendMode(blendMode);
return (SDL_BlendFactor)(((Uint32)blendMode >> 20) & 0xF);
}
SDL_BlendFactor
SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
{
blendMode = SDL_GetLongBlendMode(blendMode);
return (SDL_BlendFactor)(((Uint32)blendMode >> 24) & 0xF);
}
SDL_BlendOperation
SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
{
blendMode = SDL_GetLongBlendMode(blendMode);
return (SDL_BlendOperation)(((Uint32)blendMode >> 16) & 0xF);
}
/* vi: set ts=4 sw=4 expandtab: */
QueueCmdSetViewport
static int QueueCmdSetViewport(SDL_Renderer *renderer)
Definition: SDL_render.c:400
SDL_RenderDrawPointF
int SDL_RenderDrawPointF(SDL_Renderer *renderer, float x, float y)
Draw a point on the current rendering target.
Definition: SDL_render.c:2254
SDL_SetRenderDrawBlendMode
int SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Set the blend mode used for drawing operations (Fill and Line).
Definition: SDL_render.c:2211
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
DirectFB_RenderDriver
SDL_RenderDriver DirectFB_RenderDriver
SDL_UnlockSurface
#define SDL_UnlockSurface
Definition: SDL_dynapi_overrides.h:449
SDL_Texture::native
SDL_Texture * native
Definition: SDL_sysrender.h:58
SDL_SetRenderTarget
int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
Set a texture as the current rendering target.
Definition: SDL_render.c:1833
SDL_FRectEmpty
SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
Definition: SDL_render.c:2854
SDL_Renderer::blendMode
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:210
SW_CreateRendererForSurface
SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface *surface)
Definition: SDL_render_sw.c:802
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_RenderDrawLine
int SDL_RenderDrawLine(SDL_Renderer *renderer, int x1, int y1, int x2, int y2)
Draw a line on the current rendering target.
Definition: SDL_render.c:2403
points
GLfixed GLfixed GLint GLint GLfixed points
Definition: SDL_opengl_glext.h:4558
SDL_Point::x
int x
Definition: SDL_rect.h:50
RenderDrawPointsWithRectsF
static int RenderDrawPointsWithRectsF(SDL_Renderer *renderer, const SDL_FPoint *fpoints, const int count)
Definition: SDL_render.c:2333
SDL_RenderDrawRectsF
int SDL_RenderDrawRectsF(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
Draw some number of rectangles on the current rendering target.
Definition: SDL_render.c:2698
SDL_AllocVertGap::len
size_t len
Definition: SDL_sysrender.h:116
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_UnlockTexture
void SDL_UnlockTexture(SDL_Texture *texture)
Unlock a texture, uploading the changes to video memory, if needed.
Definition: SDL_render.c:1806
SDL_Renderer::GL_UnbindTexture
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:164
SDL_RenderCopyExF
int SDL_RenderCopyExF(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)
Copy a portion of the source texture to the current rendering target, rotating it by angle around the...
Definition: SDL_render.c:3010
SDL_HINT_RENDER_VSYNC
#define SDL_HINT_RENDER_VSYNC
A variable controlling whether updates to the SDL screen surface should be synchronized with the vert...
Definition: SDL_hints.h:154
SDL_CreateTexture
SDL_Texture * SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h)
Create a texture for a rendering context.
Definition: SDL_render.c:1112
SDL_Renderer::clip_rect_backup
SDL_Rect clip_rect_backup
Definition: SDL_sysrender.h:191
SDL_small_free
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
FlushRenderCommands
static int FlushRenderCommands(SDL_Renderer *renderer)
Definition: SDL_render.c:203
offset
GLintptr offset
Definition: SDL_opengl_glext.h:538
SDL_HINT_RENDER_BATCHING
#define SDL_HINT_RENDER_BATCHING
A variable controlling whether the 2D render API is compatible or efficient.
Definition: SDL_hints.h:1087
SDL_GL_UnbindTexture
int SDL_GL_UnbindTexture(SDL_Texture *texture)
Unbind a texture from the current OpenGL/ES/ES2 context.
Definition: SDL_render.c:3254
scale
GLenum GLenum GLenum GLenum GLenum scale
Definition: SDL_opengl_glext.h:9375
SDL_GetWindowData
#define SDL_GetWindowData
Definition: SDL_dynapi_overrides.h:523
SDL_render.h
SDL_RenderSetIntegerScale
int SDL_RenderSetIntegerScale(SDL_Renderer *renderer, SDL_bool enable)
Set whether to force integer scales for resolution-independent rendering.
Definition: SDL_render.c:2060
SDL_Palette::ncolors
int ncolors
Definition: SDL_pixels.h:306
blendMode
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
SDL_SetTextureAlphaMod
int SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha)
Set an additional alpha value used in render copy operations.
Definition: SDL_render.c:1411
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:70
SDL_Renderer::render_command_generation
Uint32 render_command_generation
Definition: SDL_sysrender.h:217
SDL_UpdateTextureYUV
static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_render.c:1468
SDL_Renderer::GetMetalLayer
void *(* GetMetalLayer)(SDL_Renderer *renderer)
Definition: SDL_sysrender.h:166
SDL_AllocVertGap::offset
size_t offset
Definition: SDL_sysrender.h:115
SDL_WINDOW_MINIMIZED
@ SDL_WINDOW_MINIMIZED
Definition: SDL_video.h:106
VerifyDrawQueueFunctions
static SDL_INLINE void VerifyDrawQueueFunctions(const SDL_Renderer *renderer)
Definition: SDL_render.c:821
SDL_RenderPresent
void SDL_RenderPresent(SDL_Renderer *renderer)
Update the screen with rendering performed.
Definition: SDL_render.c:3126
SDL_Renderer::QueueCopyEx
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)
Definition: SDL_sysrender.h:140
IsSupportedBlendMode
static SDL_bool IsSupportedBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_render.c:1040
GLES2_RenderDriver
SDL_RenderDriver GLES2_RenderDriver
SDL_PIXELFORMAT_RGB888
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:236
SDL_BLENDMODE_ADD
@ SDL_BLENDMODE_ADD
Definition: SDL_blendmode.h:47
SDL_AllocateRenderVertices
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:284
SDL_RenderGetScale
void SDL_RenderGetScale(SDL_Renderer *renderer, float *scaleX, float *scaleY)
Get the drawing scale for the current target.
Definition: SDL_render.c:2164
SDL_RenderTargetSupported
SDL_bool SDL_RenderTargetSupported(SDL_Renderer *renderer)
Determines whether a window supports the use of render targets.
Definition: SDL_render.c:1824
SDL_TEXTUREMODULATE_COLOR
@ SDL_TEXTUREMODULATE_COLOR
Definition: SDL_render.h:104
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:260
window_w
int window_w
Definition: testoverlay2.c:143
SDL_RenderCommand::cliprect
struct SDL_RenderCommand::@30::@32 cliprect
SDL_Renderer::RunCommandQueue
int(* RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
Definition: SDL_sysrender.h:143
SDL_fabs
#define SDL_fabs
Definition: SDL_dynapi_overrides.h:430
SDL_FPoint::x
float x
Definition: SDL_rect.h:62
SDL_ceil
#define SDL_ceil
Definition: SDL_dynapi_overrides.h:426
SDL_FRect::h
float h
Definition: SDL_rect.h:92
NULL
#define NULL
Definition: begin_code.h:167
SDL_ScaleModeNearest
@ SDL_ScaleModeNearest
Definition: SDL_sysrender.h:37
surface
EGLSurface surface
Definition: eglext.h:248
SDL_PixelFormat::format
Uint32 format
Definition: SDL_pixels.h:317
SDL_ALPHA_OPAQUE
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:46
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
SDL_Renderer::SetRenderTarget
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:155
enable
GLboolean enable
Definition: SDL_opengl_glext.h:4996
width
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:76
SDL_CreateSoftwareRenderer
SDL_Renderer * SDL_CreateSoftwareRenderer(SDL_Surface *surface)
Create a 2D software rendering context for a surface.
Definition: SDL_render.c:980
g
GLboolean GLboolean g
Definition: SDL_opengl_glext.h:1109
access
GLuint GLint GLboolean GLint GLenum access
Definition: SDL_opengl_glext.h:2162
SDL_ScaleModeBest
@ SDL_ScaleModeBest
Definition: SDL_sysrender.h:39
render_drivers
static const SDL_RenderDriver * render_drivers[]
Definition: SDL_render.c:79
SDL_RenderGetIntegerScale
SDL_bool SDL_RenderGetIntegerScale(SDL_Renderer *renderer)
Get whether integer scales are forced for resolution-independent rendering.
Definition: SDL_render.c:2070
SDL_log.h
SDL_Renderer::g
Uint8 g
Definition: SDL_sysrender.h:209
SDL_UpdateTextureNative
static int SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_render.c:1514
SDL_COMPOSE_BLENDMODE
#define SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation, srcAlphaFactor, dstAlphaFactor, alphaOperation)
Definition: SDL_render.c:53
SDL_render_sw_c.h
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_UnlockTextureNative
static void SDL_UnlockTextureNative(SDL_Texture *texture)
Definition: SDL_render.c:1785
SDL_SW_LockYUVTexture
int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:302
SDL_GetWindowFlags
#define SDL_GetWindowFlags
Definition: SDL_dynapi_overrides.h:518
SDL_RenderDrawLinesF
int SDL_RenderDrawLinesF(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
Draw a series of connected lines on the current rendering target.
Definition: SDL_render.c:2578
SDL_RenderCommandType
SDL_RenderCommandType
Definition: SDL_sysrender.h:72
SDL_RenderCommand::next
struct SDL_RenderCommand * next
Definition: SDL_sysrender.h:110
SDL_PIXELFORMAT_BGR888
@ SDL_PIXELFORMAT_BGR888
Definition: SDL_pixels.h:242
SDL_BlendOperation
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:62
SDL_RenderCopy
int SDL_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect)
Copy a portion of the texture to the current rendering target.
Definition: SDL_render.c:2908
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:49
SDL_Renderer::hidden
SDL_bool hidden
Definition: SDL_sysrender.h:174
SDL_Renderer::scale
SDL_FPoint scale
Definition: SDL_sysrender.h:198
SDL_HINT_RENDER_SCALE_QUALITY
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:143
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
AllocateVertexGap
static SDL_AllocVertGap * AllocateVertexGap(SDL_Renderer *renderer)
Definition: SDL_render.c:267
SDL_AllocVertGap
Definition: SDL_sysrender.h:113
SDL_MOUSEBUTTONUP
@ SDL_MOUSEBUTTONUP
Definition: SDL_events.h:107
SDL_ConvertSurface
#define SDL_ConvertSurface
Definition: SDL_dynapi_overrides.h:463
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
viewport
SDL_Rect viewport
Definition: testviewport.c:28
SDL_Renderer::last_queued_color
Uint32 last_queued_color
Definition: SDL_sysrender.h:218
SDL_CreateMutex
#define SDL_CreateMutex
Definition: SDL_dynapi_overrides.h:259
SDL_WINDOWPOS_UNDEFINED
#define SDL_WINDOWPOS_UNDEFINED
Definition: SDL_video.h:130
SDL_MUSTLOCK
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:62
SDL_Renderer::vertex_data
void * vertex_data
Definition: SDL_sysrender.h:226
SDL_IntersectRect
#define SDL_IntersectRect
Definition: SDL_dynapi_overrides.h:294
SDL_UpdateTextureYUVPlanar
static int SDL_UpdateTextureYUVPlanar(SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Definition: SDL_render.c:1593
SDL_floor
#define SDL_floor
Definition: SDL_dynapi_overrides.h:431
SDL_RenderClear
int SDL_RenderClear(SDL_Renderer *renderer)
Clear the current rendering target with the drawing color.
Definition: SDL_render.c:2232
SDL_RenderDriver
Definition: SDL_sysrender.h:236
SDL_RenderFillRect
int SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_Rect *rect)
Fill a rectangle on the current rendering target with the drawing color.
Definition: SDL_render.c:2726
SDL_Renderer::color_queued
SDL_bool color_queued
Definition: SDL_sysrender.h:222
SDL_FRect::x
float x
Definition: SDL_rect.h:89
SDL_Renderer::last_queued_viewport
SDL_Rect last_queued_viewport
Definition: SDL_sysrender.h:219
SDL_ISPIXELFORMAT_INDEXED
#define SDL_ISPIXELFORMAT_INDEXED(format)
Definition: SDL_pixels.h:134
SDL_Renderer::dpi_scale
SDL_FPoint dpi_scale
Definition: SDL_sysrender.h:202
SDL_Renderer::textures
SDL_Texture * textures
Definition: SDL_sysrender.h:205
SDL_RenderIsClipEnabled
SDL_bool SDL_RenderIsClipEnabled(SDL_Renderer *renderer)
Get whether clipping is enabled on the given renderer.
Definition: SDL_render.c:2147
SDL_Renderer::WindowEvent
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:126
SDL_GetRendererOutputSize
int SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h)
Get the output size in pixels of a rendering context.
Definition: SDL_render.c:1022
SDL_Renderer::vertex_data_used
size_t vertex_data_used
Definition: SDL_sysrender.h:227
GLES_RenderDriver
SDL_RenderDriver GLES_RenderDriver
index
GLuint index
Definition: SDL_opengl_glext.h:660
SDL_GetRenderTarget
SDL_Texture * SDL_GetRenderTarget(SDL_Renderer *renderer)
Get the current render target or NULL for the default render target.
Definition: SDL_render.c:1912
SDL_FPoint::y
float y
Definition: SDL_rect.h:63
x1
GLuint GLfloat GLfloat GLfloat x1
Definition: SDL_opengl_glext.h:8583
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1109
SDL_ScaleModeLinear
@ SDL_ScaleModeLinear
Definition: SDL_sysrender.h:38
SDL_GetHint
#define SDL_GetHint
Definition: SDL_dynapi_overrides.h:191
SDL_Renderer::vertex_data_gaps
SDL_AllocVertGap vertex_data_gaps
Definition: SDL_sysrender.h:229
SDL_CreateWindow
#define SDL_CreateWindow
Definition: SDL_dynapi_overrides.h:514
renderer_magic
static char renderer_magic
Definition: SDL_render.c:108
SDL_AllocVertGap::next
struct SDL_AllocVertGap * next
Definition: SDL_sysrender.h:117
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
SDL_RendererFlip
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
SDL_small_alloc
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
SDL_Renderer::target_mutex
SDL_mutex * target_mutex
Definition: SDL_sysrender.h:207
SDL_LockTexture
int SDL_LockTexture(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Lock a portion of the texture for write-only pixel access.
Definition: SDL_render.c:1727
SDL_GetSurfaceBlendMode
#define SDL_GetSurfaceBlendMode
Definition: SDL_dynapi_overrides.h:460
SDL_QueryTexture
int SDL_QueryTexture(SDL_Texture *texture, Uint32 *format, int *access, int *w, int *h)
Query the attributes of a texture.
Definition: SDL_render.c:1353
SDL_Rect::x
int x
Definition: SDL_rect.h:79
SDL_RENDERCMD_COPY
@ SDL_RENDERCMD_COPY
Definition: SDL_sysrender.h:82
SDL_Renderer::viewport_queued
SDL_bool viewport_queued
Definition: SDL_sysrender.h:223
FlushRenderCommandsIfTextureNeeded
static int FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
Definition: SDL_render.c:244
SDL_CreateRenderer
SDL_Renderer * SDL_CreateRenderer(SDL_Window *window, int index, Uint32 flags)
Create a 2D rendering context for a window.
Definition: SDL_render.c:835
SDL_Renderer::logical_w
int logical_w
Definition: SDL_sysrender.h:177
SDL_Renderer::viewport_backup
SDL_Rect viewport_backup
Definition: SDL_sysrender.h:187
SDL_RENDERCMD_SETCLIPRECT
@ SDL_RENDERCMD_SETCLIPRECT
Definition: SDL_sysrender.h:76
SDL_RendererInfo
Information on the capabilities of a render driver or context.
Definition: SDL_render.h:78
SDL_DestroyRenderer
void SDL_DestroyRenderer(SDL_Renderer *renderer)
Destroy the rendering context for a window and free associated textures.
Definition: SDL_render.c:3177
SDL_RenderSetLogicalSize
int SDL_RenderSetLogicalSize(SDL_Renderer *renderer, int w, int h)
Set device independent resolution for rendering.
Definition: SDL_render.c:2027
SDL_PIXELFORMAT_IYUV
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:279
SDL_AllocFormat
#define SDL_AllocFormat
Definition: SDL_dynapi_overrides.h:280
SDL_RenderFillRectsF
int SDL_RenderFillRectsF(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
Fill some number of rectangles on the current rendering target with the drawing color.
Definition: SDL_render.c:2813
SDL_GetRenderDrawColor
int SDL_GetRenderDrawColor(SDL_Renderer *renderer, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
Get the color used for drawing operations (Rect, Line and Clear).
Definition: SDL_render.c:2190
SDL_Texture::prev
SDL_Texture * prev
Definition: SDL_sysrender.h:68
SDL_GetNumRenderDrivers
int SDL_GetNumRenderDrivers(void)
Get the number of 2D rendering drivers available for the current display.
Definition: SDL_render.c:627
SDL_Rect::w
int w
Definition: SDL_rect.h:80
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_Color::a
Uint8 a
Definition: SDL_pixels.h:300
maxY
GLfloat GLfloat GLfloat GLfloat GLfloat maxY
Definition: gl2ext.h:446
n
GLdouble n
Definition: SDL_opengl_glext.h:1952
SDL_RenderGetViewport
void SDL_RenderGetViewport(SDL_Renderer *renderer, SDL_Rect *rect)
Get the drawing area for the current target.
Definition: SDL_render.c:2100
SDL_strcasecmp
#define SDL_strcasecmp
Definition: SDL_dynapi_overrides.h:419
alpha
GLfloat GLfloat GLfloat alpha
Definition: SDL_opengl_glext.h:412
SDL_CreateTextureFromSurface
SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface)
Create a texture from an existing surface.
Definition: SDL_render.c:1207
SDL_WINDOWEVENT_SHOWN
@ SDL_WINDOWEVENT_SHOWN
Definition: SDL_video.h:149
SDL_RenderDriver::CreateRenderer
SDL_Renderer *(* CreateRenderer)(SDL_Window *window, Uint32 flags)
Definition: SDL_sysrender.h:238
SDL_RenderFillRectF
int SDL_RenderFillRectF(SDL_Renderer *renderer, const SDL_FRect *rect)
Fill a rectangle on the current rendering target with the drawing color.
Definition: SDL_render.c:2751
SDL_GetWindowSize
#define SDL_GetWindowSize
Definition: SDL_dynapi_overrides.h:527
SDL_SW_CopyYUVToRGB
int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect, Uint32 target_format, int w, int h, void *pixels, int pitch)
Definition: SDL_yuv_sw.c:334
SDL_FINGERUP
@ SDL_FINGERUP
Definition: SDL_events.h:129
QueueCmdClear
static int QueueCmdClear(SDL_Renderer *renderer)
Definition: SDL_render.c:474
SDL_LockTextureNative
static int SDL_LockTextureNative(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_render.c:1715
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:75
SDL_Renderer::viewport
SDL_Rect viewport
Definition: SDL_sysrender.h:186
SDL_BLENDMODE_MOD
@ SDL_BLENDMODE_MOD
Definition: SDL_blendmode.h:50
SDL_UpdateYUVTexture
int SDL_UpdateYUVTexture(SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Update a rectangle within a planar YV12 or IYUV texture with new pixel data.
Definition: SDL_render.c:1644
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
SDL_BLENDMODE_NONE
@ SDL_BLENDMODE_NONE
Definition: SDL_blendmode.h:42
SDL_RenderSetScale
int SDL_RenderSetScale(SDL_Renderer *renderer, float scaleX, float scaleY)
Set the drawing scale for rendering on the current target.
Definition: SDL_render.c:2154
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
D3D11_RenderDriver
SDL_RenderDriver D3D11_RenderDriver
SDL_Renderer
Definition: SDL_sysrender.h:122
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_MOUSEMOTION
@ SDL_MOUSEMOTION
Definition: SDL_events.h:105
SDL_Renderer::QueueSetDrawColor
int(* QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
Definition: SDL_sysrender.h:131
SDL_GL_BindTexture
int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
Bind the texture to the current OpenGL/ES/ES2 context for use with OpenGL instructions.
Definition: SDL_render.c:3238
SDL_FPoint
The structure that defines a point (floating point)
Definition: SDL_rect.h:60
SDL_Palette::colors
SDL_Color * colors
Definition: SDL_pixels.h:307
SDL_BLENDMODE_ADD_FULL
#define SDL_BLENDMODE_ADD_FULL
Definition: SDL_render.c:70
SDL_FRect::y
float y
Definition: SDL_rect.h:90
SDL_Renderer::integer_scale
SDL_bool integer_scale
Definition: SDL_sysrender.h:183
SDL_FINGERDOWN
@ SDL_FINGERDOWN
Definition: SDL_events.h:128
SDL_Renderer::b
Uint8 b
Definition: SDL_sysrender.h:209
SDL_RenderGetLogicalSize
void SDL_RenderGetLogicalSize(SDL_Renderer *renderer, int *w, int *h)
Get device independent resolution for rendering.
Definition: SDL_render.c:2047
Android_ActivityMutex_Lock_Running
void Android_ActivityMutex_Lock_Running(void)
SDL_FRect::w
float w
Definition: SDL_rect.h:91
SDL_Renderer::last_queued_cliprect_enabled
SDL_bool last_queued_cliprect_enabled
Definition: SDL_sysrender.h:221
retval
SDL_bool retval
Definition: testgamecontroller.c:65
SDL_Renderer::scale_backup
SDL_FPoint scale_backup
Definition: SDL_sysrender.h:199
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
window_h
int window_h
Definition: testoverlay2.c:144
color
GLuint color
Definition: SDL_opengl_glext.h:1148
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_Log
#define SDL_Log
Definition: SDL_dynapi_overrides.h:31
SDL_SetWindowData
#define SDL_SetWindowData
Definition: SDL_dynapi_overrides.h:522
SDL_RendererInfo::flags
Uint32 flags
Definition: SDL_render.h:81
D3D_RenderDriver
SDL_RenderDriver D3D_RenderDriver
SDL_Rect::y
int y
Definition: SDL_rect.h:79
SDL_Renderer::render_commands_tail
SDL_RenderCommand * render_commands_tail
Definition: SDL_sysrender.h:215
SDL_UpdateTexture
int SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Update the given texture rectangle with new pixel data.
Definition: SDL_render.c:1555
SDL_memcmp
#define SDL_memcmp
Definition: SDL_dynapi_overrides.h:389
SDL_BLENDMODE_MOD_FULL
#define SDL_BLENDMODE_MOD_FULL
Definition: SDL_render.c:74
SDL_INLINE
#define SDL_INLINE
Definition: begin_code.h:134
SDL_Rect::h
int h
Definition: SDL_rect.h:80
SDL_Renderer::logical_h_backup
int logical_h_backup
Definition: SDL_sysrender.h:180
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
minY
GLfloat minY
Definition: gl2ext.h:446
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
SDL_TEXTUREACCESS_STATIC
@ SDL_TEXTUREACCESS_STATIC
Definition: SDL_render.h:93
QueueCmdFillRects
static int QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, const int count)
Definition: SDL_render.c:557
height
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
SDL_max
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
SDL_Renderer::SupportsBlendMode
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_sysrender.h:128
SDL_CreateWindowAndRenderer
int SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags, SDL_Window **window, SDL_Renderer **renderer)
Create a window and default renderer.
Definition: SDL_render.c:801
SDL_RENDERCMD_SETVIEWPORT
@ SDL_RENDERCMD_SETVIEWPORT
Definition: SDL_sysrender.h:75
UpdateLogicalSize
static int UpdateLogicalSize(SDL_Renderer *renderer)
Definition: SDL_render.c:1918
SDL_Renderer::QueueDrawLines
int(* QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
Definition: SDL_sysrender.h:134
SDL_RENDERER_PRESENTVSYNC
@ SDL_RENDERER_PRESENTVSYNC
Definition: SDL_render.h:69
SDL_RenderGetMetalLayer
void * SDL_RenderGetMetalLayer(SDL_Renderer *renderer)
Get the CAMetalLayer associated with the given Metal renderer.
Definition: SDL_render.c:3271
SDL_DestroyTexture
void SDL_DestroyTexture(SDL_Texture *texture)
Destroy the specified texture.
Definition: SDL_render.c:3140
SDL_RenderCommand::color
struct SDL_RenderCommand::@30::@34 color
SDL_RENDERCMD_DRAW_POINTS
@ SDL_RENDERCMD_DRAW_POINTS
Definition: SDL_sysrender.h:79
rect
SDL_Rect rect
Definition: testrelative.c:27
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:446
SDL_PixelFormat::palette
SDL_Palette * palette
Definition: SDL_pixels.h:318
SDL_Renderer::render_commands
SDL_RenderCommand * render_commands
Definition: SDL_sysrender.h:214
SDL_LockTextureYUV
static int SDL_LockTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_render.c:1708
SDL_ScaleMode
SDL_ScaleMode
Definition: SDL_sysrender.h:35
SDL_sysrender.h
SDL_BlendFactor
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:75
SDL_GetWindowFromID
#define SDL_GetWindowFromID
Definition: SDL_dynapi_overrides.h:517
SDL_assert.h
SDL_SW_DestroyYUVTexture
void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:404
SDL_HasIntersectionF
static SDL_bool SDL_HasIntersectionF(const SDL_FRect *A, const SDL_FRect *B)
Definition: SDL_render.c:2861
SDL_Renderer::last_queued_cliprect
SDL_Rect last_queued_cliprect
Definition: SDL_sysrender.h:220
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_FINGERMOTION
@ SDL_FINGERMOTION
Definition: SDL_events.h:130
RenderDrawPointsWithRects
static int RenderDrawPointsWithRects(SDL_Renderer *renderer, const SDL_Point *points, const int count)
Definition: SDL_render.c:2263
SDL_ComposeCustomBlendMode
SDL_BlendMode SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, SDL_BlendFactor dstColorFactor, SDL_BlendOperation colorOperation, SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor, SDL_BlendOperation alphaOperation)
Create a custom blend mode, which may or may not be supported by a given renderer.
Definition: SDL_render.c:3331
SDL_RenderReadPixels
int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
Read pixels from the current rendering target.
Definition: SDL_render.c:3087
SDL_GetTextureColorMod
int SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 *r, Uint8 *g, Uint8 *b)
Get the additional color value used in render copy operations.
Definition: SDL_render.c:1393
AllocateRenderCommand
static SDL_RenderCommand * AllocateRenderCommand(SDL_Renderer *renderer)
Definition: SDL_render.c:371
SDL_Renderer::always_batch
SDL_bool always_batch
Definition: SDL_sysrender.h:212
FlushRenderCommandsIfNotBatching
static SDL_INLINE int FlushRenderCommandsIfNotBatching(SDL_Renderer *renderer)
Definition: SDL_render.c:255
PrepQueueCmdDrawTexture
static SDL_RenderCommand * PrepQueueCmdDrawTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_RenderCommandType cmdtype)
Definition: SDL_render.c:571
SDL_UnlockTextureYUV
static void SDL_UnlockTextureYUV(SDL_Texture *texture)
Definition: SDL_render.c:1764
RenderDrawLinesWithRectsF
static int RenderDrawLinesWithRectsF(SDL_Renderer *renderer, const SDL_FPoint *points, const int count)
Definition: SDL_render.c:2480
SDL_FreeFormat
#define SDL_FreeFormat
Definition: SDL_dynapi_overrides.h:281
SDL_PixelFormat::Amask
Uint32 Amask
Definition: SDL_pixels.h:325
SDL_GetBlendModeDstAlphaFactor
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3370
SDL_Texture::next
SDL_Texture * next
Definition: SDL_sysrender.h:69
SDL_WINDOWEVENT_SIZE_CHANGED
@ SDL_WINDOWEVENT_SIZE_CHANGED
Definition: SDL_video.h:156
SDL_Renderer::GL_BindTexture
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
Definition: SDL_sysrender.h:163
SDL_Renderer::vertex_data_allocation
size_t vertex_data_allocation
Definition: SDL_sysrender.h:228
QueueCmdCopyEx
static int QueueCmdCopyEx(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)
Definition: SDL_render.c:607
SDL_Renderer::batching
SDL_bool batching
Definition: SDL_sysrender.h:213
SDL_RenderCommand::command
SDL_RenderCommandType command
Definition: SDL_sysrender.h:88
SDL_RENDERCMD_NO_OP
@ SDL_RENDERCMD_NO_OP
Definition: SDL_sysrender.h:74
SDL_Renderer::QueueSetViewport
int(* QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
Definition: SDL_sysrender.h:130
SDL_PIXELFORMAT_ARGB8888
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
SDL_PixelFormat
Definition: SDL_pixels.h:315
SDL_HINT_RENDER_LOGICAL_SIZE_MODE
#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE
A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
Definition: SDL_hints.h:131
QueueCmdSetDrawColor
static int QueueCmdSetDrawColor(SDL_Renderer *renderer, const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a)
Definition: SDL_render.c:445
SDL_SW_UpdateYUVTexturePlanar
int SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Definition: SDL_yuv_sw.c:247
GetWindowViewportValues
static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_Rect *viewport, SDL_FPoint *scale)
Definition: SDL_render.c:651
SDL_RenderSetClipRect
int SDL_RenderSetClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
Set the clip rectangle for the current target.
Definition: SDL_render.c:2113
SDL_Renderer::vertex_data_gaps_pool
SDL_AllocVertGap * vertex_data_gaps_pool
Definition: SDL_sysrender.h:230
SDL_TEXTUREMODULATE_ALPHA
@ SDL_TEXTUREMODULATE_ALPHA
Definition: SDL_render.h:105
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_GetRenderDrawBlendMode
int SDL_GetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode *blendMode)
Get the blend mode used for drawing operations.
Definition: SDL_render.c:2223
SDL_WINDOWEVENT_MINIMIZED
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
pixels
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
SDL_RENDERCMD_DRAW_LINES
@ SDL_RENDERCMD_DRAW_LINES
Definition: SDL_sysrender.h:80
SDL_Renderer::GetOutputSize
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:127
SDL_RenderDrawPoint
int SDL_RenderDrawPoint(SDL_Renderer *renderer, int x, int y)
Draw a point on the current rendering target.
Definition: SDL_render.c:2245
maxX
GLfloat GLfloat GLfloat GLfloat maxX
Definition: gl2ext.h:446
SDL_RenderCommand::data
union SDL_RenderCommand::@30 data
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_Renderer::CreateTexture
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:129
SDL_BLENDMODE_BLEND
@ SDL_BLENDMODE_BLEND
Definition: SDL_blendmode.h:44
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_LOG_CATEGORY_RENDER
@ SDL_LOG_CATEGORY_RENDER
Definition: SDL_log.h:72
SDL_Texture::format
Uint32 format
Definition: SDL_sysrender.h:46
SDL_RENDERCMD_FILL_RECTS
@ SDL_RENDERCMD_FILL_RECTS
Definition: SDL_sysrender.h:81
SDL_LockSurface
#define SDL_LockSurface
Definition: SDL_dynapi_overrides.h:448
SDL_Renderer::DestroyRenderer
void(* DestroyRenderer)(SDL_Renderer *renderer)
Definition: SDL_sysrender.h:161
SDL_Renderer::LockTexture
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:152
SDL_Renderer::GetMetalCommandEncoder
void *(* GetMetalCommandEncoder)(SDL_Renderer *renderer)
Definition: SDL_sysrender.h:167
SDL_SW_CreateYUVTexture
SDL_SW_YUVTexture * SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
Definition: SDL_yuv_sw.c:31
SDL_GetSurfaceAlphaMod
#define SDL_GetSurfaceAlphaMod
Definition: SDL_dynapi_overrides.h:458
SDL_Renderer::cliprect_queued
SDL_bool cliprect_queued
Definition: SDL_sysrender.h:224
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_atoi
#define SDL_atoi
Definition: SDL_dynapi_overrides.h:410
SDL_GetLongBlendMode
static SDL_BlendMode SDL_GetLongBlendMode(SDL_BlendMode blendMode)
Definition: SDL_render.c:3313
SDL_Renderer::logical_h
int logical_h
Definition: SDL_sysrender.h:178
SDL_LogInfo
#define SDL_LogInfo
Definition: SDL_dynapi_overrides.h:34
SDL_Renderer::RenderReadPixels
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
Definition: SDL_sysrender.h:156
SDL_GetBlendModeSrcAlphaFactor
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3363
SDL_GetBlendModeColorOperation
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3356
QueueCmdSetClipRect
static int QueueCmdSetClipRect(SDL_Renderer *renderer)
Definition: SDL_render.c:423
SDL_RENDERCMD_COPY_EX
@ SDL_RENDERCMD_COPY_EX
Definition: SDL_sysrender.h:83
Android_ActivityMutex_Unlock
void Android_ActivityMutex_Unlock(void)
SDL_RenderCommand
Definition: SDL_sysrender.h:86
SW_RenderDriver
SDL_RenderDriver SW_RenderDriver
Definition: SDL_render_sw.c:866
renderer
static SDL_Renderer * renderer
Definition: testaudiocapture.c:21
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
RenderDrawLinesWithRects
static int RenderDrawLinesWithRects(SDL_Renderer *renderer, const SDL_Point *points, const int count)
Definition: SDL_render.c:2425
QueueCmdDrawPoints
static int QueueCmdDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, const int count)
Definition: SDL_render.c:529
SDL_WINDOW_HIDDEN
@ SDL_WINDOW_HIDDEN
Definition: SDL_video.h:103
SDL_GetCurrentVideoDriver
#define SDL_GetCurrentVideoDriver
Definition: SDL_dynapi_overrides.h:500
SDL_ISPIXELFORMAT_FOURCC
#define SDL_ISPIXELFORMAT_FOURCC(format)
Definition: SDL_pixels.h:167
SDL_GetRenderer
SDL_Renderer * SDL_GetRenderer(SDL_Window *window)
Get the renderer associated with a window.
Definition: SDL_render.c:1007
SDL_GetBlendModeDstColorFactor
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3349
SDL_Point
The structure that defines a point (integer)
Definition: SDL_rect.h:48
SDL_RenderDrawRectF
int SDL_RenderDrawRectF(SDL_Renderer *renderer, const SDL_FRect *rect)
Draw a rectangle on the current rendering target.
Definition: SDL_render.c:2638
SDL_Renderer::info
SDL_RendererInfo info
Definition: SDL_sysrender.h:170
SDL_RENDERER_TARGETTEXTURE
@ SDL_RENDERER_TARGETTEXTURE
Definition: SDL_render.h:71
SDL_GetWindowPixelFormat
#define SDL_GetWindowPixelFormat
Definition: SDL_dynapi_overrides.h:513
x2
GLfixed GLfixed x2
Definition: SDL_opengl_glext.h:4583
CHECK_TEXTURE_MAGIC
#define CHECK_TEXTURE_MAGIC(texture, retval)
Definition: SDL_render.c:45
SDL_GetTextureAlphaMod
int SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha)
Get the additional alpha value used in render copy operations.
Definition: SDL_render.c:1428
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_Renderer::RenderPresent
void(* RenderPresent)(SDL_Renderer *renderer)
Definition: SDL_sysrender.h:158
SDL_BYTESPERPIXEL
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
SDL_RenderSetViewport
int SDL_RenderSetViewport(SDL_Renderer *renderer, const SDL_Rect *rect)
Set the drawing area for rendering on the current target.
Definition: SDL_render.c:2078
SDL_RenderDrawPoints
int SDL_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int count)
Draw multiple points on the current rendering target.
Definition: SDL_render.c:2290
SDL_Rect
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:77
SDL_RendererInfo::max_texture_width
int max_texture_width
Definition: SDL_render.h:84
METAL_RenderDriver
SDL_RenderDriver METAL_RenderDriver
SDL_GetScaleMode
static SDL_ScaleMode SDL_GetScaleMode(void)
Definition: SDL_render.c:1096
SDL_RenderCommand::viewport
struct SDL_RenderCommand::@30::@31 viewport
IsSupportedFormat
static SDL_bool IsSupportedFormat(SDL_Renderer *renderer, Uint32 format)
Definition: SDL_render.c:1057
SDL_Texture
Definition: SDL_sysrender.h:43
SDL_Renderer::QueueFillRects
int(* QueueFillRects)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
Definition: SDL_sysrender.h:136
SDL_Renderer::UpdateTexture
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:144
SDL_hints.h
SDL_TEXTUREACCESS_TARGET
@ SDL_TEXTUREACCESS_TARGET
Definition: SDL_render.h:95
y1
GLfixed y1
Definition: SDL_opengl_glext.h:4583
SDL_BLENDMODE_BLEND_FULL
#define SDL_BLENDMODE_BLEND_FULL
Definition: SDL_render.c:66
SDL_FLIP_NONE
@ SDL_FLIP_NONE
Definition: SDL_render.h:113
SDL_DestroyMutex
#define SDL_DestroyMutex
Definition: SDL_dynapi_overrides.h:263
SDL_PIXELFORMAT_UNKNOWN
@ SDL_PIXELFORMAT_UNKNOWN
Definition: SDL_pixels.h:173
SDL_AddEventWatch
#define SDL_AddEventWatch
Definition: SDL_dynapi_overrides.h:128
SDL_RendererEventWatch
static int SDL_RendererEventWatch(void *userdata, SDL_Event *event)
Definition: SDL_render.c:662
SDL_RenderDrawLineF
int SDL_RenderDrawLineF(SDL_Renderer *renderer, float x1, float y1, float x2, float y2)
Draw a line on the current rendering target.
Definition: SDL_render.c:2414
SDL_FRect
A rectangle, with the origin at the upper left (floating point).
Definition: SDL_rect.h:87
y2
GLfixed GLfixed GLfixed y2
Definition: SDL_opengl_glext.h:4583
SDL_GetSurfaceColorMod
#define SDL_GetSurfaceColorMod
Definition: SDL_dynapi_overrides.h:456
SDL_RenderCommand::draw
struct SDL_RenderCommand::@30::@33 draw
SDL_RenderDriver::info
SDL_RendererInfo info
Definition: SDL_sysrender.h:241
SDL_ConvertPixels
#define SDL_ConvertPixels
Definition: SDL_dynapi_overrides.h:465
SDL_RenderGetClipRect
void SDL_RenderGetClipRect(SDL_Renderer *renderer, SDL_Rect *rect)
Get the clip rectangle for the current target.
Definition: SDL_render.c:2134
SDL_MOUSEBUTTONDOWN
@ SDL_MOUSEBUTTONDOWN
Definition: SDL_events.h:106
angle
GLfloat angle
Definition: SDL_opengl_glext.h:6097
SDL_Renderer::logical_w_backup
int logical_w_backup
Definition: SDL_sysrender.h:179
SDL_Renderer::clipping_enabled
SDL_bool clipping_enabled
Definition: SDL_sysrender.h:194
SDL_Renderer::magic
const void * magic
Definition: SDL_sysrender.h:124
SDL_RenderCopyF
int SDL_RenderCopyF(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Copy a portion of the texture to the current rendering target.
Definition: SDL_render.c:2924
SDL_RendererInfo::name
const char * name
Definition: SDL_render.h:80
SDL_BLENDMODE_NONE_FULL
#define SDL_BLENDMODE_NONE_FULL
Definition: SDL_render.c:62
SDL_WINDOWEVENT_HIDDEN
@ SDL_WINDOWEVENT_HIDDEN
Definition: SDL_video.h:150
SDL_SetTextureColorMod
int SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b)
Set an additional color value used in render copy operations.
Definition: SDL_render.c:1374
CHECK_RENDERER_MAGIC
#define CHECK_RENDERER_MAGIC(renderer, retval)
Definition: SDL_render.c:38
PrepQueueCmdDraw
static int PrepQueueCmdDraw(SDL_Renderer *renderer, const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a)
Definition: SDL_render.c:491
SDL_Event
General event structure.
Definition: SDL_events.h:557
SDL_WINDOWEVENT
@ SDL_WINDOWEVENT
Definition: SDL_events.h:92
SDL_HINT_RENDER_DRIVER
#define SDL_HINT_RENDER_DRIVER
A variable specifying which render driver to use.
Definition: SDL_hints.h:85
SDL_Renderer::QueueDrawPoints
int(* QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
Definition: SDL_sysrender.h:132
SDL_WINDOWEVENT_RESTORED
@ SDL_WINDOWEVENT_RESTORED
Definition: SDL_video.h:161
PrepQueueCmdDrawSolid
static SDL_RenderCommand * PrepQueueCmdDrawSolid(SDL_Renderer *renderer, const SDL_RenderCommandType cmdtype)
Definition: SDL_render.c:507
SDL_ISPIXELFORMAT_ALPHA
#define SDL_ISPIXELFORMAT_ALPHA(format)
Definition: SDL_pixels.h:154
SDL_Renderer::r
Uint8 r
Definition: SDL_sysrender.h:209
SDL_RenderFillRects
int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect *rects, int count)
Fill some number of rectangles on the current rendering target with the drawing color.
Definition: SDL_render.c:2772
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_Renderer::render_commands_pool
SDL_RenderCommand * render_commands_pool
Definition: SDL_sysrender.h:216
SDL_Renderer::a
Uint8 a
Definition: SDL_sysrender.h:209
SDL_RenderFlush
int SDL_RenderFlush(SDL_Renderer *renderer)
Force the rendering context to flush any pending commands to the underlying rendering API.
Definition: SDL_render.c:261
SDL_SetTextureBlendMode
int SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode)
Set the blend mode used for texture copy operations.
Definition: SDL_render.c:1439
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_RendererInfo::texture_formats
Uint32 texture_formats[16]
Definition: SDL_render.h:83
SDL_RendererInfo::max_texture_height
int max_texture_height
Definition: SDL_render.h:85
SDL_GetRenderDriverInfo
int SDL_GetRenderDriverInfo(int index, SDL_RendererInfo *info)
Get information about a specific 2D rendering driver for the current display.
Definition: SDL_render.c:637
void
const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char const char const SDL_SCANF_FORMAT_STRING char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
Definition: SDL_dynapi_procs.h:89
SDL_PIXELFORMAT_YV12
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:277
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:262
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_RENDERCMD_SETDRAWCOLOR
@ SDL_RENDERCMD_SETDRAWCOLOR
Definition: SDL_sysrender.h:77
SDL_Renderer::QueueCopy
int(* QueueCopy)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Definition: SDL_sysrender.h:138
SDL_GetTextureBlendMode
int SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode)
Get the blend mode used for texture copy operations.
Definition: SDL_render.c:1457
SDL_Renderer::window
SDL_Window * window
Definition: SDL_sysrender.h:173
SDL_TEXTUREACCESS_STREAMING
@ SDL_TEXTUREACCESS_STREAMING
Definition: SDL_render.h:94
SDL_Renderer::target
SDL_Texture * target
Definition: SDL_sysrender.h:206
texture
GLenum GLenum GLuint texture
Definition: SDL_opengl_glext.h:1178
texture_magic
static char texture_magic
Definition: SDL_render.c:109
QueueCmdCopy
static int QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Definition: SDL_render.c:593
SDL_RenderDrawRects
int SDL_RenderDrawRects(SDL_Renderer *renderer, const SDL_Rect *rects, int count)
Draw some number of rectangles on the current rendering target.
Definition: SDL_render.c:2670
rects
EGLSurface EGLint * rects
Definition: eglext.h:282
SDL_FORCE_INLINE
#define SDL_FORCE_INLINE
Definition: begin_code.h:147
SDL_RenderCopyEx
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)
Copy a portion of the source texture to the current rendering target, rotating it by angle around the...
Definition: SDL_render.c:2983
SDL_RenderDrawPointsF
int SDL_RenderDrawPointsF(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
Draw multiple points on the current rendering target.
Definition: SDL_render.c:2360
SDL_PIXELFORMAT_ABGR8888
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:254
DebugLogRenderCommands
static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd)
Definition: SDL_render.c:112
SDL_GetBlendModeAlphaOperation
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3377
SDL_BlendMode
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_RenderDrawRect
int SDL_RenderDrawRect(SDL_Renderer *renderer, const SDL_Rect *rect)
Draw a rectangle on the current rendering target.
Definition: SDL_render.c:2621
GL_RenderDriver
SDL_RenderDriver GL_RenderDriver
SDL_GetBlendModeSrcColorFactor
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3342
SDL_Renderer::clipping_enabled_backup
SDL_bool clipping_enabled_backup
Definition: SDL_sysrender.h:195
PSP_RenderDriver
SDL_RenderDriver PSP_RenderDriver
SDL_GetRendererInfo
int SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info)
Get information about a rendering context.
Definition: SDL_render.c:1013
SDL_HasColorKey
#define SDL_HasColorKey
Definition: SDL_dynapi_overrides.h:699
SDL_RenderDrawLines
int SDL_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points, int count)
Draw a series of connected lines on the current rendering target.
Definition: SDL_render.c:2535
SDL_Renderer::clip_rect
SDL_Rect clip_rect
Definition: SDL_sysrender.h:190
SDL_RenderGetMetalCommandEncoder
void * SDL_RenderGetMetalCommandEncoder(SDL_Renderer *renderer)
Get the Metal command encoder for the current frame.
Definition: SDL_render.c:3283
SDL_RENDERCMD_CLEAR
@ SDL_RENDERCMD_CLEAR
Definition: SDL_sysrender.h:78
QueueCmdDrawLines
static int QueueCmdDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, const int count)
Definition: SDL_render.c:543
SDL_Point::y
int y
Definition: SDL_rect.h:51
SDL_WINDOWEVENT_MAXIMIZED
@ SDL_WINDOWEVENT_MAXIMIZED
Definition: SDL_video.h:160
SDL_WINDOWRENDERDATA
#define SDL_WINDOWRENDERDATA
Definition: SDL_render.c:36
GetClosestSupportedFormat
static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, Uint32 format)
Definition: SDL_render.c:1070
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_Renderer::UnlockTexture
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:154
SDL_RendererInfo::num_texture_formats
Uint32 num_texture_formats
Definition: SDL_render.h:82
SDL_DelEventWatch
#define SDL_DelEventWatch
Definition: SDL_dynapi_overrides.h:129
SDL_GetShortBlendMode
static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode)
Definition: SDL_render.c:3295
SDL_SW_UpdateYUVTexture
int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_yuv_sw.c:139
SDL_Renderer::DestroyTexture
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:159
SDL_Renderer::UpdateTextureYUV
int(* UpdateTextureYUV)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Definition: SDL_sysrender.h:147
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_SetRenderDrawColor
int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Set the color used for drawing operations (Rect, Line and Clear).
Definition: SDL_render.c:2177