SDL 2.0
SDL_render_sw.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#if !SDL_RENDER_DISABLED
24
25#include "../SDL_sysrender.h"
26#include "SDL_render_sw_c.h"
27#include "SDL_hints.h"
28#include "SDL_assert.h"
29
30#include "SDL_draw.h"
31#include "SDL_blendfillrect.h"
32#include "SDL_blendline.h"
33#include "SDL_blendpoint.h"
34#include "SDL_drawline.h"
35#include "SDL_drawpoint.h"
36#include "SDL_rotate.h"
37
38/* SDL surface based renderer implementation */
39
40typedef struct
41{
46
47typedef struct
48{
52
53
54static SDL_Surface *
56{
58
59 if (!data->surface) {
60 data->surface = data->window;
61 }
62 if (!data->surface) {
64 if (surface) {
65 data->surface = data->window = surface;
66 }
67 }
68 return data->surface;
69}
70
71static void
73{
75
76 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
77 data->surface = NULL;
78 data->window = NULL;
79 }
80}
81
82static int
84{
86
87 if (data->surface) {
88 if (w) {
89 *w = data->surface->w;
90 }
91 if (h) {
92 *h = data->surface->h;
93 }
94 return 0;
95 }
96
97 if (renderer->window) {
99 return 0;
100 }
101
102 SDL_SetError("Software renderer doesn't have an output surface");
103 return -1;
104}
105
106static int
108{
109 int bpp;
110 Uint32 Rmask, Gmask, Bmask, Amask;
111
113 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
114 return SDL_SetError("Unknown texture format");
115 }
116
117 texture->driverdata =
118 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
119 Bmask, Amask);
120 SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
121 texture->b);
122 SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
123 SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
124
125 /* Only RLE encode textures without an alpha channel since the RLE coder
126 * discards the color values of pixels with an alpha value of zero.
127 */
128 if (texture->access == SDL_TEXTUREACCESS_STATIC && !Amask) {
129 SDL_SetSurfaceRLE(texture->driverdata, 1);
130 }
131
132 if (!texture->driverdata) {
133 return -1;
134 }
135 return 0;
136}
137
138static int
140 const SDL_Rect * rect, const void *pixels, int pitch)
141{
142 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
143 Uint8 *src, *dst;
144 int row;
145 size_t length;
146
149 src = (Uint8 *) pixels;
150 dst = (Uint8 *) surface->pixels +
151 rect->y * surface->pitch +
152 rect->x * surface->format->BytesPerPixel;
153 length = rect->w * surface->format->BytesPerPixel;
154 for (row = 0; row < rect->h; ++row) {
156 src += pitch;
157 dst += surface->pitch;
158 }
161 return 0;
162}
163
164static int
166 const SDL_Rect * rect, void **pixels, int *pitch)
167{
168 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
169
170 *pixels =
171 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
172 rect->x * surface->format->BytesPerPixel);
173 *pitch = surface->pitch;
174 return 0;
175}
176
177static void
179{
180}
181
182static int
184{
186
187 if (texture) {
188 data->surface = (SDL_Surface *) texture->driverdata;
189 } else {
190 data->surface = data->window;
191 }
192 return 0;
193}
194
195static int
197{
198 return 0; /* nothing to do in this backend. */
199}
200
201static int
203{
205 int i;
206
207 if (!verts) {
208 return -1;
209 }
210
211 cmd->data.draw.count = count;
212
214 const int x = renderer->viewport.x;
215 const int y = renderer->viewport.y;
216 for (i = 0; i < count; i++, verts++, points++) {
217 verts->x = (int)(x + points->x);
218 verts->y = (int)(y + points->y);
219 }
220 } else {
221 for (i = 0; i < count; i++, verts++, points++) {
222 verts->x = (int)points->x;
223 verts->y = (int)points->y;
224 }
225 }
226
227 return 0;
228}
229
230static int
232{
234 int i;
235
236 if (!verts) {
237 return -1;
238 }
239
240 cmd->data.draw.count = count;
241
243 const int x = renderer->viewport.x;
244 const int y = renderer->viewport.y;
245
246 for (i = 0; i < count; i++, verts++, rects++) {
247 verts->x = (int)(x + rects->x);
248 verts->y = (int)(y + rects->y);
249 verts->w = SDL_max((int)rects->w, 1);
250 verts->h = SDL_max((int)rects->h, 1);
251 }
252 } else {
253 for (i = 0; i < count; i++, verts++, rects++) {
254 verts->x = (int)rects->x;
255 verts->y = (int)rects->y;
256 verts->w = SDL_max((int)rects->w, 1);
257 verts->h = SDL_max((int)rects->h, 1);
258 }
259 }
260
261 return 0;
262}
263
264static int
266 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
267{
268 SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, 2 * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
269
270 if (!verts) {
271 return -1;
272 }
273
274 cmd->data.draw.count = 1;
275
276 SDL_memcpy(verts, srcrect, sizeof (SDL_Rect));
277 verts++;
278
280 verts->x = (int)(renderer->viewport.x + dstrect->x);
281 verts->y = (int)(renderer->viewport.y + dstrect->y);
282 } else {
283 verts->x = (int)dstrect->x;
284 verts->y = (int)dstrect->y;
285 }
286 verts->w = (int)dstrect->w;
287 verts->h = (int)dstrect->h;
288
289 return 0;
290}
291
292typedef struct CopyExData
293{
296 double angle;
299} CopyExData;
300
301static int
303 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
304 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
305{
307
308 if (!verts) {
309 return -1;
310 }
311
312 cmd->data.draw.count = 1;
313
314 SDL_memcpy(&verts->srcrect, srcrect, sizeof (SDL_Rect));
315
317 verts->dstrect.x = (int)(renderer->viewport.x + dstrect->x);
318 verts->dstrect.y = (int)(renderer->viewport.y + dstrect->y);
319 } else {
320 verts->dstrect.x = (int)dstrect->x;
321 verts->dstrect.y = (int)dstrect->y;
322 }
323 verts->dstrect.w = (int)dstrect->w;
324 verts->dstrect.h = (int)dstrect->h;
325 verts->angle = angle;
326 SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
327 verts->flip = flip;
328
329 return 0;
330}
331
332static int
334 const SDL_Rect * srcrect, const SDL_Rect * final_rect,
335 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
336{
337 SDL_Surface *src = (SDL_Surface *) texture->driverdata;
338 SDL_Rect tmp_rect;
339 SDL_Surface *src_clone, *src_rotated, *src_scaled;
340 SDL_Surface *mask = NULL, *mask_rotated = NULL;
341 int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
342 double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
343 SDL_BlendMode blendmode;
344 Uint8 alphaMod, rMod, gMod, bMod;
345 int applyModulation = SDL_FALSE;
346 int blitRequired = SDL_FALSE;
347 int isOpaque = SDL_FALSE;
348
349 if (!surface) {
350 return -1;
351 }
352
353 tmp_rect.x = 0;
354 tmp_rect.y = 0;
355 tmp_rect.w = final_rect->w;
356 tmp_rect.h = final_rect->h;
357
358 /* It is possible to encounter an RLE encoded surface here and locking it is
359 * necessary because this code is going to access the pixel buffer directly.
360 */
361 if (SDL_MUSTLOCK(src)) {
363 }
364
365 /* Clone the source surface but use its pixel buffer directly.
366 * The original source surface must be treated as read-only.
367 */
368 src_clone = SDL_CreateRGBSurfaceFrom(src->pixels, src->w, src->h, src->format->BitsPerPixel, src->pitch,
369 src->format->Rmask, src->format->Gmask,
370 src->format->Bmask, src->format->Amask);
371 if (src_clone == NULL) {
372 if (SDL_MUSTLOCK(src)) {
374 }
375 return -1;
376 }
377
378 SDL_GetSurfaceBlendMode(src, &blendmode);
379 SDL_GetSurfaceAlphaMod(src, &alphaMod);
380 SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod);
381
382 /* SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. */
383 if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) {
384 blitRequired = SDL_TRUE;
385 }
386
387 /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
388 if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) {
389 blitRequired = SDL_TRUE;
390 }
391
392 /* srcrect is not selecting the whole src surface, so cropping is needed */
393 if (!(srcrect->w == src->w && srcrect->h == src->h && srcrect->x == 0 && srcrect->y == 0)) {
394 blitRequired = SDL_TRUE;
395 }
396
397 /* The color and alpha modulation has to be applied before the rotation when using the NONE and MOD blend modes. */
398 if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD) && (alphaMod & rMod & gMod & bMod) != 255) {
399 applyModulation = SDL_TRUE;
400 SDL_SetSurfaceAlphaMod(src_clone, alphaMod);
401 SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod);
402 }
403
404 /* Opaque surfaces are much easier to handle with the NONE blend mode. */
405 if (blendmode == SDL_BLENDMODE_NONE && !src->format->Amask && alphaMod == 255) {
406 isOpaque = SDL_TRUE;
407 }
408
409 /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used
410 * to clear the pixels in the destination surface. The other steps are explained below.
411 */
412 if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
413 mask = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
414 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
415 if (mask == NULL) {
416 retval = -1;
417 } else {
419 }
420 }
421
422 /* Create a new surface should there be a format mismatch or if scaling, cropping,
423 * or modulation is required. It's possible to use the source surface directly otherwise.
424 */
425 if (!retval && (blitRequired || applyModulation)) {
426 SDL_Rect scale_rect = tmp_rect;
427 src_scaled = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
428 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
429 if (src_scaled == NULL) {
430 retval = -1;
431 } else {
433 retval = SDL_BlitScaled(src_clone, srcrect, src_scaled, &scale_rect);
434 SDL_FreeSurface(src_clone);
435 src_clone = src_scaled;
436 src_scaled = NULL;
437 }
438 }
439
440 /* SDLgfx_rotateSurface is going to make decisions depending on the blend mode. */
441 SDL_SetSurfaceBlendMode(src_clone, blendmode);
442
443 if (!retval) {
444 SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
445 src_rotated = SDLgfx_rotateSurface(src_clone, angle, dstwidth/2, dstheight/2, (texture->scaleMode == SDL_ScaleModeNearest) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
446 if (src_rotated == NULL) {
447 retval = -1;
448 }
449 if (!retval && mask != NULL) {
450 /* The mask needed for the NONE blend mode gets rotated with the same parameters. */
451 mask_rotated = SDLgfx_rotateSurface(mask, angle, dstwidth/2, dstheight/2, SDL_FALSE, 0, 0, dstwidth, dstheight, cangle, sangle);
452 if (mask_rotated == NULL) {
453 retval = -1;
454 }
455 }
456 if (!retval) {
457 /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
458 abscenterx = final_rect->x + (int)center->x;
459 abscentery = final_rect->y + (int)center->y;
460 /* Compensate the angle inversion to match the behaviour of the other backends */
461 sangle = -sangle;
462
463 /* Top Left */
464 px = final_rect->x - abscenterx;
465 py = final_rect->y - abscentery;
466 p1x = px * cangle - py * sangle + abscenterx;
467 p1y = px * sangle + py * cangle + abscentery;
468
469 /* Top Right */
470 px = final_rect->x + final_rect->w - abscenterx;
471 py = final_rect->y - abscentery;
472 p2x = px * cangle - py * sangle + abscenterx;
473 p2y = px * sangle + py * cangle + abscentery;
474
475 /* Bottom Left */
476 px = final_rect->x - abscenterx;
477 py = final_rect->y + final_rect->h - abscentery;
478 p3x = px * cangle - py * sangle + abscenterx;
479 p3y = px * sangle + py * cangle + abscentery;
480
481 /* Bottom Right */
482 px = final_rect->x + final_rect->w - abscenterx;
483 py = final_rect->y + final_rect->h - abscentery;
484 p4x = px * cangle - py * sangle + abscenterx;
485 p4y = px * sangle + py * cangle + abscentery;
486
487 tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
488 tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
489 tmp_rect.w = dstwidth;
490 tmp_rect.h = dstheight;
491
492 /* The NONE blend mode needs some special care with non-opaque surfaces.
493 * Other blend modes or opaque surfaces can be blitted directly.
494 */
495 if (blendmode != SDL_BLENDMODE_NONE || isOpaque) {
496 if (applyModulation == SDL_FALSE) {
497 /* If the modulation wasn't already applied, make it happen now. */
498 SDL_SetSurfaceAlphaMod(src_rotated, alphaMod);
499 SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
500 }
501 retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect);
502 } else {
503 /* The NONE blend mode requires three steps to get the pixels onto the destination surface.
504 * First, the area where the rotated pixels will be blitted to get set to zero.
505 * This is accomplished by simply blitting a mask with the NONE blend mode.
506 * The colorkey set by the rotate function will discard the correct pixels.
507 */
508 SDL_Rect mask_rect = tmp_rect;
510 retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect);
511 if (!retval) {
512 /* The next step copies the alpha value. This is done with the BLEND blend mode and
513 * by modulating the source colors with 0. Since the destination is all zeros, this
514 * will effectively set the destination alpha to the source alpha.
515 */
516 SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
517 mask_rect = tmp_rect;
518 retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect);
519 if (!retval) {
520 /* The last step gets the color values in place. The ADD blend mode simply adds them to
521 * the destination (where the color values are all zero). However, because the ADD blend
522 * mode modulates the colors with the alpha channel, a surface without an alpha mask needs
523 * to be created. This makes all source pixels opaque and the colors get copied correctly.
524 */
525 SDL_Surface *src_rotated_rgb;
526 src_rotated_rgb = SDL_CreateRGBSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h,
527 src_rotated->format->BitsPerPixel, src_rotated->pitch,
528 src_rotated->format->Rmask, src_rotated->format->Gmask,
529 src_rotated->format->Bmask, 0);
530 if (src_rotated_rgb == NULL) {
531 retval = -1;
532 } else {
534 retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect);
535 SDL_FreeSurface(src_rotated_rgb);
536 }
537 }
538 }
539 SDL_FreeSurface(mask_rotated);
540 }
541 if (src_rotated != NULL) {
542 SDL_FreeSurface(src_rotated);
543 }
544 }
545 }
546
547 if (SDL_MUSTLOCK(src)) {
549 }
550 if (mask != NULL) {
552 }
553 if (src_clone != NULL) {
554 SDL_FreeSurface(src_clone);
555 }
556 return retval;
557}
558
559static void
561{
562 const Uint8 r = cmd->data.draw.r;
563 const Uint8 g = cmd->data.draw.g;
564 const Uint8 b = cmd->data.draw.b;
565 const Uint8 a = cmd->data.draw.a;
566 const SDL_BlendMode blend = cmd->data.draw.blend;
568 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
569 const SDL_bool colormod = ((r & g & b) != 0xFF);
570 const SDL_bool alphamod = (a != 0xFF);
571 const SDL_bool blending = ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD));
572
573 if (colormod || alphamod || blending) {
575 }
576
577 /* !!! FIXME: we can probably avoid some of these calls. */
581}
582
583static void
585{
586 if (drawstate->surface_cliprect_dirty) {
587 const SDL_Rect *viewport = drawstate->viewport;
588 const SDL_Rect *cliprect = drawstate->cliprect;
589 SDL_assert(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */
590
591 if (cliprect != NULL) {
592 SDL_Rect clip_rect;
593 clip_rect.x = cliprect->x + viewport->x;
594 clip_rect.y = cliprect->y + viewport->y;
595 clip_rect.w = cliprect->w;
596 clip_rect.h = cliprect->h;
597 SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
598 SDL_SetClipRect(surface, &clip_rect);
599 } else {
600 SDL_SetClipRect(surface, drawstate->viewport);
601 }
603 }
604}
605
606static int
607SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
608{
610 SW_DrawStateCache drawstate;
611
612 if (!surface) {
613 return -1;
614 }
615
616 drawstate.viewport = NULL;
617 drawstate.cliprect = NULL;
619
620 while (cmd) {
621 switch (cmd->command) {
623 break; /* Not used in this backend. */
624 }
625
627 drawstate.viewport = &cmd->data.viewport.rect;
629 break;
630 }
631
633 drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
635 break;
636 }
637
638 case SDL_RENDERCMD_CLEAR: {
639 const Uint8 r = cmd->data.color.r;
640 const Uint8 g = cmd->data.color.g;
641 const Uint8 b = cmd->data.color.b;
642 const Uint8 a = cmd->data.color.a;
643 /* By definition the clear ignores the clip rect */
645 SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
647 break;
648 }
649
651 const Uint8 r = cmd->data.draw.r;
652 const Uint8 g = cmd->data.draw.g;
653 const Uint8 b = cmd->data.draw.b;
654 const Uint8 a = cmd->data.draw.a;
655 const int count = (int) cmd->data.draw.count;
656 const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
657 const SDL_BlendMode blend = cmd->data.draw.blend;
658 SetDrawState(surface, &drawstate);
659 if (blend == SDL_BLENDMODE_NONE) {
660 SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
661 } else {
662 SDL_BlendPoints(surface, verts, count, blend, r, g, b, a);
663 }
664 break;
665 }
666
668 const Uint8 r = cmd->data.draw.r;
669 const Uint8 g = cmd->data.draw.g;
670 const Uint8 b = cmd->data.draw.b;
671 const Uint8 a = cmd->data.draw.a;
672 const int count = (int) cmd->data.draw.count;
673 const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
674 const SDL_BlendMode blend = cmd->data.draw.blend;
675 SetDrawState(surface, &drawstate);
676 if (blend == SDL_BLENDMODE_NONE) {
677 SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
678 } else {
679 SDL_BlendLines(surface, verts, count, blend, r, g, b, a);
680 }
681 break;
682 }
683
685 const Uint8 r = cmd->data.draw.r;
686 const Uint8 g = cmd->data.draw.g;
687 const Uint8 b = cmd->data.draw.b;
688 const Uint8 a = cmd->data.draw.a;
689 const int count = (int) cmd->data.draw.count;
690 const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
691 const SDL_BlendMode blend = cmd->data.draw.blend;
692 SetDrawState(surface, &drawstate);
693 if (blend == SDL_BLENDMODE_NONE) {
694 SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
695 } else {
696 SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a);
697 }
698 break;
699 }
700
701 case SDL_RENDERCMD_COPY: {
702 SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
703 const SDL_Rect *srcrect = verts;
704 SDL_Rect *dstrect = verts + 1;
706 SDL_Surface *src = (SDL_Surface *) texture->driverdata;
707
708 SetDrawState(surface, &drawstate);
709
711
712 if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
713 SDL_BlitSurface(src, srcrect, surface, dstrect);
714 } else {
715 /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
716 * to avoid potentially frequent RLE encoding/decoding.
717 */
719 SDL_BlitScaled(src, srcrect, surface, dstrect);
720 }
721 break;
722 }
723
725 const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
726 SetDrawState(surface, &drawstate);
729 &copydata->dstrect, copydata->angle, &copydata->center, copydata->flip);
730 break;
731 }
732
734 break;
735 }
736
737 cmd = cmd->next;
738 }
739
740 return 0;
741}
742
743static int
745 Uint32 format, void * pixels, int pitch)
746{
748 Uint32 src_format;
749 void *src_pixels;
750
751 if (!surface) {
752 return -1;
753 }
754
755 /* NOTE: The rect is already adjusted according to the viewport by
756 * SDL_RenderReadPixels.
757 */
758
759 if (rect->x < 0 || rect->x+rect->w > surface->w ||
760 rect->y < 0 || rect->y+rect->h > surface->h) {
761 return SDL_SetError("Tried to read outside of surface bounds");
762 }
763
764 src_format = surface->format->format;
765 src_pixels = (void*)((Uint8 *) surface->pixels +
766 rect->y * surface->pitch +
767 rect->x * surface->format->BytesPerPixel);
768
769 return SDL_ConvertPixels(rect->w, rect->h,
770 src_format, src_pixels, surface->pitch,
771 format, pixels, pitch);
772}
773
774static void
776{
778
779 if (window) {
781 }
782}
783
784static void
786{
787 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
788
790}
791
792static void
794{
796
797 SDL_free(data);
799}
800
803{
806
807 if (!surface) {
808 SDL_SetError("Can't create renderer for NULL surface");
809 return NULL;
810 }
811
812 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
813 if (!renderer) {
815 return NULL;
816 }
817
818 data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
819 if (!data) {
822 return NULL;
823 }
824 data->surface = surface;
825 data->window = surface;
826
835 renderer->QueueSetDrawColor = SW_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
837 renderer->QueueDrawLines = SW_QueueDrawPoints; /* lines and points queue vertices the same way. */
848
850
851 return renderer;
852}
853
854static SDL_Renderer *
856{
858
860 if (!surface) {
861 return NULL;
862 }
864}
865
868 {
869 "software",
871 8,
872 {
881 },
882 0,
883 0}
884};
885
886#endif /* !SDL_RENDER_DISABLED */
887
888/* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:169
int SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int SDL_BlendLines(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
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_MOD
Definition: SDL_blendmode.h:50
int SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int SDL_DrawLines(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color)
Definition: SDL_drawline.c:166
int SDL_DrawPoints(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color)
Definition: SDL_drawpoint.c:65
#define SDL_SetSurfaceRLE
#define SDL_SetError
#define SDL_GetWindowSize
#define SDL_GetSurfaceBlendMode
#define SDL_FillRects
#define SDL_SetSurfaceColorMod
#define SDL_GetSurfaceAlphaMod
#define SDL_SetSurfaceAlphaMod
#define SDL_MapRGBA
#define SDL_SetSurfaceBlendMode
#define SDL_UpdateWindowSurface
#define SDL_UnlockSurface
#define SDL_PixelFormatEnumToMasks
#define SDL_free
#define SDL_CreateRGBSurfaceFrom
#define SDL_SetClipRect
#define SDL_LockSurface
#define SDL_GetSurfaceColorMod
#define SDL_CreateRGBSurface
#define SDL_memcpy
#define SDL_FreeSurface
#define SDL_GetWindowSurface
#define SDL_IntersectRect
#define SDL_calloc
#define SDL_ConvertPixels
#define SDL_FillRect
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
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 GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
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 src
GLboolean GLboolean GLboolean GLboolean a
GLenum GLenum dst
GLenum GLenum void * row
GLboolean GLboolean g
GLfloat angle
GLbitfield flags
GLenum GLenum GLuint texture
GLuint GLsizei GLsizei * length
GLenum GLint GLuint mask
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
#define SDL_PIXELLAYOUT(X)
Definition: SDL_pixels.h:126
@ SDL_PIXELFORMAT_RGB555
Definition: SDL_pixels.h:194
@ SDL_PIXELFORMAT_RGBA8888
Definition: SDL_pixels.h:251
@ SDL_PIXELFORMAT_BGR888
Definition: SDL_pixels.h:242
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:236
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:254
@ SDL_PIXELFORMAT_BGRA8888
Definition: SDL_pixels.h:257
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
@ SDL_PIXELFORMAT_RGB565
Definition: SDL_pixels.h:224
@ SDL_PACKEDLAYOUT_8888
Definition: SDL_pixels.h:112
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:284
@ SDL_RENDERER_SOFTWARE
Definition: SDL_render.h:66
@ SDL_RENDERER_TARGETTEXTURE
Definition: SDL_render.h:71
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:112
@ SDL_FLIP_VERTICAL
Definition: SDL_render.h:115
@ SDL_FLIP_HORIZONTAL
Definition: SDL_render.h:114
@ SDL_TEXTUREACCESS_STATIC
Definition: SDL_render.h:93
static void SW_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int SW_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
static void SW_RenderPresent(SDL_Renderer *renderer)
static int SW_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int SW_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *final_rect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
static int SW_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
static void PrepTextureForCopy(const SDL_RenderCommand *cmd)
static int SW_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
static int SW_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
SDL_RenderDriver SW_RenderDriver
static int SW_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
static void SW_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_render_sw.c:72
static int SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
static int SW_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
static int SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_render_sw.c:83
static SDL_Surface * SW_ActivateRenderer(SDL_Renderer *renderer)
Definition: SDL_render_sw.c:55
static void SW_DestroyRenderer(SDL_Renderer *renderer)
static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate)
static SDL_Renderer * SW_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface *surface)
void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, int *dstwidth, int *dstheight, double *cangle, double *sangle)
Definition: SDL_rotate.c:106
SDL_Surface * SDLgfx_rotateSurface(SDL_Surface *src, double angle, int centerx, int centery, int smooth, int flipx, int flipy, int dstwidth, int dstheight, double cangle, double sangle)
Definition: SDL_rotate.c:415
#define MIN(a, b)
Definition: SDL_rotate.h:26
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_BlitScaled
Definition: SDL_surface.h:513
#define SDL_BlitSurface
Definition: SDL_surface.h:484
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:62
@ SDL_ScaleModeNearest
Definition: SDL_sysrender.h:37
@ 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
@ SDL_WINDOWEVENT_SIZE_CHANGED
Definition: SDL_video.h:156
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
#define NULL
Definition: begin_code.h:167
EGLSurface surface
Definition: eglext.h:248
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLSurface EGLint * rects
Definition: eglext.h:282
SDL_FPoint center
SDL_RendererFlip flip
SDL_Rect srcrect
SDL_Rect dstrect
double angle
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
The structure that defines a point (integer)
Definition: SDL_rect.h:49
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
int(* QueueCopy)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
SDL_Window * window
int(* QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
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)
void(* DestroyRenderer)(SDL_Renderer *renderer)
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
void(* RenderPresent)(SDL_Renderer *renderer)
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
SDL_Rect viewport
int(* QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
int(* QueueFillRects)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
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)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
SDL_RendererInfo info
void * driverdata
int(* QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
Window state change event data (event.window.*)
Definition: SDL_events.h:196
The type used to identify a window.
Definition: SDL_sysvideo.h:74
const SDL_Rect * viewport
Definition: SDL_render_sw.c:42
const SDL_Rect * cliprect
Definition: SDL_render_sw.c:43
SDL_bool surface_cliprect_dirty
Definition: SDL_render_sw.c:44
SDL_Surface * surface
Definition: SDL_render_sw.c:49
SDL_Surface * window
Definition: SDL_render_sw.c:50
static SDL_Renderer * renderer
SDL_bool retval
SDL_Rect rect
Definition: testrelative.c:27
SDL_Rect viewport
Definition: testviewport.c:28