2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "../SDL_internal.h"
23 #include "SDL_video.h"
24 #include "SDL_sysvideo.h"
26 #include "SDL_RLEaccel_c.h"
27 #include "SDL_pixels_c.h"
31 * Create an empty RGB surface of the appropriate depth
34 SDL_CreateRGBSurface(Uint32 flags,
35 int width, int height, int depth,
36 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
41 /* The flags are no longer used, make the compiler happy */
44 /* Get the pixel format */
45 format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask);
46 if (format == SDL_PIXELFORMAT_UNKNOWN) {
47 SDL_SetError("Unknown pixel format");
51 /* Allocate the surface */
52 surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface));
53 if (surface == NULL) {
58 surface->format = SDL_AllocFormat(format);
59 if (!surface->format) {
60 SDL_FreeSurface(surface);
65 surface->pitch = SDL_CalculatePitch(surface);
66 SDL_SetClipRect(surface, NULL);
68 if (SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
69 SDL_Palette *palette =
70 SDL_AllocPalette((1 << surface->format->BitsPerPixel));
72 SDL_FreeSurface(surface);
75 if (palette->ncolors == 2) {
76 /* Create a black and white bitmap palette */
77 palette->colors[0].r = 0xFF;
78 palette->colors[0].g = 0xFF;
79 palette->colors[0].b = 0xFF;
80 palette->colors[1].r = 0x00;
81 palette->colors[1].g = 0x00;
82 palette->colors[1].b = 0x00;
84 SDL_SetSurfacePalette(surface, palette);
85 SDL_FreePalette(palette);
89 if (surface->w && surface->h) {
90 surface->pixels = SDL_malloc(surface->h * surface->pitch);
91 if (!surface->pixels) {
92 SDL_FreeSurface(surface);
96 /* This is important for bitmaps */
97 SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
100 /* Allocate an empty mapping */
101 surface->map = SDL_AllocBlitMap();
103 SDL_FreeSurface(surface);
107 /* By default surface with an alpha mask are set up for blending */
109 SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
112 /* The surface is ready to go */
113 surface->refcount = 1;
118 * Create an RGB surface from an existing memory buffer
121 SDL_CreateRGBSurfaceFrom(void *pixels,
122 int width, int height, int depth, int pitch,
123 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
126 SDL_Surface *surface;
129 SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask);
130 if (surface != NULL) {
131 surface->flags |= SDL_PREALLOC;
132 surface->pixels = pixels;
135 surface->pitch = pitch;
136 SDL_SetClipRect(surface, NULL);
142 SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette)
145 return SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface");
147 if (SDL_SetPixelFormatPalette(surface->format, palette) < 0) {
150 SDL_InvalidateMap(surface->map);
156 SDL_SetSurfaceRLE(SDL_Surface * surface, int flag)
164 flags = surface->map->info.flags;
166 surface->map->info.flags |= SDL_COPY_RLE_DESIRED;
168 surface->map->info.flags &= ~SDL_COPY_RLE_DESIRED;
170 if (surface->map->info.flags != flags) {
171 SDL_InvalidateMap(surface->map);
177 SDL_SetColorKey(SDL_Surface * surface, int flag, Uint32 key)
182 return SDL_InvalidParamError("surface");
185 if (surface->format->palette && key >= ((Uint32) surface->format->palette->ncolors)) {
186 return SDL_InvalidParamError("key");
189 if (flag & SDL_RLEACCEL) {
190 SDL_SetSurfaceRLE(surface, 1);
193 flags = surface->map->info.flags;
195 surface->map->info.flags |= SDL_COPY_COLORKEY;
196 surface->map->info.colorkey = key;
197 if (surface->format->palette) {
198 surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
199 ++surface->format->palette->version;
200 if (!surface->format->palette->version) {
201 surface->format->palette->version = 1;
205 if (surface->format->palette) {
206 surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_OPAQUE;
207 ++surface->format->palette->version;
208 if (!surface->format->palette->version) {
209 surface->format->palette->version = 1;
212 surface->map->info.flags &= ~SDL_COPY_COLORKEY;
214 if (surface->map->info.flags != flags) {
215 SDL_InvalidateMap(surface->map);
222 SDL_GetColorKey(SDL_Surface * surface, Uint32 * key)
228 if (!(surface->map->info.flags & SDL_COPY_COLORKEY)) {
233 *key = surface->map->info.colorkey;
238 /* This is a fairly slow function to switch from colorkey to alpha */
240 SDL_ConvertColorkeyToAlpha(SDL_Surface * surface)
248 if (!(surface->map->info.flags & SDL_COPY_COLORKEY) ||
249 !surface->format->Amask) {
253 SDL_LockSurface(surface);
255 switch (surface->format->BytesPerPixel) {
259 Uint16 ckey = (Uint16) surface->map->info.colorkey;
260 Uint16 mask = (Uint16) (~surface->format->Amask);
262 /* Ignore alpha in colorkey comparison */
264 row = (Uint16 *) surface->pixels;
265 for (y = surface->h; y--;) {
267 for (x = surface->w; x--;) {
268 if ((*spot & mask) == ckey) {
273 row += surface->pitch / 2;
283 Uint32 ckey = surface->map->info.colorkey;
284 Uint32 mask = ~surface->format->Amask;
286 /* Ignore alpha in colorkey comparison */
288 row = (Uint32 *) surface->pixels;
289 for (y = surface->h; y--;) {
291 for (x = surface->w; x--;) {
292 if ((*spot & mask) == ckey) {
297 row += surface->pitch / 4;
303 SDL_UnlockSurface(surface);
305 SDL_SetColorKey(surface, 0, 0);
306 SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
310 SDL_SetSurfaceColorMod(SDL_Surface * surface, Uint8 r, Uint8 g, Uint8 b)
318 surface->map->info.r = r;
319 surface->map->info.g = g;
320 surface->map->info.b = b;
322 flags = surface->map->info.flags;
323 if (r != 0xFF || g != 0xFF || b != 0xFF) {
324 surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
326 surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
328 if (surface->map->info.flags != flags) {
329 SDL_InvalidateMap(surface->map);
336 SDL_GetSurfaceColorMod(SDL_Surface * surface, Uint8 * r, Uint8 * g, Uint8 * b)
343 *r = surface->map->info.r;
346 *g = surface->map->info.g;
349 *b = surface->map->info.b;
355 SDL_SetSurfaceAlphaMod(SDL_Surface * surface, Uint8 alpha)
363 surface->map->info.a = alpha;
365 flags = surface->map->info.flags;
367 surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA;
369 surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA;
371 if (surface->map->info.flags != flags) {
372 SDL_InvalidateMap(surface->map);
378 SDL_GetSurfaceAlphaMod(SDL_Surface * surface, Uint8 * alpha)
385 *alpha = surface->map->info.a;
391 SDL_SetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode blendMode)
400 flags = surface->map->info.flags;
401 surface->map->info.flags &=
402 ~(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD);
404 case SDL_BLENDMODE_NONE:
406 case SDL_BLENDMODE_BLEND:
407 surface->map->info.flags |= SDL_COPY_BLEND;
409 case SDL_BLENDMODE_ADD:
410 surface->map->info.flags |= SDL_COPY_ADD;
412 case SDL_BLENDMODE_MOD:
413 surface->map->info.flags |= SDL_COPY_MOD;
416 status = SDL_Unsupported();
420 if (surface->map->info.flags != flags) {
421 SDL_InvalidateMap(surface->map);
428 SDL_GetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode *blendMode)
438 switch (surface->map->
439 info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) {
441 *blendMode = SDL_BLENDMODE_BLEND;
444 *blendMode = SDL_BLENDMODE_ADD;
447 *blendMode = SDL_BLENDMODE_MOD;
450 *blendMode = SDL_BLENDMODE_NONE;
457 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect)
461 /* Don't do anything if there's no surface to act on */
466 /* Set up the full surface rectangle */
469 full_rect.w = surface->w;
470 full_rect.h = surface->h;
472 /* Set the clipping rectangle */
474 surface->clip_rect = full_rect;
477 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
481 SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect)
483 if (surface && rect) {
484 *rect = surface->clip_rect;
489 * Set up a blit between two surfaces -- split into three parts:
490 * The upper part, SDL_UpperBlit(), performs clipping and rectangle
491 * verification. The lower part is a pointer to a low level
492 * accelerated blitting function.
494 * These parts are separated out and each used internally by this
495 * library in the optimimum places. They are exported so that if
496 * you know exactly what you are doing, you can optimize your code
497 * by calling the one(s) you need.
500 SDL_LowerBlit(SDL_Surface * src, SDL_Rect * srcrect,
501 SDL_Surface * dst, SDL_Rect * dstrect)
503 /* Check to make sure the blit mapping is valid */
504 if ((src->map->dst != dst) ||
505 (dst->format->palette &&
506 src->map->dst_palette_version != dst->format->palette->version) ||
507 (src->format->palette &&
508 src->map->src_palette_version != src->format->palette->version)) {
509 if (SDL_MapSurface(src, dst) < 0) {
512 /* just here for debugging */
514 /* ("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", */
515 /* src, dst->flags, src->map->info.flags, dst, dst->flags, */
516 /* dst->map->info.flags, src->map->blit); */
518 return (src->map->blit(src, srcrect, dst, dstrect));
523 SDL_UpperBlit(SDL_Surface * src, const SDL_Rect * srcrect,
524 SDL_Surface * dst, SDL_Rect * dstrect)
527 int srcx, srcy, w, h;
529 /* Make sure the surfaces aren't locked */
531 return SDL_SetError("SDL_UpperBlit: passed a NULL surface");
533 if (src->locked || dst->locked) {
534 return SDL_SetError("Surfaces must not be locked during blit");
537 /* If the destination rectangle is NULL, use the entire dest surface */
538 if (dstrect == NULL) {
539 fulldst.x = fulldst.y = 0;
545 /* clip the source rectangle to the source surface */
556 maxw = src->w - srcx;
567 maxh = src->h - srcy;
577 /* clip the destination rectangle against the clip rectangle */
579 SDL_Rect *clip = &dst->clip_rect;
582 dx = clip->x - dstrect->x;
588 dx = dstrect->x + w - clip->x - clip->w;
592 dy = clip->y - dstrect->y;
598 dy = dstrect->y + h - clip->y - clip->h;
603 /* Switch back to a fast blit if we were previously stretching */
604 if (src->map->info.flags & SDL_COPY_NEAREST) {
605 src->map->info.flags &= ~SDL_COPY_NEAREST;
606 SDL_InvalidateMap(src->map);
609 if (w > 0 && h > 0) {
613 sr.w = dstrect->w = w;
614 sr.h = dstrect->h = h;
615 return SDL_LowerBlit(src, &sr, dst, dstrect);
617 dstrect->w = dstrect->h = 0;
622 SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
623 SDL_Surface * dst, SDL_Rect * dstrect)
625 double src_x0, src_y0, src_x1, src_y1;
626 double dst_x0, dst_y0, dst_x1, dst_y1;
627 SDL_Rect final_src, final_dst;
628 double scaling_w, scaling_h;
632 /* Make sure the surfaces aren't locked */
634 return SDL_SetError("SDL_UpperBlitScaled: passed a NULL surface");
636 if (src->locked || dst->locked) {
637 return SDL_SetError("Surfaces must not be locked during blit");
640 if (NULL == srcrect) {
648 if (NULL == dstrect) {
656 if (dst_w == src_w && dst_h == src_h) {
657 /* No scaling, defer to regular blit */
658 return SDL_BlitSurface(src, srcrect, dst, dstrect);
661 scaling_w = (double)dst_w / src_w;
662 scaling_h = (double)dst_h / src_h;
664 if (NULL == dstrect) {
672 dst_x1 = dst_x0 + dst_w - 1;
673 dst_y1 = dst_y0 + dst_h - 1;
676 if (NULL == srcrect) {
684 src_x1 = src_x0 + src_w - 1;
685 src_y1 = src_y0 + src_h - 1;
687 /* Clip source rectangle to the source surface */
690 dst_x0 -= src_x0 * scaling_w;
694 if (src_x1 >= src->w) {
695 dst_x1 -= (src_x1 - src->w + 1) * scaling_w;
700 dst_y0 -= src_y0 * scaling_h;
704 if (src_y1 >= src->h) {
705 dst_y1 -= (src_y1 - src->h + 1) * scaling_h;
710 /* Clip destination rectangle to the clip rectangle */
712 /* Translate to clip space for easier calculations */
713 dst_x0 -= dst->clip_rect.x;
714 dst_x1 -= dst->clip_rect.x;
715 dst_y0 -= dst->clip_rect.y;
716 dst_y1 -= dst->clip_rect.y;
719 src_x0 -= dst_x0 / scaling_w;
723 if (dst_x1 >= dst->clip_rect.w) {
724 src_x1 -= (dst_x1 - dst->clip_rect.w + 1) / scaling_w;
725 dst_x1 = dst->clip_rect.w - 1;
729 src_y0 -= dst_y0 / scaling_h;
733 if (dst_y1 >= dst->clip_rect.h) {
734 src_y1 -= (dst_y1 - dst->clip_rect.h + 1) / scaling_h;
735 dst_y1 = dst->clip_rect.h - 1;
738 /* Translate back to surface coordinates */
739 dst_x0 += dst->clip_rect.x;
740 dst_x1 += dst->clip_rect.x;
741 dst_y0 += dst->clip_rect.y;
742 dst_y1 += dst->clip_rect.y;
744 final_src.x = (int)SDL_floor(src_x0 + 0.5);
745 final_src.y = (int)SDL_floor(src_y0 + 0.5);
746 final_src.w = (int)SDL_floor(src_x1 - src_x0 + 1.5);
747 final_src.h = (int)SDL_floor(src_y1 - src_y0 + 1.5);
749 final_dst.x = (int)SDL_floor(dst_x0 + 0.5);
750 final_dst.y = (int)SDL_floor(dst_y0 + 0.5);
751 final_dst.w = (int)SDL_floor(dst_x1 - dst_x0 + 1.5);
752 final_dst.h = (int)SDL_floor(dst_y1 - dst_y0 + 1.5);
760 *dstrect = final_dst;
762 if (final_dst.w == 0 || final_dst.h == 0 ||
763 final_src.w <= 0 || final_src.h <= 0) {
768 return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst);
772 * This is a semi-private blit function and it performs low-level surface
773 * scaled blitting only.
776 SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
777 SDL_Surface * dst, SDL_Rect * dstrect)
779 static const Uint32 complex_copy_flags = (
780 SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA |
781 SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD |
785 if (!(src->map->info.flags & SDL_COPY_NEAREST)) {
786 src->map->info.flags |= SDL_COPY_NEAREST;
787 SDL_InvalidateMap(src->map);
790 if ( !(src->map->info.flags & complex_copy_flags) &&
791 src->format->format == dst->format->format &&
792 !SDL_ISPIXELFORMAT_INDEXED(src->format->format) ) {
793 return SDL_SoftStretch( src, srcrect, dst, dstrect );
795 return SDL_LowerBlit( src, srcrect, dst, dstrect );
800 * Lock a surface to directly access the pixels
803 SDL_LockSurface(SDL_Surface * surface)
805 if (!surface->locked) {
806 /* Perform the lock */
807 if (surface->flags & SDL_RLEACCEL) {
808 SDL_UnRLESurface(surface, 1);
809 surface->flags |= SDL_RLEACCEL; /* save accel'd state */
813 /* Increment the surface lock count, for recursive locks */
821 * Unlock a previously locked surface
824 SDL_UnlockSurface(SDL_Surface * surface)
826 /* Only perform an unlock if we are locked */
827 if (!surface->locked || (--surface->locked > 0)) {
831 /* Update RLE encoded surface with new data */
832 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
833 surface->flags &= ~SDL_RLEACCEL; /* stop lying */
834 SDL_RLESurface(surface);
839 * Convert a surface into the specified pixel format.
842 SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
845 SDL_Surface *convert;
847 SDL_Color copy_color;
850 /* Check for empty destination palette! (results in empty image) */
851 if (format->palette != NULL) {
853 for (i = 0; i < format->palette->ncolors; ++i) {
854 if ((format->palette->colors[i].r != 0xFF) ||
855 (format->palette->colors[i].g != 0xFF) ||
856 (format->palette->colors[i].b != 0xFF))
859 if (i == format->palette->ncolors) {
860 SDL_SetError("Empty destination palette");
865 /* Create a new surface with the desired format */
866 convert = SDL_CreateRGBSurface(flags, surface->w, surface->h,
867 format->BitsPerPixel, format->Rmask,
868 format->Gmask, format->Bmask,
870 if (convert == NULL) {
874 /* Copy the palette if any */
875 if (format->palette && convert->format->palette) {
876 SDL_memcpy(convert->format->palette->colors,
877 format->palette->colors,
878 format->palette->ncolors * sizeof(SDL_Color));
879 convert->format->palette->ncolors = format->palette->ncolors;
882 /* Save the original copy flags */
883 copy_flags = surface->map->info.flags;
884 copy_color.r = surface->map->info.r;
885 copy_color.g = surface->map->info.g;
886 copy_color.b = surface->map->info.b;
887 copy_color.a = surface->map->info.a;
888 surface->map->info.r = 0xFF;
889 surface->map->info.g = 0xFF;
890 surface->map->info.b = 0xFF;
891 surface->map->info.a = 0xFF;
892 surface->map->info.flags = 0;
893 SDL_InvalidateMap(surface->map);
895 /* Copy over the image data */
898 bounds.w = surface->w;
899 bounds.h = surface->h;
900 SDL_LowerBlit(surface, &bounds, convert, &bounds);
902 /* Clean up the original surface, and update converted surface */
903 convert->map->info.r = copy_color.r;
904 convert->map->info.g = copy_color.g;
905 convert->map->info.b = copy_color.b;
906 convert->map->info.a = copy_color.a;
907 convert->map->info.flags =
909 ~(SDL_COPY_COLORKEY | SDL_COPY_BLEND
910 | SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY |
911 SDL_COPY_RLE_ALPHAKEY));
912 surface->map->info.r = copy_color.r;
913 surface->map->info.g = copy_color.g;
914 surface->map->info.b = copy_color.b;
915 surface->map->info.a = copy_color.a;
916 surface->map->info.flags = copy_flags;
917 SDL_InvalidateMap(surface->map);
918 if (copy_flags & SDL_COPY_COLORKEY) {
919 SDL_bool set_colorkey_by_color = SDL_FALSE;
921 if (surface->format->palette) {
922 if (format->palette &&
923 surface->format->palette->ncolors <= format->palette->ncolors &&
924 (SDL_memcmp(surface->format->palette->colors, format->palette->colors,
925 surface->format->palette->ncolors * sizeof(SDL_Color)) == 0)) {
926 /* The palette is identical, just set the same colorkey */
927 SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
928 } else if (format->Amask) {
929 /* The alpha was set in the destination from the palette */
931 set_colorkey_by_color = SDL_TRUE;
934 set_colorkey_by_color = SDL_TRUE;
937 if (set_colorkey_by_color) {
938 /* Set the colorkey by color, which needs to be unique */
939 Uint8 keyR, keyG, keyB, keyA;
941 SDL_GetRGBA(surface->map->info.colorkey, surface->format, &keyR,
942 &keyG, &keyB, &keyA);
943 SDL_SetColorKey(convert, 1,
944 SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
945 /* This is needed when converting for 3D texture upload */
946 SDL_ConvertColorkeyToAlpha(convert);
949 SDL_SetClipRect(convert, &surface->clip_rect);
951 /* Enable alpha blending by default if the new surface has an
952 * alpha channel or alpha modulation */
953 if ((surface->format->Amask && format->Amask) ||
954 (copy_flags & (SDL_COPY_COLORKEY|SDL_COPY_MODULATE_ALPHA))) {
955 SDL_SetSurfaceBlendMode(convert, SDL_BLENDMODE_BLEND);
957 if ((copy_flags & SDL_COPY_RLE_DESIRED) || (flags & SDL_RLEACCEL)) {
958 SDL_SetSurfaceRLE(convert, SDL_RLEACCEL);
961 /* We're ready to go! */
966 SDL_ConvertSurfaceFormat(SDL_Surface * surface, Uint32 pixel_format,
969 SDL_PixelFormat *fmt;
970 SDL_Surface *convert = NULL;
972 fmt = SDL_AllocFormat(pixel_format);
974 convert = SDL_ConvertSurface(surface, fmt, flags);
981 * Create a surface on the stack for quick blit operations
983 static SDL_INLINE SDL_bool
984 SDL_CreateSurfaceOnStack(int width, int height, Uint32 pixel_format,
985 void * pixels, int pitch, SDL_Surface * surface,
986 SDL_PixelFormat * format, SDL_BlitMap * blitmap)
988 if (SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
989 SDL_SetError("Indexed pixel formats not supported");
992 if (SDL_InitFormat(format, pixel_format) < 0) {
997 surface->flags = SDL_PREALLOC;
998 surface->format = format;
999 surface->pixels = pixels;
1001 surface->h = height;
1002 surface->pitch = pitch;
1003 /* We don't actually need to set up the clip rect for our purposes */
1004 /* SDL_SetClipRect(surface, NULL); */
1006 /* Allocate an empty mapping */
1008 blitmap->info.r = 0xFF;
1009 blitmap->info.g = 0xFF;
1010 blitmap->info.b = 0xFF;
1011 blitmap->info.a = 0xFF;
1012 surface->map = blitmap;
1014 /* The surface is ready to go */
1015 surface->refcount = 1;
1020 * Copy a block of pixels of one format to another format
1022 int SDL_ConvertPixels(int width, int height,
1023 Uint32 src_format, const void * src, int src_pitch,
1024 Uint32 dst_format, void * dst, int dst_pitch)
1026 SDL_Surface src_surface, dst_surface;
1027 SDL_PixelFormat src_fmt, dst_fmt;
1028 SDL_BlitMap src_blitmap, dst_blitmap;
1030 void *nonconst_src = (void *) src;
1032 /* Check to make sure we are blitting somewhere, so we don't crash */
1034 return SDL_InvalidParamError("dst");
1037 return SDL_InvalidParamError("dst_pitch");
1040 /* Fast path for same format copy */
1041 if (src_format == dst_format) {
1044 if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
1045 switch (src_format) {
1046 case SDL_PIXELFORMAT_YUY2:
1047 case SDL_PIXELFORMAT_UYVY:
1048 case SDL_PIXELFORMAT_YVYU:
1051 case SDL_PIXELFORMAT_YV12:
1052 case SDL_PIXELFORMAT_IYUV:
1053 case SDL_PIXELFORMAT_NV12:
1054 case SDL_PIXELFORMAT_NV21:
1058 return SDL_SetError("Unknown FOURCC pixel format");
1061 bpp = SDL_BYTESPERPIXEL(src_format);
1065 for (i = height; i--;) {
1066 SDL_memcpy(dst, src, width);
1067 src = (Uint8*)src + src_pitch;
1068 dst = (Uint8*)dst + dst_pitch;
1071 if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV) {
1072 /* U and V planes are a quarter the size of the Y plane */
1077 for (i = height * 2; i--;) {
1078 SDL_memcpy(dst, src, width);
1079 src = (Uint8*)src + src_pitch;
1080 dst = (Uint8*)dst + dst_pitch;
1082 } else if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) {
1083 /* U/V plane is half the height of the Y plane */
1085 for (i = height; i--;) {
1086 SDL_memcpy(dst, src, width);
1087 src = (Uint8*)src + src_pitch;
1088 dst = (Uint8*)dst + dst_pitch;
1094 if (!SDL_CreateSurfaceOnStack(width, height, src_format, nonconst_src,
1096 &src_surface, &src_fmt, &src_blitmap)) {
1099 if (!SDL_CreateSurfaceOnStack(width, height, dst_format, dst, dst_pitch,
1100 &dst_surface, &dst_fmt, &dst_blitmap)) {
1104 /* Set up the rect and go! */
1109 return SDL_LowerBlit(&src_surface, &rect, &dst_surface, &rect);
1113 * Free a surface created by the above function.
1116 SDL_FreeSurface(SDL_Surface * surface)
1118 if (surface == NULL) {
1121 if (surface->flags & SDL_DONTFREE) {
1124 if (--surface->refcount > 0) {
1127 while (surface->locked > 0) {
1128 SDL_UnlockSurface(surface);
1130 if (surface->flags & SDL_RLEACCEL) {
1131 SDL_UnRLESurface(surface, 0);
1133 if (surface->format) {
1134 SDL_SetSurfacePalette(surface, NULL);
1135 SDL_FreeFormat(surface->format);
1136 surface->format = NULL;
1138 if (surface->map != NULL) {
1139 SDL_FreeBlitMap(surface->map);
1140 surface->map = NULL;
1142 if (!(surface->flags & SDL_PREALLOC)) {
1143 SDL_free(surface->pixels);
1148 /* vi: set ts=4 sw=4 expandtab: */