2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "SDL_error.h"
33 #include "SDL_video.h"
34 #include "SDL_sysvideo.h"
35 #include "SDL_cursor_c.h"
37 #include "SDL_RLEaccel_c.h"
38 #include "SDL_pixels_c.h"
39 #include "SDL_memops.h"
40 #include "SDL_leaks.h"
44 * Create an empty RGB surface of the appropriate depth
46 SDL_Surface
* SDL_CreateRGBSurface (Uint32 flags
,
47 int width
, int height
, int depth
,
48 Uint32 Rmask
, Uint32 Gmask
, Uint32 Bmask
, Uint32 Amask
)
50 SDL_VideoDevice
*video
= current_video
;
51 SDL_VideoDevice
*this = current_video
;
55 /* Check to see if we desire the surface in video memory */
57 screen
= SDL_PublicSurface
;
61 if ( screen
&& ((screen
->flags
&SDL_HWSURFACE
) == SDL_HWSURFACE
) ) {
62 if ( (flags
&(SDL_SRCCOLORKEY
|SDL_SRCALPHA
)) != 0 ) {
63 flags
|= SDL_HWSURFACE
;
65 if ( (flags
& SDL_SRCCOLORKEY
) == SDL_SRCCOLORKEY
) {
66 if ( ! current_video
->info
.blit_hw_CC
) {
67 flags
&= ~SDL_HWSURFACE
;
70 if ( (flags
& SDL_SRCALPHA
) == SDL_SRCALPHA
) {
71 if ( ! current_video
->info
.blit_hw_A
) {
72 flags
&= ~SDL_HWSURFACE
;
76 flags
&= ~SDL_HWSURFACE
;
79 /* Allocate the surface */
80 surface
= (SDL_Surface
*)malloc(sizeof(*surface
));
81 if ( surface
== NULL
) {
85 surface
->flags
= SDL_SWSURFACE
;
86 if ( (flags
& SDL_HWSURFACE
) == SDL_HWSURFACE
) {
87 depth
= screen
->format
->BitsPerPixel
;
88 Rmask
= screen
->format
->Rmask
;
89 Gmask
= screen
->format
->Gmask
;
90 Bmask
= screen
->format
->Bmask
;
91 Amask
= screen
->format
->Amask
;
93 surface
->format
= SDL_AllocFormat(depth
, Rmask
, Gmask
, Bmask
, Amask
);
94 if ( surface
->format
== NULL
) {
99 surface
->flags
|= SDL_SRCALPHA
;
103 surface
->pitch
= SDL_CalculatePitch(surface
);
104 surface
->pixels
= NULL
;
106 surface
->hwdata
= NULL
;
109 surface
->format_version
= 0;
110 surface
->unused1
= 0;
111 SDL_SetClipRect(surface
, NULL
);
114 if ( ((flags
&SDL_HWSURFACE
) == SDL_SWSURFACE
) ||
115 (video
->AllocHWSurface(this, surface
) < 0) ) {
116 if ( surface
->w
&& surface
->h
) {
117 surface
->pixels
= malloc(surface
->h
*surface
->pitch
);
118 if ( surface
->pixels
== NULL
) {
119 SDL_FreeSurface(surface
);
123 /* This is important for bitmaps */
124 memset(surface
->pixels
, 0, surface
->h
*surface
->pitch
);
128 /* Allocate an empty mapping */
129 surface
->map
= SDL_AllocBlitMap();
130 if ( surface
->map
== NULL
) {
131 SDL_FreeSurface(surface
);
135 /* The surface is ready to go */
136 surface
->refcount
= 1;
138 ++surfaces_allocated
;
143 * Create an RGB surface from an existing memory buffer
145 SDL_Surface
* SDL_CreateRGBSurfaceFrom (void *pixels
,
146 int width
, int height
, int depth
, int pitch
,
147 Uint32 Rmask
, Uint32 Gmask
, Uint32 Bmask
, Uint32 Amask
)
149 SDL_Surface
*surface
;
151 surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
, 0, 0, depth
,
152 Rmask
, Gmask
, Bmask
, Amask
);
153 if ( surface
!= NULL
) {
154 surface
->flags
|= SDL_PREALLOC
;
155 surface
->pixels
= pixels
;
158 surface
->pitch
= pitch
;
159 SDL_SetClipRect(surface
, NULL
);
164 * Set the color key in a blittable surface
166 int SDL_SetColorKey (SDL_Surface
*surface
, Uint32 flag
, Uint32 key
)
168 /* Sanity check the flag as it gets passed in */
169 if ( flag
& SDL_SRCCOLORKEY
) {
170 if ( flag
& (SDL_RLEACCEL
|SDL_RLEACCELOK
) ) {
171 flag
= (SDL_SRCCOLORKEY
| SDL_RLEACCELOK
);
173 flag
= SDL_SRCCOLORKEY
;
179 /* Optimize away operations that don't change anything */
180 if ( (flag
== (surface
->flags
& (SDL_SRCCOLORKEY
|SDL_RLEACCELOK
))) &&
181 (key
== surface
->format
->colorkey
) ) {
185 /* UnRLE surfaces before we change the colorkey */
186 if ( surface
->flags
& SDL_RLEACCEL
) {
187 SDL_UnRLESurface(surface
, 1);
191 SDL_VideoDevice
*video
= current_video
;
192 SDL_VideoDevice
*this = current_video
;
195 surface
->flags
|= SDL_SRCCOLORKEY
;
196 surface
->format
->colorkey
= key
;
197 if ( (surface
->flags
& SDL_HWACCEL
) == SDL_HWACCEL
) {
198 if ( (video
->SetHWColorKey
== NULL
) ||
199 (video
->SetHWColorKey(this, surface
, key
) < 0) ) {
200 surface
->flags
&= ~SDL_HWACCEL
;
203 if ( flag
& SDL_RLEACCELOK
) {
204 surface
->flags
|= SDL_RLEACCELOK
;
206 surface
->flags
&= ~SDL_RLEACCELOK
;
209 surface
->flags
&= ~(SDL_SRCCOLORKEY
|SDL_RLEACCELOK
);
210 surface
->format
->colorkey
= 0;
212 SDL_InvalidateMap(surface
->map
);
215 /* This function sets the alpha channel of a surface */
216 int SDL_SetAlpha (SDL_Surface
*surface
, Uint32 flag
, Uint8 value
)
218 Uint32 oldflags
= surface
->flags
;
219 Uint32 oldalpha
= surface
->format
->alpha
;
221 /* Sanity check the flag as it gets passed in */
222 if ( flag
& SDL_SRCALPHA
) {
223 if ( flag
& (SDL_RLEACCEL
|SDL_RLEACCELOK
) ) {
224 flag
= (SDL_SRCALPHA
| SDL_RLEACCELOK
);
232 /* Optimize away operations that don't change anything */
233 if ( (flag
== (surface
->flags
& (SDL_SRCALPHA
|SDL_RLEACCELOK
))) &&
234 (!flag
|| value
== oldalpha
) ) {
238 if(!(flag
& SDL_RLEACCELOK
) && (surface
->flags
& SDL_RLEACCEL
))
239 SDL_UnRLESurface(surface
, 1);
242 SDL_VideoDevice
*video
= current_video
;
243 SDL_VideoDevice
*this = current_video
;
245 surface
->flags
|= SDL_SRCALPHA
;
246 surface
->format
->alpha
= value
;
247 if ( (surface
->flags
& SDL_HWACCEL
) == SDL_HWACCEL
) {
248 if ( (video
->SetHWAlpha
== NULL
) ||
249 (video
->SetHWAlpha(this, surface
, value
) < 0) ) {
250 surface
->flags
&= ~SDL_HWACCEL
;
253 if ( flag
& SDL_RLEACCELOK
) {
254 surface
->flags
|= SDL_RLEACCELOK
;
256 surface
->flags
&= ~SDL_RLEACCELOK
;
259 surface
->flags
&= ~SDL_SRCALPHA
;
260 surface
->format
->alpha
= SDL_ALPHA_OPAQUE
;
263 * The representation for software surfaces is independent of
264 * per-surface alpha, so no need to invalidate the blit mapping
265 * if just the alpha value was changed. (If either is 255, we still
266 * need to invalidate.)
268 if((surface
->flags
& SDL_HWACCEL
) == SDL_HWACCEL
269 || oldflags
!= surface
->flags
270 || (((oldalpha
+ 1) ^ (value
+ 1)) & 0x100))
271 SDL_InvalidateMap(surface
->map
);
274 int SDL_SetAlphaChannel(SDL_Surface
*surface
, Uint8 value
)
280 if ( (surface
->format
->Amask
!= 0xFF000000) &&
281 (surface
->format
->Amask
!= 0x000000FF) ) {
282 SDL_SetError("Unsupported surface alpha mask format");
286 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
287 if ( surface
->format
->Amask
== 0xFF000000 ) {
293 if ( surface
->format
->Amask
== 0xFF000000 ) {
298 #endif /* Byte ordering */
300 /* Quickly set the alpha channel of an RGBA or ARGB surface */
301 if ( SDL_MUSTLOCK(surface
) ) {
302 if ( SDL_LockSurface(surface
) < 0 ) {
309 buf
= (Uint8
*)surface
->pixels
+ row
* surface
->pitch
+ offset
;
315 if ( SDL_MUSTLOCK(surface
) ) {
316 SDL_UnlockSurface(surface
);
322 * A function to calculate the intersection of two rectangles:
323 * return true if the rectangles intersect, false otherwise
326 SDL_bool
SDL_IntersectRect(const SDL_Rect
*A
, const SDL_Rect
*B
, SDL_Rect
*intersection
)
328 int Amin
, Amax
, Bmin
, Bmax
;
330 /* Horizontal intersection */
337 intersection
->x
= Amin
;
340 intersection
->w
= Amax
- Amin
> 0 ? Amax
- Amin
: 0;
342 /* Vertical intersection */
349 intersection
->y
= Amin
;
352 intersection
->h
= Amax
- Amin
> 0 ? Amax
- Amin
: 0;
354 return (intersection
->w
&& intersection
->h
);
357 * Set the clipping rectangle for a blittable surface
359 SDL_bool
SDL_SetClipRect(SDL_Surface
*surface
, const SDL_Rect
*rect
)
363 /* Don't do anything if there's no surface to act on */
368 /* Set up the full surface rectangle */
371 full_rect
.w
= surface
->w
;
372 full_rect
.h
= surface
->h
;
374 /* Set the clipping rectangle */
376 surface
->clip_rect
= full_rect
;
379 return SDL_IntersectRect(rect
, &full_rect
, &surface
->clip_rect
);
381 void SDL_GetClipRect(SDL_Surface
*surface
, SDL_Rect
*rect
)
383 if ( surface
&& rect
) {
384 *rect
= surface
->clip_rect
;
388 * Set up a blit between two surfaces -- split into three parts:
389 * The upper part, SDL_UpperBlit(), performs clipping and rectangle
390 * verification. The lower part is a pointer to a low level
391 * accelerated blitting function.
393 * These parts are separated out and each used internally by this
394 * library in the optimimum places. They are exported so that if
395 * you know exactly what you are doing, you can optimize your code
396 * by calling the one(s) you need.
398 int SDL_LowerBlit (SDL_Surface
*src
, SDL_Rect
*srcrect
,
399 SDL_Surface
*dst
, SDL_Rect
*dstrect
)
405 /* Check to make sure the blit mapping is valid */
406 if ( (src
->map
->dst
!= dst
) ||
407 (src
->map
->dst
->format_version
!= src
->map
->format_version
) ) {
408 if ( SDL_MapSurface(src
, dst
) < 0 ) {
413 /* Figure out which blitter to use */
414 if ( (src
->flags
& SDL_HWACCEL
) == SDL_HWACCEL
) {
415 if ( src
== SDL_VideoSurface
) {
416 hw_srcrect
= *srcrect
;
417 hw_srcrect
.x
+= current_video
->offset_x
;
418 hw_srcrect
.y
+= current_video
->offset_y
;
419 srcrect
= &hw_srcrect
;
421 if ( dst
== SDL_VideoSurface
) {
422 hw_dstrect
= *dstrect
;
423 hw_dstrect
.x
+= current_video
->offset_x
;
424 hw_dstrect
.y
+= current_video
->offset_y
;
425 dstrect
= &hw_dstrect
;
427 do_blit
= src
->map
->hw_blit
;
429 do_blit
= src
->map
->sw_blit
;
431 return(do_blit(src
, srcrect
, dst
, dstrect
));
435 int SDL_UpperBlit (SDL_Surface
*src
, SDL_Rect
*srcrect
,
436 SDL_Surface
*dst
, SDL_Rect
*dstrect
)
439 int srcx
, srcy
, w
, h
;
441 /* Make sure the surfaces aren't locked */
442 if ( ! src
|| ! dst
) {
443 SDL_SetError("SDL_UpperBlit: passed a NULL surface");
446 if ( src
->locked
|| dst
->locked
) {
447 SDL_SetError("Surfaces must not be locked during blit");
451 /* If the destination rectangle is NULL, use the entire dest surface */
452 if ( dstrect
== NULL
) {
453 fulldst
.x
= fulldst
.y
= 0;
457 /* clip the source rectangle to the source surface */
468 maxw
= src
->w
- srcx
;
479 maxh
= src
->h
- srcy
;
489 /* clip the destination rectangle against the clip rectangle */
491 SDL_Rect
*clip
= &dst
->clip_rect
;
494 dx
= clip
->x
- dstrect
->x
;
500 dx
= dstrect
->x
+ w
- clip
->x
- clip
->w
;
504 dy
= clip
->y
- dstrect
->y
;
510 dy
= dstrect
->y
+ h
- clip
->y
- clip
->h
;
519 sr
.w
= dstrect
->w
= w
;
520 sr
.h
= dstrect
->h
= h
;
521 return SDL_LowerBlit(src
, &sr
, dst
, dstrect
);
523 dstrect
->w
= dstrect
->h
= 0;
528 * This function performs a fast fill of the given rectangle with 'color'
530 int SDL_FillRect(SDL_Surface
*dst
, SDL_Rect
*dstrect
, Uint32 color
)
532 SDL_VideoDevice
*video
= current_video
;
533 SDL_VideoDevice
*this = current_video
;
537 /* If 'dstrect' == NULL, then fill the whole surface */
539 /* Perform clipping */
540 if ( !SDL_IntersectRect(dstrect
, &dst
->clip_rect
, dstrect
) ) {
544 dstrect
= &dst
->clip_rect
;
547 /* Check for hardware acceleration */
548 if ( ((dst
->flags
& SDL_HWSURFACE
) == SDL_HWSURFACE
) &&
549 video
->info
.blit_fill
) {
551 if ( dst
== SDL_VideoSurface
) {
553 hw_rect
.x
+= current_video
->offset_x
;
554 hw_rect
.y
+= current_video
->offset_y
;
557 return(video
->FillHWRect(this, dst
, dstrect
, color
));
560 /* Perform software fill */
561 if ( SDL_LockSurface(dst
) != 0 ) {
564 row
= (Uint8
*)dst
->pixels
+dstrect
->y
*dst
->pitch
+
565 dstrect
->x
*dst
->format
->BytesPerPixel
;
566 if ( dst
->format
->palette
|| (color
== 0) ) {
567 x
= dstrect
->w
*dst
->format
->BytesPerPixel
;
568 if ( !color
&& !((long)row
&3) && !(x
&3) && !(dst
->pitch
&3) ) {
570 for ( y
=dstrect
->h
; y
; --y
) {
571 SDL_memset4(row
, 0, n
);
577 * memset() on PPC (both glibc and codewarrior) uses
578 * the dcbz (Data Cache Block Zero) instruction, which
579 * causes an alignment exception if the destination is
580 * uncachable, so only use it on software surfaces
582 if((dst
->flags
& SDL_HWSURFACE
) == SDL_HWSURFACE
) {
583 if(dstrect
->w
>= 8) {
585 * 64-bit stores are probably most
586 * efficient to uncached video memory
589 memset(&fill
, color
, (sizeof fill
));
590 for(y
= dstrect
->h
; y
; y
--) {
596 while((unsigned long)d
597 & (sizeof(double) - 1)) {
601 nn
= n
/ (sizeof(double) * 4);
603 ((double *)d
)[0] = f
;
604 ((double *)d
)[1] = f
;
605 ((double *)d
)[2] = f
;
606 ((double *)d
)[3] = f
;
607 d
+= 4*sizeof(double);
610 n
&= ~(sizeof(double) * 4 - 1);
611 nn
= n
/ sizeof(double);
617 n
&= ~(sizeof(double) - 1);
626 for(y
= dstrect
->h
; y
; y
--) {
638 #endif /* __powerpc__ */
640 for(y
= dstrect
->h
; y
; y
--) {
641 memset(row
, color
, x
);
647 switch (dst
->format
->BytesPerPixel
) {
649 for ( y
=dstrect
->h
; y
; --y
) {
650 Uint16
*pixels
= (Uint16
*)row
;
652 Uint32 cc
= (Uint32
)c
<< 16 | c
;
654 if((unsigned long)pixels
& 3) {
659 SDL_memset4(pixels
, cc
, n
>> 1);
667 if(SDL_BYTEORDER
== SDL_BIG_ENDIAN
)
669 for ( y
=dstrect
->h
; y
; --y
) {
671 for ( x
=dstrect
->w
; x
; --x
) {
672 memcpy(pixels
, &color
, 3);
680 for(y
= dstrect
->h
; y
; --y
) {
681 SDL_memset4(row
, color
, dstrect
->w
);
687 SDL_UnlockSurface(dst
);
694 * Lock a surface to directly access the pixels
696 int SDL_LockSurface (SDL_Surface
*surface
)
698 if ( ! surface
->locked
) {
699 /* Perform the lock */
700 if ( surface
->flags
& (SDL_HWSURFACE
|SDL_ASYNCBLIT
) ) {
701 SDL_VideoDevice
*video
= current_video
;
702 SDL_VideoDevice
*this = current_video
;
703 if ( video
->LockHWSurface(this, surface
) < 0 ) {
707 if ( surface
->flags
& SDL_RLEACCEL
) {
708 SDL_UnRLESurface(surface
, 1);
709 surface
->flags
|= SDL_RLEACCEL
; /* save accel'd state */
711 /* This needs to be done here in case pixels changes value */
712 surface
->pixels
= (Uint8
*)surface
->pixels
+ surface
->offset
;
715 /* Increment the surface lock count, for recursive locks */
722 * Unlock a previously locked surface
724 void SDL_UnlockSurface (SDL_Surface
*surface
)
726 /* Only perform an unlock if we are locked */
727 if ( ! surface
->locked
|| (--surface
->locked
> 0) ) {
731 /* Perform the unlock */
732 surface
->pixels
= (Uint8
*)surface
->pixels
- surface
->offset
;
734 /* Unlock hardware or accelerated surfaces */
735 if ( surface
->flags
& (SDL_HWSURFACE
|SDL_ASYNCBLIT
) ) {
736 SDL_VideoDevice
*video
= current_video
;
737 SDL_VideoDevice
*this = current_video
;
738 video
->UnlockHWSurface(this, surface
);
740 /* Update RLE encoded surface with new data */
741 if ( (surface
->flags
& SDL_RLEACCEL
) == SDL_RLEACCEL
) {
742 surface
->flags
&= ~SDL_RLEACCEL
; /* stop lying */
743 SDL_RLESurface(surface
);
749 * Convert a surface into the specified pixel format.
751 SDL_Surface
* SDL_ConvertSurface (SDL_Surface
*surface
,
752 SDL_PixelFormat
*format
, Uint32 flags
)
754 SDL_Surface
*convert
;
757 Uint32 surface_flags
;
760 /* Check for empty destination palette! (results in empty image) */
761 if ( format
->palette
!= NULL
) {
763 for ( i
=0; i
<format
->palette
->ncolors
; ++i
) {
764 if ( (format
->palette
->colors
[i
].r
!= 0) ||
765 (format
->palette
->colors
[i
].g
!= 0) ||
766 (format
->palette
->colors
[i
].b
!= 0) )
769 if ( i
== format
->palette
->ncolors
) {
770 SDL_SetError("Empty destination palette");
775 /* Only create hw surfaces with alpha channel if hw alpha blits
777 if(format
->Amask
!= 0 && (flags
& SDL_HWSURFACE
)) {
778 const SDL_VideoInfo
*vi
= SDL_GetVideoInfo();
779 if(!vi
|| !vi
->blit_hw_A
)
780 flags
&= ~SDL_HWSURFACE
;
783 /* Create a new surface with the desired format */
784 convert
= SDL_CreateRGBSurface(flags
,
785 surface
->w
, surface
->h
, format
->BitsPerPixel
,
786 format
->Rmask
, format
->Gmask
, format
->Bmask
, format
->Amask
);
787 if ( convert
== NULL
) {
791 /* Copy the palette if any */
792 if ( format
->palette
&& convert
->format
->palette
) {
793 memcpy(convert
->format
->palette
->colors
,
794 format
->palette
->colors
,
795 format
->palette
->ncolors
*sizeof(SDL_Color
));
796 convert
->format
->palette
->ncolors
= format
->palette
->ncolors
;
799 /* Save the original surface color key and alpha */
800 surface_flags
= surface
->flags
;
801 if ( (surface_flags
& SDL_SRCCOLORKEY
) == SDL_SRCCOLORKEY
) {
802 /* Convert colourkeyed surfaces to RGBA if requested */
803 if((flags
& SDL_SRCCOLORKEY
) != SDL_SRCCOLORKEY
805 surface_flags
&= ~SDL_SRCCOLORKEY
;
807 colorkey
= surface
->format
->colorkey
;
808 SDL_SetColorKey(surface
, 0, 0);
811 if ( (surface_flags
& SDL_SRCALPHA
) == SDL_SRCALPHA
) {
812 /* Copy over the alpha channel to RGBA if requested */
813 if ( format
->Amask
) {
814 surface
->flags
&= ~SDL_SRCALPHA
;
816 alpha
= surface
->format
->alpha
;
817 SDL_SetAlpha(surface
, 0, 0);
821 /* Copy over the image data */
824 bounds
.w
= surface
->w
;
825 bounds
.h
= surface
->h
;
826 SDL_LowerBlit(surface
, &bounds
, convert
, &bounds
);
828 /* Clean up the original surface, and update converted surface */
829 if ( convert
!= NULL
) {
830 SDL_SetClipRect(convert
, &surface
->clip_rect
);
832 if ( (surface_flags
& SDL_SRCCOLORKEY
) == SDL_SRCCOLORKEY
) {
833 Uint32 cflags
= surface_flags
&(SDL_SRCCOLORKEY
|SDL_RLEACCELOK
);
834 if ( convert
!= NULL
) {
835 Uint8 keyR
, keyG
, keyB
;
837 SDL_GetRGB(colorkey
,surface
->format
,&keyR
,&keyG
,&keyB
);
838 SDL_SetColorKey(convert
, cflags
|(flags
&SDL_RLEACCELOK
),
839 SDL_MapRGB(convert
->format
, keyR
, keyG
, keyB
));
841 SDL_SetColorKey(surface
, cflags
, colorkey
);
843 if ( (surface_flags
& SDL_SRCALPHA
) == SDL_SRCALPHA
) {
844 Uint32 aflags
= surface_flags
&(SDL_SRCALPHA
|SDL_RLEACCELOK
);
845 if ( convert
!= NULL
) {
846 SDL_SetAlpha(convert
, aflags
|(flags
&SDL_RLEACCELOK
),
849 if ( format
->Amask
) {
850 surface
->flags
|= SDL_SRCALPHA
;
852 SDL_SetAlpha(surface
, aflags
, alpha
);
856 /* We're ready to go! */
861 * Free a surface created by the above function.
863 void SDL_FreeSurface (SDL_Surface
*surface
)
865 /* Free anything that's not NULL, and not the screen surface */
866 if ((surface
== NULL
) ||
868 ((surface
== SDL_ShadowSurface
)||(surface
== SDL_VideoSurface
)))) {
871 if ( --surface
->refcount
> 0 ) {
874 if ( (surface
->flags
& SDL_RLEACCEL
) == SDL_RLEACCEL
) {
875 SDL_UnRLESurface(surface
, 0);
877 if ( surface
->format
) {
878 SDL_FreeFormat(surface
->format
);
879 surface
->format
= NULL
;
881 if ( surface
->map
!= NULL
) {
882 SDL_FreeBlitMap(surface
->map
);
885 if ( surface
->hwdata
) {
886 SDL_VideoDevice
*video
= current_video
;
887 SDL_VideoDevice
*this = current_video
;
888 video
->FreeHWSurface(this, surface
);
890 if ( surface
->pixels
&&
891 ((surface
->flags
& SDL_PREALLOC
) != SDL_PREALLOC
) ) {
892 free(surface
->pixels
);
896 --surfaces_allocated
;