SDL  2.0
SDL_render_sw.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 
29 #include "SDL_draw.h"
30 #include "SDL_blendfillrect.h"
31 #include "SDL_blendline.h"
32 #include "SDL_blendpoint.h"
33 #include "SDL_drawline.h"
34 #include "SDL_drawpoint.h"
35 #include "SDL_rotate.h"
36 
37 /* SDL surface based renderer implementation */
38 
41  const SDL_WindowEvent *event);
42 static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
51  const SDL_Rect * rect, const void *pixels,
52  int pitch);
54  const SDL_Rect * rect, void **pixels, int *pitch);
61  const SDL_FPoint * points, int count);
63  const SDL_FPoint * points, int count);
65  const SDL_FRect * rects, int count);
67  const SDL_Rect * srcrect, const SDL_FRect * dstrect);
69  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
70  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
72  Uint32 format, void * pixels, int pitch);
76 
77 
80  {
81  "software",
83  8,
84  {
93  },
94  0,
95  0}
96 };
97 
98 typedef struct
99 {
102 } SW_RenderData;
103 
104 
105 static SDL_Surface *
107 {
108  SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
109 
110  if (!data->surface) {
111  data->surface = data->window;
112  }
113  if (!data->surface) {
115  if (surface) {
116  data->surface = data->window = surface;
117 
118  SW_UpdateViewport(renderer);
119  SW_UpdateClipRect(renderer);
120  }
121  }
122  return data->surface;
123 }
124 
125 SDL_Renderer *
127 {
130 
131  if (!surface) {
132  SDL_SetError("Can't create renderer for NULL surface");
133  return NULL;
134  }
135 
136  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
137  if (!renderer) {
138  SDL_OutOfMemory();
139  return NULL;
140  }
141 
142  data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
143  if (!data) {
144  SW_DestroyRenderer(renderer);
145  SDL_OutOfMemory();
146  return NULL;
147  }
148  data->surface = surface;
149  data->window = surface;
150 
151  renderer->WindowEvent = SW_WindowEvent;
152  renderer->GetOutputSize = SW_GetOutputSize;
153  renderer->CreateTexture = SW_CreateTexture;
157  renderer->UpdateTexture = SW_UpdateTexture;
158  renderer->LockTexture = SW_LockTexture;
159  renderer->UnlockTexture = SW_UnlockTexture;
161  renderer->UpdateViewport = SW_UpdateViewport;
162  renderer->UpdateClipRect = SW_UpdateClipRect;
163  renderer->RenderClear = SW_RenderClear;
167  renderer->RenderCopy = SW_RenderCopy;
168  renderer->RenderCopyEx = SW_RenderCopyEx;
170  renderer->RenderPresent = SW_RenderPresent;
171  renderer->DestroyTexture = SW_DestroyTexture;
173  renderer->info = SW_RenderDriver.info;
174  renderer->driverdata = data;
175 
176  SW_ActivateRenderer(renderer);
177 
178  return renderer;
179 }
180 
181 SDL_Renderer *
183 {
185 
186  surface = SDL_GetWindowSurface(window);
187  if (!surface) {
188  return NULL;
189  }
190  return SW_CreateRendererForSurface(surface);
191 }
192 
193 static void
195 {
196  SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
197 
199  data->surface = NULL;
200  data->window = NULL;
201  }
202 }
203 
204 static int
206 {
208 
209  if (surface) {
210  if (w) {
211  *w = surface->w;
212  }
213  if (h) {
214  *h = surface->h;
215  }
216  return 0;
217  } else {
218  SDL_SetError("Software renderer doesn't have an output surface");
219  return -1;
220  }
221 }
222 
223 static int
225 {
226  int bpp;
227  Uint32 Rmask, Gmask, Bmask, Amask;
228 
230  (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
231  return SDL_SetError("Unknown texture format");
232  }
233 
234  texture->driverdata =
235  SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
236  Bmask, Amask);
237  SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
238  texture->b);
239  SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
240  SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
241 
242  /* Only RLE encode textures without an alpha channel since the RLE coder
243  * discards the color values of pixels with an alpha value of zero.
244  */
245  if (texture->access == SDL_TEXTUREACCESS_STATIC && !Amask) {
246  SDL_SetSurfaceRLE(texture->driverdata, 1);
247  }
248 
249  if (!texture->driverdata) {
250  return -1;
251  }
252  return 0;
253 }
254 
255 static int
257 {
258  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
259  /* If the color mod is ever enabled (non-white), permanently disable RLE (which doesn't support
260  * color mod) to avoid potentially frequent RLE encoding/decoding.
261  */
262  if ((texture->r & texture->g & texture->b) != 255) {
263  SDL_SetSurfaceRLE(surface, 0);
264  }
265  return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
266  texture->b);
267 }
268 
269 static int
271 {
272  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
273  /* If the texture ever has multiple alpha values (surface alpha plus alpha channel), permanently
274  * disable RLE (which doesn't support this) to avoid potentially frequent RLE encoding/decoding.
275  */
276  if (texture->a != 255 && surface->format->Amask) {
277  SDL_SetSurfaceRLE(surface, 0);
278  }
279  return SDL_SetSurfaceAlphaMod(surface, texture->a);
280 }
281 
282 static int
284 {
285  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
286  /* If add or mod blending are ever enabled, permanently disable RLE (which doesn't support
287  * them) to avoid potentially frequent RLE encoding/decoding.
288  */
289  if ((texture->blendMode == SDL_BLENDMODE_ADD || texture->blendMode == SDL_BLENDMODE_MOD)) {
290  SDL_SetSurfaceRLE(surface, 0);
291  }
292  return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
293 }
294 
295 static int
297  const SDL_Rect * rect, const void *pixels, int pitch)
298 {
299  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
300  Uint8 *src, *dst;
301  int row;
302  size_t length;
303 
304  if(SDL_MUSTLOCK(surface))
305  SDL_LockSurface(surface);
306  src = (Uint8 *) pixels;
307  dst = (Uint8 *) surface->pixels +
308  rect->y * surface->pitch +
309  rect->x * surface->format->BytesPerPixel;
310  length = rect->w * surface->format->BytesPerPixel;
311  for (row = 0; row < rect->h; ++row) {
312  SDL_memcpy(dst, src, length);
313  src += pitch;
314  dst += surface->pitch;
315  }
316  if(SDL_MUSTLOCK(surface))
317  SDL_UnlockSurface(surface);
318  return 0;
319 }
320 
321 static int
323  const SDL_Rect * rect, void **pixels, int *pitch)
324 {
325  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
326 
327  *pixels =
328  (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
329  rect->x * surface->format->BytesPerPixel);
330  *pitch = surface->pitch;
331  return 0;
332 }
333 
334 static void
336 {
337 }
338 
339 static int
341 {
342  SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
343 
344  if (texture ) {
345  data->surface = (SDL_Surface *) texture->driverdata;
346  } else {
347  data->surface = data->window;
348  }
349  return 0;
350 }
351 
352 static int
354 {
355  SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
356  SDL_Surface *surface = data->surface;
357 
358  if (!surface) {
359  /* We'll update the viewport after we recreate the surface */
360  return 0;
361  }
362 
363  SDL_SetClipRect(data->surface, &renderer->viewport);
364  return 0;
365 }
366 
367 static int
369 {
370  SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
371  SDL_Surface *surface = data->surface;
372  if (surface) {
373  if (renderer->clipping_enabled) {
374  SDL_Rect clip_rect;
375  clip_rect = renderer->clip_rect;
376  clip_rect.x += renderer->viewport.x;
377  clip_rect.y += renderer->viewport.y;
378  SDL_IntersectRect(&renderer->viewport, &clip_rect, &clip_rect);
379  SDL_SetClipRect(surface, &clip_rect);
380  } else {
381  SDL_SetClipRect(surface, &renderer->viewport);
382  }
383  }
384  return 0;
385 }
386 
387 static int
389 {
391  Uint32 color;
392  SDL_Rect clip_rect;
393 
394  if (!surface) {
395  return -1;
396  }
397 
398  color = SDL_MapRGBA(surface->format,
399  renderer->r, renderer->g, renderer->b, renderer->a);
400 
401  /* By definition the clear ignores the clip rect */
402  clip_rect = surface->clip_rect;
403  SDL_SetClipRect(surface, NULL);
404  SDL_FillRect(surface, NULL, color);
405  SDL_SetClipRect(surface, &clip_rect);
406  return 0;
407 }
408 
409 static int
411  int count)
412 {
414  SDL_Point *final_points;
415  int i, status;
416 
417  if (!surface) {
418  return -1;
419  }
420 
421  final_points = SDL_stack_alloc(SDL_Point, count);
422  if (!final_points) {
423  return SDL_OutOfMemory();
424  }
425  if (renderer->viewport.x || renderer->viewport.y) {
426  int x = renderer->viewport.x;
427  int y = renderer->viewport.y;
428 
429  for (i = 0; i < count; ++i) {
430  final_points[i].x = (int)(x + points[i].x);
431  final_points[i].y = (int)(y + points[i].y);
432  }
433  } else {
434  for (i = 0; i < count; ++i) {
435  final_points[i].x = (int)points[i].x;
436  final_points[i].y = (int)points[i].y;
437  }
438  }
439 
440  /* Draw the points! */
441  if (renderer->blendMode == SDL_BLENDMODE_NONE) {
442  Uint32 color = SDL_MapRGBA(surface->format,
443  renderer->r, renderer->g, renderer->b,
444  renderer->a);
445 
446  status = SDL_DrawPoints(surface, final_points, count, color);
447  } else {
448  status = SDL_BlendPoints(surface, final_points, count,
449  renderer->blendMode,
450  renderer->r, renderer->g, renderer->b,
451  renderer->a);
452  }
453  SDL_stack_free(final_points);
454 
455  return status;
456 }
457 
458 static int
460  int count)
461 {
463  SDL_Point *final_points;
464  int i, status;
465 
466  if (!surface) {
467  return -1;
468  }
469 
470  final_points = SDL_stack_alloc(SDL_Point, count);
471  if (!final_points) {
472  return SDL_OutOfMemory();
473  }
474  if (renderer->viewport.x || renderer->viewport.y) {
475  int x = renderer->viewport.x;
476  int y = renderer->viewport.y;
477 
478  for (i = 0; i < count; ++i) {
479  final_points[i].x = (int)(x + points[i].x);
480  final_points[i].y = (int)(y + points[i].y);
481  }
482  } else {
483  for (i = 0; i < count; ++i) {
484  final_points[i].x = (int)points[i].x;
485  final_points[i].y = (int)points[i].y;
486  }
487  }
488 
489  /* Draw the lines! */
490  if (renderer->blendMode == SDL_BLENDMODE_NONE) {
491  Uint32 color = SDL_MapRGBA(surface->format,
492  renderer->r, renderer->g, renderer->b,
493  renderer->a);
494 
495  status = SDL_DrawLines(surface, final_points, count, color);
496  } else {
497  status = SDL_BlendLines(surface, final_points, count,
498  renderer->blendMode,
499  renderer->r, renderer->g, renderer->b,
500  renderer->a);
501  }
502  SDL_stack_free(final_points);
503 
504  return status;
505 }
506 
507 static int
509 {
511  SDL_Rect *final_rects;
512  int i, status;
513 
514  if (!surface) {
515  return -1;
516  }
517 
518  final_rects = SDL_stack_alloc(SDL_Rect, count);
519  if (!final_rects) {
520  return SDL_OutOfMemory();
521  }
522  if (renderer->viewport.x || renderer->viewport.y) {
523  int x = renderer->viewport.x;
524  int y = renderer->viewport.y;
525 
526  for (i = 0; i < count; ++i) {
527  final_rects[i].x = (int)(x + rects[i].x);
528  final_rects[i].y = (int)(y + rects[i].y);
529  final_rects[i].w = SDL_max((int)rects[i].w, 1);
530  final_rects[i].h = SDL_max((int)rects[i].h, 1);
531  }
532  } else {
533  for (i = 0; i < count; ++i) {
534  final_rects[i].x = (int)rects[i].x;
535  final_rects[i].y = (int)rects[i].y;
536  final_rects[i].w = SDL_max((int)rects[i].w, 1);
537  final_rects[i].h = SDL_max((int)rects[i].h, 1);
538  }
539  }
540 
541  if (renderer->blendMode == SDL_BLENDMODE_NONE) {
542  Uint32 color = SDL_MapRGBA(surface->format,
543  renderer->r, renderer->g, renderer->b,
544  renderer->a);
545  status = SDL_FillRects(surface, final_rects, count, color);
546  } else {
547  status = SDL_BlendFillRects(surface, final_rects, count,
548  renderer->blendMode,
549  renderer->r, renderer->g, renderer->b,
550  renderer->a);
551  }
552  SDL_stack_free(final_rects);
553 
554  return status;
555 }
556 
557 static int
559  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
560 {
562  SDL_Surface *src = (SDL_Surface *) texture->driverdata;
563  SDL_Rect final_rect;
564 
565  if (!surface) {
566  return -1;
567  }
568 
569  if (renderer->viewport.x || renderer->viewport.y) {
570  final_rect.x = (int)(renderer->viewport.x + dstrect->x);
571  final_rect.y = (int)(renderer->viewport.y + dstrect->y);
572  } else {
573  final_rect.x = (int)dstrect->x;
574  final_rect.y = (int)dstrect->y;
575  }
576  final_rect.w = (int)dstrect->w;
577  final_rect.h = (int)dstrect->h;
578 
579  if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {
580  return SDL_BlitSurface(src, srcrect, surface, &final_rect);
581  } else {
582  /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
583  * to avoid potentially frequent RLE encoding/decoding.
584  */
585  SDL_SetSurfaceRLE(surface, 0);
586  return SDL_BlitScaled(src, srcrect, surface, &final_rect);
587  }
588 }
589 
590 static int
592  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
593  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
594 {
596  SDL_Surface *src = (SDL_Surface *) texture->driverdata;
597  SDL_Rect final_rect, tmp_rect;
598  SDL_Surface *src_clone, *src_rotated, *src_scaled;
599  SDL_Surface *mask = NULL, *mask_rotated = NULL;
600  int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
601  double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
602  SDL_BlendMode blendmode;
603  Uint8 alphaMod, rMod, gMod, bMod;
604  int applyModulation = SDL_FALSE;
605  int blitRequired = SDL_FALSE;
606  int isOpaque = SDL_FALSE;
607 
608  if (!surface) {
609  return -1;
610  }
611 
612  if (renderer->viewport.x || renderer->viewport.y) {
613  final_rect.x = (int)(renderer->viewport.x + dstrect->x);
614  final_rect.y = (int)(renderer->viewport.y + dstrect->y);
615  } else {
616  final_rect.x = (int)dstrect->x;
617  final_rect.y = (int)dstrect->y;
618  }
619  final_rect.w = (int)dstrect->w;
620  final_rect.h = (int)dstrect->h;
621 
622  tmp_rect = final_rect;
623  tmp_rect.x = 0;
624  tmp_rect.y = 0;
625 
626  /* It is possible to encounter an RLE encoded surface here and locking it is
627  * necessary because this code is going to access the pixel buffer directly.
628  */
629  if (SDL_MUSTLOCK(src)) {
630  SDL_LockSurface(src);
631  }
632 
633  /* Clone the source surface but use its pixel buffer directly.
634  * The original source surface must be treated as read-only.
635  */
636  src_clone = SDL_CreateRGBSurfaceFrom(src->pixels, src->w, src->h, src->format->BitsPerPixel, src->pitch,
637  src->format->Rmask, src->format->Gmask,
638  src->format->Bmask, src->format->Amask);
639  if (src_clone == NULL) {
640  if (SDL_MUSTLOCK(src)) {
641  SDL_UnlockSurface(src);
642  }
643  return -1;
644  }
645 
646  SDL_GetSurfaceBlendMode(src, &blendmode);
647  SDL_GetSurfaceAlphaMod(src, &alphaMod);
648  SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod);
649 
650  /* SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. */
651  if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) {
652  blitRequired = SDL_TRUE;
653  }
654 
655  /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
656  if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) {
657  blitRequired = SDL_TRUE;
658  }
659 
660  /* srcrect is not selecting the whole src surface, so cropping is needed */
661  if (!(srcrect->w == src->w && srcrect->h == src->h && srcrect->x == 0 && srcrect->y == 0)) {
662  blitRequired = SDL_TRUE;
663  }
664 
665  /* The color and alpha modulation has to be applied before the rotation when using the NONE and MOD blend modes. */
666  if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD) && (alphaMod & rMod & gMod & bMod) != 255) {
667  applyModulation = SDL_TRUE;
668  SDL_SetSurfaceAlphaMod(src_clone, alphaMod);
669  SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod);
670  }
671 
672  /* Opaque surfaces are much easier to handle with the NONE blend mode. */
673  if (blendmode == SDL_BLENDMODE_NONE && !src->format->Amask && alphaMod == 255) {
674  isOpaque = SDL_TRUE;
675  }
676 
677  /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used
678  * to clear the pixels in the destination surface. The other steps are explained below.
679  */
680  if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
681  mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
682  0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
683  if (mask == NULL) {
684  retval = -1;
685  } else {
687  }
688  }
689 
690  /* Create a new surface should there be a format mismatch or if scaling, cropping,
691  * or modulation is required. It's possible to use the source surface directly otherwise.
692  */
693  if (!retval && (blitRequired || applyModulation)) {
694  SDL_Rect scale_rect = tmp_rect;
695  src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
696  0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
697  if (src_scaled == NULL) {
698  retval = -1;
699  } else {
701  retval = SDL_BlitScaled(src_clone, srcrect, src_scaled, &scale_rect);
702  SDL_FreeSurface(src_clone);
703  src_clone = src_scaled;
704  src_scaled = NULL;
705  }
706  }
707 
708  /* SDLgfx_rotateSurface is going to make decisions depending on the blend mode. */
709  SDL_SetSurfaceBlendMode(src_clone, blendmode);
710 
711  if (!retval) {
712  SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
713  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);
714  if (src_rotated == NULL) {
715  retval = -1;
716  }
717  if (!retval && mask != NULL) {
718  /* The mask needed for the NONE blend mode gets rotated with the same parameters. */
719  mask_rotated = SDLgfx_rotateSurface(mask, angle, dstwidth/2, dstheight/2, SDL_FALSE, 0, 0, dstwidth, dstheight, cangle, sangle);
720  if (mask_rotated == NULL) {
721  retval = -1;
722  }
723  }
724  if (!retval) {
725  /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
726  abscenterx = final_rect.x + (int)center->x;
727  abscentery = final_rect.y + (int)center->y;
728  /* Compensate the angle inversion to match the behaviour of the other backends */
729  sangle = -sangle;
730 
731  /* Top Left */
732  px = final_rect.x - abscenterx;
733  py = final_rect.y - abscentery;
734  p1x = px * cangle - py * sangle + abscenterx;
735  p1y = px * sangle + py * cangle + abscentery;
736 
737  /* Top Right */
738  px = final_rect.x + final_rect.w - abscenterx;
739  py = final_rect.y - abscentery;
740  p2x = px * cangle - py * sangle + abscenterx;
741  p2y = px * sangle + py * cangle + abscentery;
742 
743  /* Bottom Left */
744  px = final_rect.x - abscenterx;
745  py = final_rect.y + final_rect.h - abscentery;
746  p3x = px * cangle - py * sangle + abscenterx;
747  p3y = px * sangle + py * cangle + abscentery;
748 
749  /* Bottom Right */
750  px = final_rect.x + final_rect.w - abscenterx;
751  py = final_rect.y + final_rect.h - abscentery;
752  p4x = px * cangle - py * sangle + abscenterx;
753  p4y = px * sangle + py * cangle + abscentery;
754 
755  tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
756  tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
757  tmp_rect.w = dstwidth;
758  tmp_rect.h = dstheight;
759 
760  /* The NONE blend mode needs some special care with non-opaque surfaces.
761  * Other blend modes or opaque surfaces can be blitted directly.
762  */
763  if (blendmode != SDL_BLENDMODE_NONE || isOpaque) {
764  if (applyModulation == SDL_FALSE) {
765  /* If the modulation wasn't already applied, make it happen now. */
766  SDL_SetSurfaceAlphaMod(src_rotated, alphaMod);
767  SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
768  }
769  retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect);
770  } else {
771  /* The NONE blend mode requires three steps to get the pixels onto the destination surface.
772  * First, the area where the rotated pixels will be blitted to get set to zero.
773  * This is accomplished by simply blitting a mask with the NONE blend mode.
774  * The colorkey set by the rotate function will discard the correct pixels.
775  */
776  SDL_Rect mask_rect = tmp_rect;
778  retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect);
779  if (!retval) {
780  /* The next step copies the alpha value. This is done with the BLEND blend mode and
781  * by modulating the source colors with 0. Since the destination is all zeros, this
782  * will effectively set the destination alpha to the source alpha.
783  */
784  SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
785  mask_rect = tmp_rect;
786  retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect);
787  if (!retval) {
788  /* The last step gets the color values in place. The ADD blend mode simply adds them to
789  * the destination (where the color values are all zero). However, because the ADD blend
790  * mode modulates the colors with the alpha channel, a surface without an alpha mask needs
791  * to be created. This makes all source pixels opaque and the colors get copied correctly.
792  */
793  SDL_Surface *src_rotated_rgb;
794  src_rotated_rgb = SDL_CreateRGBSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h,
795  src_rotated->format->BitsPerPixel, src_rotated->pitch,
796  src_rotated->format->Rmask, src_rotated->format->Gmask,
797  src_rotated->format->Bmask, 0);
798  if (src_rotated_rgb == NULL) {
799  retval = -1;
800  } else {
801  SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
802  retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect);
803  SDL_FreeSurface(src_rotated_rgb);
804  }
805  }
806  }
807  SDL_FreeSurface(mask_rotated);
808  }
809  if (src_rotated != NULL) {
810  SDL_FreeSurface(src_rotated);
811  }
812  }
813  }
814 
815  if (SDL_MUSTLOCK(src)) {
816  SDL_UnlockSurface(src);
817  }
818  if (mask != NULL) {
820  }
821  if (src_clone != NULL) {
822  SDL_FreeSurface(src_clone);
823  }
824  return retval;
825 }
826 
827 static int
829  Uint32 format, void * pixels, int pitch)
830 {
832  Uint32 src_format;
833  void *src_pixels;
834 
835  if (!surface) {
836  return -1;
837  }
838 
839  /* NOTE: The rect is already adjusted according to the viewport by
840  * SDL_RenderReadPixels.
841  */
842 
843  if (rect->x < 0 || rect->x+rect->w > surface->w ||
844  rect->y < 0 || rect->y+rect->h > surface->h) {
845  return SDL_SetError("Tried to read outside of surface bounds");
846  }
847 
848  src_format = surface->format->format;
849  src_pixels = (void*)((Uint8 *) surface->pixels +
850  rect->y * surface->pitch +
851  rect->x * surface->format->BytesPerPixel);
852 
853  return SDL_ConvertPixels(rect->w, rect->h,
854  src_format, src_pixels, surface->pitch,
855  format, pixels, pitch);
856 }
857 
858 static void
860 {
861  SDL_Window *window = renderer->window;
862 
863  if (window) {
864  SDL_UpdateWindowSurface(window);
865  }
866 }
867 
868 static void
870 {
871  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
872 
873  SDL_FreeSurface(surface);
874 }
875 
876 static void
878 {
879  SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
880 
881  SDL_free(data);
882  SDL_free(renderer);
883 }
884 
885 #endif /* !SDL_RENDER_DISABLED */
886 
887 /* vi: set ts=4 sw=4 expandtab: */
static int SW_SetTextureAlphaMod(SDL_Renderer *renderer, SDL_Texture *texture)
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:65
#define SDL_SetClipRect
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
int SDL_DrawLines(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color)
Definition: SDL_drawline.c:166
static int SW_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
#define SDL_UnlockSurface
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
static int SW_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
SDL_RendererInfo info
GLenum GLenum dst
#define SDL_PIXELLAYOUT(X)
Definition: SDL_pixels.h:126
#define SDL_MapRGBA
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
static int SW_UpdateViewport(SDL_Renderer *renderer)
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
Uint8 BytesPerPixel
Definition: SDL_pixels.h:320
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
GLfloat GLfloat GLfloat GLfloat h
#define SDL_FillRects
void * driverdata
EGLSurface surface
Definition: eglext.h:248
The structure that defines a point.
Definition: SDL_rect.h:48
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
static int SW_SetTextureColorMod(SDL_Renderer *renderer, SDL_Texture *texture)
static int SW_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
#define SDL_BlitSurface
Definition: SDL_surface.h:483
static int SW_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
SDL_Rect clip_rect
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp
GLenum src
#define SDL_IntersectRect
static int SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
static int SW_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
SDL_Window * window
SDL_RendererInfo info
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
#define SDL_CreateRGBSurfaceFrom
int(* RenderClear)(SDL_Renderer *renderer)
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfixed GLfixed GLint GLint GLfixed points
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:90
int(* SetTextureBlendMode)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:97
#define SDL_BlitScaled
Definition: SDL_surface.h:512
#define SDL_GetSurfaceBlendMode
SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface *surface)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:99
int x
Definition: SDL_rect.h:50
#define SDL_UpdateWindowSurface
int SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
SDL_bool retval
static int SW_SetTextureBlendMode(SDL_Renderer *renderer, SDL_Texture *texture)
int(* SetTextureColorMod)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:93
#define SDL_memcpy
GLenum GLenum GLuint texture
SDL_RenderDriver SW_RenderDriver
Definition: SDL_render_sw.c:78
SDL_Surface * surface
static void SW_RenderPresent(SDL_Renderer *renderer)
int y
Definition: SDL_rect.h:51
static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
void * pixels
Definition: SDL_surface.h:75
#define SDL_FreeSurface
static SDL_Renderer * renderer
#define SDL_SetSurfaceColorMod
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
struct _cl_event * event
Uint8 BitsPerPixel
Definition: SDL_pixels.h:319
SDL_BlendMode blendMode
static SDL_Surface * SW_ActivateRenderer(SDL_Renderer *renderer)
static int SW_RenderCopyEx(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)
GLenum GLint GLuint mask
static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GLubyte GLubyte GLubyte GLubyte w
static int SW_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
static void SW_DestroyRenderer(SDL_Renderer *renderer)
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define SDL_GetWindowSurface
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int SDL_BlendLines(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
#define SDL_PixelFormatEnumToMasks
int x
Definition: SDL_rect.h:66
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateViewport)(SDL_Renderer *renderer)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
static int SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
int w
Definition: SDL_rect.h:67
#define SDL_GetSurfaceAlphaMod
static int SW_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
SDL_Rect clip_rect
Definition: SDL_surface.h:85
#define SDL_SetSurfaceRLE
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
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Window state change event data (event.window.*)
Definition: SDL_events.h:195
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
static int SW_RenderClear(SDL_Renderer *renderer)
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_SetError
#define SDL_LockSurface
SDL_Surface * window
GLbitfield flags
int SDL_DrawPoints(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color)
Definition: SDL_drawpoint.c:65
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
#define SDL_calloc
#define SDL_CreateRGBSurface
#define SDL_GetSurfaceColorMod
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:61
SDL_Rect viewport
int h
Definition: SDL_rect.h:67
int(* SetTextureAlphaMod)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:95
#define SDL_SetSurfaceBlendMode
The type used to identify a window.
Definition: SDL_sysvideo.h:73
static void SW_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_FillRect
GLuint color
static void SW_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:89
GLfloat angle
Uint32 format
Definition: SDL_sysrender.h:60
static SDL_Renderer * SW_CreateRenderer(SDL_Window *window, Uint32 flags)
void * driverdata
Definition: SDL_sysrender.h:78
static int SW_UpdateClipRect(SDL_Renderer *renderer)
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:92
void(* RenderPresent)(SDL_Renderer *renderer)
EGLSurface EGLint * rects
Definition: eglext.h:282
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
SDL_ScaleMode scaleMode
Definition: SDL_sysrender.h:66
GLuint GLsizei GLsizei * length
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
int(* UpdateClipRect)(SDL_Renderer *renderer)
int SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, int *dstwidth, int *dstheight, double *cangle, double *sangle)
Definition: SDL_rotate.c:106
GLenum GLenum void * row
int y
Definition: SDL_rect.h:66
#define SDL_SetSurfaceAlphaMod
SDL_bool clipping_enabled
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
#define MIN(a, b)
Definition: SDL_rotate.h:26