SDL 2.0
SDL_render.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../SDL_internal.h"
22
23/* The SDL 2D rendering system */
24
25#include "SDL_assert.h"
26#include "SDL_hints.h"
27#include "SDL_log.h"
28#include "SDL_render.h"
29#include "SDL_sysrender.h"
31
32#if defined(__ANDROID__)
33# include "../core/android/SDL_android.h"
34#endif
35
36#define SDL_WINDOWRENDERDATA "_SDL_WindowRenderData"
37
38#define CHECK_RENDERER_MAGIC(renderer, retval) \
39 SDL_assert(renderer && renderer->magic == &renderer_magic); \
40 if (!renderer || renderer->magic != &renderer_magic) { \
41 SDL_SetError("Invalid renderer"); \
42 return retval; \
43 }
44
45#define CHECK_TEXTURE_MAGIC(texture, retval) \
46 SDL_assert(texture && texture->magic == &texture_magic); \
47 if (!texture || texture->magic != &texture_magic) { \
48 SDL_SetError("Invalid texture"); \
49 return retval; \
50 }
51
52/* Predefined blend modes */
53#define SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation, \
54 srcAlphaFactor, dstAlphaFactor, alphaOperation) \
55 (SDL_BlendMode)(((Uint32)colorOperation << 0) | \
56 ((Uint32)srcColorFactor << 4) | \
57 ((Uint32)dstColorFactor << 8) | \
58 ((Uint32)alphaOperation << 16) | \
59 ((Uint32)srcAlphaFactor << 20) | \
60 ((Uint32)dstAlphaFactor << 24))
61
62#define SDL_BLENDMODE_NONE_FULL \
63 SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD, \
64 SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD)
65
66#define SDL_BLENDMODE_BLEND_FULL \
67 SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, \
68 SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD)
69
70#define SDL_BLENDMODE_ADD_FULL \
71 SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD, \
72 SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
73
74#define SDL_BLENDMODE_MOD_FULL \
75 SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR, SDL_BLENDOPERATION_ADD, \
76 SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
77
78#if !SDL_RENDER_DISABLED
80#if SDL_VIDEO_RENDER_D3D
82#endif
83#if SDL_VIDEO_RENDER_D3D11
85#endif
86#if SDL_VIDEO_RENDER_METAL
88#endif
89#if SDL_VIDEO_RENDER_OGL
91#endif
92#if SDL_VIDEO_RENDER_OGL_ES2
94#endif
95#if SDL_VIDEO_RENDER_OGL_ES
97#endif
98#if SDL_VIDEO_RENDER_DIRECTFB
100#endif
101#if SDL_VIDEO_RENDER_PSP
103#endif
105};
106#endif /* !SDL_RENDER_DISABLED */
107
108static char renderer_magic;
109static char texture_magic;
110
111static SDL_INLINE void
113{
114#if 0
115 unsigned int i = 1;
116 SDL_Log("Render commands to flush:");
117 while (cmd) {
118 switch (cmd->command) {
120 SDL_Log(" %u. no-op", i++);
121 break;
122
124 SDL_Log(" %u. set viewport (first=%u, rect={(%d, %d), %dx%d})", i++,
125 (unsigned int) cmd->data.viewport.first,
126 cmd->data.viewport.rect.x, cmd->data.viewport.rect.y,
127 cmd->data.viewport.rect.w, cmd->data.viewport.rect.h);
128 break;
129
131 SDL_Log(" %u. set cliprect (enabled=%s, rect={(%d, %d), %dx%d})", i++,
132 cmd->data.cliprect.enabled ? "true" : "false",
133 cmd->data.cliprect.rect.x, cmd->data.cliprect.rect.y,
134 cmd->data.cliprect.rect.w, cmd->data.cliprect.rect.h);
135 break;
136
138 SDL_Log(" %u. set draw color (first=%u, r=%d, g=%d, b=%d, a=%d)", i++,
139 (unsigned int) cmd->data.color.first,
140 (int) cmd->data.color.r, (int) cmd->data.color.g,
141 (int) cmd->data.color.b, (int) cmd->data.color.a);
142 break;
143
145 SDL_Log(" %u. clear (first=%u, r=%d, g=%d, b=%d, a=%d)", i++,
146 (unsigned int) cmd->data.color.first,
147 (int) cmd->data.color.r, (int) cmd->data.color.g,
148 (int) cmd->data.color.b, (int) cmd->data.color.a);
149 break;
150
152 SDL_Log(" %u. draw points (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++,
153 (unsigned int) cmd->data.draw.first,
154 (unsigned int) cmd->data.draw.count,
155 (int) cmd->data.draw.r, (int) cmd->data.draw.g,
156 (int) cmd->data.draw.b, (int) cmd->data.draw.a,
157 (int) cmd->data.draw.blend);
158 break;
159
161 SDL_Log(" %u. draw lines (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++,
162 (unsigned int) cmd->data.draw.first,
163 (unsigned int) cmd->data.draw.count,
164 (int) cmd->data.draw.r, (int) cmd->data.draw.g,
165 (int) cmd->data.draw.b, (int) cmd->data.draw.a,
166 (int) cmd->data.draw.blend);
167 break;
168
170 SDL_Log(" %u. fill rects (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++,
171 (unsigned int) cmd->data.draw.first,
172 (unsigned int) cmd->data.draw.count,
173 (int) cmd->data.draw.r, (int) cmd->data.draw.g,
174 (int) cmd->data.draw.b, (int) cmd->data.draw.a,
175 (int) cmd->data.draw.blend);
176 break;
177
179 SDL_Log(" %u. copy (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++,
180 (unsigned int) cmd->data.draw.first,
181 (unsigned int) cmd->data.draw.count,
182 (int) cmd->data.draw.r, (int) cmd->data.draw.g,
183 (int) cmd->data.draw.b, (int) cmd->data.draw.a,
184 (int) cmd->data.draw.blend, cmd->data.draw.texture);
185 break;
186
187
189 SDL_Log(" %u. copyex (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++,
190 (unsigned int) cmd->data.draw.first,
191 (unsigned int) cmd->data.draw.count,
192 (int) cmd->data.draw.r, (int) cmd->data.draw.g,
193 (int) cmd->data.draw.b, (int) cmd->data.draw.a,
194 (int) cmd->data.draw.blend, cmd->data.draw.texture);
195 break;
196 }
197 cmd = cmd->next;
198 }
199#endif
200}
201
202static int
204{
206 SDL_AllocVertGap *gap = prevgap;
207 int retval;
208
210
211 if (renderer->render_commands == NULL) { /* nothing to do! */
213 return 0;
214 }
215
217
219
220 while (gap) {
221 prevgap = gap;
222 gap = gap->next;
223 }
227
228 /* Move the whole render command queue to the unused pool so we can reuse them next time. */
234 }
240 return retval;
241}
242
243static int
245{
246 SDL_Renderer *renderer = texture->renderer;
247 if (texture->last_command_generation == renderer->render_command_generation) {
248 /* the current command queue depends on this texture, flush the queue now before it changes */
250 }
251 return 0;
252}
253
254static SDL_INLINE int
256{
258}
259
260int
262{
264}
265
266static SDL_AllocVertGap *
268{
270 if (retval) {
272 retval->next = NULL;
273 } else {
275 if (!retval) {
277 }
278 }
279 return retval;
280}
281
282
283void *
284SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
285{
286 const size_t needed = renderer->vertex_data_used + numbytes + alignment;
287 size_t aligner, aligned;
288 void *retval;
289
291 SDL_AllocVertGap *gap = prevgap->next;
292 while (gap) {
293 const size_t gapoffset = gap->offset;
294 aligner = (alignment && ((gap->offset % alignment) != 0)) ? (alignment - (gap->offset % alignment)) : 0;
295 aligned = gapoffset + aligner;
296
297 /* Can we use this gap? */
298 if ((aligner < gap->len) && ((gap->len - aligner) >= numbytes)) {
299 /* we either finished this gap off, trimmed the left, trimmed the right, or split it into two gaps. */
300 if (gap->len == numbytes) { /* finished it off, remove it */
301 SDL_assert(aligned == gapoffset);
302 prevgap->next = gap->next;
305 } else if (aligned == gapoffset) { /* trimmed the left */
306 gap->offset += numbytes;
307 gap->len -= numbytes;
308 } else if (((aligned - gapoffset) + numbytes) == gap->len) { /* trimmed the right */
309 gap->len -= numbytes;
310 } else { /* split into two gaps */
312 if (!newgap) {
313 return NULL;
314 }
315 newgap->offset = aligned + numbytes;
316 newgap->len = gap->len - (aligner + numbytes);
317 newgap->next = gap->next;
318 // gap->offset doesn't change.
319 gap->len = aligner;
320 gap->next = newgap;
321 }
322
323 if (offset) {
324 *offset = aligned;
325 }
326 return ((Uint8 *) renderer->vertex_data) + aligned;
327 }
328
329 /* Try the next gap */
330 prevgap = gap;
331 gap = gap->next;
332 }
333
334 /* no gaps with enough space; get a new piece of the vertex buffer */
335 while (needed > renderer->vertex_data_allocation) {
336 const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 1024;
337 const size_t newsize = current_allocation * 2;
338 void *ptr = SDL_realloc(renderer->vertex_data, newsize);
339 if (ptr == NULL) {
341 return NULL;
342 }
343 renderer->vertex_data = ptr;
345 }
346
347 aligner = (alignment && ((renderer->vertex_data_used % alignment) != 0)) ? (alignment - (renderer->vertex_data_used % alignment)) : 0;
348 aligned = renderer->vertex_data_used + aligner;
349
350 retval = ((Uint8 *) renderer->vertex_data) + aligned;
351 if (offset) {
352 *offset = aligned;
353 }
354
355 if (aligner) { /* made a new gap... */
357 if (newgap) { /* just let it slide as lost space if malloc fails. */
359 newgap->len = aligner;
360 newgap->next = NULL;
361 prevgap->next = newgap;
362 }
363 }
364
365 renderer->vertex_data_used += aligner + numbytes;
366
367 return retval;
368}
369
370static SDL_RenderCommand *
372{
374
375 /* !!! FIXME: are there threading limitations in SDL's render API? If not, we need to mutex this. */
377 if (retval != NULL) {
379 retval->next = NULL;
380 } else {
381 retval = SDL_calloc(1, sizeof (*retval));
382 if (!retval) {
384 return NULL;
385 }
386 }
387
391 } else {
393 }
395
396 return retval;
397}
398
399static int
401{
402 int retval = 0;
405 retval = -1;
406 if (cmd != NULL) {
408 cmd->data.viewport.first = 0; /* render backend will fill this in. */
411 if (retval < 0) {
413 } else {
416 }
417 }
418 }
419 return retval;
420}
421
422static int
424{
425 int retval = 0;
426 if ((!renderer->cliprect_queued) ||
430 if (cmd == NULL) {
431 retval = -1;
432 } else {
439 }
440 }
441 return retval;
442}
443
444static int
446{
447 const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
448 int retval = 0;
449
452 retval = -1;
453
454 if (cmd != NULL) {
456 cmd->data.color.first = 0; /* render backend will fill this in. */
457 cmd->data.color.r = r;
458 cmd->data.color.g = g;
459 cmd->data.color.b = b;
460 cmd->data.color.a = a;
462 if (retval < 0) {
464 } else {
467 }
468 }
469 }
470 return retval;
471}
472
473static int
475{
477 if (cmd == NULL) {
478 return -1;
479 }
480
482 cmd->data.color.first = 0;
483 cmd->data.color.r = renderer->r;
484 cmd->data.color.g = renderer->g;
485 cmd->data.color.b = renderer->b;
486 cmd->data.color.a = renderer->a;
487 return 0;
488}
489
490static int
492{
493 int retval = 0;
494 if (retval == 0) {
496 }
497 if (retval == 0) {
499 }
500 if (retval == 0) {
502 }
503 return retval;
504}
505
506static SDL_RenderCommand *
508{
509 /* !!! FIXME: drop this draw if viewport w or h is zero. */
510 SDL_RenderCommand *cmd = NULL;
513 if (cmd != NULL) {
514 cmd->command = cmdtype;
515 cmd->data.draw.first = 0; /* render backend will fill this in. */
516 cmd->data.draw.count = 0; /* render backend will fill this in. */
517 cmd->data.draw.r = renderer->r;
518 cmd->data.draw.g = renderer->g;
519 cmd->data.draw.b = renderer->b;
520 cmd->data.draw.a = renderer->a;
522 cmd->data.draw.texture = NULL; /* no texture. */
523 }
524 }
525 return cmd;
526}
527
528static int
530{
532 int retval = -1;
533 if (cmd != NULL) {
535 if (retval < 0) {
537 }
538 }
539 return retval;
540}
541
542static int
544{
546 int retval = -1;
547 if (cmd != NULL) {
549 if (retval < 0) {
551 }
552 }
553 return retval;
554}
555
556static int
558{
560 int retval = -1;
561 if (cmd != NULL) {
563 if (retval < 0) {
565 }
566 }
567 return retval;
568}
569
570static SDL_RenderCommand *
572{
573 /* !!! FIXME: drop this draw if viewport w or h is zero. */
574 SDL_RenderCommand *cmd = NULL;
575 if (PrepQueueCmdDraw(renderer, texture->r, texture->g, texture->b, texture->a) == 0) {
577 if (cmd != NULL) {
578 cmd->command = cmdtype;
579 cmd->data.draw.first = 0; /* render backend will fill this in. */
580 cmd->data.draw.count = 0; /* render backend will fill this in. */
581 cmd->data.draw.r = texture->r;
582 cmd->data.draw.g = texture->g;
583 cmd->data.draw.b = texture->b;
584 cmd->data.draw.a = texture->a;
585 cmd->data.draw.blend = texture->blendMode;
586 cmd->data.draw.texture = texture;
587 }
588 }
589 return cmd;
590}
591
592static int
594{
596 int retval = -1;
597 if (cmd != NULL) {
598 retval = renderer->QueueCopy(renderer, cmd, texture, srcrect, dstrect);
599 if (retval < 0) {
601 }
602 }
603 return retval;
604}
605
606static int
608 const SDL_Rect * srcquad, const SDL_FRect * dstrect,
609 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
610{
612 int retval = -1;
613 SDL_assert(renderer->QueueCopyEx != NULL); /* should have caught at higher level. */
614 if (cmd != NULL) {
615 retval = renderer->QueueCopyEx(renderer, cmd, texture, srcquad, dstrect, angle, center, flip);
616 if (retval < 0) {
618 }
619 }
620 return retval;
621}
622
623
625
626int
628{
629#if !SDL_RENDER_DISABLED
631#else
632 return 0;
633#endif
634}
635
636int
638{
639#if !SDL_RENDER_DISABLED
641 return SDL_SetError("index must be in the range of 0 - %d",
643 }
644 *info = render_drivers[index]->info;
645 return 0;
646#else
647 return SDL_SetError("SDL not built with rendering support");
648#endif
649}
650
651static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_Rect *viewport, SDL_FPoint *scale)
652{
659}
660
661static int SDLCALL
663{
664 SDL_Renderer *renderer = (SDL_Renderer *)userdata;
665
666 if (event->type == SDL_WINDOWEVENT) {
667 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
668 if (window == renderer->window) {
669 if (renderer->WindowEvent) {
671 }
672
673 if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
674 /* Make sure we're operating on the default render target */
676 if (saved_target) {
678 }
679
680 if (renderer->logical_w) {
682 } else {
683 /* Window was resized, reset viewport */
684 int w, h;
685
686 if (renderer->GetOutputSize) {
688 } else {
690 }
691
692 if (renderer->target) {
697 } else {
698 renderer->viewport.x = 0;
699 renderer->viewport.y = 0;
700 renderer->viewport.w = w;
701 renderer->viewport.h = h;
704 }
705 }
706
707 if (saved_target) {
708 SDL_SetRenderTarget(renderer, saved_target);
709 }
710 } else if (event->window.event == SDL_WINDOWEVENT_HIDDEN) {
712 } else if (event->window.event == SDL_WINDOWEVENT_SHOWN) {
715 }
716 } else if (event->window.event == SDL_WINDOWEVENT_MINIMIZED) {
718 } else if (event->window.event == SDL_WINDOWEVENT_RESTORED ||
719 event->window.event == SDL_WINDOWEVENT_MAXIMIZED) {
722 }
723 }
724 }
725 } else if (event->type == SDL_MOUSEMOTION) {
726 SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID);
727 if (window == renderer->window) {
728 int logical_w, logical_h;
731 GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
732 if (logical_w) {
733 event->motion.x -= (int)(viewport.x * renderer->dpi_scale.x);
734 event->motion.y -= (int)(viewport.y * renderer->dpi_scale.y);
735 event->motion.x = (int)(event->motion.x / (scale.x * renderer->dpi_scale.x));
736 event->motion.y = (int)(event->motion.y / (scale.y * renderer->dpi_scale.y));
737 if (event->motion.xrel > 0) {
738 event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
739 } else if (event->motion.xrel < 0) {
740 event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
741 }
742 if (event->motion.yrel > 0) {
743 event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
744 } else if (event->motion.yrel < 0) {
745 event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
746 }
747 }
748 }
749 } else if (event->type == SDL_MOUSEBUTTONDOWN ||
750 event->type == SDL_MOUSEBUTTONUP) {
751 SDL_Window *window = SDL_GetWindowFromID(event->button.windowID);
752 if (window == renderer->window) {
753 int logical_w, logical_h;
756 GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
757 if (logical_w) {
758 event->button.x -= (int)(viewport.x * renderer->dpi_scale.x);
759 event->button.y -= (int)(viewport.y * renderer->dpi_scale.y);
760 event->button.x = (int)(event->button.x / (scale.x * renderer->dpi_scale.x));
761 event->button.y = (int)(event->button.y / (scale.y * renderer->dpi_scale.y));
762 }
763 }
764 } else if (event->type == SDL_FINGERDOWN ||
765 event->type == SDL_FINGERUP ||
766 event->type == SDL_FINGERMOTION) {
767 int logical_w, logical_h;
770 GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
771 if (logical_w) {
772 int w = 1;
773 int h = 1;
775
776 event->tfinger.x *= (w - 1);
777 event->tfinger.y *= (h - 1);
778
779 event->tfinger.x -= (viewport.x * renderer->dpi_scale.x);
780 event->tfinger.y -= (viewport.y * renderer->dpi_scale.y);
781 event->tfinger.x = (event->tfinger.x / (scale.x * renderer->dpi_scale.x));
782 event->tfinger.y = (event->tfinger.y / (scale.y * renderer->dpi_scale.y));
783
784 if (logical_w > 1) {
785 event->tfinger.x = event->tfinger.x / (logical_w - 1);
786 } else {
787 event->tfinger.x = 0.5f;
788 }
789 if (logical_h > 1) {
790 event->tfinger.y = event->tfinger.y / (logical_h - 1);
791 } else {
792 event->tfinger.y = 0.5f;
793 }
794 }
795 }
796
797 return 0;
798}
799
800int
803{
806 width, height, window_flags);
807 if (!*window) {
808 *renderer = NULL;
809 return -1;
810 }
811
813 if (!*renderer) {
814 return -1;
815 }
816
817 return 0;
818}
819
820static SDL_INLINE
822{
823 /* all of these functions are required to be implemented, even as no-ops, so we don't
824 have to check that they aren't NULL over and over. */
832}
833
836{
837#if !SDL_RENDER_DISABLED
840 SDL_bool batching = SDL_TRUE;
841 const char *hint;
842
843#if defined(__ANDROID__)
845#endif
846
847 if (!window) {
848 SDL_SetError("Invalid window");
849 goto error;
850 }
851
852 if (SDL_GetRenderer(window)) {
853 SDL_SetError("Renderer already associated with window");
854 goto error;
855 }
856
860 } else {
861 flags &= ~SDL_RENDERER_PRESENTVSYNC;
862 }
863 }
864
865 if (index < 0) {
867 if (hint) {
868 for (index = 0; index < n; ++index) {
869 const SDL_RenderDriver *driver = render_drivers[index];
870
871 if (SDL_strcasecmp(hint, driver->info.name) == 0) {
872 /* Create a new renderer instance */
874 if (renderer) {
875 batching = SDL_FALSE;
876 }
877 break;
878 }
879 }
880 }
881
882 if (!renderer) {
883 for (index = 0; index < n; ++index) {
884 const SDL_RenderDriver *driver = render_drivers[index];
885
886 if ((driver->info.flags & flags) == flags) {
887 /* Create a new renderer instance */
889 if (renderer) {
890 /* Yay, we got one! */
891 break;
892 }
893 }
894 }
895 }
896 if (index == n) {
897 SDL_SetError("Couldn't find matching render driver");
898 goto error;
899 }
900 } else {
902 SDL_SetError("index must be -1 or in the range of 0 - %d",
904 goto error;
905 }
906 /* Create a new renderer instance */
908 batching = SDL_FALSE;
909 }
910
911 if (!renderer) {
912 goto error;
913 }
914
916
917 /* let app/user override batching decisions. */
918 if (renderer->always_batch) {
919 batching = SDL_TRUE;
922 }
923
924 renderer->batching = batching;
928 renderer->scale.x = 1.0f;
929 renderer->scale.y = 1.0f;
930 renderer->dpi_scale.x = 1.0f;
931 renderer->dpi_scale.y = 1.0f;
932
933 /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */
935
936 if (window && renderer->GetOutputSize) {
937 int window_w, window_h;
938 int output_w, output_h;
939 if (renderer->GetOutputSize(renderer, &output_w, &output_h) == 0) {
941 renderer->dpi_scale.x = (float)window_w / output_w;
942 renderer->dpi_scale.y = (float)window_h / output_h;
943 }
944 }
945
948 } else {
950 }
951
953
955
957
959 "Created renderer: %s", renderer->info.name);
960
961#if defined(__ANDROID__)
963#endif
964 return renderer;
965
966error:
967
968#if defined(__ANDROID__)
970#endif
971 return NULL;
972
973#else
974 SDL_SetError("SDL not built with rendering support");
975 return NULL;
976#endif
977}
978
981{
982#if !SDL_RENDER_DISABLED
984
986
987 if (renderer) {
991 renderer->scale.x = 1.0f;
992 renderer->scale.y = 1.0f;
993
994 /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */
996
998 }
999 return renderer;
1000#else
1001 SDL_SetError("SDL not built with rendering support");
1002 return NULL;
1003#endif /* !SDL_RENDER_DISABLED */
1004}
1005
1008{
1010}
1011
1012int
1014{
1016
1017 *info = renderer->info;
1018 return 0;
1019}
1020
1021int
1023{
1025
1026 if (renderer->target) {
1028 } else if (renderer->GetOutputSize) {
1029 return renderer->GetOutputSize(renderer, w, h);
1030 } else if (renderer->window) {
1032 return 0;
1033 } else {
1034 SDL_assert(0 && "This should never happen");
1035 return SDL_SetError("Renderer doesn't support querying output size");
1036 }
1037}
1038
1039static SDL_bool
1041{
1042 switch (blendMode)
1043 {
1044 /* These are required to be supported by all renderers */
1045 case SDL_BLENDMODE_NONE:
1047 case SDL_BLENDMODE_ADD:
1048 case SDL_BLENDMODE_MOD:
1049 return SDL_TRUE;
1050
1051 default:
1053 }
1054}
1055
1056static SDL_bool
1058{
1059 Uint32 i;
1060
1061 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
1063 return SDL_TRUE;
1064 }
1065 }
1066 return SDL_FALSE;
1067}
1068
1069static Uint32
1071{
1072 Uint32 i;
1073
1075 /* Look for an exact match */
1076 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
1078 return renderer->info.texture_formats[i];
1079 }
1080 }
1081 } else {
1083
1084 /* We just want to match the first format that has the same channels */
1085 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
1088 return renderer->info.texture_formats[i];
1089 }
1090 }
1091 }
1092 return renderer->info.texture_formats[0];
1093}
1094
1095
1097{
1098 const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
1099
1100 if (!hint || SDL_strcasecmp(hint, "nearest") == 0) {
1101 return SDL_ScaleModeNearest;
1102 } else if (SDL_strcasecmp(hint, "linear") == 0) {
1103 return SDL_ScaleModeLinear;
1104 } else if (SDL_strcasecmp(hint, "best") == 0) {
1105 return SDL_ScaleModeBest;
1106 } else {
1107 return (SDL_ScaleMode)SDL_atoi(hint);
1108 }
1109}
1110
1113{
1115
1117
1118 if (!format) {
1120 }
1121 if (SDL_BYTESPERPIXEL(format) == 0) {
1122 SDL_SetError("Invalid texture format");
1123 return NULL;
1124 }
1126 SDL_SetError("Palettized textures are not supported");
1127 return NULL;
1128 }
1129 if (w <= 0 || h <= 0) {
1130 SDL_SetError("Texture dimensions can't be 0");
1131 return NULL;
1132 }
1135 SDL_SetError("Texture dimensions are limited to %dx%d", renderer->info.max_texture_width, renderer->info.max_texture_height);
1136 return NULL;
1137 }
1138 texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
1139 if (!texture) {
1141 return NULL;
1142 }
1143 texture->magic = &texture_magic;
1144 texture->format = format;
1145 texture->access = access;
1146 texture->w = w;
1147 texture->h = h;
1148 texture->r = 255;
1149 texture->g = 255;
1150 texture->b = 255;
1151 texture->a = 255;
1152 texture->scaleMode = SDL_GetScaleMode();
1153 texture->renderer = renderer;
1154 texture->next = renderer->textures;
1155 if (renderer->textures) {
1157 }
1159
1163 return NULL;
1164 }
1165 } else {
1168 access, w, h);
1169 if (!texture->native) {
1171 return NULL;
1172 }
1173
1174 /* Swap textures to have texture before texture->native in the list */
1175 texture->native->next = texture->next;
1176 if (texture->native->next) {
1177 texture->native->next->prev = texture->native;
1178 }
1179 texture->prev = texture->native->prev;
1180 if (texture->prev) {
1181 texture->prev->next = texture;
1182 }
1183 texture->native->prev = texture;
1184 texture->next = texture->native;
1186
1187 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
1189 if (!texture->yuv) {
1191 return NULL;
1192 }
1193 } else if (access == SDL_TEXTUREACCESS_STREAMING) {
1194 /* The pitch is 4 byte aligned */
1195 texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
1196 texture->pixels = SDL_calloc(1, texture->pitch * h);
1197 if (!texture->pixels) {
1199 return NULL;
1200 }
1201 }
1202 }
1203 return texture;
1204}
1205
1208{
1209 const SDL_PixelFormat *fmt;
1210 SDL_bool needAlpha;
1211 SDL_bool direct_update;
1212 int i;
1215
1217
1218 if (!surface) {
1219 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
1220 return NULL;
1221 }
1222
1223 /* See what the best texture format is */
1224 fmt = surface->format;
1225 if (fmt->Amask || SDL_HasColorKey(surface)) {
1226 needAlpha = SDL_TRUE;
1227 } else {
1228 needAlpha = SDL_FALSE;
1229 }
1230
1231 /* If Palette contains alpha values, promotes to alpha format */
1232 if (fmt->palette) {
1233 for (i = 0; i < fmt->palette->ncolors; i++) {
1234 Uint8 alpha_value = fmt->palette->colors[i].a;
1235 if (alpha_value != 0 || alpha_value != SDL_ALPHA_OPAQUE) {
1236 needAlpha = SDL_TRUE;
1237 break;
1238 }
1239 }
1240 }
1241
1242 /* Try to have the best pixel format for the texture */
1243 /* No alpha, but a colorkey => promote to alpha */
1244 if (!fmt->Amask && SDL_HasColorKey(surface)) {
1245 if (fmt->format == SDL_PIXELFORMAT_RGB888) {
1246 for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
1249 break;
1250 }
1251 }
1252 } else if (fmt->format == SDL_PIXELFORMAT_BGR888) {
1253 for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
1256 break;
1257 }
1258 }
1259 }
1260 } else {
1261 /* Exact match would be fine */
1262 for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
1263 if (renderer->info.texture_formats[i] == fmt->format) {
1264 format = fmt->format;
1265 break;
1266 }
1267 }
1268 }
1269
1270 /* Fallback, choose a valid pixel format */
1273 for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
1277 break;
1278 }
1279 }
1280 }
1281
1283 surface->w, surface->h);
1284 if (!texture) {
1285 return NULL;
1286 }
1287
1288 if (format == surface->format->format) {
1289 if (surface->format->Amask && SDL_HasColorKey(surface)) {
1290 /* Surface and Renderer formats are identicals.
1291 * Intermediate conversion is needed to convert color key to alpha (SDL_ConvertColorkeyToAlpha()). */
1292 direct_update = SDL_FALSE;
1293 } else {
1294 /* Update Texture directly */
1295 direct_update = SDL_TRUE;
1296 }
1297 } else {
1298 /* Surface and Renderer formats are differents, it needs an intermediate conversion. */
1299 direct_update = SDL_FALSE;
1300 }
1301
1302 if (direct_update) {
1303 if (SDL_MUSTLOCK(surface)) {
1305 SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
1307 } else {
1308 SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
1309 }
1310 } else {
1311 SDL_PixelFormat *dst_fmt;
1312 SDL_Surface *temp = NULL;
1313
1314 /* Set up a destination surface for the texture update */
1315 dst_fmt = SDL_AllocFormat(format);
1316 if (!dst_fmt) {
1318 return NULL;
1319 }
1320 temp = SDL_ConvertSurface(surface, dst_fmt, 0);
1321 SDL_FreeFormat(dst_fmt);
1322 if (temp) {
1323 SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
1324 SDL_FreeSurface(temp);
1325 } else {
1327 return NULL;
1328 }
1329 }
1330
1331 {
1332 Uint8 r, g, b, a;
1334
1337
1340
1341 if (SDL_HasColorKey(surface)) {
1342 /* We converted to a texture with alpha format */
1344 } else {
1347 }
1348 }
1349 return texture;
1350}
1351
1352int
1354 int *w, int *h)
1355{
1357
1358 if (format) {
1359 *format = texture->format;
1360 }
1361 if (access) {
1362 *access = texture->access;
1363 }
1364 if (w) {
1365 *w = texture->w;
1366 }
1367 if (h) {
1368 *h = texture->h;
1369 }
1370 return 0;
1371}
1372
1373int
1375{
1377
1378 if (r < 255 || g < 255 || b < 255) {
1380 } else {
1381 texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
1382 }
1383 texture->r = r;
1384 texture->g = g;
1385 texture->b = b;
1386 if (texture->native) {
1387 return SDL_SetTextureColorMod(texture->native, r, g, b);
1388 }
1389 return 0;
1390}
1391
1392int
1394 Uint8 * b)
1395{
1397
1398 if (r) {
1399 *r = texture->r;
1400 }
1401 if (g) {
1402 *g = texture->g;
1403 }
1404 if (b) {
1405 *b = texture->b;
1406 }
1407 return 0;
1408}
1409
1410int
1412{
1414
1415 if (alpha < 255) {
1417 } else {
1418 texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
1419 }
1420 texture->a = alpha;
1421 if (texture->native) {
1422 return SDL_SetTextureAlphaMod(texture->native, alpha);
1423 }
1424 return 0;
1425}
1426
1427int
1429{
1431
1432 if (alpha) {
1433 *alpha = texture->a;
1434 }
1435 return 0;
1436}
1437
1438int
1440{
1442
1444
1445 renderer = texture->renderer;
1447 return SDL_Unsupported();
1448 }
1449 texture->blendMode = blendMode;
1450 if (texture->native) {
1451 return SDL_SetTextureBlendMode(texture->native, blendMode);
1452 }
1453 return 0;
1454}
1455
1456int
1458{
1460
1461 if (blendMode) {
1462 *blendMode = texture->blendMode;
1463 }
1464 return 0;
1465}
1466
1467static int
1469 const void *pixels, int pitch)
1470{
1471 SDL_Texture *native = texture->native;
1472 SDL_Rect full_rect;
1473
1474 if (SDL_SW_UpdateYUVTexture(texture->yuv, rect, pixels, pitch) < 0) {
1475 return -1;
1476 }
1477
1478 full_rect.x = 0;
1479 full_rect.y = 0;
1480 full_rect.w = texture->w;
1481 full_rect.h = texture->h;
1482 rect = &full_rect;
1483
1484 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
1485 /* We can lock the texture and copy to it */
1486 void *native_pixels = NULL;
1487 int native_pitch = 0;
1488
1489 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
1490 return -1;
1491 }
1492 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
1493 rect->w, rect->h, native_pixels, native_pitch);
1494 SDL_UnlockTexture(native);
1495 } else {
1496 /* Use a temporary buffer for updating */
1497 const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
1498 const size_t alloclen = rect->h * temp_pitch;
1499 if (alloclen > 0) {
1500 void *temp_pixels = SDL_malloc(alloclen);
1501 if (!temp_pixels) {
1502 return SDL_OutOfMemory();
1503 }
1504 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
1505 rect->w, rect->h, temp_pixels, temp_pitch);
1506 SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
1507 SDL_free(temp_pixels);
1508 }
1509 }
1510 return 0;
1511}
1512
1513static int
1515 const void *pixels, int pitch)
1516{
1517 SDL_Texture *native = texture->native;
1518
1519 if (!rect->w || !rect->h) {
1520 return 0; /* nothing to do. */
1521 }
1522
1523 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
1524 /* We can lock the texture and copy to it */
1525 void *native_pixels = NULL;
1526 int native_pitch = 0;
1527
1528 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
1529 return -1;
1530 }
1532 texture->format, pixels, pitch,
1533 native->format, native_pixels, native_pitch);
1534 SDL_UnlockTexture(native);
1535 } else {
1536 /* Use a temporary buffer for updating */
1537 const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
1538 const size_t alloclen = rect->h * temp_pitch;
1539 if (alloclen > 0) {
1540 void *temp_pixels = SDL_malloc(alloclen);
1541 if (!temp_pixels) {
1542 return SDL_OutOfMemory();
1543 }
1545 texture->format, pixels, pitch,
1546 native->format, temp_pixels, temp_pitch);
1547 SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
1548 SDL_free(temp_pixels);
1549 }
1550 }
1551 return 0;
1552}
1553
1554int
1556 const void *pixels, int pitch)
1557{
1558 SDL_Rect full_rect;
1559
1561
1562 if (!pixels) {
1563 return SDL_InvalidParamError("pixels");
1564 }
1565 if (!pitch) {
1566 return SDL_InvalidParamError("pitch");
1567 }
1568
1569 if (!rect) {
1570 full_rect.x = 0;
1571 full_rect.y = 0;
1572 full_rect.w = texture->w;
1573 full_rect.h = texture->h;
1574 rect = &full_rect;
1575 }
1576
1577 if ((rect->w == 0) || (rect->h == 0)) {
1578 return 0; /* nothing to do. */
1579 } else if (texture->yuv) {
1580 return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);
1581 } else if (texture->native) {
1582 return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
1583 } else {
1584 SDL_Renderer *renderer = texture->renderer;
1586 return -1;
1587 }
1588 return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
1589 }
1590}
1591
1592static int
1594 const Uint8 *Yplane, int Ypitch,
1595 const Uint8 *Uplane, int Upitch,
1596 const Uint8 *Vplane, int Vpitch)
1597{
1598 SDL_Texture *native = texture->native;
1599 SDL_Rect full_rect;
1600
1601 if (SDL_SW_UpdateYUVTexturePlanar(texture->yuv, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch) < 0) {
1602 return -1;
1603 }
1604
1605 full_rect.x = 0;
1606 full_rect.y = 0;
1607 full_rect.w = texture->w;
1608 full_rect.h = texture->h;
1609 rect = &full_rect;
1610
1611 if (!rect->w || !rect->h) {
1612 return 0; /* nothing to do. */
1613 }
1614
1615 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
1616 /* We can lock the texture and copy to it */
1617 void *native_pixels = NULL;
1618 int native_pitch = 0;
1619
1620 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
1621 return -1;
1622 }
1623 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
1624 rect->w, rect->h, native_pixels, native_pitch);
1625 SDL_UnlockTexture(native);
1626 } else {
1627 /* Use a temporary buffer for updating */
1628 const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
1629 const size_t alloclen = rect->h * temp_pitch;
1630 if (alloclen > 0) {
1631 void *temp_pixels = SDL_malloc(alloclen);
1632 if (!temp_pixels) {
1633 return SDL_OutOfMemory();
1634 }
1635 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
1636 rect->w, rect->h, temp_pixels, temp_pitch);
1637 SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
1638 SDL_free(temp_pixels);
1639 }
1640 }
1641 return 0;
1642}
1643
1645 const Uint8 *Yplane, int Ypitch,
1646 const Uint8 *Uplane, int Upitch,
1647 const Uint8 *Vplane, int Vpitch)
1648{
1650 SDL_Rect full_rect;
1651
1653
1654 if (!Yplane) {
1655 return SDL_InvalidParamError("Yplane");
1656 }
1657 if (!Ypitch) {
1658 return SDL_InvalidParamError("Ypitch");
1659 }
1660 if (!Uplane) {
1661 return SDL_InvalidParamError("Uplane");
1662 }
1663 if (!Upitch) {
1664 return SDL_InvalidParamError("Upitch");
1665 }
1666 if (!Vplane) {
1667 return SDL_InvalidParamError("Vplane");
1668 }
1669 if (!Vpitch) {
1670 return SDL_InvalidParamError("Vpitch");
1671 }
1672
1673 if (texture->format != SDL_PIXELFORMAT_YV12 &&
1674 texture->format != SDL_PIXELFORMAT_IYUV) {
1675 return SDL_SetError("Texture format must by YV12 or IYUV");
1676 }
1677
1678 if (!rect) {
1679 full_rect.x = 0;
1680 full_rect.y = 0;
1681 full_rect.w = texture->w;
1682 full_rect.h = texture->h;
1683 rect = &full_rect;
1684 }
1685
1686 if (!rect->w || !rect->h) {
1687 return 0; /* nothing to do. */
1688 }
1689
1690 if (texture->yuv) {
1691 return SDL_UpdateTextureYUVPlanar(texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
1692 } else {
1693 SDL_assert(!texture->native);
1694 renderer = texture->renderer;
1698 return -1;
1699 }
1700 return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
1701 } else {
1702 return SDL_Unsupported();
1703 }
1704 }
1705}
1706
1707static int
1709 void **pixels, int *pitch)
1710{
1711 return SDL_SW_LockYUVTexture(texture->yuv, rect, pixels, pitch);
1712}
1713
1714static int
1716 void **pixels, int *pitch)
1717{
1718 texture->locked_rect = *rect;
1719 *pixels = (void *) ((Uint8 *) texture->pixels +
1720 rect->y * texture->pitch +
1721 rect->x * SDL_BYTESPERPIXEL(texture->format));
1722 *pitch = texture->pitch;
1723 return 0;
1724}
1725
1726int
1728 void **pixels, int *pitch)
1729{
1730 SDL_Rect full_rect;
1731
1733
1734 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
1735 return SDL_SetError("SDL_LockTexture(): texture must be streaming");
1736 }
1737
1738 if (!rect) {
1739 full_rect.x = 0;
1740 full_rect.y = 0;
1741 full_rect.w = texture->w;
1742 full_rect.h = texture->h;
1743 rect = &full_rect;
1744 }
1745
1746 if (texture->yuv) {
1748 return -1;
1749 }
1750 return SDL_LockTextureYUV(texture, rect, pixels, pitch);
1751 } else if (texture->native) {
1752 /* Calls a real SDL_LockTexture/SDL_UnlockTexture on unlock, flushing then. */
1753 return SDL_LockTextureNative(texture, rect, pixels, pitch);
1754 } else {
1755 SDL_Renderer *renderer = texture->renderer;
1757 return -1;
1758 }
1759 return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
1760 }
1761}
1762
1763static void
1765{
1766 SDL_Texture *native = texture->native;
1767 void *native_pixels = NULL;
1768 int native_pitch = 0;
1769 SDL_Rect rect;
1770
1771 rect.x = 0;
1772 rect.y = 0;
1773 rect.w = texture->w;
1774 rect.h = texture->h;
1775
1776 if (SDL_LockTexture(native, &rect, &native_pixels, &native_pitch) < 0) {
1777 return;
1778 }
1779 SDL_SW_CopyYUVToRGB(texture->yuv, &rect, native->format,
1780 rect.w, rect.h, native_pixels, native_pitch);
1781 SDL_UnlockTexture(native);
1782}
1783
1784static void
1786{
1787 SDL_Texture *native = texture->native;
1788 void *native_pixels = NULL;
1789 int native_pitch = 0;
1790 const SDL_Rect *rect = &texture->locked_rect;
1791 const void* pixels = (void *) ((Uint8 *) texture->pixels +
1792 rect->y * texture->pitch +
1793 rect->x * SDL_BYTESPERPIXEL(texture->format));
1794 int pitch = texture->pitch;
1795
1796 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
1797 return;
1798 }
1800 texture->format, pixels, pitch,
1801 native->format, native_pixels, native_pitch);
1802 SDL_UnlockTexture(native);
1803}
1804
1805void
1807{
1809
1810 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
1811 return;
1812 }
1813 if (texture->yuv) {
1815 } else if (texture->native) {
1817 } else {
1818 SDL_Renderer *renderer = texture->renderer;
1820 }
1821}
1822
1825{
1826 if (!renderer || !renderer->SetRenderTarget) {
1827 return SDL_FALSE;
1828 }
1830}
1831
1832int
1834{
1836 return SDL_Unsupported();
1837 }
1838 if (texture == renderer->target) {
1839 /* Nothing to do! */
1840 return 0;
1841 }
1842
1843 FlushRenderCommands(renderer); /* time to send everything to the GPU! */
1844
1845 /* texture == NULL is valid and means reset the target to the window */
1846 if (texture) {
1848 if (renderer != texture->renderer) {
1849 return SDL_SetError("Texture was not created with this renderer");
1850 }
1851 if (texture->access != SDL_TEXTUREACCESS_TARGET) {
1852 return SDL_SetError("Texture not created with SDL_TEXTUREACCESS_TARGET");
1853 }
1854 if (texture->native) {
1855 /* Always render to the native texture */
1856 texture = texture->native;
1857 }
1858 }
1859
1861
1862 if (texture && !renderer->target) {
1863 /* Make a backup of the viewport */
1870 }
1872
1875 return -1;
1876 }
1877
1878 if (texture) {
1879 renderer->viewport.x = 0;
1880 renderer->viewport.y = 0;
1881 renderer->viewport.w = texture->w;
1882 renderer->viewport.h = texture->h;
1885 renderer->scale.x = 1.0f;
1886 renderer->scale.y = 1.0f;
1889 } else {
1896 }
1897
1899
1900 if (QueueCmdSetViewport(renderer) < 0) {
1901 return -1;
1902 }
1903 if (QueueCmdSetClipRect(renderer) < 0) {
1904 return -1;
1905 }
1906
1907 /* All set! */
1909}
1910
1913{
1914 return renderer->target;
1915}
1916
1917static int
1919{
1920 int w = 1, h = 1;
1921 float want_aspect;
1922 float real_aspect;
1923 float scale;
1925 /* 0 is for letterbox, 1 is for overscan */
1926 int scale_policy = 0;
1927 const char *hint;
1928
1929 if (!renderer->logical_w || !renderer->logical_h) {
1930 return 0;
1931 }
1932 if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
1933 return -1;
1934 }
1935
1937 if (hint && (*hint == '1' || SDL_strcasecmp(hint, "overscan") == 0)) {
1938#if SDL_VIDEO_RENDER_D3D
1939 SDL_bool overscan_supported = SDL_TRUE;
1940 /* Unfortunately, Direct3D 9 doesn't support negative viewport numbers
1941 which the overscan implementation relies on.
1942 */
1943 if (SDL_strcasecmp(SDL_GetCurrentVideoDriver(), "direct3d") == 0) {
1944 overscan_supported = SDL_FALSE;
1945 }
1946 if (overscan_supported) {
1947 scale_policy = 1;
1948 }
1949#else
1950 scale_policy = 1;
1951#endif
1952 }
1953
1954 want_aspect = (float)renderer->logical_w / renderer->logical_h;
1955 real_aspect = (float)w / h;
1956
1957 /* Clear the scale because we're setting viewport in output coordinates */
1958 SDL_RenderSetScale(renderer, 1.0f, 1.0f);
1959
1960 if (renderer->integer_scale) {
1961 if (want_aspect > real_aspect) {
1962 scale = (float)(w / renderer->logical_w);
1963 } else {
1964 scale = (float)(h / renderer->logical_h);
1965 }
1967 viewport.x = (w - viewport.w) / 2;
1969 viewport.y = (h - viewport.h) / 2;
1970
1972 } else if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
1973 /* The aspect ratios are the same, just scale appropriately */
1974 scale = (float)w / renderer->logical_w;
1976 } else if (want_aspect > real_aspect) {
1977 if (scale_policy == 1) {
1978 /* We want a wider aspect ratio than is available -
1979 zoom so logical height matches the real height
1980 and the width will grow off the screen
1981 */
1982 scale = (float)h / renderer->logical_h;
1983 viewport.y = 0;
1984 viewport.h = h;
1986 viewport.x = (w - viewport.w) / 2;
1988 } else {
1989 /* We want a wider aspect ratio than is available - letterbox it */
1990 scale = (float)w / renderer->logical_w;
1991 viewport.x = 0;
1992 viewport.w = w;
1994 viewport.y = (h - viewport.h) / 2;
1996 }
1997 } else {
1998 if (scale_policy == 1) {
1999 /* We want a narrower aspect ratio than is available -
2000 zoom so logical width matches the real width
2001 and the height will grow off the screen
2002 */
2003 scale = (float)w / renderer->logical_w;
2004 viewport.x = 0;
2005 viewport.w = w;
2007 viewport.y = (h - viewport.h) / 2;
2009 } else {
2010 /* We want a narrower aspect ratio than is available - use side-bars */
2011 scale = (float)h / renderer->logical_h;
2012 viewport.y = 0;
2013 viewport.h = h;
2015 viewport.x = (w - viewport.w) / 2;
2017 }
2018 }
2019
2020 /* Set the new scale */
2022
2023 return 0;
2024}
2025
2026int
2028{
2030
2031 if (!w || !h) {
2032 /* Clear any previous logical resolution */
2033 renderer->logical_w = 0;
2034 renderer->logical_h = 0;
2036 SDL_RenderSetScale(renderer, 1.0f, 1.0f);
2037 return 0;
2038 }
2039
2040 renderer->logical_w = w;
2041 renderer->logical_h = h;
2042
2044}
2045
2046void
2048{
2050
2051 if (w) {
2052 *w = renderer->logical_w;
2053 }
2054 if (h) {
2055 *h = renderer->logical_h;
2056 }
2057}
2058
2059int
2061{
2063
2065
2067}
2068
2071{
2073
2074 return renderer->integer_scale;
2075}
2076
2077int
2079{
2080 int retval;
2082
2083 if (rect) {
2088 } else {
2089 renderer->viewport.x = 0;
2090 renderer->viewport.y = 0;
2092 return -1;
2093 }
2094 }
2097}
2098
2099void
2101{
2103
2104 if (rect) {
2105 rect->x = (int)(renderer->viewport.x / renderer->scale.x);
2106 rect->y = (int)(renderer->viewport.y / renderer->scale.y);
2107 rect->w = (int)(renderer->viewport.w / renderer->scale.x);
2108 rect->h = (int)(renderer->viewport.h / renderer->scale.y);
2109 }
2110}
2111
2112int
2114{
2115 int retval;
2117
2118 if (rect) {
2124 } else {
2127 }
2128
2131}
2132
2133void
2135{
2137
2138 if (rect) {
2139 rect->x = (int)(renderer->clip_rect.x / renderer->scale.x);
2140 rect->y = (int)(renderer->clip_rect.y / renderer->scale.y);
2141 rect->w = (int)(renderer->clip_rect.w / renderer->scale.x);
2142 rect->h = (int)(renderer->clip_rect.h / renderer->scale.y);
2143 }
2144}
2145
2148{
2150 return renderer->clipping_enabled;
2151}
2152
2153int
2154SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
2155{
2157
2158 renderer->scale.x = scaleX;
2159 renderer->scale.y = scaleY;
2160 return 0;
2161}
2162
2163void
2164SDL_RenderGetScale(SDL_Renderer * renderer, float *scaleX, float *scaleY)
2165{
2167
2168 if (scaleX) {
2169 *scaleX = renderer->scale.x;
2170 }
2171 if (scaleY) {
2172 *scaleY = renderer->scale.y;
2173 }
2174}
2175
2176int
2178 Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2179{
2181
2182 renderer->r = r;
2183 renderer->g = g;
2184 renderer->b = b;
2185 renderer->a = a;
2186 return 0;
2187}
2188
2189int
2191 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
2192{
2194
2195 if (r) {
2196 *r = renderer->r;
2197 }
2198 if (g) {
2199 *g = renderer->g;
2200 }
2201 if (b) {
2202 *b = renderer->b;
2203 }
2204 if (a) {
2205 *a = renderer->a;
2206 }
2207 return 0;
2208}
2209
2210int
2212{
2214
2216 return SDL_Unsupported();
2217 }
2219 return 0;
2220}
2221
2222int
2224{
2226
2228 return 0;
2229}
2230
2231int
2233{
2234 int retval;
2238}
2239
2240
2241/* !!! FIXME: delete all the duplicate code for the integer versions in 2.1,
2242 !!! FIXME: making the floating point versions the only available APIs. */
2243
2244int
2246{
2247 SDL_FPoint fpoint;
2248 fpoint.x = (float) x;
2249 fpoint.y = (float) y;
2250 return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
2251}
2252
2253int
2255{
2256 SDL_FPoint fpoint;
2257 fpoint.x = x;
2258 fpoint.y = y;
2259 return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
2260}
2261
2262static int
2264 const SDL_Point * points, const int count)
2265{
2266 int retval = -1;
2267 SDL_bool isstack;
2268 SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
2269 int i;
2270
2271 if (!frects) {
2272 return SDL_OutOfMemory();
2273 }
2274
2275 for (i = 0; i < count; ++i) {
2276 frects[i].x = points[i].x * renderer->scale.x;
2277 frects[i].y = points[i].y * renderer->scale.y;
2278 frects[i].w = renderer->scale.x;
2279 frects[i].h = renderer->scale.y;
2280 }
2281
2283
2284 SDL_small_free(frects, isstack);
2285
2287}
2288
2289int
2291 const SDL_Point * points, int count)
2292{
2293 SDL_FPoint *fpoints;
2294 int i;
2295 int retval;
2296 SDL_bool isstack;
2297
2299
2300 if (!points) {
2301 return SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
2302 }
2303 if (count < 1) {
2304 return 0;
2305 }
2306
2307 /* Don't draw while we're hidden */
2308 if (renderer->hidden) {
2309 return 0;
2310 }
2311
2312 if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
2314 }
2315
2316 fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
2317 if (!fpoints) {
2318 return SDL_OutOfMemory();
2319 }
2320 for (i = 0; i < count; ++i) {
2321 fpoints[i].x = points[i].x * renderer->scale.x;
2322 fpoints[i].y = points[i].y * renderer->scale.y;
2323 }
2324
2326
2327 SDL_small_free(fpoints, isstack);
2328
2330}
2331
2332static int
2334 const SDL_FPoint * fpoints, const int count)
2335{
2336 int retval = -1;
2337 SDL_bool isstack;
2338 SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
2339 int i;
2340
2341 if (!frects) {
2342 return SDL_OutOfMemory();
2343 }
2344
2345 for (i = 0; i < count; ++i) {
2346 frects[i].x = fpoints[i].x * renderer->scale.x;
2347 frects[i].y = fpoints[i].y * renderer->scale.y;
2348 frects[i].w = renderer->scale.x;
2349 frects[i].h = renderer->scale.y;
2350 }
2351
2353
2354 SDL_small_free(frects, isstack);
2355
2357}
2358
2359int
2361 const SDL_FPoint * points, int count)
2362{
2363 SDL_FPoint *fpoints;
2364 int i;
2365 int retval;
2366 SDL_bool isstack;
2367
2369
2370 if (!points) {
2371 return SDL_SetError("SDL_RenderDrawFPoints(): Passed NULL points");
2372 }
2373 if (count < 1) {
2374 return 0;
2375 }
2376
2377 /* Don't draw while we're hidden */
2378 if (renderer->hidden) {
2379 return 0;
2380 }
2381
2382 if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
2384 }
2385
2386 fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
2387 if (!fpoints) {
2388 return SDL_OutOfMemory();
2389 }
2390 for (i = 0; i < count; ++i) {
2391 fpoints[i].x = points[i].x * renderer->scale.x;
2392 fpoints[i].y = points[i].y * renderer->scale.y;
2393 }
2394
2396
2397 SDL_small_free(fpoints, isstack);
2398
2400}
2401
2402int
2404{
2405 SDL_FPoint points[2];
2406 points[0].x = (float) x1;
2407 points[0].y = (float) y1;
2408 points[1].x = (float) x2;
2409 points[1].y = (float) y2;
2411}
2412
2413int
2414SDL_RenderDrawLineF(SDL_Renderer * renderer, float x1, float y1, float x2, float y2)
2415{
2416 SDL_FPoint points[2];
2417 points[0].x = x1;
2418 points[0].y = y1;
2419 points[1].x = x2;
2420 points[1].y = y2;
2422}
2423
2424static int
2426 const SDL_Point * points, const int count)
2427{
2428 SDL_FRect *frect;
2429 SDL_FRect *frects;
2430 SDL_FPoint fpoints[2];
2431 int i, nrects = 0;
2432 int retval = 0;
2433 SDL_bool isstack;
2434
2435 frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
2436 if (!frects) {
2437 return SDL_OutOfMemory();
2438 }
2439
2440 for (i = 0; i < count-1; ++i) {
2441 if (points[i].x == points[i+1].x) {
2442 const int minY = SDL_min(points[i].y, points[i+1].y);
2443 const int maxY = SDL_max(points[i].y, points[i+1].y);
2444
2445 frect = &frects[nrects++];
2446 frect->x = points[i].x * renderer->scale.x;
2447 frect->y = minY * renderer->scale.y;
2448 frect->w = renderer->scale.x;
2449 frect->h = (maxY - minY + 1) * renderer->scale.y;
2450 } else if (points[i].y == points[i+1].y) {
2451 const int minX = SDL_min(points[i].x, points[i+1].x);
2452 const int maxX = SDL_max(points[i].x, points[i+1].x);
2453
2454 frect = &frects[nrects++];
2455 frect->x = minX * renderer->scale.x;
2456 frect->y = points[i].y * renderer->scale.y;
2457 frect->w = (maxX - minX + 1) * renderer->scale.x;
2458 frect->h = renderer->scale.y;
2459 } else {
2460 /* FIXME: We can't use a rect for this line... */
2461 fpoints[0].x = points[i].x * renderer->scale.x;
2462 fpoints[0].y = points[i].y * renderer->scale.y;
2463 fpoints[1].x = points[i+1].x * renderer->scale.x;
2464 fpoints[1].y = points[i+1].y * renderer->scale.y;
2465 retval += QueueCmdDrawLines(renderer, fpoints, 2);
2466 }
2467 }
2468
2469 retval += QueueCmdFillRects(renderer, frects, nrects);
2470
2471 SDL_small_free(frects, isstack);
2472
2473 if (retval < 0) {
2474 retval = -1;
2475 }
2477}
2478
2479static int
2481 const SDL_FPoint * points, const int count)
2482{
2483 SDL_FRect *frect;
2484 SDL_FRect *frects;
2485 SDL_FPoint fpoints[2];
2486 int i, nrects = 0;
2487 int retval = 0;
2488 SDL_bool isstack;
2489
2490 frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
2491 if (!frects) {
2492 return SDL_OutOfMemory();
2493 }
2494
2495 for (i = 0; i < count-1; ++i) {
2496 if (points[i].x == points[i+1].x) {
2497 const int minY = (int)SDL_min(points[i].y, points[i+1].y);
2498 const int maxY = (int)SDL_max(points[i].y, points[i+1].y);
2499
2500 frect = &frects[nrects++];
2501 frect->x = points[i].x * renderer->scale.x;
2502 frect->y = minY * renderer->scale.y;
2503 frect->w = renderer->scale.x;
2504 frect->h = (maxY - minY + 1) * renderer->scale.y;
2505 } else if (points[i].y == points[i+1].y) {
2506 const int minX = (int)SDL_min(points[i].x, points[i+1].x);
2507 const int maxX = (int)SDL_max(points[i].x, points[i+1].x);
2508
2509 frect = &frects[nrects++];
2510 frect->x = minX * renderer->scale.x;
2511 frect->y = points[i].y * renderer->scale.y;
2512 frect->w = (maxX - minX + 1) * renderer->scale.x;
2513 frect->h = renderer->scale.y;
2514 } else {
2515 /* FIXME: We can't use a rect for this line... */
2516 fpoints[0].x = points[i].x * renderer->scale.x;
2517 fpoints[0].y = points[i].y * renderer->scale.y;
2518 fpoints[1].x = points[i+1].x * renderer->scale.x;
2519 fpoints[1].y = points[i+1].y * renderer->scale.y;
2520 retval += QueueCmdDrawLines(renderer, fpoints, 2);
2521 }
2522 }
2523
2524 retval += QueueCmdFillRects(renderer, frects, nrects);
2525
2526 SDL_small_free(frects, isstack);
2527
2528 if (retval < 0) {
2529 retval = -1;
2530 }
2532}
2533
2534int
2536 const SDL_Point * points, int count)
2537{
2538 SDL_FPoint *fpoints;
2539 int i;
2540 int retval;
2541 SDL_bool isstack;
2542
2544
2545 if (!points) {
2546 return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
2547 }
2548 if (count < 2) {
2549 return 0;
2550 }
2551
2552 /* Don't draw while we're hidden */
2553 if (renderer->hidden) {
2554 return 0;
2555 }
2556
2557 if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
2559 }
2560
2561 fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
2562 if (!fpoints) {
2563 return SDL_OutOfMemory();
2564 }
2565 for (i = 0; i < count; ++i) {
2566 fpoints[i].x = points[i].x * renderer->scale.x;
2567 fpoints[i].y = points[i].y * renderer->scale.y;
2568 }
2569
2571
2572 SDL_small_free(fpoints, isstack);
2573
2575}
2576
2577int
2579 const SDL_FPoint * points, int count)
2580{
2581 SDL_FPoint *fpoints;
2582 int i;
2583 int retval;
2584 SDL_bool isstack;
2585
2587
2588 if (!points) {
2589 return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
2590 }
2591 if (count < 2) {
2592 return 0;
2593 }
2594
2595 /* Don't draw while we're hidden */
2596 if (renderer->hidden) {
2597 return 0;
2598 }
2599
2600 if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
2602 }
2603
2604 fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
2605 if (!fpoints) {
2606 return SDL_OutOfMemory();
2607 }
2608 for (i = 0; i < count; ++i) {
2609 fpoints[i].x = points[i].x * renderer->scale.x;
2610 fpoints[i].y = points[i].y * renderer->scale.y;
2611 }
2612
2614
2615 SDL_small_free(fpoints, isstack);
2616
2618}
2619
2620int
2622{
2623 SDL_FRect frect;
2624 SDL_FRect *prect = NULL;
2625
2626 if (rect) {
2627 frect.x = (float) rect->x;
2628 frect.y = (float) rect->y;
2629 frect.w = (float) rect->w;
2630 frect.h = (float) rect->h;
2631 prect = &frect;
2632 }
2633
2634 return SDL_RenderDrawRectF(renderer, prect);
2635}
2636
2637int
2639{
2640 SDL_FRect frect;
2641 SDL_FPoint points[5];
2642
2644
2645 /* If 'rect' == NULL, then outline the whole surface */
2646 if (!rect) {
2647 SDL_Rect r;
2649 frect.x = 0.0f;
2650 frect.y = 0.0f;
2651 frect.w = (float) r.w;
2652 frect.h = (float) r.h;
2653 rect = &frect;
2654 }
2655
2656 points[0].x = rect->x;
2657 points[0].y = rect->y;
2658 points[1].x = rect->x+rect->w-1;
2659 points[1].y = rect->y;
2660 points[2].x = rect->x+rect->w-1;
2661 points[2].y = rect->y+rect->h-1;
2662 points[3].x = rect->x;
2663 points[3].y = rect->y+rect->h-1;
2664 points[4].x = rect->x;
2665 points[4].y = rect->y;
2667}
2668
2669int
2671 const SDL_Rect * rects, int count)
2672{
2673 int i;
2674
2676
2677 if (!rects) {
2678 return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
2679 }
2680 if (count < 1) {
2681 return 0;
2682 }
2683
2684 /* Don't draw while we're hidden */
2685 if (renderer->hidden) {
2686 return 0;
2687 }
2688
2689 for (i = 0; i < count; ++i) {
2690 if (SDL_RenderDrawRect(renderer, &rects[i]) < 0) {
2691 return -1;
2692 }
2693 }
2694 return 0;
2695}
2696
2697int
2699 const SDL_FRect * rects, int count)
2700{
2701 int i;
2702
2704
2705 if (!rects) {
2706 return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
2707 }
2708 if (count < 1) {
2709 return 0;
2710 }
2711
2712 /* Don't draw while we're hidden */
2713 if (renderer->hidden) {
2714 return 0;
2715 }
2716
2717 for (i = 0; i < count; ++i) {
2718 if (SDL_RenderDrawRectF(renderer, &rects[i]) < 0) {
2719 return -1;
2720 }
2721 }
2722 return 0;
2723}
2724
2725int
2727{
2728 SDL_FRect frect;
2729
2731
2732 /* If 'rect' == NULL, then outline the whole surface */
2733 if (rect) {
2734 frect.x = (float) rect->x;
2735 frect.y = (float) rect->y;
2736 frect.w = (float) rect->w;
2737 frect.h = (float) rect->h;
2738 } else {
2739 SDL_Rect r;
2740 SDL_zero(r);
2742 frect.x = 0.0f;
2743 frect.y = 0.0f;
2744 frect.w = (float) r.w;
2745 frect.h = (float) r.h;
2746 }
2747 return SDL_RenderFillRectsF(renderer, &frect, 1);
2748}
2749
2750int
2752{
2753 SDL_FRect frect;
2754
2756
2757 /* If 'rect' == NULL, then outline the whole surface */
2758 if (!rect) {
2759 SDL_Rect r;
2760 SDL_zero(r);
2762 frect.x = 0.0f;
2763 frect.y = 0.0f;
2764 frect.w = (float) r.w;
2765 frect.h = (float) r.h;
2766 rect = &frect;
2767 }
2769}
2770
2771int
2773 const SDL_Rect * rects, int count)
2774{
2775 SDL_FRect *frects;
2776 int i;
2777 int retval;
2778 SDL_bool isstack;
2779
2781
2782 if (!rects) {
2783 return SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
2784 }
2785 if (count < 1) {
2786 return 0;
2787 }
2788
2789 /* Don't draw while we're hidden */
2790 if (renderer->hidden) {
2791 return 0;
2792 }
2793
2794 frects = SDL_small_alloc(SDL_FRect, count, &isstack);
2795 if (!frects) {
2796 return SDL_OutOfMemory();
2797 }
2798 for (i = 0; i < count; ++i) {
2799 frects[i].x = rects[i].x * renderer->scale.x;
2800 frects[i].y = rects[i].y * renderer->scale.y;
2801 frects[i].w = rects[i].w * renderer->scale.x;
2802 frects[i].h = rects[i].h * renderer->scale.y;
2803 }
2804
2806
2807 SDL_small_free(frects, isstack);
2808
2810}
2811
2812int
2814 const SDL_FRect * rects, int count)
2815{
2816 SDL_FRect *frects;
2817 int i;
2818 int retval;
2819 SDL_bool isstack;
2820
2822
2823 if (!rects) {
2824 return SDL_SetError("SDL_RenderFillFRects(): Passed NULL rects");
2825 }
2826 if (count < 1) {
2827 return 0;
2828 }
2829
2830 /* Don't draw while we're hidden */
2831 if (renderer->hidden) {
2832 return 0;
2833 }
2834
2835 frects = SDL_small_alloc(SDL_FRect, count, &isstack);
2836 if (!frects) {
2837 return SDL_OutOfMemory();
2838 }
2839 for (i = 0; i < count; ++i) {
2840 frects[i].x = rects[i].x * renderer->scale.x;
2841 frects[i].y = rects[i].y * renderer->scale.y;
2842 frects[i].w = rects[i].w * renderer->scale.x;
2843 frects[i].h = rects[i].h * renderer->scale.y;
2844 }
2845
2847
2848 SDL_small_free(frects, isstack);
2849
2851}
2852
2853/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
2855{
2856 return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
2857}
2858
2859/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
2860static SDL_bool
2862{
2863 float Amin, Amax, Bmin, Bmax;
2864
2865 if (!A) {
2867 return SDL_FALSE;
2868 }
2869
2870 if (!B) {
2872 return SDL_FALSE;
2873 }
2874
2875 /* Special cases for empty rects */
2876 if (SDL_FRectEmpty(A) || SDL_FRectEmpty(B)) {
2877 return SDL_FALSE;
2878 }
2879
2880 /* Horizontal intersection */
2881 Amin = A->x;
2882 Amax = Amin + A->w;
2883 Bmin = B->x;
2884 Bmax = Bmin + B->w;
2885 if (Bmin > Amin)
2886 Amin = Bmin;
2887 if (Bmax < Amax)
2888 Amax = Bmax;
2889 if (Amax <= Amin)
2890 return SDL_FALSE;
2891
2892 /* Vertical intersection */
2893 Amin = A->y;
2894 Amax = Amin + A->h;
2895 Bmin = B->y;
2896 Bmax = Bmin + B->h;
2897 if (Bmin > Amin)
2898 Amin = Bmin;
2899 if (Bmax < Amax)
2900 Amax = Bmax;
2901 if (Amax <= Amin)
2902 return SDL_FALSE;
2903
2904 return SDL_TRUE;
2905}
2906
2907int
2909 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
2910{
2911 SDL_FRect dstfrect;
2912 SDL_FRect *pdstfrect = NULL;
2913 if (dstrect) {
2914 dstfrect.x = (float) dstrect->x;
2915 dstfrect.y = (float) dstrect->y;
2916 dstfrect.w = (float) dstrect->w;
2917 dstfrect.h = (float) dstrect->h;
2918 pdstfrect = &dstfrect;
2919 }
2920 return SDL_RenderCopyF(renderer, texture, srcrect, pdstfrect);
2921}
2922
2923int
2925 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
2926{
2927 SDL_Rect real_srcrect;
2928 SDL_FRect real_dstrect;
2929 SDL_Rect r;
2930 int retval;
2931
2934
2935 if (renderer != texture->renderer) {
2936 return SDL_SetError("Texture was not created with this renderer");
2937 }
2938
2939 /* Don't draw while we're hidden */
2940 if (renderer->hidden) {
2941 return 0;
2942 }
2943
2944 real_srcrect.x = 0;
2945 real_srcrect.y = 0;
2946 real_srcrect.w = texture->w;
2947 real_srcrect.h = texture->h;
2948 if (srcrect) {
2949 if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
2950 return 0;
2951 }
2952 }
2953
2954 SDL_zero(r);
2956 real_dstrect.x = 0.0f;
2957 real_dstrect.y = 0.0f;
2958 real_dstrect.w = (float) r.w;
2959 real_dstrect.h = (float) r.h;
2960 if (dstrect) {
2961 if (!SDL_HasIntersectionF(dstrect, &real_dstrect)) {
2962 return 0;
2963 }
2964 real_dstrect = *dstrect;
2965 }
2966
2967 if (texture->native) {
2968 texture = texture->native;
2969 }
2970
2971 real_dstrect.x *= renderer->scale.x;
2972 real_dstrect.y *= renderer->scale.y;
2973 real_dstrect.w *= renderer->scale.x;
2974 real_dstrect.h *= renderer->scale.y;
2975
2976 texture->last_command_generation = renderer->render_command_generation;
2977
2978 retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect);
2980}
2981
2982int
2984 const SDL_Rect * srcrect, const SDL_Rect * dstrect,
2985 const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
2986{
2987 SDL_FRect dstfrect;
2988 SDL_FRect *pdstfrect = NULL;
2989 SDL_FPoint fcenter;
2990 SDL_FPoint *pfcenter = NULL;
2991
2992 if (dstrect) {
2993 dstfrect.x = (float) dstrect->x;
2994 dstfrect.y = (float) dstrect->y;
2995 dstfrect.w = (float) dstrect->w;
2996 dstfrect.h = (float) dstrect->h;
2997 pdstfrect = &dstfrect;
2998 }
2999
3000 if (center) {
3001 fcenter.x = (float) center->x;
3002 fcenter.y = (float) center->y;
3003 pfcenter = &fcenter;
3004 }
3005
3006 return SDL_RenderCopyExF(renderer, texture, srcrect, pdstfrect, angle, pfcenter, flip);
3007}
3008
3009int
3011 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
3012 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
3013{
3014 SDL_Rect real_srcrect;
3015 SDL_FRect real_dstrect;
3016 SDL_FPoint real_center;
3017 int retval;
3018
3019 if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */
3020 return SDL_RenderCopyF(renderer, texture, srcrect, dstrect);
3021 }
3022
3025
3026 if (renderer != texture->renderer) {
3027 return SDL_SetError("Texture was not created with this renderer");
3028 }
3029 if (!renderer->QueueCopyEx) {
3030 return SDL_SetError("Renderer does not support RenderCopyEx");
3031 }
3032
3033 /* Don't draw while we're hidden */
3034 if (renderer->hidden) {
3035 return 0;
3036 }
3037
3038 real_srcrect.x = 0;
3039 real_srcrect.y = 0;
3040 real_srcrect.w = texture->w;
3041 real_srcrect.h = texture->h;
3042 if (srcrect) {
3043 if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
3044 return 0;
3045 }
3046 }
3047
3048 /* We don't intersect the dstrect with the viewport as RenderCopy does because of potential rotation clipping issues... TODO: should we? */
3049 if (dstrect) {
3050 real_dstrect = *dstrect;
3051 } else {
3052 SDL_Rect r;
3053 SDL_zero(r);
3055 real_dstrect.x = 0.0f;
3056 real_dstrect.y = 0.0f;
3057 real_dstrect.w = (float) r.w;
3058 real_dstrect.h = (float) r.h;
3059 }
3060
3061 if (texture->native) {
3062 texture = texture->native;
3063 }
3064
3065 if (center) {
3066 real_center = *center;
3067 } else {
3068 real_center.x = real_dstrect.w / 2.0f;
3069 real_center.y = real_dstrect.h / 2.0f;
3070 }
3071
3072 real_dstrect.x *= renderer->scale.x;
3073 real_dstrect.y *= renderer->scale.y;
3074 real_dstrect.w *= renderer->scale.x;
3075 real_dstrect.h *= renderer->scale.y;
3076
3077 real_center.x *= renderer->scale.x;
3078 real_center.y *= renderer->scale.y;
3079
3080 texture->last_command_generation = renderer->render_command_generation;
3081
3082 retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
3084}
3085
3086int
3088 Uint32 format, void * pixels, int pitch)
3089{
3090 SDL_Rect real_rect;
3091
3093
3094 if (!renderer->RenderReadPixels) {
3095 return SDL_Unsupported();
3096 }
3097
3098 FlushRenderCommands(renderer); /* we need to render before we read the results. */
3099
3100 if (!format) {
3102 }
3103
3104 real_rect.x = renderer->viewport.x;
3105 real_rect.y = renderer->viewport.y;
3106 real_rect.w = renderer->viewport.w;
3107 real_rect.h = renderer->viewport.h;
3108 if (rect) {
3109 if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
3110 return 0;
3111 }
3112 if (real_rect.y > rect->y) {
3113 pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
3114 }
3115 if (real_rect.x > rect->x) {
3116 int bpp = SDL_BYTESPERPIXEL(format);
3117 pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
3118 }
3119 }
3120
3121 return renderer->RenderReadPixels(renderer, &real_rect,
3122 format, pixels, pitch);
3123}
3124
3125void
3127{
3129
3130 FlushRenderCommands(renderer); /* time to send everything to the GPU! */
3131
3132 /* Don't present while we're hidden */
3133 if (renderer->hidden) {
3134 return;
3135 }
3137}
3138
3139void
3141{
3143
3145
3146 renderer = texture->renderer;
3147 if (texture == renderer->target) {
3148 SDL_SetRenderTarget(renderer, NULL); /* implies command queue flush */
3149 } else {
3151 }
3152
3153 texture->magic = NULL;
3154
3155 if (texture->next) {
3156 texture->next->prev = texture->prev;
3157 }
3158 if (texture->prev) {
3159 texture->prev->next = texture->next;
3160 } else {
3162 }
3163
3164 if (texture->native) {
3165 SDL_DestroyTexture(texture->native);
3166 }
3167 if (texture->yuv) {
3169 }
3170 SDL_free(texture->pixels);
3171
3174}
3175
3176void
3178{
3179 SDL_RenderCommand *cmd;
3180 SDL_AllocVertGap *gap;
3181 SDL_AllocVertGap *nextgap;
3182
3184
3186
3190 } else {
3192 }
3193
3197
3198 while (cmd != NULL) {
3199 SDL_RenderCommand *next = cmd->next;
3200 SDL_free(cmd);
3201 cmd = next;
3202 }
3203
3205
3206 for (gap = renderer->vertex_data_gaps.next; gap; gap = nextgap) {
3207 nextgap = gap->next;
3208 SDL_free(gap);
3209 }
3210
3211 for (gap = renderer->vertex_data_gaps_pool; gap; gap = nextgap) {
3212 nextgap = gap->next;
3213 SDL_free(gap);
3214 }
3215
3216 /* Free existing textures for this renderer */
3217 while (renderer->textures) {
3218 SDL_Texture *tex = renderer->textures; (void) tex;
3220 SDL_assert(tex != renderer->textures); /* satisfy static analysis. */
3221 }
3222
3223 if (renderer->window) {
3225 }
3226
3227 /* It's no longer magical... */
3228 renderer->magic = NULL;
3229
3230 /* Free the target mutex */
3233
3234 /* Free the renderer instance */
3236}
3237
3238int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
3239{
3241
3243 renderer = texture->renderer;
3244 if (texture->native) {
3245 return SDL_GL_BindTexture(texture->native, texw, texh);
3246 } else if (renderer && renderer->GL_BindTexture) {
3247 FlushRenderCommandsIfTextureNeeded(texture); /* in case the app is going to mess with it. */
3248 return renderer->GL_BindTexture(renderer, texture, texw, texh);
3249 } else {
3250 return SDL_Unsupported();
3251 }
3252}
3253
3255{
3257
3259 renderer = texture->renderer;
3260 if (texture->native) {
3261 return SDL_GL_UnbindTexture(texture->native);
3262 } else if (renderer && renderer->GL_UnbindTexture) {
3263 FlushRenderCommandsIfTextureNeeded(texture); /* in case the app messed with it. */
3265 }
3266
3267 return SDL_Unsupported();
3268}
3269
3270void *
3272{
3274
3275 if (renderer->GetMetalLayer) {
3276 FlushRenderCommands(renderer); /* in case the app is going to mess with it. */
3278 }
3279 return NULL;
3280}
3281
3282void *
3284{
3286
3288 FlushRenderCommands(renderer); /* in case the app is going to mess with it. */
3290 }
3291 return NULL;
3292}
3293
3294static SDL_BlendMode
3296{
3298 return SDL_BLENDMODE_NONE;
3299 }
3301 return SDL_BLENDMODE_BLEND;
3302 }
3304 return SDL_BLENDMODE_ADD;
3305 }
3307 return SDL_BLENDMODE_MOD;
3308 }
3309 return blendMode;
3310}
3311
3312static SDL_BlendMode
3314{
3317 }
3320 }
3323 }
3326 }
3327 return blendMode;
3328}
3329
3332 SDL_BlendOperation colorOperation,
3333 SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor,
3334 SDL_BlendOperation alphaOperation)
3335{
3336 SDL_BlendMode blendMode = SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation,
3337 srcAlphaFactor, dstAlphaFactor, alphaOperation);
3339}
3340
3343{
3345 return (SDL_BlendFactor)(((Uint32)blendMode >> 4) & 0xF);
3346}
3347
3350{
3352 return (SDL_BlendFactor)(((Uint32)blendMode >> 8) & 0xF);
3353}
3354
3357{
3359 return (SDL_BlendOperation)(((Uint32)blendMode >> 0) & 0xF);
3360}
3361
3364{
3366 return (SDL_BlendFactor)(((Uint32)blendMode >> 20) & 0xF);
3367}
3368
3371{
3373 return (SDL_BlendFactor)(((Uint32)blendMode >> 24) & 0xF);
3374}
3375
3378{
3380 return (SDL_BlendOperation)(((Uint32)blendMode >> 16) & 0xF);
3381}
3382
3383/* vi: set ts=4 sw=4 expandtab: */
void Android_ActivityMutex_Unlock(void)
void Android_ActivityMutex_Lock_Running(void)
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:63
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:76
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:41
@ SDL_BLENDMODE_NONE
Definition: SDL_blendmode.h:42
@ SDL_BLENDMODE_ADD
Definition: SDL_blendmode.h:47
@ SDL_BLENDMODE_BLEND
Definition: SDL_blendmode.h:44
@ SDL_BLENDMODE_MOD
Definition: SDL_blendmode.h:50
#define SDL_SetError
#define SDL_GetWindowSize
#define SDL_GetSurfaceBlendMode
#define SDL_GetCurrentVideoDriver
#define SDL_FreeFormat
#define SDL_GetWindowData
#define SDL_GetSurfaceAlphaMod
#define SDL_CreateWindow
#define SDL_GetWindowFlags
#define SDL_floor
#define SDL_GetWindowPixelFormat
#define SDL_DelEventWatch
#define SDL_LockMutex
#define SDL_AllocFormat
#define SDL_AddEventWatch
#define SDL_malloc
#define SDL_realloc
#define SDL_strcasecmp
#define SDL_fabs
#define SDL_CreateMutex
#define SDL_UnlockSurface
#define SDL_free
#define SDL_HasColorKey
#define SDL_memcmp
#define SDL_GetWindowFromID
#define SDL_SetWindowData
#define SDL_GetHintBoolean
#define SDL_LockSurface
#define SDL_GetSurfaceColorMod
#define SDL_memcpy
#define SDL_FreeSurface
#define SDL_DestroyMutex
#define SDL_atoi
#define SDL_Log
#define SDL_LogInfo
#define SDL_IntersectRect
#define SDL_calloc
#define SDL_GetHint
#define SDL_ConvertPixels
#define SDL_UnlockMutex
#define SDL_ceil
#define SDL_ConvertSurface
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
@ SDL_MOUSEMOTION
Definition: SDL_events.h:105
@ SDL_FINGERMOTION
Definition: SDL_events.h:130
@ SDL_MOUSEBUTTONUP
Definition: SDL_events.h:107
@ SDL_WINDOWEVENT
Definition: SDL_events.h:92
@ SDL_FINGERUP
Definition: SDL_events.h:129
@ SDL_MOUSEBUTTONDOWN
Definition: SDL_events.h:106
@ SDL_FINGERDOWN
Definition: SDL_events.h:128
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:143
#define SDL_HINT_RENDER_DRIVER
A variable specifying which render driver to use.
Definition: SDL_hints.h:85
#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE
A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
Definition: SDL_hints.h:131
#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
#define SDL_HINT_RENDER_BATCHING
A variable controlling whether the 2D render API is compatible or efficient.
Definition: SDL_hints.h:1087
#define SDLCALL
Definition: SDL_internal.h:49
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
@ SDL_LOG_CATEGORY_RENDER
Definition: SDL_log.h:72
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLboolean GLboolean GLboolean b
struct _cl_event * event
GLfixed GLfixed GLint GLint GLfixed points
GLenum GLenum GLenum GLenum GLenum scale
GLfixed GLfixed GLfixed y2
GLfixed y1
GLuint color
GLuint GLfloat GLfloat GLfloat x1
GLintptr offset
GLuint index
GLenum GLsizei len
GLboolean GLboolean GLboolean GLboolean a
GLfixed GLfixed x2
GLboolean GLboolean g
GLfloat angle
GLuint GLint GLboolean GLint GLenum access
GLbitfield flags
GLboolean enable
GLenum GLenum GLuint texture
GLfloat GLfloat GLfloat alpha
GLdouble n
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
#define SDL_ISPIXELFORMAT_ALPHA(format)
Definition: SDL_pixels.h:154
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:46
#define SDL_ISPIXELFORMAT_INDEXED(format)
Definition: SDL_pixels.h:134
@ SDL_PIXELFORMAT_BGR888
Definition: SDL_pixels.h:242
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:277
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:236
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:254
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:279
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
@ SDL_PIXELFORMAT_UNKNOWN
Definition: SDL_pixels.h:173
#define SDL_ISPIXELFORMAT_FOURCC(format)
Definition: SDL_pixels.h:167
void SDL_DestroyTexture(SDL_Texture *texture)
Destroy the specified texture.
Definition: SDL_render.c:3140
static void SDL_UnlockTextureNative(SDL_Texture *texture)
Definition: SDL_render.c:1785
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3349
int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
Set a texture as the current rendering target.
Definition: SDL_render.c:1833
void SDL_RenderGetScale(SDL_Renderer *renderer, float *scaleX, float *scaleY)
Get the drawing scale for the current target.
Definition: SDL_render.c:2164
static const SDL_RenderDriver * render_drivers[]
Definition: SDL_render.c:79
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3342
static int QueueCmdSetDrawColor(SDL_Renderer *renderer, const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a)
Definition: SDL_render.c:445
int SDL_RenderDrawPoint(SDL_Renderer *renderer, int x, int y)
Draw a point on the current rendering target.
Definition: SDL_render.c:2245
static int QueueCmdSetViewport(SDL_Renderer *renderer)
Definition: SDL_render.c:400
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
static int PrepQueueCmdDraw(SDL_Renderer *renderer, const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a)
Definition: SDL_render.c:491
int SDL_RenderClear(SDL_Renderer *renderer)
Clear the current rendering target with the drawing color.
Definition: SDL_render.c:2232
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
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
static SDL_RenderCommand * PrepQueueCmdDrawSolid(SDL_Renderer *renderer, const SDL_RenderCommandType cmdtype)
Definition: SDL_render.c:507
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
static SDL_RenderCommand * AllocateRenderCommand(SDL_Renderer *renderer)
Definition: SDL_render.c:371
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
void SDL_DestroyRenderer(SDL_Renderer *renderer)
Destroy the rendering context for a window and free associated textures.
Definition: SDL_render.c:3177
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3370
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3363
void SDL_UnlockTexture(SDL_Texture *texture)
Unlock a texture, uploading the changes to video memory, if needed.
Definition: SDL_render.c:1806
int SDL_GetNumRenderDrivers(void)
Get the number of 2D rendering drivers available for the current display.
Definition: SDL_render.c:627
#define SDL_WINDOWRENDERDATA
Definition: SDL_render.c:36
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
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
void SDL_RenderPresent(SDL_Renderer *renderer)
Update the screen with rendering performed.
Definition: SDL_render.c:3126
int SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode)
Get the blend mode used for texture copy operations.
Definition: SDL_render.c:1457
static int QueueCmdSetClipRect(SDL_Renderer *renderer)
Definition: SDL_render.c:423
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
int SDL_GL_UnbindTexture(SDL_Texture *texture)
Unbind a texture from the current OpenGL/ES/ES2 context.
Definition: SDL_render.c:3254
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
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
static int RenderDrawPointsWithRectsF(SDL_Renderer *renderer, const SDL_FPoint *fpoints, const int count)
Definition: SDL_render.c:2333
static SDL_RenderCommand * PrepQueueCmdDrawTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_RenderCommandType cmdtype)
Definition: SDL_render.c:571
void SDL_RenderGetViewport(SDL_Renderer *renderer, SDL_Rect *rect)
Get the drawing area for the current target.
Definition: SDL_render.c:2100
int SDL_RenderDrawPointF(SDL_Renderer *renderer, float x, float y)
Draw a point on the current rendering target.
Definition: SDL_render.c:2254
#define CHECK_TEXTURE_MAGIC(texture, retval)
Definition: SDL_render.c:45
static SDL_AllocVertGap * AllocateVertexGap(SDL_Renderer *renderer)
Definition: SDL_render.c:267
SDL_bool SDL_RenderIsClipEnabled(SDL_Renderer *renderer)
Get whether clipping is enabled on the given renderer.
Definition: SDL_render.c:2147
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_bool SDL_RenderTargetSupported(SDL_Renderer *renderer)
Determines whether a window supports the use of render targets.
Definition: SDL_render.c:1824
static int FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
Definition: SDL_render.c:244
SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface)
Create a texture from an existing surface.
Definition: SDL_render.c:1207
void SDL_RenderGetClipRect(SDL_Renderer *renderer, SDL_Rect *rect)
Get the clip rectangle for the current target.
Definition: SDL_render.c:2134
int SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info)
Get information about a rendering context.
Definition: SDL_render.c:1013
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
int SDL_RenderSetClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
Set the clip rectangle for the current target.
Definition: SDL_render.c:2113
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
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
static int UpdateLogicalSize(SDL_Renderer *renderer)
Definition: SDL_render.c:1918
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_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3377
SDL_Renderer * SDL_CreateSoftwareRenderer(SDL_Surface *surface)
Create a 2D software rendering context for a surface.
Definition: SDL_render.c:980
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
int SDL_RenderSetIntegerScale(SDL_Renderer *renderer, SDL_bool enable)
Set whether to force integer scales for resolution-independent rendering.
Definition: SDL_render.c:2060
int SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha)
Set an additional alpha value used in render copy operations.
Definition: SDL_render.c:1411
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
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
static int SDL_RendererEventWatch(void *userdata, SDL_Event *event)
Definition: SDL_render.c:662
static SDL_BlendMode SDL_GetLongBlendMode(SDL_BlendMode blendMode)
Definition: SDL_render.c:3313
static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, Uint32 format)
Definition: SDL_render.c:1070
static SDL_bool SDL_HasIntersectionF(const SDL_FRect *A, const SDL_FRect *B)
Definition: SDL_render.c:2861
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_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_bool SDL_RenderGetIntegerScale(SDL_Renderer *renderer)
Get whether integer scales are forced for resolution-independent rendering.
Definition: SDL_render.c:2070
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
static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_Rect *viewport, SDL_FPoint *scale)
Definition: SDL_render.c:651
#define SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation, srcAlphaFactor, dstAlphaFactor, alphaOperation)
Definition: SDL_render.c:53
static int SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_render.c:1514
static int FlushRenderCommands(SDL_Renderer *renderer)
Definition: SDL_render.c:203
static int RenderDrawPointsWithRects(SDL_Renderer *renderer, const SDL_Point *points, const int count)
Definition: SDL_render.c:2263
#define SDL_BLENDMODE_NONE_FULL
Definition: SDL_render.c:62
static SDL_bool IsSupportedFormat(SDL_Renderer *renderer, Uint32 format)
Definition: SDL_render.c:1057
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
SDL_Renderer * SDL_GetRenderer(SDL_Window *window)
Get the renderer associated with a window.
Definition: SDL_render.c:1007
static SDL_bool IsSupportedBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_render.c:1040
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
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
int SDL_GetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode *blendMode)
Get the blend mode used for drawing operations.
Definition: SDL_render.c:2223
static SDL_INLINE int FlushRenderCommandsIfNotBatching(SDL_Renderer *renderer)
Definition: SDL_render.c:255
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
static int QueueCmdDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, const int count)
Definition: SDL_render.c:529
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
#define SDL_BLENDMODE_MOD_FULL
Definition: SDL_render.c:74
static int QueueCmdClear(SDL_Renderer *renderer)
Definition: SDL_render.c:474
#define SDL_BLENDMODE_ADD_FULL
Definition: SDL_render.c:70
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
static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_render.c:1468
static int RenderDrawLinesWithRectsF(SDL_Renderer *renderer, const SDL_FPoint *points, const int count)
Definition: SDL_render.c:2480
void SDL_RenderGetLogicalSize(SDL_Renderer *renderer, int *w, int *h)
Get device independent resolution for rendering.
Definition: SDL_render.c:2047
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
static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode)
Definition: SDL_render.c:3295
void * SDL_RenderGetMetalLayer(SDL_Renderer *renderer)
Get the CAMetalLayer associated with the given Metal renderer.
Definition: SDL_render.c:3271
SDL_Texture * SDL_GetRenderTarget(SDL_Renderer *renderer)
Get the current render target or NULL for the default render target.
Definition: SDL_render.c:1912
void * SDL_RenderGetMetalCommandEncoder(SDL_Renderer *renderer)
Get the Metal command encoder for the current frame.
Definition: SDL_render.c:3283
int SDL_RenderDrawRectF(SDL_Renderer *renderer, const SDL_FRect *rect)
Draw a rectangle on the current rendering target.
Definition: SDL_render.c:2638
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3356
static int SDL_LockTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_render.c:1708
#define CHECK_RENDERER_MAGIC(renderer, retval)
Definition: SDL_render.c:38
static int QueueCmdDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, const int count)
Definition: SDL_render.c:543
static int RenderDrawLinesWithRects(SDL_Renderer *renderer, const SDL_Point *points, const int count)
Definition: SDL_render.c:2425
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
static int QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Definition: SDL_render.c:593
int SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha)
Get the additional alpha value used in render copy operations.
Definition: SDL_render.c:1428
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
static SDL_INLINE void VerifyDrawQueueFunctions(const SDL_Renderer *renderer)
Definition: SDL_render.c:821
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
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
int SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode)
Set the blend mode used for texture copy operations.
Definition: SDL_render.c:1439
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
static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd)
Definition: SDL_render.c:112
static void SDL_UnlockTextureYUV(SDL_Texture *texture)
Definition: SDL_render.c:1764
static SDL_ScaleMode SDL_GetScaleMode(void)
Definition: SDL_render.c:1096
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
int SDL_RenderSetLogicalSize(SDL_Renderer *renderer, int w, int h)
Set device independent resolution for rendering.
Definition: SDL_render.c:2027
static int QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, const int count)
Definition: SDL_render.c:557
SDL_Renderer * SDL_CreateRenderer(SDL_Window *window, int index, Uint32 flags)
Create a 2D rendering context for a window.
Definition: SDL_render.c:835
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:284
#define SDL_BLENDMODE_BLEND_FULL
Definition: SDL_render.c:66
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
int SDL_RenderDrawRect(SDL_Renderer *renderer, const SDL_Rect *rect)
Draw a rectangle on the current rendering target.
Definition: SDL_render.c:2621
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_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
Definition: SDL_render.c:2854
static int SDL_LockTextureNative(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_render.c:1715
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
static char renderer_magic
Definition: SDL_render.c:108
static char texture_magic
Definition: SDL_render.c:109
@ SDL_RENDERER_PRESENTVSYNC
Definition: SDL_render.h:69
@ SDL_RENDERER_TARGETTEXTURE
Definition: SDL_render.h:71
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:112
@ SDL_FLIP_NONE
Definition: SDL_render.h:113
@ SDL_TEXTUREACCESS_STATIC
Definition: SDL_render.h:93
@ SDL_TEXTUREACCESS_STREAMING
Definition: SDL_render.h:94
@ SDL_TEXTUREACCESS_TARGET
Definition: SDL_render.h:95
@ SDL_TEXTUREMODULATE_ALPHA
Definition: SDL_render.h:105
@ SDL_TEXTUREMODULATE_COLOR
Definition: SDL_render.h:104
SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface *surface)
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:62
SDL_RenderDriver PSP_RenderDriver
SDL_RenderDriver METAL_RenderDriver
SDL_RenderDriver DirectFB_RenderDriver
SDL_RenderDriver GLES2_RenderDriver
SDL_RenderDriver GL_RenderDriver
SDL_RenderDriver SW_RenderDriver
SDL_ScaleMode
Definition: SDL_sysrender.h:36
@ SDL_ScaleModeLinear
Definition: SDL_sysrender.h:38
@ SDL_ScaleModeBest
Definition: SDL_sysrender.h:39
@ SDL_ScaleModeNearest
Definition: SDL_sysrender.h:37
SDL_RenderDriver D3D_RenderDriver
SDL_RenderDriver GLES_RenderDriver
SDL_RenderDriver D3D11_RenderDriver
SDL_RenderCommandType
Definition: SDL_sysrender.h:73
@ SDL_RENDERCMD_SETCLIPRECT
Definition: SDL_sysrender.h:76
@ SDL_RENDERCMD_DRAW_LINES
Definition: SDL_sysrender.h:80
@ SDL_RENDERCMD_SETVIEWPORT
Definition: SDL_sysrender.h:75
@ SDL_RENDERCMD_DRAW_POINTS
Definition: SDL_sysrender.h:79
@ SDL_RENDERCMD_NO_OP
Definition: SDL_sysrender.h:74
@ SDL_RENDERCMD_FILL_RECTS
Definition: SDL_sysrender.h:81
@ SDL_RENDERCMD_COPY
Definition: SDL_sysrender.h:82
@ SDL_RENDERCMD_CLEAR
Definition: SDL_sysrender.h:78
@ SDL_RENDERCMD_SETDRAWCOLOR
Definition: SDL_sysrender.h:77
@ SDL_RENDERCMD_COPY_EX
Definition: SDL_sysrender.h:83
#define SDL_WINDOWPOS_UNDEFINED
Definition: SDL_video.h:130
@ SDL_WINDOW_MINIMIZED
Definition: SDL_video.h:106
@ SDL_WINDOW_HIDDEN
Definition: SDL_video.h:103
@ SDL_WINDOWEVENT_HIDDEN
Definition: SDL_video.h:150
@ SDL_WINDOWEVENT_SHOWN
Definition: SDL_video.h:149
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
@ SDL_WINDOWEVENT_MAXIMIZED
Definition: SDL_video.h:160
@ SDL_WINDOWEVENT_SIZE_CHANGED
Definition: SDL_video.h:156
@ SDL_WINDOWEVENT_RESTORED
Definition: SDL_video.h:161
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
void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:404
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
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
int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_yuv_sw.c:139
int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:302
SDL_SW_YUVTexture * SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
Definition: SDL_yuv_sw.c:31
#define NULL
Definition: begin_code.h:167
#define SDL_INLINE
Definition: begin_code.h:134
#define SDL_FORCE_INLINE
Definition: begin_code.h:147
EGLSurface surface
Definition: eglext.h:248
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLSurface EGLint * rects
Definition: eglext.h:282
GLfloat GLfloat GLfloat GLfloat GLfloat maxY
Definition: gl2ext.h:446
GLfloat minY
Definition: gl2ext.h:446
GLfloat GLfloat GLfloat GLfloat maxX
Definition: gl2ext.h:446
struct SDL_AllocVertGap * next
Uint8 a
Definition: SDL_pixels.h:300
The structure that defines a point (floating point)
Definition: SDL_rect.h:61
float x
Definition: SDL_rect.h:62
float y
Definition: SDL_rect.h:63
A rectangle, with the origin at the upper left (floating point).
Definition: SDL_rect.h:88
float h
Definition: SDL_rect.h:92
float x
Definition: SDL_rect.h:89
float w
Definition: SDL_rect.h:91
float y
Definition: SDL_rect.h:90
SDL_Color * colors
Definition: SDL_pixels.h:307
SDL_Palette * palette
Definition: SDL_pixels.h:318
The structure that defines a point (integer)
Definition: SDL_rect.h:49
int x
Definition: SDL_rect.h:50
int y
Definition: SDL_rect.h:51
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int w
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
int x
Definition: SDL_rect.h:79
union SDL_RenderCommand::@30 data
struct SDL_RenderCommand * next
struct SDL_RenderCommand::@30::@33 draw
struct SDL_RenderCommand::@30::@31 viewport
SDL_BlendMode blend
SDL_RenderCommandType command
Definition: SDL_sysrender.h:88
struct SDL_RenderCommand::@30::@32 cliprect
SDL_Texture * texture
struct SDL_RenderCommand::@30::@34 color
SDL_RendererInfo info
SDL_Renderer *(* CreateRenderer)(SDL_Window *window, Uint32 flags)
int(* QueueCopy)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
SDL_AllocVertGap vertex_data_gaps
SDL_Rect last_queued_viewport
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
SDL_bool clipping_enabled
SDL_Window * window
const void * magic
SDL_Rect clip_rect_backup
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)
int(* QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
SDL_RenderCommand * render_commands
SDL_Texture * textures
SDL_bool cliprect_queued
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_bool always_batch
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_bool batching
void(* DestroyRenderer)(SDL_Renderer *renderer)
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
size_t vertex_data_allocation
SDL_RenderCommand * render_commands_tail
SDL_mutex * target_mutex
SDL_Rect clip_rect
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
SDL_bool integer_scale
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
void *(* GetMetalLayer)(SDL_Renderer *renderer)
void *(* GetMetalCommandEncoder)(SDL_Renderer *renderer)
void * vertex_data
SDL_bool color_queued
void(* RenderPresent)(SDL_Renderer *renderer)
SDL_FPoint scale
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
SDL_RenderCommand * render_commands_pool
SDL_Rect viewport
int(* QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
SDL_bool hidden
int(* QueueFillRects)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
int(* RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
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)
SDL_AllocVertGap * vertex_data_gaps_pool
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_bool viewport_queued
SDL_FPoint scale_backup
int(* QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
SDL_RendererInfo info
SDL_Rect last_queued_cliprect
Uint32 render_command_generation
size_t vertex_data_used
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_bool last_queued_cliprect_enabled
Uint32 last_queued_color
SDL_Texture * target
SDL_FPoint dpi_scale
SDL_bool clipping_enabled_backup
SDL_Rect viewport_backup
SDL_BlendMode blendMode
int(* QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
Information on the capabilities of a render driver or context.
Definition: SDL_render.h:79
const char * name
Definition: SDL_render.h:80
int max_texture_height
Definition: SDL_render.h:85
Uint32 texture_formats[16]
Definition: SDL_render.h:83
Uint32 num_texture_formats
Definition: SDL_render.h:82
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
void * pixels
Definition: SDL_surface.h:76
SDL_Texture * prev
Definition: SDL_sysrender.h:68
Uint32 format
Definition: SDL_sysrender.h:46
SDL_Texture * next
Definition: SDL_sysrender.h:69
SDL_Texture * native
Definition: SDL_sysrender.h:58
The type used to identify a window.
Definition: SDL_sysvideo.h:74
static SDL_Renderer * renderer
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
SDL_bool retval
int window_w
Definition: testoverlay2.c:143
int window_h
Definition: testoverlay2.c:144
SDL_Rect rect
Definition: testrelative.c:27
SDL_Rect viewport
Definition: testviewport.c:28
General event structure.
Definition: SDL_events.h:558