mirror of
https://github.com/Ryujinx/SDL.git
synced 2025-01-09 01:25:41 +00:00
render: Move to a batching system for rendering (work in progress).
This commit is contained in:
parent
e0cc19f2d8
commit
5fb67f9f55
|
@ -1029,6 +1029,31 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
|
#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A variable controlling whether the 2D render API is compatible or efficient.
|
||||||
|
*
|
||||||
|
* This variable can be set to the following values:
|
||||||
|
*
|
||||||
|
* "0" - Don't use batching to make rendering more efficient.
|
||||||
|
* "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls.
|
||||||
|
*
|
||||||
|
* Up to SDL 2.0.9, the render API would draw immediately when requested. Now
|
||||||
|
* it batches up draw requests and sends them all to the GPU only when forced
|
||||||
|
* to (during SDL_RenderPresent, when changing render targets, by updating a
|
||||||
|
* texture that the batch needs, etc). This is significantly more efficient,
|
||||||
|
* but it can cause problems for apps that expect to render on top of the
|
||||||
|
* render API's output. As such, SDL will disable batching if a specific
|
||||||
|
* render backend is requested (since this might indicate that the app is
|
||||||
|
* planning to use the underlying graphics API directly). This hint can
|
||||||
|
* be used to explicitly request batching in this instance. It is a contract
|
||||||
|
* that you will either never use the underlying graphics API directly, or
|
||||||
|
* if you do, you will call SDL_RenderFlush() before you do so any current
|
||||||
|
* batch goes to the GPU before your work begins. Not following this contract
|
||||||
|
* will result in undefined behavior.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief An enumeration of hint priorities
|
* \brief An enumeration of hint priorities
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -105,6 +105,258 @@ static const SDL_RenderDriver *render_drivers[] = {
|
||||||
static char renderer_magic;
|
static char renderer_magic;
|
||||||
static char texture_magic;
|
static char texture_magic;
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
FlushRenderCommands(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = renderer->RunCommandQueue(renderer, renderer->render_commands, renderer->vertex_data, renderer->vertex_data_used);
|
||||||
|
|
||||||
|
/* 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++;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, size_t *offset)
|
||||||
|
{
|
||||||
|
const size_t needed = renderer->vertex_data_used + numbytes;
|
||||||
|
void *retval;
|
||||||
|
|
||||||
|
while (needed > renderer->vertex_data_allocation) {
|
||||||
|
const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 128;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = ((Uint8 *) renderer->vertex_data) + renderer->vertex_data_used;
|
||||||
|
if (offset) {
|
||||||
|
*offset = renderer->vertex_data_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->vertex_data_used += 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
|
||||||
|
QueueCmdUpdateViewport(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->command = SDL_RENDERCMD_SETVIEWPORT;
|
||||||
|
SDL_memcpy(&cmd->data.viewport, &renderer->viewport, sizeof (cmd->data.viewport));
|
||||||
|
return FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
QueueCmdUpdateClipRect(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
return FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
QueueCmdClear(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->command = SDL_RENDERCMD_CLEAR;
|
||||||
|
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 FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_RenderCommand *
|
||||||
|
PrepQueueCmdDrawSolid(SDL_Renderer *renderer, const SDL_RenderCommandType cmdtype)
|
||||||
|
{
|
||||||
|
SDL_RenderCommand *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 < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_RenderCommand *
|
||||||
|
PrepQueueCmdDrawTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_RenderCommandType cmdtype)
|
||||||
|
{
|
||||||
|
SDL_RenderCommand *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 < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
SDL_assert(renderer->QueueCopyEx != NULL); /* should have caught at higher level. */
|
||||||
|
int retval = -1;
|
||||||
|
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 < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int UpdateLogicalSize(SDL_Renderer *renderer);
|
static int UpdateLogicalSize(SDL_Renderer *renderer);
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -183,7 +435,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
||||||
renderer->viewport.y = 0;
|
renderer->viewport.y = 0;
|
||||||
renderer->viewport.w = w;
|
renderer->viewport.w = w;
|
||||||
renderer->viewport.h = h;
|
renderer->viewport.h = h;
|
||||||
renderer->UpdateViewport(renderer);
|
QueueCmdUpdateViewport(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,12 +552,25 @@ SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags,
|
||||||
return 0;
|
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->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_Renderer *
|
||||||
SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
|
SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
|
||||||
{
|
{
|
||||||
#if !SDL_RENDER_DISABLED
|
#if !SDL_RENDER_DISABLED
|
||||||
SDL_Renderer *renderer = NULL;
|
SDL_Renderer *renderer = NULL;
|
||||||
int n = SDL_GetNumRenderDrivers();
|
int n = SDL_GetNumRenderDrivers();
|
||||||
|
SDL_bool batching = SDL_TRUE;
|
||||||
const char *hint;
|
const char *hint;
|
||||||
|
|
||||||
if (!window) {
|
if (!window) {
|
||||||
|
@ -335,6 +600,9 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
|
||||||
if (SDL_strcasecmp(hint, driver->info.name) == 0) {
|
if (SDL_strcasecmp(hint, driver->info.name) == 0) {
|
||||||
/* Create a new renderer instance */
|
/* Create a new renderer instance */
|
||||||
renderer = driver->CreateRenderer(window, flags);
|
renderer = driver->CreateRenderer(window, flags);
|
||||||
|
if (renderer) {
|
||||||
|
batching = SDL_FALSE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,9 +634,18 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
|
||||||
}
|
}
|
||||||
/* Create a new renderer instance */
|
/* Create a new renderer instance */
|
||||||
renderer = render_drivers[index]->CreateRenderer(window, flags);
|
renderer = render_drivers[index]->CreateRenderer(window, flags);
|
||||||
|
batching = SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
|
VerifyDrawQueueFunctions(renderer);
|
||||||
|
|
||||||
|
/* let app/user override batching decisions. */
|
||||||
|
if (SDL_GetHint(SDL_HINT_RENDER_BATCHING)) {
|
||||||
|
batching = SDL_GetHintBoolean(SDL_HINT_RENDER_BATCHING, SDL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->batching = batching;
|
||||||
renderer->magic = &renderer_magic;
|
renderer->magic = &renderer_magic;
|
||||||
renderer->window = window;
|
renderer->window = window;
|
||||||
renderer->target_mutex = SDL_CreateMutex();
|
renderer->target_mutex = SDL_CreateMutex();
|
||||||
|
@ -377,6 +654,9 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
|
||||||
renderer->dpi_scale.x = 1.0f;
|
renderer->dpi_scale.x = 1.0f;
|
||||||
renderer->dpi_scale.y = 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) {
|
if (window && renderer->GetOutputSize) {
|
||||||
int window_w, window_h;
|
int window_w, window_h;
|
||||||
int output_w, output_h;
|
int output_w, output_h;
|
||||||
|
@ -418,11 +698,15 @@ SDL_CreateSoftwareRenderer(SDL_Surface * surface)
|
||||||
renderer = SW_CreateRendererForSurface(surface);
|
renderer = SW_CreateRendererForSurface(surface);
|
||||||
|
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
|
VerifyDrawQueueFunctions(renderer);
|
||||||
renderer->magic = &renderer_magic;
|
renderer->magic = &renderer_magic;
|
||||||
renderer->target_mutex = SDL_CreateMutex();
|
renderer->target_mutex = SDL_CreateMutex();
|
||||||
renderer->scale.x = 1.0f;
|
renderer->scale.x = 1.0f;
|
||||||
renderer->scale.y = 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);
|
SDL_RenderSetViewport(renderer, NULL);
|
||||||
}
|
}
|
||||||
return renderer;
|
return renderer;
|
||||||
|
@ -758,11 +1042,8 @@ SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
|
||||||
texture->b = b;
|
texture->b = b;
|
||||||
if (texture->native) {
|
if (texture->native) {
|
||||||
return SDL_SetTextureColorMod(texture->native, r, g, b);
|
return SDL_SetTextureColorMod(texture->native, r, g, b);
|
||||||
} else if (renderer->SetTextureColorMod) {
|
|
||||||
return renderer->SetTextureColorMod(renderer, texture);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -799,11 +1080,8 @@ SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
|
||||||
texture->a = alpha;
|
texture->a = alpha;
|
||||||
if (texture->native) {
|
if (texture->native) {
|
||||||
return SDL_SetTextureAlphaMod(texture->native, alpha);
|
return SDL_SetTextureAlphaMod(texture->native, alpha);
|
||||||
} else if (renderer->SetTextureAlphaMod) {
|
|
||||||
return renderer->SetTextureAlphaMod(renderer, texture);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -831,11 +1109,8 @@ SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
|
||||||
texture->blendMode = blendMode;
|
texture->blendMode = blendMode;
|
||||||
if (texture->native) {
|
if (texture->native) {
|
||||||
return SDL_SetTextureBlendMode(texture->native, blendMode);
|
return SDL_SetTextureBlendMode(texture->native, blendMode);
|
||||||
} else if (renderer->SetTextureBlendMode) {
|
|
||||||
return renderer->SetTextureBlendMode(renderer, texture);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -940,7 +1215,6 @@ int
|
||||||
SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
||||||
const void *pixels, int pitch)
|
const void *pixels, int pitch)
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer;
|
|
||||||
SDL_Rect full_rect;
|
SDL_Rect full_rect;
|
||||||
|
|
||||||
CHECK_TEXTURE_MAGIC(texture, -1);
|
CHECK_TEXTURE_MAGIC(texture, -1);
|
||||||
|
@ -967,7 +1241,10 @@ SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
||||||
} else if (texture->native) {
|
} else if (texture->native) {
|
||||||
return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
|
return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
|
||||||
} else {
|
} else {
|
||||||
renderer = texture->renderer;
|
SDL_Renderer *renderer = texture->renderer;
|
||||||
|
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
|
return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,6 +1354,9 @@ int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
||||||
renderer = texture->renderer;
|
renderer = texture->renderer;
|
||||||
SDL_assert(renderer->UpdateTextureYUV);
|
SDL_assert(renderer->UpdateTextureYUV);
|
||||||
if (renderer->UpdateTextureYUV) {
|
if (renderer->UpdateTextureYUV) {
|
||||||
|
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
|
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
|
||||||
} else {
|
} else {
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
|
@ -1107,7 +1387,6 @@ int
|
||||||
SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
||||||
void **pixels, int *pitch)
|
void **pixels, int *pitch)
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer;
|
|
||||||
SDL_Rect full_rect;
|
SDL_Rect full_rect;
|
||||||
|
|
||||||
CHECK_TEXTURE_MAGIC(texture, -1);
|
CHECK_TEXTURE_MAGIC(texture, -1);
|
||||||
|
@ -1125,11 +1404,18 @@ SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture->yuv) {
|
if (texture->yuv) {
|
||||||
|
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return SDL_LockTextureYUV(texture, rect, pixels, pitch);
|
return SDL_LockTextureYUV(texture, rect, pixels, pitch);
|
||||||
} else if (texture->native) {
|
} else if (texture->native) {
|
||||||
|
/* Calls a real SDL_LockTexture/SDL_UnlockTexture on unlock, flushing then. */
|
||||||
return SDL_LockTextureNative(texture, rect, pixels, pitch);
|
return SDL_LockTextureNative(texture, rect, pixels, pitch);
|
||||||
} else {
|
} else {
|
||||||
renderer = texture->renderer;
|
SDL_Renderer *renderer = texture->renderer;
|
||||||
|
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
|
return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1179,8 +1465,6 @@ SDL_UnlockTextureNative(SDL_Texture * texture)
|
||||||
void
|
void
|
||||||
SDL_UnlockTexture(SDL_Texture * texture)
|
SDL_UnlockTexture(SDL_Texture * texture)
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer;
|
|
||||||
|
|
||||||
CHECK_TEXTURE_MAGIC(texture, );
|
CHECK_TEXTURE_MAGIC(texture, );
|
||||||
|
|
||||||
if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
|
if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
|
||||||
|
@ -1191,7 +1475,7 @@ SDL_UnlockTexture(SDL_Texture * texture)
|
||||||
} else if (texture->native) {
|
} else if (texture->native) {
|
||||||
SDL_UnlockTextureNative(texture);
|
SDL_UnlockTextureNative(texture);
|
||||||
} else {
|
} else {
|
||||||
renderer = texture->renderer;
|
SDL_Renderer *renderer = texture->renderer;
|
||||||
renderer->UnlockTexture(renderer, texture);
|
renderer->UnlockTexture(renderer, texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,6 +1500,8 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlushRenderCommands(renderer); /* time to send everything to the GPU! */
|
||||||
|
|
||||||
/* texture == NULL is valid and means reset the target to the window */
|
/* texture == NULL is valid and means reset the target to the window */
|
||||||
if (texture) {
|
if (texture) {
|
||||||
CHECK_TEXTURE_MAGIC(texture, -1);
|
CHECK_TEXTURE_MAGIC(texture, -1);
|
||||||
|
@ -1271,10 +1557,10 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->target_mutex);
|
SDL_UnlockMutex(renderer->target_mutex);
|
||||||
|
|
||||||
if (renderer->UpdateViewport(renderer) < 0) {
|
if (QueueCmdUpdateViewport(renderer) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (renderer->UpdateClipRect(renderer) < 0) {
|
if (QueueCmdUpdateClipRect(renderer) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1465,7 +1751,7 @@ SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return renderer->UpdateViewport(renderer);
|
return QueueCmdUpdateViewport(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1496,7 +1782,7 @@ SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
|
||||||
renderer->clipping_enabled = SDL_FALSE;
|
renderer->clipping_enabled = SDL_FALSE;
|
||||||
SDL_zero(renderer->clip_rect);
|
SDL_zero(renderer->clip_rect);
|
||||||
}
|
}
|
||||||
return renderer->UpdateClipRect(renderer);
|
return QueueCmdUpdateClipRect(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1601,12 +1887,7 @@ int
|
||||||
SDL_RenderClear(SDL_Renderer * renderer)
|
SDL_RenderClear(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
CHECK_RENDERER_MAGIC(renderer, -1);
|
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||||
|
return QueueCmdClear(renderer);
|
||||||
/* Don't draw while we're hidden */
|
|
||||||
if (renderer->hidden) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return renderer->RenderClear(renderer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1625,7 +1906,7 @@ RenderDrawPointsWithRects(SDL_Renderer * renderer,
|
||||||
{
|
{
|
||||||
SDL_FRect *frects;
|
SDL_FRect *frects;
|
||||||
int i;
|
int i;
|
||||||
int status;
|
int status = -1;
|
||||||
|
|
||||||
frects = SDL_stack_alloc(SDL_FRect, count);
|
frects = SDL_stack_alloc(SDL_FRect, count);
|
||||||
if (!frects) {
|
if (!frects) {
|
||||||
|
@ -1638,7 +1919,7 @@ RenderDrawPointsWithRects(SDL_Renderer * renderer,
|
||||||
frects[i].h = renderer->scale.y;
|
frects[i].h = renderer->scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = renderer->RenderFillRects(renderer, frects, count);
|
status = QueueCmdFillRects(renderer, frects, count);
|
||||||
|
|
||||||
SDL_stack_free(frects);
|
SDL_stack_free(frects);
|
||||||
|
|
||||||
|
@ -1680,7 +1961,7 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,
|
||||||
fpoints[i].y = points[i].y * renderer->scale.y;
|
fpoints[i].y = points[i].y * renderer->scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = renderer->RenderDrawPoints(renderer, fpoints, count);
|
status = QueueCmdDrawPoints(renderer, fpoints, count);
|
||||||
|
|
||||||
SDL_stack_free(fpoints);
|
SDL_stack_free(fpoints);
|
||||||
|
|
||||||
|
@ -1706,20 +1987,18 @@ RenderDrawLinesWithRects(SDL_Renderer * renderer,
|
||||||
SDL_FRect *frect;
|
SDL_FRect *frect;
|
||||||
SDL_FRect *frects;
|
SDL_FRect *frects;
|
||||||
SDL_FPoint fpoints[2];
|
SDL_FPoint fpoints[2];
|
||||||
int i, nrects;
|
int i, nrects = 0;
|
||||||
int status;
|
int status = 0;
|
||||||
|
|
||||||
frects = SDL_stack_alloc(SDL_FRect, count-1);
|
frects = SDL_stack_alloc(SDL_FRect, count-1);
|
||||||
if (!frects) {
|
if (!frects) {
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
status = 0;
|
|
||||||
nrects = 0;
|
|
||||||
for (i = 0; i < count-1; ++i) {
|
for (i = 0; i < count-1; ++i) {
|
||||||
if (points[i].x == points[i+1].x) {
|
if (points[i].x == points[i+1].x) {
|
||||||
int minY = SDL_min(points[i].y, points[i+1].y);
|
const int minY = SDL_min(points[i].y, points[i+1].y);
|
||||||
int maxY = SDL_max(points[i].y, points[i+1].y);
|
const int maxY = SDL_max(points[i].y, points[i+1].y);
|
||||||
|
|
||||||
frect = &frects[nrects++];
|
frect = &frects[nrects++];
|
||||||
frect->x = points[i].x * renderer->scale.x;
|
frect->x = points[i].x * renderer->scale.x;
|
||||||
|
@ -1727,8 +2006,8 @@ RenderDrawLinesWithRects(SDL_Renderer * renderer,
|
||||||
frect->w = renderer->scale.x;
|
frect->w = renderer->scale.x;
|
||||||
frect->h = (maxY - minY + 1) * renderer->scale.y;
|
frect->h = (maxY - minY + 1) * renderer->scale.y;
|
||||||
} else if (points[i].y == points[i+1].y) {
|
} else if (points[i].y == points[i+1].y) {
|
||||||
int minX = SDL_min(points[i].x, points[i+1].x);
|
const int minX = SDL_min(points[i].x, points[i+1].x);
|
||||||
int maxX = SDL_max(points[i].x, points[i+1].x);
|
const int maxX = SDL_max(points[i].x, points[i+1].x);
|
||||||
|
|
||||||
frect = &frects[nrects++];
|
frect = &frects[nrects++];
|
||||||
frect->x = minX * renderer->scale.x;
|
frect->x = minX * renderer->scale.x;
|
||||||
|
@ -1741,11 +2020,11 @@ RenderDrawLinesWithRects(SDL_Renderer * renderer,
|
||||||
fpoints[0].y = points[i].y * renderer->scale.y;
|
fpoints[0].y = points[i].y * renderer->scale.y;
|
||||||
fpoints[1].x = points[i+1].x * renderer->scale.x;
|
fpoints[1].x = points[i+1].x * renderer->scale.x;
|
||||||
fpoints[1].y = points[i+1].y * renderer->scale.y;
|
fpoints[1].y = points[i+1].y * renderer->scale.y;
|
||||||
status += renderer->RenderDrawLines(renderer, fpoints, 2);
|
status += QueueCmdDrawLines(renderer, fpoints, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status += renderer->RenderFillRects(renderer, frects, nrects);
|
status += QueueCmdFillRects(renderer, frects, nrects);
|
||||||
|
|
||||||
SDL_stack_free(frects);
|
SDL_stack_free(frects);
|
||||||
|
|
||||||
|
@ -1790,7 +2069,7 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,
|
||||||
fpoints[i].y = points[i].y * renderer->scale.y;
|
fpoints[i].y = points[i].y * renderer->scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = renderer->RenderDrawLines(renderer, fpoints, count);
|
status = QueueCmdDrawLines(renderer, fpoints, count);
|
||||||
|
|
||||||
SDL_stack_free(fpoints);
|
SDL_stack_free(fpoints);
|
||||||
|
|
||||||
|
@ -1904,7 +2183,7 @@ SDL_RenderFillRects(SDL_Renderer * renderer,
|
||||||
frects[i].h = rects[i].h * renderer->scale.y;
|
frects[i].h = rects[i].h * renderer->scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = renderer->RenderFillRects(renderer, frects, count);
|
status = QueueCmdFillRects(renderer, frects, count);
|
||||||
|
|
||||||
SDL_stack_free(frects);
|
SDL_stack_free(frects);
|
||||||
|
|
||||||
|
@ -1960,7 +2239,9 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
frect.w = real_dstrect.w * renderer->scale.x;
|
frect.w = real_dstrect.w * renderer->scale.x;
|
||||||
frect.h = real_dstrect.h * renderer->scale.y;
|
frect.h = real_dstrect.h * renderer->scale.y;
|
||||||
|
|
||||||
return renderer->RenderCopy(renderer, texture, &real_srcrect, &frect);
|
texture->last_command_generation = renderer->render_command_generation;
|
||||||
|
|
||||||
|
return QueueCmdCopy(renderer, texture, &real_srcrect, &frect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1985,7 +2266,7 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
if (renderer != texture->renderer) {
|
if (renderer != texture->renderer) {
|
||||||
return SDL_SetError("Texture was not created with this renderer");
|
return SDL_SetError("Texture was not created with this renderer");
|
||||||
}
|
}
|
||||||
if (!renderer->RenderCopyEx) {
|
if (!renderer->QueueCopyEx) {
|
||||||
return SDL_SetError("Renderer does not support RenderCopyEx");
|
return SDL_SetError("Renderer does not support RenderCopyEx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2032,7 +2313,9 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
fcenter.x = real_center.x * renderer->scale.x;
|
fcenter.x = real_center.x * renderer->scale.x;
|
||||||
fcenter.y = real_center.y * renderer->scale.y;
|
fcenter.y = real_center.y * renderer->scale.y;
|
||||||
|
|
||||||
return renderer->RenderCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip);
|
texture->last_command_generation = renderer->render_command_generation;
|
||||||
|
|
||||||
|
return QueueCmdCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2047,6 +2330,8 @@ SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlushRenderCommands(renderer); /* we need to render before we read the results. */
|
||||||
|
|
||||||
if (!format) {
|
if (!format) {
|
||||||
format = SDL_GetWindowPixelFormat(renderer->window);
|
format = SDL_GetWindowPixelFormat(renderer->window);
|
||||||
}
|
}
|
||||||
|
@ -2077,7 +2362,9 @@ SDL_RenderPresent(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
CHECK_RENDERER_MAGIC(renderer, );
|
CHECK_RENDERER_MAGIC(renderer, );
|
||||||
|
|
||||||
/* Don't draw while we're hidden */
|
FlushRenderCommands(renderer); /* time to send everything to the GPU! */
|
||||||
|
|
||||||
|
/* Don't present while we're hidden */
|
||||||
if (renderer->hidden) {
|
if (renderer->hidden) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2093,7 +2380,9 @@ SDL_DestroyTexture(SDL_Texture * texture)
|
||||||
|
|
||||||
renderer = texture->renderer;
|
renderer = texture->renderer;
|
||||||
if (texture == renderer->target) {
|
if (texture == renderer->target) {
|
||||||
SDL_SetRenderTarget(renderer, NULL);
|
SDL_SetRenderTarget(renderer, NULL); /* implies command queue flush */
|
||||||
|
} else {
|
||||||
|
FlushRenderCommandsIfTextureNeeded(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->magic = NULL;
|
texture->magic = NULL;
|
||||||
|
@ -2122,10 +2411,31 @@ SDL_DestroyTexture(SDL_Texture * texture)
|
||||||
void
|
void
|
||||||
SDL_DestroyRenderer(SDL_Renderer * renderer)
|
SDL_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
SDL_RenderCommand *cmd;
|
||||||
|
|
||||||
CHECK_RENDERER_MAGIC(renderer, );
|
CHECK_RENDERER_MAGIC(renderer, );
|
||||||
|
|
||||||
SDL_DelEventWatch(SDL_RendererEventWatch, 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);
|
||||||
|
|
||||||
/* Free existing textures for this renderer */
|
/* Free existing textures for this renderer */
|
||||||
while (renderer->textures) {
|
while (renderer->textures) {
|
||||||
SDL_Texture *tex = renderer->textures; (void) tex;
|
SDL_Texture *tex = renderer->textures; (void) tex;
|
||||||
|
@ -2157,6 +2467,7 @@ int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
|
||||||
if (texture->native) {
|
if (texture->native) {
|
||||||
return SDL_GL_BindTexture(texture->native, texw, texh);
|
return SDL_GL_BindTexture(texture->native, texw, texh);
|
||||||
} else if (renderer && renderer->GL_BindTexture) {
|
} 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);
|
return renderer->GL_BindTexture(renderer, texture, texw, texh);
|
||||||
} else {
|
} else {
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
|
@ -2172,6 +2483,7 @@ int SDL_GL_UnbindTexture(SDL_Texture *texture)
|
||||||
if (texture->native) {
|
if (texture->native) {
|
||||||
return SDL_GL_UnbindTexture(texture->native);
|
return SDL_GL_UnbindTexture(texture->native);
|
||||||
} else if (renderer && renderer->GL_UnbindTexture) {
|
} else if (renderer && renderer->GL_UnbindTexture) {
|
||||||
|
FlushRenderCommandsIfTextureNeeded(texture); /* in case the app messed with it. */
|
||||||
return renderer->GL_UnbindTexture(renderer, texture);
|
return renderer->GL_UnbindTexture(renderer, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2184,6 +2496,7 @@ SDL_RenderGetMetalLayer(SDL_Renderer * renderer)
|
||||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||||
|
|
||||||
if (renderer->GetMetalLayer) {
|
if (renderer->GetMetalLayer) {
|
||||||
|
FlushRenderCommands(renderer); /* in case the app is going to mess with it. */
|
||||||
return renderer->GetMetalLayer(renderer);
|
return renderer->GetMetalLayer(renderer);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2195,6 +2508,7 @@ SDL_RenderGetMetalCommandEncoder(SDL_Renderer * renderer)
|
||||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||||
|
|
||||||
if (renderer->GetMetalCommandEncoder) {
|
if (renderer->GetMetalCommandEncoder) {
|
||||||
|
FlushRenderCommands(renderer); /* in case the app is going to mess with it. */
|
||||||
return renderer->GetMetalCommandEncoder(renderer);
|
return renderer->GetMetalCommandEncoder(renderer);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -75,12 +75,51 @@ struct SDL_Texture
|
||||||
int pitch;
|
int pitch;
|
||||||
SDL_Rect locked_rect;
|
SDL_Rect locked_rect;
|
||||||
|
|
||||||
|
Uint32 last_command_generation; /* last command queue generation this texture was in. */
|
||||||
|
|
||||||
void *driverdata; /**< Driver specific texture representation */
|
void *driverdata; /**< Driver specific texture representation */
|
||||||
|
|
||||||
SDL_Texture *prev;
|
SDL_Texture *prev;
|
||||||
SDL_Texture *next;
|
SDL_Texture *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SDL_RENDERCMD_NO_OP,
|
||||||
|
SDL_RENDERCMD_SETVIEWPORT,
|
||||||
|
SDL_RENDERCMD_SETCLIPRECT,
|
||||||
|
SDL_RENDERCMD_CLEAR,
|
||||||
|
SDL_RENDERCMD_DRAW_POINTS,
|
||||||
|
SDL_RENDERCMD_DRAW_LINES,
|
||||||
|
SDL_RENDERCMD_FILL_RECTS,
|
||||||
|
SDL_RENDERCMD_COPY,
|
||||||
|
SDL_RENDERCMD_COPY_EX
|
||||||
|
} SDL_RenderCommandType;
|
||||||
|
|
||||||
|
typedef struct SDL_RenderCommand
|
||||||
|
{
|
||||||
|
SDL_RenderCommandType command;
|
||||||
|
union {
|
||||||
|
SDL_Rect viewport;
|
||||||
|
struct {
|
||||||
|
SDL_bool enabled;
|
||||||
|
SDL_Rect rect;
|
||||||
|
} cliprect;
|
||||||
|
struct {
|
||||||
|
size_t first;
|
||||||
|
size_t count;
|
||||||
|
Uint8 r, g, b, a;
|
||||||
|
SDL_BlendMode blend;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
} draw;
|
||||||
|
struct {
|
||||||
|
Uint8 r, g, b, a;
|
||||||
|
} color;
|
||||||
|
} data;
|
||||||
|
struct SDL_RenderCommand *next;
|
||||||
|
} SDL_RenderCommand;
|
||||||
|
|
||||||
|
|
||||||
/* Define the SDL renderer structure */
|
/* Define the SDL renderer structure */
|
||||||
struct SDL_Renderer
|
struct SDL_Renderer
|
||||||
{
|
{
|
||||||
|
@ -90,12 +129,18 @@ struct SDL_Renderer
|
||||||
int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
|
int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
|
||||||
SDL_bool (*SupportsBlendMode)(SDL_Renderer * renderer, SDL_BlendMode blendMode);
|
SDL_bool (*SupportsBlendMode)(SDL_Renderer * renderer, SDL_BlendMode blendMode);
|
||||||
int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
int (*SetTextureColorMod) (SDL_Renderer * renderer,
|
int (*QueueDrawPoints) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points,
|
||||||
SDL_Texture * texture);
|
int count);
|
||||||
int (*SetTextureAlphaMod) (SDL_Renderer * renderer,
|
int (*QueueDrawLines) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points,
|
||||||
SDL_Texture * texture);
|
int count);
|
||||||
int (*SetTextureBlendMode) (SDL_Renderer * renderer,
|
int (*QueueFillRects) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects,
|
||||||
SDL_Texture * texture);
|
int count);
|
||||||
|
int (*QueueCopy) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
|
||||||
|
int (*QueueCopyEx) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
|
||||||
|
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
|
||||||
|
int (*RunCommandQueue) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
|
||||||
int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
|
int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * rect, const void *pixels,
|
const SDL_Rect * rect, const void *pixels,
|
||||||
int pitch);
|
int pitch);
|
||||||
|
@ -108,20 +153,6 @@ struct SDL_Renderer
|
||||||
const SDL_Rect * rect, void **pixels, int *pitch);
|
const SDL_Rect * rect, void **pixels, int *pitch);
|
||||||
void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture);
|
int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
int (*UpdateViewport) (SDL_Renderer * renderer);
|
|
||||||
int (*UpdateClipRect) (SDL_Renderer * renderer);
|
|
||||||
int (*RenderClear) (SDL_Renderer * renderer);
|
|
||||||
int (*RenderDrawPoints) (SDL_Renderer * renderer, const SDL_FPoint * points,
|
|
||||||
int count);
|
|
||||||
int (*RenderDrawLines) (SDL_Renderer * renderer, const SDL_FPoint * points,
|
|
||||||
int count);
|
|
||||||
int (*RenderFillRects) (SDL_Renderer * renderer, const SDL_FRect * rects,
|
|
||||||
int count);
|
|
||||||
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
|
|
||||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
|
|
||||||
int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,
|
|
||||||
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
|
|
||||||
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
|
|
||||||
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch);
|
Uint32 format, void * pixels, int pitch);
|
||||||
void (*RenderPresent) (SDL_Renderer * renderer);
|
void (*RenderPresent) (SDL_Renderer * renderer);
|
||||||
|
@ -178,6 +209,16 @@ struct SDL_Renderer
|
||||||
Uint8 r, g, b, a; /**< Color for drawing operations values */
|
Uint8 r, g, b, a; /**< Color for drawing operations values */
|
||||||
SDL_BlendMode blendMode; /**< The drawing blend mode */
|
SDL_BlendMode blendMode; /**< The drawing blend mode */
|
||||||
|
|
||||||
|
SDL_bool batching;
|
||||||
|
SDL_RenderCommand *render_commands;
|
||||||
|
SDL_RenderCommand *render_commands_tail;
|
||||||
|
SDL_RenderCommand *render_commands_pool;
|
||||||
|
Uint32 render_command_generation;
|
||||||
|
|
||||||
|
void *vertex_data;
|
||||||
|
size_t vertex_data_used;
|
||||||
|
size_t vertex_data_allocation;
|
||||||
|
|
||||||
void *driverdata;
|
void *driverdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,6 +250,11 @@ extern SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode);
|
||||||
extern SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode);
|
extern SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode);
|
||||||
extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode);
|
extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode);
|
||||||
|
|
||||||
|
/* drivers call this during their Queue*() methods to make space in a array that are used
|
||||||
|
for a vertex buffer during RunCommandQueue(). Pointers returned here are only valid until
|
||||||
|
the next call, because it might be in an array that gets realloc()'d. */
|
||||||
|
extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, size_t *offset);
|
||||||
|
|
||||||
#endif /* SDL_sysrender_h_ */
|
#endif /* SDL_sysrender_h_ */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
Loading…
Reference in a new issue