Patched to compile on C89 compilers.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 /* The SDL 2D rendering system */
25 #include "SDL_assert.h"
26 #include "SDL_hints.h"
28 #include "SDL_render.h"
29 #include "SDL_sysrender.h"
30 #include "software/SDL_render_sw_c.h"
33 #define SDL_WINDOWRENDERDATA "_SDL_WindowRenderData"
35 #define CHECK_RENDERER_MAGIC(renderer, retval) \
36 if (!renderer || renderer->magic != &renderer_magic) { \
37 SDL_SetError("Invalid renderer"); \
41 #define CHECK_TEXTURE_MAGIC(texture, retval) \
42 if (!texture || texture->magic != &texture_magic) { \
43 SDL_SetError("Invalid texture"); \
48 #if !SDL_RENDER_DISABLED
49 static const SDL_RenderDriver *render_drivers[] = {
50 #if SDL_VIDEO_RENDER_D3D
53 #if SDL_VIDEO_RENDER_D3D11
56 #if SDL_VIDEO_RENDER_OGL
59 #if SDL_VIDEO_RENDER_OGL_ES2
62 #if SDL_VIDEO_RENDER_OGL_ES
65 #if SDL_VIDEO_RENDER_DIRECTFB
66 &DirectFB_RenderDriver,
68 #if SDL_VIDEO_RENDER_PSP
73 #endif /* !SDL_RENDER_DISABLED */
75 static char renderer_magic;
76 static char texture_magic;
78 static int UpdateLogicalSize(SDL_Renderer *renderer);
81 SDL_GetNumRenderDrivers(void)
83 #if !SDL_RENDER_DISABLED
84 return SDL_arraysize(render_drivers);
91 SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
93 #if !SDL_RENDER_DISABLED
94 if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
95 return SDL_SetError("index must be in the range of 0 - %d",
96 SDL_GetNumRenderDrivers() - 1);
98 *info = render_drivers[index]->info;
101 return SDL_SetError("SDL not built with rendering support");
106 SDL_RendererEventWatch(void *userdata, SDL_Event *event)
108 SDL_Renderer *renderer = (SDL_Renderer *)userdata;
110 if (event->type == SDL_WINDOWEVENT) {
111 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
112 if (window == renderer->window) {
113 if (renderer->WindowEvent) {
114 renderer->WindowEvent(renderer, &event->window);
117 if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
118 /* Make sure we're operating on the default render target */
119 SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
121 SDL_SetRenderTarget(renderer, NULL);
124 if (renderer->logical_w) {
125 UpdateLogicalSize(renderer);
127 /* Window was resized, reset viewport */
130 if (renderer->GetOutputSize) {
131 renderer->GetOutputSize(renderer, &w, &h);
133 SDL_GetWindowSize(renderer->window, &w, &h);
136 if (renderer->target) {
137 renderer->viewport_backup.x = 0;
138 renderer->viewport_backup.y = 0;
139 renderer->viewport_backup.w = w;
140 renderer->viewport_backup.h = h;
142 renderer->viewport.x = 0;
143 renderer->viewport.y = 0;
144 renderer->viewport.w = w;
145 renderer->viewport.h = h;
146 renderer->UpdateViewport(renderer);
151 SDL_SetRenderTarget(renderer, saved_target);
153 } else if (event->window.event == SDL_WINDOWEVENT_HIDDEN) {
154 renderer->hidden = SDL_TRUE;
155 } else if (event->window.event == SDL_WINDOWEVENT_SHOWN) {
156 if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)) {
157 renderer->hidden = SDL_FALSE;
159 } else if (event->window.event == SDL_WINDOWEVENT_MINIMIZED) {
160 renderer->hidden = SDL_TRUE;
161 } else if (event->window.event == SDL_WINDOWEVENT_RESTORED) {
162 if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
163 renderer->hidden = SDL_FALSE;
167 } else if (event->type == SDL_MOUSEMOTION) {
168 if (renderer->logical_w) {
169 event->motion.x -= renderer->viewport.x;
170 event->motion.y -= renderer->viewport.y;
171 event->motion.x = (int)(event->motion.x / renderer->scale.x);
172 event->motion.y = (int)(event->motion.y / renderer->scale.y);
173 if (event->motion.xrel > 0) {
174 event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / renderer->scale.x));
175 } else if (event->motion.xrel < 0) {
176 event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / renderer->scale.x));
178 if (event->motion.yrel > 0) {
179 event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / renderer->scale.y));
180 } else if (event->motion.yrel < 0) {
181 event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / renderer->scale.y));
184 } else if (event->type == SDL_MOUSEBUTTONDOWN ||
185 event->type == SDL_MOUSEBUTTONUP) {
186 if (renderer->logical_w) {
187 event->button.x -= renderer->viewport.x;
188 event->button.y -= renderer->viewport.y;
189 event->button.x = (int)(event->button.x / renderer->scale.x);
190 event->button.y = (int)(event->button.y / renderer->scale.y);
197 SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags,
198 SDL_Window **window, SDL_Renderer **renderer)
200 *window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED,
201 SDL_WINDOWPOS_UNDEFINED,
202 width, height, window_flags);
208 *renderer = SDL_CreateRenderer(*window, -1, 0);
217 SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
219 #if !SDL_RENDER_DISABLED
220 SDL_Renderer *renderer = NULL;
221 int n = SDL_GetNumRenderDrivers();
225 SDL_SetError("Invalid window");
229 if (SDL_GetRenderer(window)) {
230 SDL_SetError("Renderer already associated with window");
234 hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
237 flags &= ~SDL_RENDERER_PRESENTVSYNC;
239 flags |= SDL_RENDERER_PRESENTVSYNC;
244 hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
246 for (index = 0; index < n; ++index) {
247 const SDL_RenderDriver *driver = render_drivers[index];
249 if (SDL_strcasecmp(hint, driver->info.name) == 0) {
250 /* Create a new renderer instance */
251 renderer = driver->CreateRenderer(window, flags);
258 for (index = 0; index < n; ++index) {
259 const SDL_RenderDriver *driver = render_drivers[index];
261 if ((driver->info.flags & flags) == flags) {
262 /* Create a new renderer instance */
263 renderer = driver->CreateRenderer(window, flags);
265 /* Yay, we got one! */
272 SDL_SetError("Couldn't find matching render driver");
276 if (index >= SDL_GetNumRenderDrivers()) {
277 SDL_SetError("index must be -1 or in the range of 0 - %d",
278 SDL_GetNumRenderDrivers() - 1);
281 /* Create a new renderer instance */
282 renderer = render_drivers[index]->CreateRenderer(window, flags);
286 renderer->magic = &renderer_magic;
287 renderer->window = window;
288 renderer->scale.x = 1.0f;
289 renderer->scale.y = 1.0f;
291 if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {
292 renderer->hidden = SDL_TRUE;
294 renderer->hidden = SDL_FALSE;
297 SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer);
299 SDL_RenderSetViewport(renderer, NULL);
301 SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
303 SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
304 "Created renderer: %s", renderer->info.name);
308 SDL_SetError("SDL not built with rendering support");
314 SDL_CreateSoftwareRenderer(SDL_Surface * surface)
316 #if !SDL_RENDER_DISABLED
317 SDL_Renderer *renderer;
319 renderer = SW_CreateRendererForSurface(surface);
322 renderer->magic = &renderer_magic;
323 renderer->scale.x = 1.0f;
324 renderer->scale.y = 1.0f;
326 SDL_RenderSetViewport(renderer, NULL);
330 SDL_SetError("SDL not built with rendering support");
332 #endif /* !SDL_RENDER_DISABLED */
336 SDL_GetRenderer(SDL_Window * window)
338 return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA);
342 SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
344 CHECK_RENDERER_MAGIC(renderer, -1);
346 *info = renderer->info;
351 SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
353 CHECK_RENDERER_MAGIC(renderer, -1);
355 if (renderer->target) {
356 return SDL_QueryTexture(renderer->target, NULL, NULL, w, h);
357 } else if (renderer->GetOutputSize) {
358 return renderer->GetOutputSize(renderer, w, h);
359 } else if (renderer->window) {
360 SDL_GetWindowSize(renderer->window, w, h);
363 SDL_assert(0 && "This should never happen");
364 return SDL_SetError("Renderer doesn't support querying output size");
369 IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
373 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
374 if (renderer->info.texture_formats[i] == format) {
382 GetClosestSupportedFormat(SDL_Renderer * renderer, Uint32 format)
386 if (SDL_ISPIXELFORMAT_FOURCC(format)) {
387 /* Look for an exact match */
388 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
389 if (renderer->info.texture_formats[i] == format) {
390 return renderer->info.texture_formats[i];
394 SDL_bool hasAlpha = SDL_ISPIXELFORMAT_ALPHA(format);
396 /* We just want to match the first format that has the same channels */
397 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
398 if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
399 SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == hasAlpha) {
400 return renderer->info.texture_formats[i];
404 return renderer->info.texture_formats[0];
408 SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
410 SDL_Texture *texture;
412 CHECK_RENDERER_MAGIC(renderer, NULL);
415 format = renderer->info.texture_formats[0];
417 if (SDL_BYTESPERPIXEL(format) == 0) {
418 SDL_SetError("Invalid texture format");
421 if (SDL_ISPIXELFORMAT_INDEXED(format)) {
422 SDL_SetError("Palettized textures are not supported");
425 if (w <= 0 || h <= 0) {
426 SDL_SetError("Texture dimensions can't be 0");
429 if ((renderer->info.max_texture_width && w > renderer->info.max_texture_width) ||
430 (renderer->info.max_texture_height && h > renderer->info.max_texture_height)) {
431 SDL_SetError("Texture dimensions are limited to %dx%d", renderer->info.max_texture_width, renderer->info.max_texture_height);
434 texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
439 texture->magic = &texture_magic;
440 texture->format = format;
441 texture->access = access;
448 texture->renderer = renderer;
449 texture->next = renderer->textures;
450 if (renderer->textures) {
451 renderer->textures->prev = texture;
453 renderer->textures = texture;
455 if (IsSupportedFormat(renderer, format)) {
456 if (renderer->CreateTexture(renderer, texture) < 0) {
457 SDL_DestroyTexture(texture);
461 texture->native = SDL_CreateTexture(renderer,
462 GetClosestSupportedFormat(renderer, format),
464 if (!texture->native) {
465 SDL_DestroyTexture(texture);
469 /* Swap textures to have texture before texture->native in the list */
470 texture->native->next = texture->next;
471 if (texture->native->next) {
472 texture->native->next->prev = texture->native;
474 texture->prev = texture->native->prev;
476 texture->prev->next = texture;
478 texture->native->prev = texture;
479 texture->next = texture->native;
480 renderer->textures = texture;
482 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
483 texture->yuv = SDL_SW_CreateYUVTexture(format, w, h);
485 SDL_DestroyTexture(texture);
488 } else if (access == SDL_TEXTUREACCESS_STREAMING) {
489 /* The pitch is 4 byte aligned */
490 texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
491 texture->pixels = SDL_calloc(1, texture->pitch * h);
492 if (!texture->pixels) {
493 SDL_DestroyTexture(texture);
502 SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
504 const SDL_PixelFormat *fmt;
508 SDL_Texture *texture;
510 CHECK_RENDERER_MAGIC(renderer, NULL);
513 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
517 /* See what the best texture format is */
518 fmt = surface->format;
519 if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) {
520 needAlpha = SDL_TRUE;
522 needAlpha = SDL_FALSE;
524 format = renderer->info.texture_formats[0];
525 for (i = 0; i < renderer->info.num_texture_formats; ++i) {
526 if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
527 SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
528 format = renderer->info.texture_formats[i];
533 texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
534 surface->w, surface->h);
539 if (format == surface->format->format) {
540 if (SDL_MUSTLOCK(surface)) {
541 SDL_LockSurface(surface);
542 SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
543 SDL_UnlockSurface(surface);
545 SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
548 SDL_PixelFormat *dst_fmt;
549 SDL_Surface *temp = NULL;
551 /* Set up a destination surface for the texture update */
552 dst_fmt = SDL_AllocFormat(format);
554 SDL_DestroyTexture(texture);
557 temp = SDL_ConvertSurface(surface, dst_fmt, 0);
558 SDL_FreeFormat(dst_fmt);
560 SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
561 SDL_FreeSurface(temp);
563 SDL_DestroyTexture(texture);
570 SDL_BlendMode blendMode;
572 SDL_GetSurfaceColorMod(surface, &r, &g, &b);
573 SDL_SetTextureColorMod(texture, r, g, b);
575 SDL_GetSurfaceAlphaMod(surface, &a);
576 SDL_SetTextureAlphaMod(texture, a);
578 if (SDL_GetColorKey(surface, NULL) == 0) {
579 /* We converted to a texture with alpha format */
580 SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
582 SDL_GetSurfaceBlendMode(surface, &blendMode);
583 SDL_SetTextureBlendMode(texture, blendMode);
590 SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access,
593 CHECK_TEXTURE_MAGIC(texture, -1);
596 *format = texture->format;
599 *access = texture->access;
611 SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
613 SDL_Renderer *renderer;
615 CHECK_TEXTURE_MAGIC(texture, -1);
617 renderer = texture->renderer;
618 if (r < 255 || g < 255 || b < 255) {
619 texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
621 texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
626 if (texture->native) {
627 return SDL_SetTextureColorMod(texture->native, r, g, b);
628 } else if (renderer->SetTextureColorMod) {
629 return renderer->SetTextureColorMod(renderer, texture);
636 SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g,
639 CHECK_TEXTURE_MAGIC(texture, -1);
654 SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
656 SDL_Renderer *renderer;
658 CHECK_TEXTURE_MAGIC(texture, -1);
660 renderer = texture->renderer;
662 texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
664 texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
667 if (texture->native) {
668 return SDL_SetTextureAlphaMod(texture->native, alpha);
669 } else if (renderer->SetTextureAlphaMod) {
670 return renderer->SetTextureAlphaMod(renderer, texture);
677 SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha)
679 CHECK_TEXTURE_MAGIC(texture, -1);
688 SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
690 SDL_Renderer *renderer;
692 CHECK_TEXTURE_MAGIC(texture, -1);
694 renderer = texture->renderer;
695 texture->blendMode = blendMode;
696 if (texture->native) {
697 return SDL_SetTextureBlendMode(texture->native, blendMode);
698 } else if (renderer->SetTextureBlendMode) {
699 return renderer->SetTextureBlendMode(renderer, texture);
706 SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode)
708 CHECK_TEXTURE_MAGIC(texture, -1);
711 *blendMode = texture->blendMode;
717 SDL_UpdateTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
718 const void *pixels, int pitch)
720 SDL_Texture *native = texture->native;
723 if (SDL_SW_UpdateYUVTexture(texture->yuv, rect, pixels, pitch) < 0) {
729 full_rect.w = texture->w;
730 full_rect.h = texture->h;
733 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
734 /* We can lock the texture and copy to it */
738 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
741 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
742 rect->w, rect->h, native_pixels, native_pitch);
743 SDL_UnlockTexture(native);
745 /* Use a temporary buffer for updating */
749 temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
750 temp_pixels = SDL_malloc(rect->h * temp_pitch);
752 return SDL_OutOfMemory();
754 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
755 rect->w, rect->h, temp_pixels, temp_pitch);
756 SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
757 SDL_free(temp_pixels);
763 SDL_UpdateTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
764 const void *pixels, int pitch)
766 SDL_Texture *native = texture->native;
768 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
769 /* We can lock the texture and copy to it */
773 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
776 SDL_ConvertPixels(rect->w, rect->h,
777 texture->format, pixels, pitch,
778 native->format, native_pixels, native_pitch);
779 SDL_UnlockTexture(native);
781 /* Use a temporary buffer for updating */
785 temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
786 temp_pixels = SDL_malloc(rect->h * temp_pitch);
788 return SDL_OutOfMemory();
790 SDL_ConvertPixels(rect->w, rect->h,
791 texture->format, pixels, pitch,
792 native->format, temp_pixels, temp_pitch);
793 SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
794 SDL_free(temp_pixels);
800 SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
801 const void *pixels, int pitch)
803 SDL_Renderer *renderer;
806 CHECK_TEXTURE_MAGIC(texture, -1);
809 return SDL_InvalidParamError("pixels");
812 return SDL_InvalidParamError("pitch");
818 full_rect.w = texture->w;
819 full_rect.h = texture->h;
823 if ((rect->w == 0) || (rect->h == 0)) {
824 return 0; /* nothing to do. */
825 } else if (texture->yuv) {
826 return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);
827 } else if (texture->native) {
828 return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
830 renderer = texture->renderer;
831 return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
836 SDL_UpdateTextureYUVPlanar(SDL_Texture * texture, const SDL_Rect * rect,
837 const Uint8 *Yplane, int Ypitch,
838 const Uint8 *Uplane, int Upitch,
839 const Uint8 *Vplane, int Vpitch)
841 SDL_Texture *native = texture->native;
844 if (SDL_SW_UpdateYUVTexturePlanar(texture->yuv, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch) < 0) {
850 full_rect.w = texture->w;
851 full_rect.h = texture->h;
854 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
855 /* We can lock the texture and copy to it */
859 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
862 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
863 rect->w, rect->h, native_pixels, native_pitch);
864 SDL_UnlockTexture(native);
866 /* Use a temporary buffer for updating */
870 temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
871 temp_pixels = SDL_malloc(rect->h * temp_pitch);
873 return SDL_OutOfMemory();
875 SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
876 rect->w, rect->h, temp_pixels, temp_pitch);
877 SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
878 SDL_free(temp_pixels);
883 int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
884 const Uint8 *Yplane, int Ypitch,
885 const Uint8 *Uplane, int Upitch,
886 const Uint8 *Vplane, int Vpitch)
888 SDL_Renderer *renderer;
891 CHECK_TEXTURE_MAGIC(texture, -1);
894 return SDL_InvalidParamError("Yplane");
897 return SDL_InvalidParamError("Ypitch");
900 return SDL_InvalidParamError("Uplane");
903 return SDL_InvalidParamError("Upitch");
906 return SDL_InvalidParamError("Vplane");
909 return SDL_InvalidParamError("Vpitch");
912 if (texture->format != SDL_PIXELFORMAT_YV12 &&
913 texture->format != SDL_PIXELFORMAT_IYUV) {
914 return SDL_SetError("Texture format must by YV12 or IYUV");
920 full_rect.w = texture->w;
921 full_rect.h = texture->h;
926 return SDL_UpdateTextureYUVPlanar(texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
928 SDL_assert(!texture->native);
929 renderer = texture->renderer;
930 SDL_assert(renderer->UpdateTextureYUV);
931 if (renderer->UpdateTextureYUV) {
932 return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
934 return SDL_Unsupported();
940 SDL_LockTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
941 void **pixels, int *pitch)
943 return SDL_SW_LockYUVTexture(texture->yuv, rect, pixels, pitch);
947 SDL_LockTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
948 void **pixels, int *pitch)
950 texture->locked_rect = *rect;
951 *pixels = (void *) ((Uint8 *) texture->pixels +
952 rect->y * texture->pitch +
953 rect->x * SDL_BYTESPERPIXEL(texture->format));
954 *pitch = texture->pitch;
959 SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
960 void **pixels, int *pitch)
962 SDL_Renderer *renderer;
965 CHECK_TEXTURE_MAGIC(texture, -1);
967 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
968 return SDL_SetError("SDL_LockTexture(): texture must be streaming");
974 full_rect.w = texture->w;
975 full_rect.h = texture->h;
980 return SDL_LockTextureYUV(texture, rect, pixels, pitch);
981 } else if (texture->native) {
982 return SDL_LockTextureNative(texture, rect, pixels, pitch);
984 renderer = texture->renderer;
985 return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
990 SDL_UnlockTextureYUV(SDL_Texture * texture)
992 SDL_Texture *native = texture->native;
993 void *native_pixels = NULL;
994 int native_pitch = 0;
1000 rect.h = texture->h;
1002 if (SDL_LockTexture(native, &rect, &native_pixels, &native_pitch) < 0) {
1005 SDL_SW_CopyYUVToRGB(texture->yuv, &rect, native->format,
1006 rect.w, rect.h, native_pixels, native_pitch);
1007 SDL_UnlockTexture(native);
1011 SDL_UnlockTextureNative(SDL_Texture * texture)
1013 SDL_Texture *native = texture->native;
1014 void *native_pixels = NULL;
1015 int native_pitch = 0;
1016 const SDL_Rect *rect = &texture->locked_rect;
1017 const void* pixels = (void *) ((Uint8 *) texture->pixels +
1018 rect->y * texture->pitch +
1019 rect->x * SDL_BYTESPERPIXEL(texture->format));
1020 int pitch = texture->pitch;
1022 if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
1025 SDL_ConvertPixels(rect->w, rect->h,
1026 texture->format, pixels, pitch,
1027 native->format, native_pixels, native_pitch);
1028 SDL_UnlockTexture(native);
1032 SDL_UnlockTexture(SDL_Texture * texture)
1034 SDL_Renderer *renderer;
1036 CHECK_TEXTURE_MAGIC(texture, );
1038 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
1042 SDL_UnlockTextureYUV(texture);
1043 } else if (texture->native) {
1044 SDL_UnlockTextureNative(texture);
1046 renderer = texture->renderer;
1047 renderer->UnlockTexture(renderer, texture);
1052 SDL_RenderTargetSupported(SDL_Renderer *renderer)
1054 if (!renderer || !renderer->SetRenderTarget) {
1057 return (renderer->info.flags & SDL_RENDERER_TARGETTEXTURE) != 0;
1061 SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
1063 if (!SDL_RenderTargetSupported(renderer)) {
1064 return SDL_Unsupported();
1066 if (texture == renderer->target) {
1067 /* Nothing to do! */
1071 /* texture == NULL is valid and means reset the target to the window */
1073 CHECK_TEXTURE_MAGIC(texture, -1);
1074 if (renderer != texture->renderer) {
1075 return SDL_SetError("Texture was not created with this renderer");
1077 if (texture->access != SDL_TEXTUREACCESS_TARGET) {
1078 return SDL_SetError("Texture not created with SDL_TEXTUREACCESS_TARGET");
1080 if (texture->native) {
1081 /* Always render to the native texture */
1082 texture = texture->native;
1086 if (texture && !renderer->target) {
1087 /* Make a backup of the viewport */
1088 renderer->viewport_backup = renderer->viewport;
1089 renderer->clip_rect_backup = renderer->clip_rect;
1090 renderer->clipping_enabled_backup = renderer->clipping_enabled;
1091 renderer->scale_backup = renderer->scale;
1092 renderer->logical_w_backup = renderer->logical_w;
1093 renderer->logical_h_backup = renderer->logical_h;
1095 renderer->target = texture;
1097 if (renderer->SetRenderTarget(renderer, texture) < 0) {
1102 renderer->viewport.x = 0;
1103 renderer->viewport.y = 0;
1104 renderer->viewport.w = texture->w;
1105 renderer->viewport.h = texture->h;
1106 renderer->scale.x = 1.0f;
1107 renderer->scale.y = 1.0f;
1108 renderer->logical_w = texture->w;
1109 renderer->logical_h = texture->h;
1111 renderer->viewport = renderer->viewport_backup;
1112 renderer->clip_rect = renderer->clip_rect_backup;
1113 renderer->clipping_enabled = renderer->clipping_enabled_backup;
1114 renderer->scale = renderer->scale_backup;
1115 renderer->logical_w = renderer->logical_w_backup;
1116 renderer->logical_h = renderer->logical_h_backup;
1118 if (renderer->UpdateViewport(renderer) < 0) {
1121 if (renderer->UpdateClipRect(renderer) < 0) {
1130 SDL_GetRenderTarget(SDL_Renderer *renderer)
1132 return renderer->target;
1136 UpdateLogicalSize(SDL_Renderer *renderer)
1144 if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
1148 want_aspect = (float)renderer->logical_w / renderer->logical_h;
1149 real_aspect = (float)w / h;
1151 /* Clear the scale because we're setting viewport in output coordinates */
1152 SDL_RenderSetScale(renderer, 1.0f, 1.0f);
1154 if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
1155 /* The aspect ratios are the same, just scale appropriately */
1156 scale = (float)w / renderer->logical_w;
1157 SDL_RenderSetViewport(renderer, NULL);
1158 } else if (want_aspect > real_aspect) {
1159 /* We want a wider aspect ratio than is available - letterbox it */
1160 scale = (float)w / renderer->logical_w;
1163 viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
1164 viewport.y = (h - viewport.h) / 2;
1165 SDL_RenderSetViewport(renderer, &viewport);
1167 /* We want a narrower aspect ratio than is available - use side-bars */
1168 scale = (float)h / renderer->logical_h;
1171 viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
1172 viewport.x = (w - viewport.w) / 2;
1173 SDL_RenderSetViewport(renderer, &viewport);
1176 /* Set the new scale */
1177 SDL_RenderSetScale(renderer, scale, scale);
1183 SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h)
1185 CHECK_RENDERER_MAGIC(renderer, -1);
1188 /* Clear any previous logical resolution */
1189 renderer->logical_w = 0;
1190 renderer->logical_h = 0;
1191 SDL_RenderSetViewport(renderer, NULL);
1192 SDL_RenderSetScale(renderer, 1.0f, 1.0f);
1196 renderer->logical_w = w;
1197 renderer->logical_h = h;
1199 return UpdateLogicalSize(renderer);
1203 SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h)
1205 CHECK_RENDERER_MAGIC(renderer, );
1208 *w = renderer->logical_w;
1211 *h = renderer->logical_h;
1216 SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
1218 CHECK_RENDERER_MAGIC(renderer, -1);
1221 renderer->viewport.x = (int)SDL_floor(rect->x * renderer->scale.x);
1222 renderer->viewport.y = (int)SDL_floor(rect->y * renderer->scale.y);
1223 renderer->viewport.w = (int)SDL_ceil(rect->w * renderer->scale.x);
1224 renderer->viewport.h = (int)SDL_ceil(rect->h * renderer->scale.y);
1226 renderer->viewport.x = 0;
1227 renderer->viewport.y = 0;
1228 if (SDL_GetRendererOutputSize(renderer, &renderer->viewport.w, &renderer->viewport.h) < 0) {
1232 return renderer->UpdateViewport(renderer);
1236 SDL_RenderGetViewport(SDL_Renderer * renderer, SDL_Rect * rect)
1238 CHECK_RENDERER_MAGIC(renderer, );
1241 rect->x = (int)(renderer->viewport.x / renderer->scale.x);
1242 rect->y = (int)(renderer->viewport.y / renderer->scale.y);
1243 rect->w = (int)(renderer->viewport.w / renderer->scale.x);
1244 rect->h = (int)(renderer->viewport.h / renderer->scale.y);
1249 SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
1251 CHECK_RENDERER_MAGIC(renderer, -1)
1254 renderer->clipping_enabled = SDL_TRUE;
1255 renderer->clip_rect.x = (int)SDL_floor(rect->x * renderer->scale.x);
1256 renderer->clip_rect.y = (int)SDL_floor(rect->y * renderer->scale.y);
1257 renderer->clip_rect.w = (int)SDL_ceil(rect->w * renderer->scale.x);
1258 renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y);
1260 renderer->clipping_enabled = SDL_FALSE;
1261 SDL_zero(renderer->clip_rect);
1263 return renderer->UpdateClipRect(renderer);
1267 SDL_RenderGetClipRect(SDL_Renderer * renderer, SDL_Rect * rect)
1269 CHECK_RENDERER_MAGIC(renderer, )
1272 rect->x = (int)(renderer->clip_rect.x / renderer->scale.x);
1273 rect->y = (int)(renderer->clip_rect.y / renderer->scale.y);
1274 rect->w = (int)(renderer->clip_rect.w / renderer->scale.x);
1275 rect->h = (int)(renderer->clip_rect.h / renderer->scale.y);
1280 SDL_RenderIsClipEnabled(SDL_Renderer * renderer)
1282 CHECK_RENDERER_MAGIC(renderer, SDL_FALSE)
1283 return renderer->clipping_enabled;
1287 SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
1289 CHECK_RENDERER_MAGIC(renderer, -1);
1291 renderer->scale.x = scaleX;
1292 renderer->scale.y = scaleY;
1297 SDL_RenderGetScale(SDL_Renderer * renderer, float *scaleX, float *scaleY)
1299 CHECK_RENDERER_MAGIC(renderer, );
1302 *scaleX = renderer->scale.x;
1305 *scaleY = renderer->scale.y;
1310 SDL_SetRenderDrawColor(SDL_Renderer * renderer,
1311 Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1313 CHECK_RENDERER_MAGIC(renderer, -1);
1323 SDL_GetRenderDrawColor(SDL_Renderer * renderer,
1324 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
1326 CHECK_RENDERER_MAGIC(renderer, -1);
1344 SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
1346 CHECK_RENDERER_MAGIC(renderer, -1);
1348 renderer->blendMode = blendMode;
1353 SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode *blendMode)
1355 CHECK_RENDERER_MAGIC(renderer, -1);
1357 *blendMode = renderer->blendMode;
1362 SDL_RenderClear(SDL_Renderer * renderer)
1364 CHECK_RENDERER_MAGIC(renderer, -1);
1366 /* Don't draw while we're hidden */
1367 if (renderer->hidden) {
1370 return renderer->RenderClear(renderer);
1374 SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
1380 return SDL_RenderDrawPoints(renderer, &point, 1);
1384 RenderDrawPointsWithRects(SDL_Renderer * renderer,
1385 const SDL_Point * points, int count)
1391 frects = SDL_stack_alloc(SDL_FRect, count);
1393 return SDL_OutOfMemory();
1395 for (i = 0; i < count; ++i) {
1396 frects[i].x = points[i].x * renderer->scale.x;
1397 frects[i].y = points[i].y * renderer->scale.y;
1398 frects[i].w = renderer->scale.x;
1399 frects[i].h = renderer->scale.y;
1402 status = renderer->RenderFillRects(renderer, frects, count);
1404 SDL_stack_free(frects);
1410 SDL_RenderDrawPoints(SDL_Renderer * renderer,
1411 const SDL_Point * points, int count)
1413 SDL_FPoint *fpoints;
1417 CHECK_RENDERER_MAGIC(renderer, -1);
1420 return SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
1425 /* Don't draw while we're hidden */
1426 if (renderer->hidden) {
1430 if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
1431 return RenderDrawPointsWithRects(renderer, points, count);
1434 fpoints = SDL_stack_alloc(SDL_FPoint, count);
1436 return SDL_OutOfMemory();
1438 for (i = 0; i < count; ++i) {
1439 fpoints[i].x = points[i].x * renderer->scale.x;
1440 fpoints[i].y = points[i].y * renderer->scale.y;
1443 status = renderer->RenderDrawPoints(renderer, fpoints, count);
1445 SDL_stack_free(fpoints);
1451 SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
1453 SDL_Point points[2];
1459 return SDL_RenderDrawLines(renderer, points, 2);
1463 RenderDrawLinesWithRects(SDL_Renderer * renderer,
1464 const SDL_Point * points, int count)
1468 SDL_FPoint fpoints[2];
1472 frects = SDL_stack_alloc(SDL_FRect, count-1);
1474 return SDL_OutOfMemory();
1479 for (i = 0; i < count-1; ++i) {
1480 if (points[i].x == points[i+1].x) {
1481 int minY = SDL_min(points[i].y, points[i+1].y);
1482 int maxY = SDL_max(points[i].y, points[i+1].y);
1484 frect = &frects[nrects++];
1485 frect->x = points[i].x * renderer->scale.x;
1486 frect->y = minY * renderer->scale.y;
1487 frect->w = renderer->scale.x;
1488 frect->h = (maxY - minY + 1) * renderer->scale.y;
1489 } else if (points[i].y == points[i+1].y) {
1490 int minX = SDL_min(points[i].x, points[i+1].x);
1491 int maxX = SDL_max(points[i].x, points[i+1].x);
1493 frect = &frects[nrects++];
1494 frect->x = minX * renderer->scale.x;
1495 frect->y = points[i].y * renderer->scale.y;
1496 frect->w = (maxX - minX + 1) * renderer->scale.x;
1497 frect->h = renderer->scale.y;
1499 /* FIXME: We can't use a rect for this line... */
1500 fpoints[0].x = points[i].x * renderer->scale.x;
1501 fpoints[0].y = points[i].y * renderer->scale.y;
1502 fpoints[1].x = points[i+1].x * renderer->scale.x;
1503 fpoints[1].y = points[i+1].y * renderer->scale.y;
1504 status += renderer->RenderDrawLines(renderer, fpoints, 2);
1508 status += renderer->RenderFillRects(renderer, frects, nrects);
1510 SDL_stack_free(frects);
1519 SDL_RenderDrawLines(SDL_Renderer * renderer,
1520 const SDL_Point * points, int count)
1522 SDL_FPoint *fpoints;
1526 CHECK_RENDERER_MAGIC(renderer, -1);
1529 return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
1534 /* Don't draw while we're hidden */
1535 if (renderer->hidden) {
1539 if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
1540 return RenderDrawLinesWithRects(renderer, points, count);
1543 fpoints = SDL_stack_alloc(SDL_FPoint, count);
1545 return SDL_OutOfMemory();
1547 for (i = 0; i < count; ++i) {
1548 fpoints[i].x = points[i].x * renderer->scale.x;
1549 fpoints[i].y = points[i].y * renderer->scale.y;
1552 status = renderer->RenderDrawLines(renderer, fpoints, count);
1554 SDL_stack_free(fpoints);
1560 SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
1563 SDL_Point points[5];
1565 CHECK_RENDERER_MAGIC(renderer, -1);
1567 /* If 'rect' == NULL, then outline the whole surface */
1569 SDL_RenderGetViewport(renderer, &full_rect);
1575 points[0].x = rect->x;
1576 points[0].y = rect->y;
1577 points[1].x = rect->x+rect->w-1;
1578 points[1].y = rect->y;
1579 points[2].x = rect->x+rect->w-1;
1580 points[2].y = rect->y+rect->h-1;
1581 points[3].x = rect->x;
1582 points[3].y = rect->y+rect->h-1;
1583 points[4].x = rect->x;
1584 points[4].y = rect->y;
1585 return SDL_RenderDrawLines(renderer, points, 5);
1589 SDL_RenderDrawRects(SDL_Renderer * renderer,
1590 const SDL_Rect * rects, int count)
1594 CHECK_RENDERER_MAGIC(renderer, -1);
1597 return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
1603 /* Don't draw while we're hidden */
1604 if (renderer->hidden) {
1607 for (i = 0; i < count; ++i) {
1608 if (SDL_RenderDrawRect(renderer, &rects[i]) < 0) {
1616 SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
1618 SDL_Rect full_rect = { 0, 0, 0, 0 };
1620 CHECK_RENDERER_MAGIC(renderer, -1);
1622 /* If 'rect' == NULL, then outline the whole surface */
1624 SDL_RenderGetViewport(renderer, &full_rect);
1629 return SDL_RenderFillRects(renderer, rect, 1);
1633 SDL_RenderFillRects(SDL_Renderer * renderer,
1634 const SDL_Rect * rects, int count)
1640 CHECK_RENDERER_MAGIC(renderer, -1);
1643 return SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
1648 /* Don't draw while we're hidden */
1649 if (renderer->hidden) {
1653 frects = SDL_stack_alloc(SDL_FRect, count);
1655 return SDL_OutOfMemory();
1657 for (i = 0; i < count; ++i) {
1658 frects[i].x = rects[i].x * renderer->scale.x;
1659 frects[i].y = rects[i].y * renderer->scale.y;
1660 frects[i].w = rects[i].w * renderer->scale.x;
1661 frects[i].h = rects[i].h * renderer->scale.y;
1664 status = renderer->RenderFillRects(renderer, frects, count);
1666 SDL_stack_free(frects);
1672 SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1673 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
1675 SDL_Rect real_srcrect = { 0, 0, 0, 0 };
1676 SDL_Rect real_dstrect = { 0, 0, 0, 0 };
1679 CHECK_RENDERER_MAGIC(renderer, -1);
1680 CHECK_TEXTURE_MAGIC(texture, -1);
1682 if (renderer != texture->renderer) {
1683 return SDL_SetError("Texture was not created with this renderer");
1688 real_srcrect.w = texture->w;
1689 real_srcrect.h = texture->h;
1691 if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
1696 SDL_RenderGetViewport(renderer, &real_dstrect);
1700 if (!SDL_HasIntersection(dstrect, &real_dstrect)) {
1703 real_dstrect = *dstrect;
1706 if (texture->native) {
1707 texture = texture->native;
1710 /* Don't draw while we're hidden */
1711 if (renderer->hidden) {
1715 frect.x = real_dstrect.x * renderer->scale.x;
1716 frect.y = real_dstrect.y * renderer->scale.y;
1717 frect.w = real_dstrect.w * renderer->scale.x;
1718 frect.h = real_dstrect.h * renderer->scale.y;
1720 return renderer->RenderCopy(renderer, texture, &real_srcrect, &frect);
1725 SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1726 const SDL_Rect * srcrect, const SDL_Rect * dstrect,
1727 const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
1729 SDL_Rect real_srcrect = { 0, 0, 0, 0 };
1730 SDL_Rect real_dstrect = { 0, 0, 0, 0 };
1731 SDL_Point real_center;
1735 CHECK_RENDERER_MAGIC(renderer, -1);
1736 CHECK_TEXTURE_MAGIC(texture, -1);
1738 if (renderer != texture->renderer) {
1739 return SDL_SetError("Texture was not created with this renderer");
1741 if (!renderer->RenderCopyEx) {
1742 return SDL_SetError("Renderer does not support RenderCopyEx");
1747 real_srcrect.w = texture->w;
1748 real_srcrect.h = texture->h;
1750 if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
1755 /* We don't intersect the dstrect with the viewport as RenderCopy does because of potential rotation clipping issues... TODO: should we? */
1757 real_dstrect = *dstrect;
1759 SDL_RenderGetViewport(renderer, &real_dstrect);
1764 if (texture->native) {
1765 texture = texture->native;
1768 if(center) real_center = *center;
1770 real_center.x = real_dstrect.w/2;
1771 real_center.y = real_dstrect.h/2;
1774 frect.x = real_dstrect.x * renderer->scale.x;
1775 frect.y = real_dstrect.y * renderer->scale.y;
1776 frect.w = real_dstrect.w * renderer->scale.x;
1777 frect.h = real_dstrect.h * renderer->scale.y;
1779 fcenter.x = real_center.x * renderer->scale.x;
1780 fcenter.y = real_center.y * renderer->scale.y;
1782 return renderer->RenderCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip);
1786 SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1787 Uint32 format, void * pixels, int pitch)
1791 CHECK_RENDERER_MAGIC(renderer, -1);
1793 if (!renderer->RenderReadPixels) {
1794 return SDL_Unsupported();
1798 format = SDL_GetWindowPixelFormat(renderer->window);
1801 real_rect.x = renderer->viewport.x;
1802 real_rect.y = renderer->viewport.y;
1803 real_rect.w = renderer->viewport.w;
1804 real_rect.h = renderer->viewport.h;
1806 if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
1809 if (real_rect.y > rect->y) {
1810 pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
1812 if (real_rect.x > rect->x) {
1813 int bpp = SDL_BYTESPERPIXEL(format);
1814 pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
1818 return renderer->RenderReadPixels(renderer, &real_rect,
1819 format, pixels, pitch);
1823 SDL_RenderPresent(SDL_Renderer * renderer)
1825 CHECK_RENDERER_MAGIC(renderer, );
1827 /* Don't draw while we're hidden */
1828 if (renderer->hidden) {
1831 renderer->RenderPresent(renderer);
1835 SDL_DestroyTexture(SDL_Texture * texture)
1837 SDL_Renderer *renderer;
1839 CHECK_TEXTURE_MAGIC(texture, );
1841 renderer = texture->renderer;
1842 if (texture == renderer->target) {
1843 SDL_SetRenderTarget(renderer, NULL);
1846 texture->magic = NULL;
1848 if (texture->next) {
1849 texture->next->prev = texture->prev;
1851 if (texture->prev) {
1852 texture->prev->next = texture->next;
1854 renderer->textures = texture->next;
1857 if (texture->native) {
1858 SDL_DestroyTexture(texture->native);
1861 SDL_SW_DestroyYUVTexture(texture->yuv);
1863 SDL_free(texture->pixels);
1865 renderer->DestroyTexture(renderer, texture);
1870 SDL_DestroyRenderer(SDL_Renderer * renderer)
1872 CHECK_RENDERER_MAGIC(renderer, );
1874 SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
1876 /* Free existing textures for this renderer */
1877 while (renderer->textures) {
1878 SDL_DestroyTexture(renderer->textures);
1881 if (renderer->window) {
1882 SDL_SetWindowData(renderer->window, SDL_WINDOWRENDERDATA, NULL);
1885 /* It's no longer magical... */
1886 renderer->magic = NULL;
1888 /* Free the renderer instance */
1889 renderer->DestroyRenderer(renderer);
1892 int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
1894 SDL_Renderer *renderer;
1896 CHECK_TEXTURE_MAGIC(texture, -1);
1897 renderer = texture->renderer;
1898 if (texture->native) {
1899 return SDL_GL_BindTexture(texture->native, texw, texh);
1900 } else if (renderer && renderer->GL_BindTexture) {
1901 return renderer->GL_BindTexture(renderer, texture, texw, texh);
1903 return SDL_Unsupported();
1907 int SDL_GL_UnbindTexture(SDL_Texture *texture)
1909 SDL_Renderer *renderer;
1911 CHECK_TEXTURE_MAGIC(texture, -1);
1912 renderer = texture->renderer;
1913 if (texture->native) {
1914 return SDL_GL_UnbindTexture(texture->native);
1915 } else if (renderer && renderer->GL_UnbindTexture) {
1916 return renderer->GL_UnbindTexture(renderer, texture);
1919 return SDL_Unsupported();
1922 /* vi: set ts=4 sw=4 expandtab: */