SDL  2.0
SDL_render_sw.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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_VIDEO_RENDER_SW && !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 
39 typedef struct
40 {
45 
46 typedef struct
47 {
51 
52 
53 static SDL_Surface *
55 {
57 
58  if (!data->surface) {
59  data->surface = data->window;
60  }
61  if (!data->surface) {
63  if (surface) {
64  data->surface = data->window = surface;
65  }
66  }
67  return data->surface;
68 }
69 
70 static void
72 {
74 
76  data->surface = NULL;
77  data->window = NULL;
78  }
79 }
80 
81 static int
83 {
85 
86  if (data->surface) {
87  if (w) {
88  *w = data->surface->w;
89  }
90  if (h) {
91  *h = data->surface->h;
92  }
93  return 0;
94  }
95 
96  if (renderer->window) {
98  return 0;
99  }
100 
101  SDL_SetError("Software renderer doesn't have an output surface");
102  return -1;
103 }
104 
105 static int
107 {
108  int bpp;
109  Uint32 Rmask, Gmask, Bmask, Amask;
110 
112  (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
113  return SDL_SetError("Unknown texture format");
114  }
115 
116  texture->driverdata =
117  SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
118  Bmask, Amask);
119  SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
120  texture->b);
121  SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
122  SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
123 
124  /* Only RLE encode textures without an alpha channel since the RLE coder
125  * discards the color values of pixels with an alpha value of zero.
126  */
127  if (texture->access == SDL_TEXTUREACCESS_STATIC && !Amask) {
128  SDL_SetSurfaceRLE(texture->driverdata, 1);
129  }
130 
131  if (!texture->driverdata) {
132  return -1;
133  }
134  return 0;
135 }
136 
137 static int
139  const SDL_Rect * rect, const void *pixels, int pitch)
140 {
141  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
142  Uint8 *src, *dst;
143  int row;
144  size_t length;
145 
146  if(SDL_MUSTLOCK(surface))
148  src = (Uint8 *) pixels;
149  dst = (Uint8 *) surface->pixels +
150  rect->y * surface->pitch +
151  rect->x * surface->format->BytesPerPixel;
152  length = rect->w * surface->format->BytesPerPixel;
153  for (row = 0; row < rect->h; ++row) {
155  src += pitch;
156  dst += surface->pitch;
157  }
158  if(SDL_MUSTLOCK(surface))
160  return 0;
161 }
162 
163 static int
165  const SDL_Rect * rect, void **pixels, int *pitch)
166 {
167  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
168 
169  *pixels =
170  (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
171  rect->x * surface->format->BytesPerPixel);
172  *pitch = surface->pitch;
173  return 0;
174 }
175 
176 static void
178 {
179 }
180 
181 static void
183 {
184 }
185 
186 static int
188 {
190 
191  if (texture) {
192  data->surface = (SDL_Surface *) texture->driverdata;
193  } else {
194  data->surface = data->window;
195  }
196  return 0;
197 }
198 
199 static int
201 {
202  return 0; /* nothing to do in this backend. */
203 }
204 
205 static int
207 {
208  SDL_Point *verts = (SDL_Point *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Point), 0, &cmd->data.draw.first);
209  int i;
210 
211  if (!verts) {
212  return -1;
213  }
214 
215  cmd->data.draw.count = count;
216 
217  if (renderer->viewport.x || renderer->viewport.y) {
218  const int x = renderer->viewport.x;
219  const int y = renderer->viewport.y;
220  for (i = 0; i < count; i++, verts++, points++) {
221  verts->x = (int)(x + points->x);
222  verts->y = (int)(y + points->y);
223  }
224  } else {
225  for (i = 0; i < count; i++, verts++, points++) {
226  verts->x = (int)points->x;
227  verts->y = (int)points->y;
228  }
229  }
230 
231  return 0;
232 }
233 
234 static int
236 {
237  SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
238  int i;
239 
240  if (!verts) {
241  return -1;
242  }
243 
244  cmd->data.draw.count = count;
245 
246  if (renderer->viewport.x || renderer->viewport.y) {
247  const int x = renderer->viewport.x;
248  const int y = renderer->viewport.y;
249 
250  for (i = 0; i < count; i++, verts++, rects++) {
251  verts->x = (int)(x + rects->x);
252  verts->y = (int)(y + rects->y);
253  verts->w = SDL_max((int)rects->w, 1);
254  verts->h = SDL_max((int)rects->h, 1);
255  }
256  } else {
257  for (i = 0; i < count; i++, verts++, rects++) {
258  verts->x = (int)rects->x;
259  verts->y = (int)rects->y;
260  verts->w = SDL_max((int)rects->w, 1);
261  verts->h = SDL_max((int)rects->h, 1);
262  }
263  }
264 
265  return 0;
266 }
267 
268 static int
270  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
271 {
272  SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, 2 * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
273 
274  if (!verts) {
275  return -1;
276  }
277 
278  cmd->data.draw.count = 1;
279 
280  SDL_memcpy(verts, srcrect, sizeof (SDL_Rect));
281  verts++;
282 
283  if (renderer->viewport.x || renderer->viewport.y) {
284  verts->x = (int)(renderer->viewport.x + dstrect->x);
285  verts->y = (int)(renderer->viewport.y + dstrect->y);
286  } else {
287  verts->x = (int)dstrect->x;
288  verts->y = (int)dstrect->y;
289  }
290  verts->w = (int)dstrect->w;
291  verts->h = (int)dstrect->h;
292 
293  return 0;
294 }
295 
296 typedef struct CopyExData
297 {
300  double angle;
303 } CopyExData;
304 
305 static int
307  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
308  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
309 {
310  CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
311 
312  if (!verts) {
313  return -1;
314  }
315 
316  cmd->data.draw.count = 1;
317 
318  SDL_memcpy(&verts->srcrect, srcrect, sizeof (SDL_Rect));
319 
320  if (renderer->viewport.x || renderer->viewport.y) {
321  verts->dstrect.x = (int)(renderer->viewport.x + dstrect->x);
322  verts->dstrect.y = (int)(renderer->viewport.y + dstrect->y);
323  } else {
324  verts->dstrect.x = (int)dstrect->x;
325  verts->dstrect.y = (int)dstrect->y;
326  }
327  verts->dstrect.w = (int)dstrect->w;
328  verts->dstrect.h = (int)dstrect->h;
329  verts->angle = angle;
330  SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
331  verts->flip = flip;
332 
333  return 0;
334 }
335 
336 static int
338  const SDL_Rect * srcrect, const SDL_Rect * final_rect,
339  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
340 {
341  SDL_Surface *src = (SDL_Surface *) texture->driverdata;
342  SDL_Rect tmp_rect;
343  SDL_Surface *src_clone, *src_rotated, *src_scaled;
344  SDL_Surface *mask = NULL, *mask_rotated = NULL;
345  int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
346  double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
347  SDL_BlendMode blendmode;
348  Uint8 alphaMod, rMod, gMod, bMod;
349  int applyModulation = SDL_FALSE;
350  int blitRequired = SDL_FALSE;
351  int isOpaque = SDL_FALSE;
352 
353  if (!surface) {
354  return -1;
355  }
356 
357  tmp_rect.x = 0;
358  tmp_rect.y = 0;
359  tmp_rect.w = final_rect->w;
360  tmp_rect.h = final_rect->h;
361 
362  /* It is possible to encounter an RLE encoded surface here and locking it is
363  * necessary because this code is going to access the pixel buffer directly.
364  */
365  if (SDL_MUSTLOCK(src)) {
367  }
368 
369  /* Clone the source surface but use its pixel buffer directly.
370  * The original source surface must be treated as read-only.
371  */
372  src_clone = SDL_CreateRGBSurfaceFrom(src->pixels, src->w, src->h, src->format->BitsPerPixel, src->pitch,
373  src->format->Rmask, src->format->Gmask,
374  src->format->Bmask, src->format->Amask);
375  if (src_clone == NULL) {
376  if (SDL_MUSTLOCK(src)) {
378  }
379  return -1;
380  }
381 
382  SDL_GetSurfaceBlendMode(src, &blendmode);
383  SDL_GetSurfaceAlphaMod(src, &alphaMod);
384  SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod);
385 
386  /* SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. */
387  if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) {
388  blitRequired = SDL_TRUE;
389  }
390 
391  /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
392  if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) {
393  blitRequired = SDL_TRUE;
394  }
395 
396  /* srcrect is not selecting the whole src surface, so cropping is needed */
397  if (!(srcrect->w == src->w && srcrect->h == src->h && srcrect->x == 0 && srcrect->y == 0)) {
398  blitRequired = SDL_TRUE;
399  }
400 
401  /* The color and alpha modulation has to be applied before the rotation when using the NONE, MOD or MUL blend modes. */
402  if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD || blendmode == SDL_BLENDMODE_MUL) && (alphaMod & rMod & gMod & bMod) != 255) {
403  applyModulation = SDL_TRUE;
404  SDL_SetSurfaceAlphaMod(src_clone, alphaMod);
405  SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod);
406  }
407 
408  /* Opaque surfaces are much easier to handle with the NONE blend mode. */
409  if (blendmode == SDL_BLENDMODE_NONE && !src->format->Amask && alphaMod == 255) {
410  isOpaque = SDL_TRUE;
411  }
412 
413  /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used
414  * to clear the pixels in the destination surface. The other steps are explained below.
415  */
416  if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
417  mask = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
418  0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
419  if (mask == NULL) {
420  retval = -1;
421  } else {
423  }
424  }
425 
426  /* Create a new surface should there be a format mismatch or if scaling, cropping,
427  * or modulation is required. It's possible to use the source surface directly otherwise.
428  */
429  if (!retval && (blitRequired || applyModulation)) {
430  SDL_Rect scale_rect = tmp_rect;
431  src_scaled = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
432  0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
433  if (src_scaled == NULL) {
434  retval = -1;
435  } else {
437  retval = SDL_BlitScaled(src_clone, srcrect, src_scaled, &scale_rect);
438  SDL_FreeSurface(src_clone);
439  src_clone = src_scaled;
440  src_scaled = NULL;
441  }
442  }
443 
444  /* SDLgfx_rotateSurface is going to make decisions depending on the blend mode. */
445  SDL_SetSurfaceBlendMode(src_clone, blendmode);
446 
447  if (!retval) {
448  SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
449  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);
450  if (src_rotated == NULL) {
451  retval = -1;
452  }
453  if (!retval && mask != NULL) {
454  /* The mask needed for the NONE blend mode gets rotated with the same parameters. */
455  mask_rotated = SDLgfx_rotateSurface(mask, angle, dstwidth/2, dstheight/2, SDL_FALSE, 0, 0, dstwidth, dstheight, cangle, sangle);
456  if (mask_rotated == NULL) {
457  retval = -1;
458  }
459  }
460  if (!retval) {
461  /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
462  abscenterx = final_rect->x + (int)center->x;
463  abscentery = final_rect->y + (int)center->y;
464  /* Compensate the angle inversion to match the behaviour of the other backends */
465  sangle = -sangle;
466 
467  /* Top Left */
468  px = final_rect->x - abscenterx;
469  py = final_rect->y - abscentery;
470  p1x = px * cangle - py * sangle + abscenterx;
471  p1y = px * sangle + py * cangle + abscentery;
472 
473  /* Top Right */
474  px = final_rect->x + final_rect->w - abscenterx;
475  py = final_rect->y - abscentery;
476  p2x = px * cangle - py * sangle + abscenterx;
477  p2y = px * sangle + py * cangle + abscentery;
478 
479  /* Bottom Left */
480  px = final_rect->x - abscenterx;
481  py = final_rect->y + final_rect->h - abscentery;
482  p3x = px * cangle - py * sangle + abscenterx;
483  p3y = px * sangle + py * cangle + abscentery;
484 
485  /* Bottom Right */
486  px = final_rect->x + final_rect->w - abscenterx;
487  py = final_rect->y + final_rect->h - abscentery;
488  p4x = px * cangle - py * sangle + abscenterx;
489  p4y = px * sangle + py * cangle + abscentery;
490 
491  tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
492  tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
493  tmp_rect.w = dstwidth;
494  tmp_rect.h = dstheight;
495 
496  /* The NONE blend mode needs some special care with non-opaque surfaces.
497  * Other blend modes or opaque surfaces can be blitted directly.
498  */
499  if (blendmode != SDL_BLENDMODE_NONE || isOpaque) {
500  if (applyModulation == SDL_FALSE) {
501  /* If the modulation wasn't already applied, make it happen now. */
502  SDL_SetSurfaceAlphaMod(src_rotated, alphaMod);
503  SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
504  }
505  retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect);
506  } else {
507  /* The NONE blend mode requires three steps to get the pixels onto the destination surface.
508  * First, the area where the rotated pixels will be blitted to get set to zero.
509  * This is accomplished by simply blitting a mask with the NONE blend mode.
510  * The colorkey set by the rotate function will discard the correct pixels.
511  */
512  SDL_Rect mask_rect = tmp_rect;
514  retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect);
515  if (!retval) {
516  /* The next step copies the alpha value. This is done with the BLEND blend mode and
517  * by modulating the source colors with 0. Since the destination is all zeros, this
518  * will effectively set the destination alpha to the source alpha.
519  */
520  SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
521  mask_rect = tmp_rect;
522  retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect);
523  if (!retval) {
524  /* The last step gets the color values in place. The ADD blend mode simply adds them to
525  * the destination (where the color values are all zero). However, because the ADD blend
526  * mode modulates the colors with the alpha channel, a surface without an alpha mask needs
527  * to be created. This makes all source pixels opaque and the colors get copied correctly.
528  */
529  SDL_Surface *src_rotated_rgb;
530  src_rotated_rgb = SDL_CreateRGBSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h,
531  src_rotated->format->BitsPerPixel, src_rotated->pitch,
532  src_rotated->format->Rmask, src_rotated->format->Gmask,
533  src_rotated->format->Bmask, 0);
534  if (src_rotated_rgb == NULL) {
535  retval = -1;
536  } else {
537  SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
538  retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect);
539  SDL_FreeSurface(src_rotated_rgb);
540  }
541  }
542  }
543  SDL_FreeSurface(mask_rotated);
544  }
545  if (src_rotated != NULL) {
546  SDL_FreeSurface(src_rotated);
547  }
548  }
549  }
550 
551  if (SDL_MUSTLOCK(src)) {
553  }
554  if (mask != NULL) {
556  }
557  if (src_clone != NULL) {
558  SDL_FreeSurface(src_clone);
559  }
560  return retval;
561 }
562 
563 static void
565 {
566  const Uint8 r = cmd->data.draw.r;
567  const Uint8 g = cmd->data.draw.g;
568  const Uint8 b = cmd->data.draw.b;
569  const Uint8 a = cmd->data.draw.a;
570  const SDL_BlendMode blend = cmd->data.draw.blend;
571  SDL_Texture *texture = cmd->data.draw.texture;
572  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
573  const SDL_bool colormod = ((r & g & b) != 0xFF);
574  const SDL_bool alphamod = (a != 0xFF);
575  const SDL_bool blending = ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD) || (blend == SDL_BLENDMODE_MUL));
576 
577  if (colormod || alphamod || blending) {
579  }
580 
581  /* !!! FIXME: we can probably avoid some of these calls. */
585 }
586 
587 static void
589 {
590  if (drawstate->surface_cliprect_dirty) {
591  const SDL_Rect *viewport = drawstate->viewport;
592  const SDL_Rect *cliprect = drawstate->cliprect;
593  SDL_assert(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */
594 
595  if (cliprect != NULL) {
596  SDL_Rect clip_rect;
597  clip_rect.x = cliprect->x + viewport->x;
598  clip_rect.y = cliprect->y + viewport->y;
599  clip_rect.w = cliprect->w;
600  clip_rect.h = cliprect->h;
601  SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
602  SDL_SetClipRect(surface, &clip_rect);
603  } else {
604  SDL_SetClipRect(surface, drawstate->viewport);
605  }
606  drawstate->surface_cliprect_dirty = SDL_FALSE;
607  }
608 }
609 
610 static int
611 SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
612 {
614  SW_DrawStateCache drawstate;
615 
616  if (!surface) {
617  return -1;
618  }
619 
620  drawstate.viewport = NULL;
621  drawstate.cliprect = NULL;
622  drawstate.surface_cliprect_dirty = SDL_TRUE;
623 
624  while (cmd) {
625  switch (cmd->command) {
627  break; /* Not used in this backend. */
628  }
629 
631  drawstate.viewport = &cmd->data.viewport.rect;
632  drawstate.surface_cliprect_dirty = SDL_TRUE;
633  break;
634  }
635 
637  drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
638  drawstate.surface_cliprect_dirty = SDL_TRUE;
639  break;
640  }
641 
642  case SDL_RENDERCMD_CLEAR: {
643  const Uint8 r = cmd->data.color.r;
644  const Uint8 g = cmd->data.color.g;
645  const Uint8 b = cmd->data.color.b;
646  const Uint8 a = cmd->data.color.a;
647  /* By definition the clear ignores the clip rect */
649  SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
650  drawstate.surface_cliprect_dirty = SDL_TRUE;
651  break;
652  }
653 
655  const Uint8 r = cmd->data.draw.r;
656  const Uint8 g = cmd->data.draw.g;
657  const Uint8 b = cmd->data.draw.b;
658  const Uint8 a = cmd->data.draw.a;
659  const int count = (int) cmd->data.draw.count;
660  const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
661  const SDL_BlendMode blend = cmd->data.draw.blend;
662  SetDrawState(surface, &drawstate);
663  if (blend == SDL_BLENDMODE_NONE) {
664  SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
665  } else {
666  SDL_BlendPoints(surface, verts, count, blend, r, g, b, a);
667  }
668  break;
669  }
670 
672  const Uint8 r = cmd->data.draw.r;
673  const Uint8 g = cmd->data.draw.g;
674  const Uint8 b = cmd->data.draw.b;
675  const Uint8 a = cmd->data.draw.a;
676  const int count = (int) cmd->data.draw.count;
677  const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
678  const SDL_BlendMode blend = cmd->data.draw.blend;
679  SetDrawState(surface, &drawstate);
680  if (blend == SDL_BLENDMODE_NONE) {
681  SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
682  } else {
683  SDL_BlendLines(surface, verts, count, blend, r, g, b, a);
684  }
685  break;
686  }
687 
689  const Uint8 r = cmd->data.draw.r;
690  const Uint8 g = cmd->data.draw.g;
691  const Uint8 b = cmd->data.draw.b;
692  const Uint8 a = cmd->data.draw.a;
693  const int count = (int) cmd->data.draw.count;
694  const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
695  const SDL_BlendMode blend = cmd->data.draw.blend;
696  SetDrawState(surface, &drawstate);
697  if (blend == SDL_BLENDMODE_NONE) {
698  SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
699  } else {
700  SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a);
701  }
702  break;
703  }
704 
705  case SDL_RENDERCMD_COPY: {
706  SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
707  const SDL_Rect *srcrect = verts;
708  SDL_Rect *dstrect = verts + 1;
709  SDL_Texture *texture = cmd->data.draw.texture;
710  SDL_Surface *src = (SDL_Surface *) texture->driverdata;
711 
712  SetDrawState(surface, &drawstate);
713 
714  PrepTextureForCopy(cmd);
715 
716  if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
717  SDL_BlitSurface(src, srcrect, surface, dstrect);
718  } else {
719  /* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
720  * to avoid potentially frequent RLE encoding/decoding.
721  */
723  SDL_BlitScaled(src, srcrect, surface, dstrect);
724  }
725  break;
726  }
727 
728  case SDL_RENDERCMD_COPY_EX: {
729  const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
730  SetDrawState(surface, &drawstate);
731  PrepTextureForCopy(cmd);
732  SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
733  &copydata->dstrect, copydata->angle, &copydata->center, copydata->flip);
734  break;
735  }
736 
737  case SDL_RENDERCMD_NO_OP:
738  break;
739  }
740 
741  cmd = cmd->next;
742  }
743 
744  return 0;
745 }
746 
747 static int
749  Uint32 format, void * pixels, int pitch)
750 {
752  Uint32 src_format;
753  void *src_pixels;
754 
755  if (!surface) {
756  return -1;
757  }
758 
759  /* NOTE: The rect is already adjusted according to the viewport by
760  * SDL_RenderReadPixels.
761  */
762 
763  if (rect->x < 0 || rect->x+rect->w > surface->w ||
764  rect->y < 0 || rect->y+rect->h > surface->h) {
765  return SDL_SetError("Tried to read outside of surface bounds");
766  }
767 
768  src_format = surface->format->format;
769  src_pixels = (void*)((Uint8 *) surface->pixels +
770  rect->y * surface->pitch +
771  rect->x * surface->format->BytesPerPixel);
772 
773  return SDL_ConvertPixels(rect->w, rect->h,
774  src_format, src_pixels, surface->pitch,
775  format, pixels, pitch);
776 }
777 
778 static void
780 {
782 
783  if (window) {
785  }
786 }
787 
788 static void
790 {
791  SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
792 
794 }
795 
796 static void
798 {
800 
801  SDL_free(data);
803 }
804 
805 SDL_Renderer *
807 {
810 
811  if (!surface) {
812  SDL_SetError("Can't create renderer for NULL surface");
813  return NULL;
814  }
815 
816  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
817  if (!renderer) {
818  SDL_OutOfMemory();
819  return NULL;
820  }
821 
822  data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
823  if (!data) {
825  SDL_OutOfMemory();
826  return NULL;
827  }
828  data->surface = surface;
829  data->window = surface;
830 
840  renderer->QueueSetDrawColor = SW_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
842  renderer->QueueDrawLines = SW_QueueDrawPoints; /* lines and points queue vertices the same way. */
853 
855 
856  return renderer;
857 }
858 
859 static SDL_Renderer *
861 {
863 
865  if (!surface) {
866  return NULL;
867  }
869 }
870 
873  {
874  "software",
876  8,
877  {
886  },
887  0,
888  0}
889 };
890 
891 #endif /* SDL_VIDEO_RENDER_SW && !SDL_RENDER_DISABLED */
892 
893 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
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_MUL
Definition: SDL_blendmode.h:53
@ 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:88
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
@ SDL_PACKEDLAYOUT_8888
Definition: SDL_pixels.h:112
#define SDL_PIXELLAYOUT(X)
Definition: SDL_pixels.h:126
@ SDL_PIXELFORMAT_RGB555
Definition: SDL_pixels.h:202
@ SDL_PIXELFORMAT_RGBA8888
Definition: SDL_pixels.h:260
@ SDL_PIXELFORMAT_BGR888
Definition: SDL_pixels.h:253
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:246
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:263
@ SDL_PIXELFORMAT_BGRA8888
Definition: SDL_pixels.h:266
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:257
@ SDL_PIXELFORMAT_RGB565
Definition: SDL_pixels.h:231
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:262
@ 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:122
@ SDL_FLIP_VERTICAL
Definition: SDL_render.h:125
@ SDL_FLIP_HORIZONTAL
Definition: SDL_render.h:124
@ SDL_TEXTUREACCESS_STATIC
Definition: SDL_render.h:103
SDL_ScaleMode
The scaling mode for a texture.
Definition: SDL_render.h:92
@ SDL_ScaleModeNearest
Definition: SDL_render.h:93
static SDL_Renderer * SW_CreateRenderer(SDL_Window *window, Uint32 flags)
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)
SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface *surface)
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:71
static SDL_Surface * SW_ActivateRenderer(SDL_Renderer *renderer)
Definition: SDL_render_sw.c:54
static void SW_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
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:82
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)
void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, int *dstwidth, int *dstheight, double *cangle, double *sangle)
Definition: SDL_rotate.c:108
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:417
#define MIN(a, b)
Definition: SDL_rotate.h:26
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
uint32_t Uint32
Definition: SDL_stdinc.h:209
#define SDL_max(x, y)
Definition: SDL_stdinc.h:413
#define SDL_BlitScaled
Definition: SDL_surface.h:522
#define SDL_BlitSurface
Definition: SDL_surface.h:493
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:62
@ SDL_RENDERCMD_SETCLIPRECT
Definition: SDL_sysrender.h:70
@ SDL_RENDERCMD_DRAW_LINES
Definition: SDL_sysrender.h:74
@ SDL_RENDERCMD_SETVIEWPORT
Definition: SDL_sysrender.h:69
@ SDL_RENDERCMD_DRAW_POINTS
Definition: SDL_sysrender.h:73
@ SDL_RENDERCMD_NO_OP
Definition: SDL_sysrender.h:68
@ SDL_RENDERCMD_FILL_RECTS
Definition: SDL_sysrender.h:75
@ SDL_RENDERCMD_COPY
Definition: SDL_sysrender.h:76
@ SDL_RENDERCMD_CLEAR
Definition: SDL_sysrender.h:72
@ SDL_RENDERCMD_SETDRAWCOLOR
Definition: SDL_sysrender.h:71
@ SDL_RENDERCMD_COPY_EX
Definition: SDL_sysrender.h:77
@ 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:163
EGLSurface surface
Definition: eglext.h:248
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLSurface EGLint * rects
Definition: eglext.h:282
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 skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
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
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
struct SDL_RenderCommand::@38::@42 color
struct SDL_RenderCommand * next
struct SDL_RenderCommand::@38::@39 viewport
struct SDL_RenderCommand::@38::@41 draw
SDL_RenderCommandType command
Definition: SDL_sysrender.h:82
union SDL_RenderCommand::@38 data
struct SDL_RenderCommand::@38::@40 cliprect
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(* SetTextureScaleMode)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
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:202
The type used to identify a window.
Definition: SDL_sysvideo.h:75
const SDL_Rect * viewport
Definition: SDL_render_sw.c:41
const SDL_Rect * cliprect
Definition: SDL_render_sw.c:42
SDL_bool surface_cliprect_dirty
Definition: SDL_render_sw.c:43
SDL_Surface * surface
Definition: SDL_render_sw.c:48
SDL_Surface * window
Definition: SDL_render_sw.c:49
static SDL_Renderer * renderer
SDL_bool retval
SDL_Rect rect
Definition: testrelative.c:27
static SDL_Rect viewport
Definition: testviewport.c:28
typedef int(__stdcall *FARPROC)()