SDL  2.0
SDL_surface.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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 #include "SDL_video.h"
24 #include "SDL_sysvideo.h"
25 #include "SDL_blit.h"
26 #include "SDL_RLEaccel_c.h"
27 #include "SDL_pixels_c.h"
28 
29 /* Check to make sure we can safely check multiplication of surface w and pitch and it won't overflow size_t */
30 SDL_COMPILE_TIME_ASSERT(surface_size_assumptions,
31  sizeof(int) == sizeof(Sint32) && sizeof(size_t) >= sizeof(Sint32));
32 
33 /* Public routines */
34 /*
35  * Create an empty RGB surface of the appropriate depth
36  */
39  int width, int height, int depth,
40  Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
41 {
42  SDL_Surface *surface;
43  Uint32 format;
44 
45  /* The flags are no longer used, make the compiler happy */
46  (void)flags;
47 
48  /* Get the pixel format */
49  format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask);
50  if (format == SDL_PIXELFORMAT_UNKNOWN) {
51  SDL_SetError("Unknown pixel format");
52  return NULL;
53  }
54 
55  /* Allocate the surface */
56  surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface));
57  if (surface == NULL) {
59  return NULL;
60  }
61 
62  surface->format = SDL_AllocFormat(format);
63  if (!surface->format) {
64  SDL_FreeSurface(surface);
65  return NULL;
66  }
67  surface->w = width;
68  surface->h = height;
69  surface->pitch = SDL_CalculatePitch(surface);
70  SDL_SetClipRect(surface, NULL);
71 
72  if (SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
73  SDL_Palette *palette =
74  SDL_AllocPalette((1 << surface->format->BitsPerPixel));
75  if (!palette) {
76  SDL_FreeSurface(surface);
77  return NULL;
78  }
79  if (palette->ncolors == 2) {
80  /* Create a black and white bitmap palette */
81  palette->colors[0].r = 0xFF;
82  palette->colors[0].g = 0xFF;
83  palette->colors[0].b = 0xFF;
84  palette->colors[1].r = 0x00;
85  palette->colors[1].g = 0x00;
86  palette->colors[1].b = 0x00;
87  }
88  SDL_SetSurfacePalette(surface, palette);
89  SDL_FreePalette(palette);
90  }
91 
92  /* Get the pixels */
93  if (surface->w && surface->h) {
94  /* Assumptions checked in surface_size_assumptions assert above */
95  Sint64 size = ((Sint64)surface->h * surface->pitch);
97  /* Overflow... */
98  SDL_FreeSurface(surface);
100  return NULL;
101  }
102 
103  surface->pixels = SDL_malloc((size_t)size);
104  if (!surface->pixels) {
105  SDL_FreeSurface(surface);
106  SDL_OutOfMemory();
107  return NULL;
108  }
109  /* This is important for bitmaps */
110  SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
111  }
112 
113  /* Allocate an empty mapping */
114  surface->map = SDL_AllocBlitMap();
115  if (!surface->map) {
116  SDL_FreeSurface(surface);
117  return NULL;
118  }
119 
120  /* By default surface with an alpha mask are set up for blending */
121  if (Amask) {
123  }
124 
125  /* The surface is ready to go */
126  surface->refcount = 1;
127  return surface;
128 }
129 
130 /*
131  * Create an RGB surface from an existing memory buffer
132  */
133 SDL_Surface *
135  int width, int height, int depth, int pitch,
136  Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
137  Uint32 Amask)
138 {
139  SDL_Surface *surface;
140 
141  surface =
142  SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask);
143  if (surface != NULL) {
144  surface->flags |= SDL_PREALLOC;
145  surface->pixels = pixels;
146  surface->w = width;
147  surface->h = height;
148  surface->pitch = pitch;
149  SDL_SetClipRect(surface, NULL);
150  }
151  return surface;
152 }
153 
154 int
156 {
157  if (!surface) {
158  return SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface");
159  }
160  if (SDL_SetPixelFormatPalette(surface->format, palette) < 0) {
161  return -1;
162  }
163  SDL_InvalidateMap(surface->map);
164 
165  return 0;
166 }
167 
168 int
169 SDL_SetSurfaceRLE(SDL_Surface * surface, int flag)
170 {
171  int flags;
172 
173  if (!surface) {
174  return -1;
175  }
176 
177  flags = surface->map->info.flags;
178  if (flag) {
179  surface->map->info.flags |= SDL_COPY_RLE_DESIRED;
180  } else {
181  surface->map->info.flags &= ~SDL_COPY_RLE_DESIRED;
182  }
183  if (surface->map->info.flags != flags) {
184  SDL_InvalidateMap(surface->map);
185  }
186  return 0;
187 }
188 
189 int
190 SDL_SetColorKey(SDL_Surface * surface, int flag, Uint32 key)
191 {
192  int flags;
193 
194  if (!surface) {
195  return SDL_InvalidParamError("surface");
196  }
197 
198  if (surface->format->palette && key >= ((Uint32) surface->format->palette->ncolors)) {
199  return SDL_InvalidParamError("key");
200  }
201 
202  if (flag & SDL_RLEACCEL) {
203  SDL_SetSurfaceRLE(surface, 1);
204  }
205 
206  flags = surface->map->info.flags;
207  if (flag) {
208  surface->map->info.flags |= SDL_COPY_COLORKEY;
209  surface->map->info.colorkey = key;
210  if (surface->format->palette) {
211  surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
212  ++surface->format->palette->version;
213  if (!surface->format->palette->version) {
214  surface->format->palette->version = 1;
215  }
216  }
217  } else {
218  if (surface->format->palette) {
219  surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_OPAQUE;
220  ++surface->format->palette->version;
221  if (!surface->format->palette->version) {
222  surface->format->palette->version = 1;
223  }
224  }
225  surface->map->info.flags &= ~SDL_COPY_COLORKEY;
226  }
227  if (surface->map->info.flags != flags) {
228  SDL_InvalidateMap(surface->map);
229  }
230 
231  return 0;
232 }
233 
234 int
236 {
237  if (!surface) {
238  return -1;
239  }
240 
241  if (!(surface->map->info.flags & SDL_COPY_COLORKEY)) {
242  return -1;
243  }
244 
245  if (key) {
246  *key = surface->map->info.colorkey;
247  }
248  return 0;
249 }
250 
251 /* This is a fairly slow function to switch from colorkey to alpha */
252 static void
254 {
255  int x, y;
256 
257  if (!surface) {
258  return;
259  }
260 
261  if (!(surface->map->info.flags & SDL_COPY_COLORKEY) ||
262  !surface->format->Amask) {
263  return;
264  }
265 
266  SDL_LockSurface(surface);
267 
268  switch (surface->format->BytesPerPixel) {
269  case 2:
270  {
271  Uint16 *row, *spot;
272  Uint16 ckey = (Uint16) surface->map->info.colorkey;
273  Uint16 mask = (Uint16) (~surface->format->Amask);
274 
275  /* Ignore alpha in colorkey comparison */
276  ckey &= mask;
277  row = (Uint16 *) surface->pixels;
278  for (y = surface->h; y--;) {
279  spot = row;
280  for (x = surface->w; x--;) {
281  if ((*spot & mask) == ckey) {
282  *spot &= mask;
283  }
284  ++spot;
285  }
286  row += surface->pitch / 2;
287  }
288  }
289  break;
290  case 3:
291  /* FIXME */
292  break;
293  case 4:
294  {
295  Uint32 *row, *spot;
296  Uint32 ckey = surface->map->info.colorkey;
297  Uint32 mask = ~surface->format->Amask;
298 
299  /* Ignore alpha in colorkey comparison */
300  ckey &= mask;
301  row = (Uint32 *) surface->pixels;
302  for (y = surface->h; y--;) {
303  spot = row;
304  for (x = surface->w; x--;) {
305  if ((*spot & mask) == ckey) {
306  *spot &= mask;
307  }
308  ++spot;
309  }
310  row += surface->pitch / 4;
311  }
312  }
313  break;
314  }
315 
316  SDL_UnlockSurface(surface);
317 
318  SDL_SetColorKey(surface, 0, 0);
320 }
321 
322 int
324 {
325  int flags;
326 
327  if (!surface) {
328  return -1;
329  }
330 
331  surface->map->info.r = r;
332  surface->map->info.g = g;
333  surface->map->info.b = b;
334 
335  flags = surface->map->info.flags;
336  if (r != 0xFF || g != 0xFF || b != 0xFF) {
337  surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
338  } else {
339  surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
340  }
341  if (surface->map->info.flags != flags) {
342  SDL_InvalidateMap(surface->map);
343  }
344  return 0;
345 }
346 
347 
348 int
350 {
351  if (!surface) {
352  return -1;
353  }
354 
355  if (r) {
356  *r = surface->map->info.r;
357  }
358  if (g) {
359  *g = surface->map->info.g;
360  }
361  if (b) {
362  *b = surface->map->info.b;
363  }
364  return 0;
365 }
366 
367 int
369 {
370  int flags;
371 
372  if (!surface) {
373  return -1;
374  }
375 
376  surface->map->info.a = alpha;
377 
378  flags = surface->map->info.flags;
379  if (alpha != 0xFF) {
380  surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA;
381  } else {
382  surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA;
383  }
384  if (surface->map->info.flags != flags) {
385  SDL_InvalidateMap(surface->map);
386  }
387  return 0;
388 }
389 
390 int
392 {
393  if (!surface) {
394  return -1;
395  }
396 
397  if (alpha) {
398  *alpha = surface->map->info.a;
399  }
400  return 0;
401 }
402 
403 int
405 {
406  int flags, status;
407 
408  if (!surface) {
409  return -1;
410  }
411 
412  status = 0;
413  flags = surface->map->info.flags;
414  surface->map->info.flags &=
416  switch (blendMode) {
417  case SDL_BLENDMODE_NONE:
418  break;
419  case SDL_BLENDMODE_BLEND:
420  surface->map->info.flags |= SDL_COPY_BLEND;
421  break;
422  case SDL_BLENDMODE_ADD:
423  surface->map->info.flags |= SDL_COPY_ADD;
424  break;
425  case SDL_BLENDMODE_MOD:
426  surface->map->info.flags |= SDL_COPY_MOD;
427  break;
428  default:
429  status = SDL_Unsupported();
430  break;
431  }
432 
433  if (surface->map->info.flags != flags) {
434  SDL_InvalidateMap(surface->map);
435  }
436 
437  return status;
438 }
439 
440 int
442 {
443  if (!surface) {
444  return -1;
445  }
446 
447  if (!blendMode) {
448  return 0;
449  }
450 
451  switch (surface->map->
452  info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) {
453  case SDL_COPY_BLEND:
454  *blendMode = SDL_BLENDMODE_BLEND;
455  break;
456  case SDL_COPY_ADD:
457  *blendMode = SDL_BLENDMODE_ADD;
458  break;
459  case SDL_COPY_MOD:
460  *blendMode = SDL_BLENDMODE_MOD;
461  break;
462  default:
463  *blendMode = SDL_BLENDMODE_NONE;
464  break;
465  }
466  return 0;
467 }
468 
469 SDL_bool
471 {
472  SDL_Rect full_rect;
473 
474  /* Don't do anything if there's no surface to act on */
475  if (!surface) {
476  return SDL_FALSE;
477  }
478 
479  /* Set up the full surface rectangle */
480  full_rect.x = 0;
481  full_rect.y = 0;
482  full_rect.w = surface->w;
483  full_rect.h = surface->h;
484 
485  /* Set the clipping rectangle */
486  if (!rect) {
487  surface->clip_rect = full_rect;
488  return SDL_TRUE;
489  }
490  return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
491 }
492 
493 void
495 {
496  if (surface && rect) {
497  *rect = surface->clip_rect;
498  }
499 }
500 
501 /*
502  * Set up a blit between two surfaces -- split into three parts:
503  * The upper part, SDL_UpperBlit(), performs clipping and rectangle
504  * verification. The lower part is a pointer to a low level
505  * accelerated blitting function.
506  *
507  * These parts are separated out and each used internally by this
508  * library in the optimimum places. They are exported so that if
509  * you know exactly what you are doing, you can optimize your code
510  * by calling the one(s) you need.
511  */
512 int
514  SDL_Surface * dst, SDL_Rect * dstrect)
515 {
516  /* Check to make sure the blit mapping is valid */
517  if ((src->map->dst != dst) ||
518  (dst->format->palette &&
519  src->map->dst_palette_version != dst->format->palette->version) ||
520  (src->format->palette &&
521  src->map->src_palette_version != src->format->palette->version)) {
522  if (SDL_MapSurface(src, dst) < 0) {
523  return (-1);
524  }
525  /* just here for debugging */
526 /* printf */
527 /* ("src = 0x%08X src->flags = %08X src->map->info.flags = %08x\ndst = 0x%08X dst->flags = %08X dst->map->info.flags = %08X\nsrc->map->blit = 0x%08x\n", */
528 /* src, dst->flags, src->map->info.flags, dst, dst->flags, */
529 /* dst->map->info.flags, src->map->blit); */
530  }
531  return (src->map->blit(src, srcrect, dst, dstrect));
532 }
533 
534 
535 int
537  SDL_Surface * dst, SDL_Rect * dstrect)
538 {
539  SDL_Rect fulldst;
540  int srcx, srcy, w, h;
541 
542  /* Make sure the surfaces aren't locked */
543  if (!src || !dst) {
544  return SDL_SetError("SDL_UpperBlit: passed a NULL surface");
545  }
546  if (src->locked || dst->locked) {
547  return SDL_SetError("Surfaces must not be locked during blit");
548  }
549 
550  /* If the destination rectangle is NULL, use the entire dest surface */
551  if (dstrect == NULL) {
552  fulldst.x = fulldst.y = 0;
553  fulldst.w = dst->w;
554  fulldst.h = dst->h;
555  dstrect = &fulldst;
556  }
557 
558  /* clip the source rectangle to the source surface */
559  if (srcrect) {
560  int maxw, maxh;
561 
562  srcx = srcrect->x;
563  w = srcrect->w;
564  if (srcx < 0) {
565  w += srcx;
566  dstrect->x -= srcx;
567  srcx = 0;
568  }
569  maxw = src->w - srcx;
570  if (maxw < w)
571  w = maxw;
572 
573  srcy = srcrect->y;
574  h = srcrect->h;
575  if (srcy < 0) {
576  h += srcy;
577  dstrect->y -= srcy;
578  srcy = 0;
579  }
580  maxh = src->h - srcy;
581  if (maxh < h)
582  h = maxh;
583 
584  } else {
585  srcx = srcy = 0;
586  w = src->w;
587  h = src->h;
588  }
589 
590  /* clip the destination rectangle against the clip rectangle */
591  {
592  SDL_Rect *clip = &dst->clip_rect;
593  int dx, dy;
594 
595  dx = clip->x - dstrect->x;
596  if (dx > 0) {
597  w -= dx;
598  dstrect->x += dx;
599  srcx += dx;
600  }
601  dx = dstrect->x + w - clip->x - clip->w;
602  if (dx > 0)
603  w -= dx;
604 
605  dy = clip->y - dstrect->y;
606  if (dy > 0) {
607  h -= dy;
608  dstrect->y += dy;
609  srcy += dy;
610  }
611  dy = dstrect->y + h - clip->y - clip->h;
612  if (dy > 0)
613  h -= dy;
614  }
615 
616  /* Switch back to a fast blit if we were previously stretching */
617  if (src->map->info.flags & SDL_COPY_NEAREST) {
618  src->map->info.flags &= ~SDL_COPY_NEAREST;
619  SDL_InvalidateMap(src->map);
620  }
621 
622  if (w > 0 && h > 0) {
623  SDL_Rect sr;
624  sr.x = srcx;
625  sr.y = srcy;
626  sr.w = dstrect->w = w;
627  sr.h = dstrect->h = h;
628  return SDL_LowerBlit(src, &sr, dst, dstrect);
629  }
630  dstrect->w = dstrect->h = 0;
631  return 0;
632 }
633 
634 int
636  SDL_Surface * dst, SDL_Rect * dstrect)
637 {
638  double src_x0, src_y0, src_x1, src_y1;
639  double dst_x0, dst_y0, dst_x1, dst_y1;
640  SDL_Rect final_src, final_dst;
641  double scaling_w, scaling_h;
642  int src_w, src_h;
643  int dst_w, dst_h;
644 
645  /* Make sure the surfaces aren't locked */
646  if (!src || !dst) {
647  return SDL_SetError("SDL_UpperBlitScaled: passed a NULL surface");
648  }
649  if (src->locked || dst->locked) {
650  return SDL_SetError("Surfaces must not be locked during blit");
651  }
652 
653  if (NULL == srcrect) {
654  src_w = src->w;
655  src_h = src->h;
656  } else {
657  src_w = srcrect->w;
658  src_h = srcrect->h;
659  }
660 
661  if (NULL == dstrect) {
662  dst_w = dst->w;
663  dst_h = dst->h;
664  } else {
665  dst_w = dstrect->w;
666  dst_h = dstrect->h;
667  }
668 
669  if (dst_w == src_w && dst_h == src_h) {
670  /* No scaling, defer to regular blit */
671  return SDL_BlitSurface(src, srcrect, dst, dstrect);
672  }
673 
674  scaling_w = (double)dst_w / src_w;
675  scaling_h = (double)dst_h / src_h;
676 
677  if (NULL == dstrect) {
678  dst_x0 = 0;
679  dst_y0 = 0;
680  dst_x1 = dst_w - 1;
681  dst_y1 = dst_h - 1;
682  } else {
683  dst_x0 = dstrect->x;
684  dst_y0 = dstrect->y;
685  dst_x1 = dst_x0 + dst_w - 1;
686  dst_y1 = dst_y0 + dst_h - 1;
687  }
688 
689  if (NULL == srcrect) {
690  src_x0 = 0;
691  src_y0 = 0;
692  src_x1 = src_w - 1;
693  src_y1 = src_h - 1;
694  } else {
695  src_x0 = srcrect->x;
696  src_y0 = srcrect->y;
697  src_x1 = src_x0 + src_w - 1;
698  src_y1 = src_y0 + src_h - 1;
699 
700  /* Clip source rectangle to the source surface */
701 
702  if (src_x0 < 0) {
703  dst_x0 -= src_x0 * scaling_w;
704  src_x0 = 0;
705  }
706 
707  if (src_x1 >= src->w) {
708  dst_x1 -= (src_x1 - src->w + 1) * scaling_w;
709  src_x1 = src->w - 1;
710  }
711 
712  if (src_y0 < 0) {
713  dst_y0 -= src_y0 * scaling_h;
714  src_y0 = 0;
715  }
716 
717  if (src_y1 >= src->h) {
718  dst_y1 -= (src_y1 - src->h + 1) * scaling_h;
719  src_y1 = src->h - 1;
720  }
721  }
722 
723  /* Clip destination rectangle to the clip rectangle */
724 
725  /* Translate to clip space for easier calculations */
726  dst_x0 -= dst->clip_rect.x;
727  dst_x1 -= dst->clip_rect.x;
728  dst_y0 -= dst->clip_rect.y;
729  dst_y1 -= dst->clip_rect.y;
730 
731  if (dst_x0 < 0) {
732  src_x0 -= dst_x0 / scaling_w;
733  dst_x0 = 0;
734  }
735 
736  if (dst_x1 >= dst->clip_rect.w) {
737  src_x1 -= (dst_x1 - dst->clip_rect.w + 1) / scaling_w;
738  dst_x1 = dst->clip_rect.w - 1;
739  }
740 
741  if (dst_y0 < 0) {
742  src_y0 -= dst_y0 / scaling_h;
743  dst_y0 = 0;
744  }
745 
746  if (dst_y1 >= dst->clip_rect.h) {
747  src_y1 -= (dst_y1 - dst->clip_rect.h + 1) / scaling_h;
748  dst_y1 = dst->clip_rect.h - 1;
749  }
750 
751  /* Translate back to surface coordinates */
752  dst_x0 += dst->clip_rect.x;
753  dst_x1 += dst->clip_rect.x;
754  dst_y0 += dst->clip_rect.y;
755  dst_y1 += dst->clip_rect.y;
756 
757  final_src.x = (int)SDL_floor(src_x0 + 0.5);
758  final_src.y = (int)SDL_floor(src_y0 + 0.5);
759  final_src.w = (int)SDL_floor(src_x1 - src_x0 + 1.5);
760  final_src.h = (int)SDL_floor(src_y1 - src_y0 + 1.5);
761 
762  final_dst.x = (int)SDL_floor(dst_x0 + 0.5);
763  final_dst.y = (int)SDL_floor(dst_y0 + 0.5);
764  final_dst.w = (int)SDL_floor(dst_x1 - dst_x0 + 1.5);
765  final_dst.h = (int)SDL_floor(dst_y1 - dst_y0 + 1.5);
766 
767  if (final_dst.w < 0)
768  final_dst.w = 0;
769  if (final_dst.h < 0)
770  final_dst.h = 0;
771 
772  if (dstrect)
773  *dstrect = final_dst;
774 
775  if (final_dst.w == 0 || final_dst.h == 0 ||
776  final_src.w <= 0 || final_src.h <= 0) {
777  /* No-op. */
778  return 0;
779  }
780 
781  return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst);
782 }
783 
784 /**
785  * This is a semi-private blit function and it performs low-level surface
786  * scaled blitting only.
787  */
788 int
790  SDL_Surface * dst, SDL_Rect * dstrect)
791 {
792  static const Uint32 complex_copy_flags = (
796  );
797 
798  if (!(src->map->info.flags & SDL_COPY_NEAREST)) {
799  src->map->info.flags |= SDL_COPY_NEAREST;
800  SDL_InvalidateMap(src->map);
801  }
802 
803  if ( !(src->map->info.flags & complex_copy_flags) &&
804  src->format->format == dst->format->format &&
806  return SDL_SoftStretch( src, srcrect, dst, dstrect );
807  } else {
808  return SDL_LowerBlit( src, srcrect, dst, dstrect );
809  }
810 }
811 
812 /*
813  * Lock a surface to directly access the pixels
814  */
815 int
817 {
818  if (!surface->locked) {
819  /* Perform the lock */
820  if (surface->flags & SDL_RLEACCEL) {
821  SDL_UnRLESurface(surface, 1);
822  surface->flags |= SDL_RLEACCEL; /* save accel'd state */
823  }
824  }
825 
826  /* Increment the surface lock count, for recursive locks */
827  ++surface->locked;
828 
829  /* Ready to go.. */
830  return (0);
831 }
832 
833 /*
834  * Unlock a previously locked surface
835  */
836 void
838 {
839  /* Only perform an unlock if we are locked */
840  if (!surface->locked || (--surface->locked > 0)) {
841  return;
842  }
843 
844  /* Update RLE encoded surface with new data */
845  if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
846  surface->flags &= ~SDL_RLEACCEL; /* stop lying */
847  SDL_RLESurface(surface);
848  }
849 }
850 
851 /*
852  * Convert a surface into the specified pixel format.
853  */
854 SDL_Surface *
856  Uint32 flags)
857 {
858  SDL_Surface *convert;
859  Uint32 copy_flags;
860  SDL_Color copy_color;
861  SDL_Rect bounds;
862 
863  /* Check for empty destination palette! (results in empty image) */
864  if (format->palette != NULL) {
865  int i;
866  for (i = 0; i < format->palette->ncolors; ++i) {
867  if ((format->palette->colors[i].r != 0xFF) ||
868  (format->palette->colors[i].g != 0xFF) ||
869  (format->palette->colors[i].b != 0xFF))
870  break;
871  }
872  if (i == format->palette->ncolors) {
873  SDL_SetError("Empty destination palette");
874  return (NULL);
875  }
876  }
877 
878  /* Create a new surface with the desired format */
879  convert = SDL_CreateRGBSurface(flags, surface->w, surface->h,
880  format->BitsPerPixel, format->Rmask,
881  format->Gmask, format->Bmask,
882  format->Amask);
883  if (convert == NULL) {
884  return (NULL);
885  }
886 
887  /* Copy the palette if any */
888  if (format->palette && convert->format->palette) {
889  SDL_memcpy(convert->format->palette->colors,
890  format->palette->colors,
891  format->palette->ncolors * sizeof(SDL_Color));
892  convert->format->palette->ncolors = format->palette->ncolors;
893  }
894 
895  /* Save the original copy flags */
896  copy_flags = surface->map->info.flags;
897  copy_color.r = surface->map->info.r;
898  copy_color.g = surface->map->info.g;
899  copy_color.b = surface->map->info.b;
900  copy_color.a = surface->map->info.a;
901  surface->map->info.r = 0xFF;
902  surface->map->info.g = 0xFF;
903  surface->map->info.b = 0xFF;
904  surface->map->info.a = 0xFF;
905  surface->map->info.flags = 0;
906  SDL_InvalidateMap(surface->map);
907 
908  /* Copy over the image data */
909  bounds.x = 0;
910  bounds.y = 0;
911  bounds.w = surface->w;
912  bounds.h = surface->h;
913  SDL_LowerBlit(surface, &bounds, convert, &bounds);
914 
915  /* Clean up the original surface, and update converted surface */
916  convert->map->info.r = copy_color.r;
917  convert->map->info.g = copy_color.g;
918  convert->map->info.b = copy_color.b;
919  convert->map->info.a = copy_color.a;
920  convert->map->info.flags =
921  (copy_flags &
925  surface->map->info.r = copy_color.r;
926  surface->map->info.g = copy_color.g;
927  surface->map->info.b = copy_color.b;
928  surface->map->info.a = copy_color.a;
929  surface->map->info.flags = copy_flags;
930  SDL_InvalidateMap(surface->map);
931  if (copy_flags & SDL_COPY_COLORKEY) {
932  SDL_bool set_colorkey_by_color = SDL_FALSE;
933 
934  if (surface->format->palette) {
935  if (format->palette &&
936  surface->format->palette->ncolors <= format->palette->ncolors &&
937  (SDL_memcmp(surface->format->palette->colors, format->palette->colors,
938  surface->format->palette->ncolors * sizeof(SDL_Color)) == 0)) {
939  /* The palette is identical, just set the same colorkey */
940  SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
941  } else if (format->Amask) {
942  /* The alpha was set in the destination from the palette */
943  } else {
944  set_colorkey_by_color = SDL_TRUE;
945  }
946  } else {
947  set_colorkey_by_color = SDL_TRUE;
948  }
949 
950  if (set_colorkey_by_color) {
951  /* Set the colorkey by color, which needs to be unique */
952  Uint8 keyR, keyG, keyB, keyA;
953 
954  SDL_GetRGBA(surface->map->info.colorkey, surface->format, &keyR,
955  &keyG, &keyB, &keyA);
956  SDL_SetColorKey(convert, 1,
957  SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
958  /* This is needed when converting for 3D texture upload */
960  }
961  }
962  SDL_SetClipRect(convert, &surface->clip_rect);
963 
964  /* Enable alpha blending by default if the new surface has an
965  * alpha channel or alpha modulation */
966  if ((surface->format->Amask && format->Amask) ||
967  (copy_flags & (SDL_COPY_COLORKEY|SDL_COPY_MODULATE_ALPHA))) {
969  }
970  if ((copy_flags & SDL_COPY_RLE_DESIRED) || (flags & SDL_RLEACCEL)) {
971  SDL_SetSurfaceRLE(convert, SDL_RLEACCEL);
972  }
973 
974  /* We're ready to go! */
975  return (convert);
976 }
977 
978 SDL_Surface *
980  Uint32 flags)
981 {
982  SDL_PixelFormat *fmt;
983  SDL_Surface *convert = NULL;
984 
985  fmt = SDL_AllocFormat(pixel_format);
986  if (fmt) {
987  convert = SDL_ConvertSurface(surface, fmt, flags);
988  SDL_FreeFormat(fmt);
989  }
990  return convert;
991 }
992 
993 /*
994  * Create a surface on the stack for quick blit operations
995  */
996 static SDL_INLINE SDL_bool
998  void * pixels, int pitch, SDL_Surface * surface,
999  SDL_PixelFormat * format, SDL_BlitMap * blitmap)
1000 {
1001  if (SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
1002  SDL_SetError("Indexed pixel formats not supported");
1003  return SDL_FALSE;
1004  }
1005  if (SDL_InitFormat(format, pixel_format) < 0) {
1006  return SDL_FALSE;
1007  }
1008 
1009  SDL_zerop(surface);
1010  surface->flags = SDL_PREALLOC;
1011  surface->format = format;
1012  surface->pixels = pixels;
1013  surface->w = width;
1014  surface->h = height;
1015  surface->pitch = pitch;
1016  /* We don't actually need to set up the clip rect for our purposes */
1017  /* SDL_SetClipRect(surface, NULL); */
1018 
1019  /* Allocate an empty mapping */
1020  SDL_zerop(blitmap);
1021  blitmap->info.r = 0xFF;
1022  blitmap->info.g = 0xFF;
1023  blitmap->info.b = 0xFF;
1024  blitmap->info.a = 0xFF;
1025  surface->map = blitmap;
1026 
1027  /* The surface is ready to go */
1028  surface->refcount = 1;
1029  return SDL_TRUE;
1030 }
1031 
1032 /*
1033  * Copy a block of pixels of one format to another format
1034  */
1036  Uint32 src_format, const void * src, int src_pitch,
1037  Uint32 dst_format, void * dst, int dst_pitch)
1038 {
1039  SDL_Surface src_surface, dst_surface;
1040  SDL_PixelFormat src_fmt, dst_fmt;
1041  SDL_BlitMap src_blitmap, dst_blitmap;
1042  SDL_Rect rect;
1043  void *nonconst_src = (void *) src;
1044 
1045  /* Check to make sure we are blitting somewhere, so we don't crash */
1046  if (!dst) {
1047  return SDL_InvalidParamError("dst");
1048  }
1049  if (!dst_pitch) {
1050  return SDL_InvalidParamError("dst_pitch");
1051  }
1052 
1053  /* Fast path for same format copy */
1054  if (src_format == dst_format) {
1055  int bpp, i;
1056 
1057  if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
1058  switch (src_format) {
1059  case SDL_PIXELFORMAT_YUY2:
1060  case SDL_PIXELFORMAT_UYVY:
1061  case SDL_PIXELFORMAT_YVYU:
1062  bpp = 2;
1063  break;
1064  case SDL_PIXELFORMAT_YV12:
1065  case SDL_PIXELFORMAT_IYUV:
1066  case SDL_PIXELFORMAT_NV12:
1067  case SDL_PIXELFORMAT_NV21:
1068  bpp = 1;
1069  break;
1070  default:
1071  return SDL_SetError("Unknown FOURCC pixel format");
1072  }
1073  } else {
1074  bpp = SDL_BYTESPERPIXEL(src_format);
1075  }
1076  width *= bpp;
1077 
1078  for (i = height; i--;) {
1079  SDL_memcpy(dst, src, width);
1080  src = (Uint8*)src + src_pitch;
1081  dst = (Uint8*)dst + dst_pitch;
1082  }
1083 
1084  if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV) {
1085  /* U and V planes are a quarter the size of the Y plane */
1086  width /= 2;
1087  height /= 2;
1088  src_pitch /= 2;
1089  dst_pitch /= 2;
1090  for (i = height * 2; i--;) {
1091  SDL_memcpy(dst, src, width);
1092  src = (Uint8*)src + src_pitch;
1093  dst = (Uint8*)dst + dst_pitch;
1094  }
1095  } else if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) {
1096  /* U/V plane is half the height of the Y plane */
1097  height /= 2;
1098  for (i = height; i--;) {
1099  SDL_memcpy(dst, src, width);
1100  src = (Uint8*)src + src_pitch;
1101  dst = (Uint8*)dst + dst_pitch;
1102  }
1103  }
1104  return 0;
1105  }
1106 
1107  if (!SDL_CreateSurfaceOnStack(width, height, src_format, nonconst_src,
1108  src_pitch,
1109  &src_surface, &src_fmt, &src_blitmap)) {
1110  return -1;
1111  }
1112  if (!SDL_CreateSurfaceOnStack(width, height, dst_format, dst, dst_pitch,
1113  &dst_surface, &dst_fmt, &dst_blitmap)) {
1114  return -1;
1115  }
1116 
1117  /* Set up the rect and go! */
1118  rect.x = 0;
1119  rect.y = 0;
1120  rect.w = width;
1121  rect.h = height;
1122  return SDL_LowerBlit(&src_surface, &rect, &dst_surface, &rect);
1123 }
1124 
1125 /*
1126  * Free a surface created by the above function.
1127  */
1128 void
1130 {
1131  if (surface == NULL) {
1132  return;
1133  }
1134  if (surface->flags & SDL_DONTFREE) {
1135  return;
1136  }
1137  if (--surface->refcount > 0) {
1138  return;
1139  }
1140  while (surface->locked > 0) {
1141  SDL_UnlockSurface(surface);
1142  }
1143  if (surface->flags & SDL_RLEACCEL) {
1144  SDL_UnRLESurface(surface, 0);
1145  }
1146  if (surface->format) {
1147  SDL_SetSurfacePalette(surface, NULL);
1148  SDL_FreeFormat(surface->format);
1149  surface->format = NULL;
1150  }
1151  if (surface->map != NULL) {
1152  SDL_FreeBlitMap(surface->map);
1153  surface->map = NULL;
1154  }
1155  if (!(surface->flags & SDL_PREALLOC)) {
1156  SDL_free(surface->pixels);
1157  }
1158  SDL_free(surface);
1159 }
1160 
1161 /* vi: set ts=4 sw=4 expandtab: */
int SDL_GetColorKey(SDL_Surface *surface, Uint32 *key)
Gets the color key (transparent pixel) in a blittable surface.
Definition: SDL_surface.c:235
GLenum GLenum dst
Uint8 r
Definition: SDL_blit.h:70
#define SDL_COPY_MODULATE_COLOR
Definition: SDL_blit.h:34
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
void SDL_UnlockSurface(SDL_Surface *surface)
Definition: SDL_surface.c:837
Uint32 version
Definition: SDL_pixels.h:292
Uint8 b
Definition: SDL_blit.h:70
SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect)
Definition: SDL_surface.c:470
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2072
#define SDL_COPY_COLORKEY
Definition: SDL_blit.h:39
GLint GLint GLsizei width
Definition: SDL_opengl.h:1565
SDL_blit blit
Definition: SDL_blit.h:89
int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag)
Sets the RLE acceleration hint for a surface.
Definition: SDL_surface.c:169
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:157
Uint8 g
Definition: SDL_pixels.h:282
#define SDL_MapRGBA
#define SDL_SoftStretch
#define SDL_ISPIXELFORMAT_INDEXED(format)
Definition: SDL_pixels.h:133
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
int SDL_LockSurface(SDL_Surface *surface)
Sets up a surface for directly accessing the pixels.
Definition: SDL_surface.c:816
SDL_Surface * SDL_ConvertSurfaceFormat(SDL_Surface *surface, Uint32 pixel_format, Uint32 flags)
Definition: SDL_surface.c:979
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
Uint8 BytesPerPixel
Definition: SDL_pixels.h:304
SDL_Rect rect
Definition: testrelative.c:27
Uint8 g
Definition: SDL_blit.h:70
#define SDL_MasksToPixelFormatEnum
SDL_Surface * SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format, Uint32 flags)
Definition: SDL_surface.c:855
static SDL_INLINE SDL_bool SDL_CreateSurfaceOnStack(int width, int height, Uint32 pixel_format, void *pixels, int pitch, SDL_Surface *surface, SDL_PixelFormat *format, SDL_BlitMap *blitmap)
Definition: SDL_surface.c:997
#define SDL_COPY_MOD
Definition: SDL_blit.h:38
int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
Set an additional color value used in blit operations.
Definition: SDL_surface.c:323
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
SDL_COMPILE_TIME_ASSERT(surface_size_assumptions, sizeof(int)==sizeof(Sint32)&&sizeof(size_t) >=sizeof(Sint32))
int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha)
Set an additional alpha value used in blit operations.
Definition: SDL_surface.c:368
#define SDL_DONTFREE
Definition: SDL_surface.h:55
int SDL_UpperBlitScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
Definition: SDL_surface.c:635
int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode)
Set the blend mode used for blit operations.
Definition: SDL_surface.c:404
void SDL_UnRLESurface(SDL_Surface *surface, int recode)
#define SDL_BlitSurface
Definition: SDL_surface.h:447
static void SDL_ConvertColorkeyToAlpha(SDL_Surface *surface)
Definition: SDL_surface.c:253
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:127
Uint32 dst_palette_version
Definition: SDL_blit.h:95
Uint8 b
Definition: SDL_pixels.h:283
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1565
#define SDL_AllocFormat
#define SDL_COPY_RLE_COLORKEY
Definition: SDL_blit.h:42
#define SDL_MAX_SINT32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:151
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1565
#define SDL_IntersectRect
#define SDL_floor
int SDL_LowerBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
Definition: SDL_surface.c:513
#define SDL_zerop(x)
Definition: SDL_stdinc.h:358
int SDL_SetColorKey(SDL_Surface *surface, int flag, Uint32 key)
Sets the color key (transparent pixel) in a blittable surface.
Definition: SDL_surface.c:190
GLsizeiptr size
int SDL_UpperBlit(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
Definition: SDL_surface.c:536
GLfloat GLfloat GLfloat alpha
#define SDL_COPY_ADD
Definition: SDL_blit.h:37
Uint32 colorkey
Definition: SDL_blit.h:69
Uint32 flags
Definition: SDL_surface.h:71
void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
Definition: SDL_surface.c:494
Uint32 src_palette_version
Definition: SDL_blit.h:96
#define SDL_COPY_RLE_DESIRED
Definition: SDL_blit.h:41
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
SDL_bool
Definition: SDL_stdinc.h:126
void SDL_InvalidateMap(SDL_BlitMap *map)
Definition: SDL_pixels.c:974
GLboolean GLboolean g
#define SDL_COPY_NEAREST
Definition: SDL_blit.h:40
#define SDL_ALPHA_TRANSPARENT
Definition: SDL_pixels.h:46
struct SDL_BlitMap * map
Definition: SDL_surface.h:88
#define SDL_memcpy
void * SDL_calloc(size_t nmemb, size_t size)
Uint8 r
Definition: SDL_pixels.h:281
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst)
Definition: SDL_pixels.c:993
void * pixels
Definition: SDL_surface.h:75
Uint8 a
Definition: SDL_pixels.h:284
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
Uint8 BitsPerPixel
Definition: SDL_pixels.h:303
int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
Set the palette used by a surface.
Definition: SDL_surface.c:155
void SDL_free(void *mem)
int SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode)
Get the blend mode used for blit operations.
Definition: SDL_surface.c:441
int SDL_ConvertPixels(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch)
Copy a block of pixels of one format to another format.
Definition: SDL_surface.c:1035
#define SDL_FreeFormat
#define SDL_memcmp
int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha)
Get the additional alpha value used in blit operations.
Definition: SDL_surface.c:391
int x
Definition: SDL_rect.h:66
int32_t Sint32
Definition: SDL_stdinc.h:153
int w
Definition: SDL_rect.h:67
GLenum GLint GLuint mask
#define SDL_GetRGBA
#define SDL_AllocPalette
int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format)
Definition: SDL_pixels.c:521
SDL_Rect clip_rect
Definition: SDL_surface.h:85
void SDL_FreeSurface(SDL_Surface *surface)
Definition: SDL_surface.c:1129
int SDL_RLESurface(SDL_Surface *surface)
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:42
SDL_Surface * dst
Definition: SDL_blit.h:87
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_Color * colors
Definition: SDL_pixels.h:291
SDL_PixelFormat * format
Definition: SDL_surface.h:72
GLint GLint GLsizei GLsizei GLsizei depth
Definition: SDL_opengl.h:1565
#define SDL_FreePalette
#define SDL_SetError
SDL_Surface * SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
Definition: SDL_surface.c:38
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_COPY_MODULATE_ALPHA
Definition: SDL_blit.h:35
int h
Definition: SDL_rect.h:67
#define SDL_COPY_RLE_ALPHAKEY
Definition: SDL_blit.h:43
int SDL_LowerBlitScaled(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
Definition: SDL_surface.c:789
SDL_BlitMap * SDL_AllocBlitMap(void)
Definition: SDL_pixels.c:954
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
Uint32 pixel_format
Definition: testoverlay2.c:152
GLbitfield flags
#define SDL_INLINE
Definition: begin_code.h:120
int SDL_CalculatePitch(SDL_Surface *surface)
Definition: SDL_pixels.c:748
#define SDL_malloc
GLubyte GLubyte GLubyte GLubyte w
SDL_Palette * palette
Definition: SDL_pixels.h:302
#define SDL_ISPIXELFORMAT_FOURCC(format)
Definition: SDL_pixels.h:166
SDL_Surface * SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
Definition: SDL_surface.c:134
int64_t Sint64
A signed 64-bit integer type.
Definition: SDL_stdinc.h:162
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:45
GLenum src
GLboolean GLboolean GLboolean b
void SDL_FreeBlitMap(SDL_BlitMap *map)
Definition: SDL_pixels.c:1079
int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b)
Get the additional color value used in blit operations.
Definition: SDL_surface.c:349
GLenum GLenum void * row
int y
Definition: SDL_rect.h:66
#define SDL_SetPixelFormatPalette
#define SDL_Unsupported()
Definition: SDL_error.h:53
GLfloat GLfloat GLfloat GLfloat h
#define SDL_COPY_BLEND
Definition: SDL_blit.h:36
SDL_BlitInfo info
Definition: SDL_blit.h:91
#define SDL_memset
#define SDL_PREALLOC
Definition: SDL_surface.h:53
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
#define SDL_RLEACCEL
Definition: SDL_surface.h:54
Uint8 a
Definition: SDL_blit.h:70