Mercurial > sdl-ios-xcode
annotate src/video/SDL_surface.c @ 765:4c2ba6161939
Editors Note: The original patch was modified to use SDL_Delay() instead of
nanosleep because nanosleep may not be portable to all systems
using SDL with the ALSA backend. This may be a moot point with
the switch to blocking writes anyway...
Date: Sat, 27 Dec 2003 21:47:36 +0100
From: Michel Daenzer
To: Debian Bug Tracking System
Subject: [SDL] Bug#225252: [PATCH] ALSA fixes
Package: libsdl1.2debian-all
Version: 1.2.6-2
Severity: normal
Tags: patch
For SDL 1.2.6, the ALSA backend was changed to call snd_pcm_open() with
SND_PCM_NONBLOCK. That's a good idea per se, however, it causes high CPU
usage, interrupted sound and stuttering in some games here. Taking a nanosleep
whenever snd_pcm_writei() returns -EAGAIN fixes this, but I think it's more
efficient to use blocking mode for the actual sound playback. Feedback from the
SDL and ALSA lists appreciated.
The patch also fixes the default ALSA device to be used.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 04 Jan 2004 15:40:50 +0000 |
parents | 058d47b7a3b4 |
children | b8d311d90021 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
296
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
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. | |
9 | |
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. | |
14 | |
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 | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
130
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #include <stdio.h> | |
29 #include <stdlib.h> | |
30 #include <string.h> | |
31 | |
32 #include "SDL_error.h" | |
33 #include "SDL_video.h" | |
34 #include "SDL_sysvideo.h" | |
35 #include "SDL_cursor_c.h" | |
36 #include "SDL_blit.h" | |
37 #include "SDL_RLEaccel_c.h" | |
38 #include "SDL_pixels_c.h" | |
39 #include "SDL_memops.h" | |
40 #include "SDL_leaks.h" | |
41 | |
42 /* Public routines */ | |
43 /* | |
44 * Create an empty RGB surface of the appropriate depth | |
45 */ | |
46 SDL_Surface * SDL_CreateRGBSurface (Uint32 flags, | |
47 int width, int height, int depth, | |
48 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) | |
49 { | |
50 SDL_VideoDevice *video = current_video; | |
51 SDL_VideoDevice *this = current_video; | |
52 SDL_Surface *screen; | |
53 SDL_Surface *surface; | |
54 | |
55 /* Check to see if we desire the surface in video memory */ | |
56 if ( video ) { | |
57 screen = SDL_PublicSurface; | |
58 } else { | |
59 screen = NULL; | |
60 } | |
61 if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) { | |
62 if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) { | |
63 flags |= SDL_HWSURFACE; | |
64 } | |
65 if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
66 if ( ! current_video->info.blit_hw_CC ) { | |
67 flags &= ~SDL_HWSURFACE; | |
68 } | |
69 } | |
70 if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
71 if ( ! current_video->info.blit_hw_A ) { | |
72 flags &= ~SDL_HWSURFACE; | |
73 } | |
74 } | |
75 } else { | |
76 flags &= ~SDL_HWSURFACE; | |
77 } | |
78 | |
79 /* Allocate the surface */ | |
80 surface = (SDL_Surface *)malloc(sizeof(*surface)); | |
81 if ( surface == NULL ) { | |
82 SDL_OutOfMemory(); | |
83 return(NULL); | |
84 } | |
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; | |
92 } | |
93 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); | |
94 if ( surface->format == NULL ) { | |
95 free(surface); | |
96 return(NULL); | |
97 } | |
98 if ( Amask ) { | |
99 surface->flags |= SDL_SRCALPHA; | |
100 } | |
101 surface->w = width; | |
102 surface->h = height; | |
103 surface->pitch = SDL_CalculatePitch(surface); | |
104 surface->pixels = NULL; | |
105 surface->offset = 0; | |
106 surface->hwdata = NULL; | |
107 surface->locked = 0; | |
108 surface->map = NULL; | |
109 surface->format_version = 0; | |
441
598b25b9bffe
Zeroed out SDL_Surface::unused1 so glSDL will work on stock SDL
Sam Lantinga <slouken@libsdl.org>
parents:
431
diff
changeset
|
110 surface->unused1 = 0; |
0 | 111 SDL_SetClipRect(surface, NULL); |
112 | |
113 /* Get the pixels */ | |
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); | |
120 SDL_OutOfMemory(); | |
121 return(NULL); | |
122 } | |
123 /* This is important for bitmaps */ | |
124 memset(surface->pixels, 0, surface->h*surface->pitch); | |
125 } | |
126 } | |
127 | |
128 /* Allocate an empty mapping */ | |
129 surface->map = SDL_AllocBlitMap(); | |
130 if ( surface->map == NULL ) { | |
131 SDL_FreeSurface(surface); | |
132 return(NULL); | |
133 } | |
134 | |
135 /* The surface is ready to go */ | |
136 surface->refcount = 1; | |
137 #ifdef CHECK_LEAKS | |
138 ++surfaces_allocated; | |
139 #endif | |
140 return(surface); | |
141 } | |
142 /* | |
143 * Create an RGB surface from an existing memory buffer | |
144 */ | |
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) | |
148 { | |
149 SDL_Surface *surface; | |
150 | |
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; | |
156 surface->w = width; | |
157 surface->h = height; | |
158 surface->pitch = pitch; | |
159 SDL_SetClipRect(surface, NULL); | |
160 } | |
161 return(surface); | |
162 } | |
163 /* | |
164 * Set the color key in a blittable surface | |
165 */ | |
166 int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key) | |
167 { | |
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); | |
172 } else { | |
173 flag = SDL_SRCCOLORKEY; | |
174 } | |
175 } else { | |
176 flag = 0; | |
177 } | |
178 | |
179 /* Optimize away operations that don't change anything */ | |
180 if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) && | |
181 (key == surface->format->colorkey) ) { | |
182 return(0); | |
183 } | |
184 | |
185 /* UnRLE surfaces before we change the colorkey */ | |
186 if ( surface->flags & SDL_RLEACCEL ) { | |
187 SDL_UnRLESurface(surface, 1); | |
188 } | |
189 | |
190 if ( flag ) { | |
191 SDL_VideoDevice *video = current_video; | |
192 SDL_VideoDevice *this = current_video; | |
193 | |
194 | |
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; | |
201 } | |
202 } | |
203 if ( flag & SDL_RLEACCELOK ) { | |
204 surface->flags |= SDL_RLEACCELOK; | |
205 } else { | |
206 surface->flags &= ~SDL_RLEACCELOK; | |
207 } | |
208 } else { | |
209 surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK); | |
210 surface->format->colorkey = 0; | |
211 } | |
212 SDL_InvalidateMap(surface->map); | |
213 return(0); | |
214 } | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
215 /* This function sets the alpha channel of a surface */ |
0 | 216 int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value) |
217 { | |
218 Uint32 oldflags = surface->flags; | |
219 Uint32 oldalpha = surface->format->alpha; | |
220 | |
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); | |
225 } else { | |
226 flag = SDL_SRCALPHA; | |
227 } | |
228 } else { | |
229 flag = 0; | |
230 } | |
231 | |
232 /* Optimize away operations that don't change anything */ | |
233 if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) && | |
234 (!flag || value == oldalpha) ) { | |
235 return(0); | |
236 } | |
237 | |
238 if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) | |
239 SDL_UnRLESurface(surface, 1); | |
240 | |
241 if ( flag ) { | |
242 SDL_VideoDevice *video = current_video; | |
243 SDL_VideoDevice *this = current_video; | |
244 | |
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; | |
251 } | |
252 } | |
253 if ( flag & SDL_RLEACCELOK ) { | |
254 surface->flags |= SDL_RLEACCELOK; | |
255 } else { | |
256 surface->flags &= ~SDL_RLEACCELOK; | |
257 } | |
258 } else { | |
259 surface->flags &= ~SDL_SRCALPHA; | |
260 surface->format->alpha = SDL_ALPHA_OPAQUE; | |
261 } | |
262 /* | |
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.) | |
267 */ | |
268 if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL | |
269 || oldflags != surface->flags | |
270 || (((oldalpha + 1) ^ (value + 1)) & 0x100)) | |
271 SDL_InvalidateMap(surface->map); | |
272 return(0); | |
273 } | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
274 int SDL_SetAlphaChannel(SDL_Surface *surface, Uint8 value) |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
275 { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
276 int row, col; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
277 int offset; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
278 Uint8 *buf; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
279 |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
280 if ( (surface->format->Amask != 0xFF000000) && |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
281 (surface->format->Amask != 0x000000FF) ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
282 SDL_SetError("Unsupported surface alpha mask format"); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
283 return -1; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
284 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
285 |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
286 #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
287 if ( surface->format->Amask == 0xFF000000 ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
288 offset = 3; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
289 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
290 offset = 0; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
291 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
292 #else |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
293 if ( surface->format->Amask == 0xFF000000 ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
294 offset = 0; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
295 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
296 offset = 3; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
297 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
298 #endif /* Byte ordering */ |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
299 |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
300 /* Quickly set the alpha channel of an RGBA or ARGB surface */ |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
301 if ( SDL_MUSTLOCK(surface) ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
302 if ( SDL_LockSurface(surface) < 0 ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
303 return -1; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
304 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
305 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
306 row = surface->h; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
307 while (row--) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
308 col = surface->w; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
309 buf = (Uint8 *)surface->pixels + row * surface->pitch + offset; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
310 while(col--) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
311 *buf = value; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
312 buf += 4; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
313 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
314 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
315 if ( SDL_MUSTLOCK(surface) ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
316 SDL_UnlockSurface(surface); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
317 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
318 return 0; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
319 } |
0 | 320 |
321 /* | |
322 * A function to calculate the intersection of two rectangles: | |
323 * return true if the rectangles intersect, false otherwise | |
324 */ | |
325 static __inline__ | |
130
14af14ff7c19
The rectangle argument to SDL_SetClipRect is really const
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
326 SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection) |
0 | 327 { |
328 int Amin, Amax, Bmin, Bmax; | |
329 | |
330 /* Horizontal intersection */ | |
331 Amin = A->x; | |
332 Amax = Amin + A->w; | |
333 Bmin = B->x; | |
334 Bmax = Bmin + B->w; | |
335 if(Bmin > Amin) | |
336 Amin = Bmin; | |
337 intersection->x = Amin; | |
338 if(Bmax < Amax) | |
339 Amax = Bmax; | |
340 intersection->w = Amax - Amin > 0 ? Amax - Amin : 0; | |
341 | |
342 /* Vertical intersection */ | |
343 Amin = A->y; | |
344 Amax = Amin + A->h; | |
345 Bmin = B->y; | |
346 Bmax = Bmin + B->h; | |
347 if(Bmin > Amin) | |
348 Amin = Bmin; | |
349 intersection->y = Amin; | |
350 if(Bmax < Amax) | |
351 Amax = Bmax; | |
352 intersection->h = Amax - Amin > 0 ? Amax - Amin : 0; | |
353 | |
354 return (intersection->w && intersection->h); | |
355 } | |
356 /* | |
357 * Set the clipping rectangle for a blittable surface | |
358 */ | |
130
14af14ff7c19
The rectangle argument to SDL_SetClipRect is really const
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
359 SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect) |
0 | 360 { |
361 SDL_Rect full_rect; | |
362 | |
363 /* Don't do anything if there's no surface to act on */ | |
364 if ( ! surface ) { | |
365 return SDL_FALSE; | |
366 } | |
367 | |
368 /* Set up the full surface rectangle */ | |
369 full_rect.x = 0; | |
370 full_rect.y = 0; | |
371 full_rect.w = surface->w; | |
372 full_rect.h = surface->h; | |
373 | |
374 /* Set the clipping rectangle */ | |
375 if ( ! rect ) { | |
376 surface->clip_rect = full_rect; | |
377 return 1; | |
378 } | |
379 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); | |
380 } | |
381 void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect) | |
382 { | |
383 if ( surface && rect ) { | |
384 *rect = surface->clip_rect; | |
385 } | |
386 } | |
387 /* | |
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. | |
392 * | |
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. | |
397 */ | |
398 int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect, | |
399 SDL_Surface *dst, SDL_Rect *dstrect) | |
400 { | |
401 SDL_blit do_blit; | |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
402 SDL_Rect hw_srcrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
403 SDL_Rect hw_dstrect; |
0 | 404 |
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 ) { | |
409 return(-1); | |
410 } | |
411 } | |
412 | |
413 /* Figure out which blitter to use */ | |
414 if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) { | |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
415 if ( src == SDL_VideoSurface ) { |
519
c7da0cd5ae5e
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
462
diff
changeset
|
416 hw_srcrect = *srcrect; |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
417 hw_srcrect.x += current_video->offset_x; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
418 hw_srcrect.y += current_video->offset_y; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
419 srcrect = &hw_srcrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
420 } |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
421 if ( dst == SDL_VideoSurface ) { |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
422 hw_dstrect = *dstrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
423 hw_dstrect.x += current_video->offset_x; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
424 hw_dstrect.y += current_video->offset_y; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
425 dstrect = &hw_dstrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
426 } |
0 | 427 do_blit = src->map->hw_blit; |
428 } else { | |
429 do_blit = src->map->sw_blit; | |
430 } | |
431 return(do_blit(src, srcrect, dst, dstrect)); | |
432 } | |
433 | |
434 | |
435 int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect, | |
436 SDL_Surface *dst, SDL_Rect *dstrect) | |
437 { | |
438 SDL_Rect fulldst; | |
439 int srcx, srcy, w, h; | |
440 | |
441 /* Make sure the surfaces aren't locked */ | |
442 if ( ! src || ! dst ) { | |
443 SDL_SetError("SDL_UpperBlit: passed a NULL surface"); | |
444 return(-1); | |
445 } | |
446 if ( src->locked || dst->locked ) { | |
447 SDL_SetError("Surfaces must not be locked during blit"); | |
448 return(-1); | |
449 } | |
450 | |
451 /* If the destination rectangle is NULL, use the entire dest surface */ | |
452 if ( dstrect == NULL ) { | |
453 fulldst.x = fulldst.y = 0; | |
454 dstrect = &fulldst; | |
455 } | |
456 | |
457 /* clip the source rectangle to the source surface */ | |
458 if(srcrect) { | |
459 int maxw, maxh; | |
460 | |
461 srcx = srcrect->x; | |
462 w = srcrect->w; | |
463 if(srcx < 0) { | |
464 w += srcx; | |
465 dstrect->x -= srcx; | |
466 srcx = 0; | |
467 } | |
468 maxw = src->w - srcx; | |
469 if(maxw < w) | |
470 w = maxw; | |
471 | |
472 srcy = srcrect->y; | |
473 h = srcrect->h; | |
474 if(srcy < 0) { | |
475 h += srcy; | |
476 dstrect->y -= srcy; | |
477 srcy = 0; | |
478 } | |
479 maxh = src->h - srcy; | |
480 if(maxh < h) | |
481 h = maxh; | |
482 | |
483 } else { | |
484 srcx = srcy = 0; | |
485 w = src->w; | |
486 h = src->h; | |
487 } | |
488 | |
489 /* clip the destination rectangle against the clip rectangle */ | |
490 { | |
491 SDL_Rect *clip = &dst->clip_rect; | |
492 int dx, dy; | |
493 | |
494 dx = clip->x - dstrect->x; | |
495 if(dx > 0) { | |
496 w -= dx; | |
497 dstrect->x += dx; | |
498 srcx += dx; | |
499 } | |
500 dx = dstrect->x + w - clip->x - clip->w; | |
501 if(dx > 0) | |
502 w -= dx; | |
503 | |
504 dy = clip->y - dstrect->y; | |
505 if(dy > 0) { | |
506 h -= dy; | |
507 dstrect->y += dy; | |
508 srcy += dy; | |
509 } | |
510 dy = dstrect->y + h - clip->y - clip->h; | |
511 if(dy > 0) | |
512 h -= dy; | |
513 } | |
514 | |
515 if(w > 0 && h > 0) { | |
516 SDL_Rect sr; | |
517 sr.x = srcx; | |
518 sr.y = srcy; | |
519 sr.w = dstrect->w = w; | |
520 sr.h = dstrect->h = h; | |
521 return SDL_LowerBlit(src, &sr, dst, dstrect); | |
522 } | |
523 dstrect->w = dstrect->h = 0; | |
524 return 0; | |
525 } | |
526 | |
532
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
527 static int SDL_FillRect1(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
528 { |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
529 /* FIXME: We have to worry about packing order.. *sigh* */ |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
530 SDL_SetError("1-bpp rect fill not yet implemented"); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
531 return -1; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
532 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
533 |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
534 static int SDL_FillRect4(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
535 { |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
536 /* FIXME: We have to worry about packing order.. *sigh* */ |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
537 SDL_SetError("4-bpp rect fill not yet implemented"); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
538 return -1; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
539 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
540 |
0 | 541 /* |
542 * This function performs a fast fill of the given rectangle with 'color' | |
543 */ | |
544 int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) | |
545 { | |
546 SDL_VideoDevice *video = current_video; | |
547 SDL_VideoDevice *this = current_video; | |
548 int x, y; | |
549 Uint8 *row; | |
550 | |
532
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
551 /* This function doesn't work on surfaces < 8 bpp */ |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
552 if ( dst->format->BitsPerPixel < 8 ) { |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
553 switch(dst->format->BitsPerPixel) { |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
554 case 1: |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
555 return SDL_FillRect1(dst, dstrect, color); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
556 break; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
557 case 4: |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
558 return SDL_FillRect4(dst, dstrect, color); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
559 break; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
560 default: |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
561 SDL_SetError("Fill rect on unsupported surface format"); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
562 return(-1); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
563 break; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
564 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
565 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
566 |
0 | 567 /* If 'dstrect' == NULL, then fill the whole surface */ |
568 if ( dstrect ) { | |
569 /* Perform clipping */ | |
570 if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) { | |
571 return(0); | |
572 } | |
573 } else { | |
574 dstrect = &dst->clip_rect; | |
575 } | |
576 | |
577 /* Check for hardware acceleration */ | |
578 if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && | |
579 video->info.blit_fill ) { | |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
580 SDL_Rect hw_rect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
581 if ( dst == SDL_VideoSurface ) { |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
582 hw_rect = *dstrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
583 hw_rect.x += current_video->offset_x; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
584 hw_rect.y += current_video->offset_y; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
585 dstrect = &hw_rect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
586 } |
0 | 587 return(video->FillHWRect(this, dst, dstrect, color)); |
588 } | |
589 | |
590 /* Perform software fill */ | |
591 if ( SDL_LockSurface(dst) != 0 ) { | |
592 return(-1); | |
593 } | |
594 row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+ | |
595 dstrect->x*dst->format->BytesPerPixel; | |
596 if ( dst->format->palette || (color == 0) ) { | |
597 x = dstrect->w*dst->format->BytesPerPixel; | |
598 if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) { | |
599 int n = x >> 2; | |
600 for ( y=dstrect->h; y; --y ) { | |
601 SDL_memset4(row, 0, n); | |
602 row += dst->pitch; | |
603 } | |
604 } else { | |
605 #ifdef __powerpc__ | |
606 /* | |
607 * memset() on PPC (both glibc and codewarrior) uses | |
608 * the dcbz (Data Cache Block Zero) instruction, which | |
609 * causes an alignment exception if the destination is | |
610 * uncachable, so only use it on software surfaces | |
611 */ | |
612 if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { | |
613 if(dstrect->w >= 8) { | |
614 /* | |
615 * 64-bit stores are probably most | |
616 * efficient to uncached video memory | |
617 */ | |
618 double fill; | |
619 memset(&fill, color, (sizeof fill)); | |
620 for(y = dstrect->h; y; y--) { | |
621 Uint8 *d = row; | |
622 unsigned n = x; | |
623 unsigned nn; | |
624 Uint8 c = color; | |
625 double f = fill; | |
626 while((unsigned long)d | |
627 & (sizeof(double) - 1)) { | |
628 *d++ = c; | |
629 n--; | |
630 } | |
631 nn = n / (sizeof(double) * 4); | |
632 while(nn) { | |
633 ((double *)d)[0] = f; | |
634 ((double *)d)[1] = f; | |
635 ((double *)d)[2] = f; | |
636 ((double *)d)[3] = f; | |
637 d += 4*sizeof(double); | |
638 nn--; | |
639 } | |
640 n &= ~(sizeof(double) * 4 - 1); | |
641 nn = n / sizeof(double); | |
642 while(nn) { | |
643 *(double *)d = f; | |
644 d += sizeof(double); | |
645 nn--; | |
646 } | |
647 n &= ~(sizeof(double) - 1); | |
648 while(n) { | |
649 *d++ = c; | |
650 n--; | |
651 } | |
652 row += dst->pitch; | |
653 } | |
654 } else { | |
655 /* narrow boxes */ | |
656 for(y = dstrect->h; y; y--) { | |
657 Uint8 *d = row; | |
658 Uint8 c = color; | |
659 int n = x; | |
660 while(n) { | |
661 *d++ = c; | |
662 n--; | |
663 } | |
664 row += dst->pitch; | |
665 } | |
666 } | |
667 } else | |
668 #endif /* __powerpc__ */ | |
669 { | |
670 for(y = dstrect->h; y; y--) { | |
671 memset(row, color, x); | |
672 row += dst->pitch; | |
673 } | |
674 } | |
675 } | |
676 } else { | |
677 switch (dst->format->BytesPerPixel) { | |
678 case 2: | |
679 for ( y=dstrect->h; y; --y ) { | |
680 Uint16 *pixels = (Uint16 *)row; | |
681 Uint16 c = color; | |
682 Uint32 cc = (Uint32)c << 16 | c; | |
683 int n = dstrect->w; | |
684 if((unsigned long)pixels & 3) { | |
685 *pixels++ = c; | |
686 n--; | |
687 } | |
688 if(n >> 1) | |
689 SDL_memset4(pixels, cc, n >> 1); | |
690 if(n & 1) | |
691 pixels[n - 1] = c; | |
692 row += dst->pitch; | |
693 } | |
694 break; | |
695 | |
696 case 3: | |
697 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) | |
698 color <<= 8; | |
699 for ( y=dstrect->h; y; --y ) { | |
700 Uint8 *pixels = row; | |
701 for ( x=dstrect->w; x; --x ) { | |
702 memcpy(pixels, &color, 3); | |
703 pixels += 3; | |
704 } | |
705 row += dst->pitch; | |
706 } | |
707 break; | |
708 | |
709 case 4: | |
710 for(y = dstrect->h; y; --y) { | |
711 SDL_memset4(row, color, dstrect->w); | |
712 row += dst->pitch; | |
713 } | |
714 break; | |
715 } | |
716 } | |
717 SDL_UnlockSurface(dst); | |
718 | |
719 /* We're done! */ | |
720 return(0); | |
721 } | |
722 | |
723 /* | |
724 * Lock a surface to directly access the pixels | |
725 */ | |
726 int SDL_LockSurface (SDL_Surface *surface) | |
727 { | |
728 if ( ! surface->locked ) { | |
729 /* Perform the lock */ | |
730 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { | |
731 SDL_VideoDevice *video = current_video; | |
732 SDL_VideoDevice *this = current_video; | |
733 if ( video->LockHWSurface(this, surface) < 0 ) { | |
734 return(-1); | |
735 } | |
736 } | |
737 if ( surface->flags & SDL_RLEACCEL ) { | |
738 SDL_UnRLESurface(surface, 1); | |
739 surface->flags |= SDL_RLEACCEL; /* save accel'd state */ | |
740 } | |
741 /* This needs to be done here in case pixels changes value */ | |
742 surface->pixels = (Uint8 *)surface->pixels + surface->offset; | |
743 } | |
744 | |
745 /* Increment the surface lock count, for recursive locks */ | |
746 ++surface->locked; | |
747 | |
748 /* Ready to go.. */ | |
749 return(0); | |
750 } | |
751 /* | |
752 * Unlock a previously locked surface | |
753 */ | |
754 void SDL_UnlockSurface (SDL_Surface *surface) | |
755 { | |
756 /* Only perform an unlock if we are locked */ | |
757 if ( ! surface->locked || (--surface->locked > 0) ) { | |
758 return; | |
759 } | |
760 | |
761 /* Perform the unlock */ | |
762 surface->pixels = (Uint8 *)surface->pixels - surface->offset; | |
763 | |
764 /* Unlock hardware or accelerated surfaces */ | |
765 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { | |
766 SDL_VideoDevice *video = current_video; | |
767 SDL_VideoDevice *this = current_video; | |
768 video->UnlockHWSurface(this, surface); | |
769 } else { | |
770 /* Update RLE encoded surface with new data */ | |
771 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | |
772 surface->flags &= ~SDL_RLEACCEL; /* stop lying */ | |
773 SDL_RLESurface(surface); | |
774 } | |
775 } | |
776 } | |
777 | |
778 /* | |
779 * Convert a surface into the specified pixel format. | |
780 */ | |
781 SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface, | |
782 SDL_PixelFormat *format, Uint32 flags) | |
783 { | |
784 SDL_Surface *convert; | |
785 Uint32 colorkey = 0; | |
786 Uint8 alpha = 0; | |
787 Uint32 surface_flags; | |
788 SDL_Rect bounds; | |
789 | |
790 /* Check for empty destination palette! (results in empty image) */ | |
791 if ( format->palette != NULL ) { | |
792 int i; | |
793 for ( i=0; i<format->palette->ncolors; ++i ) { | |
794 if ( (format->palette->colors[i].r != 0) || | |
795 (format->palette->colors[i].g != 0) || | |
796 (format->palette->colors[i].b != 0) ) | |
797 break; | |
798 } | |
799 if ( i == format->palette->ncolors ) { | |
800 SDL_SetError("Empty destination palette"); | |
801 return(NULL); | |
802 } | |
803 } | |
804 | |
264
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
805 /* Only create hw surfaces with alpha channel if hw alpha blits |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
806 are supported */ |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
807 if(format->Amask != 0 && (flags & SDL_HWSURFACE)) { |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
808 const SDL_VideoInfo *vi = SDL_GetVideoInfo(); |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
809 if(!vi || !vi->blit_hw_A) |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
810 flags &= ~SDL_HWSURFACE; |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
811 } |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
812 |
0 | 813 /* Create a new surface with the desired format */ |
814 convert = SDL_CreateRGBSurface(flags, | |
815 surface->w, surface->h, format->BitsPerPixel, | |
816 format->Rmask, format->Gmask, format->Bmask, format->Amask); | |
817 if ( convert == NULL ) { | |
818 return(NULL); | |
819 } | |
820 | |
821 /* Copy the palette if any */ | |
822 if ( format->palette && convert->format->palette ) { | |
823 memcpy(convert->format->palette->colors, | |
824 format->palette->colors, | |
825 format->palette->ncolors*sizeof(SDL_Color)); | |
826 convert->format->palette->ncolors = format->palette->ncolors; | |
827 } | |
828 | |
829 /* Save the original surface color key and alpha */ | |
830 surface_flags = surface->flags; | |
831 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
832 /* Convert colourkeyed surfaces to RGBA if requested */ | |
833 if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY | |
834 && format->Amask) { | |
835 surface_flags &= ~SDL_SRCCOLORKEY; | |
836 } else { | |
837 colorkey = surface->format->colorkey; | |
838 SDL_SetColorKey(surface, 0, 0); | |
839 } | |
840 } | |
841 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
842 /* Copy over the alpha channel to RGBA if requested */ |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
843 if ( format->Amask ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
844 surface->flags &= ~SDL_SRCALPHA; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
845 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
846 alpha = surface->format->alpha; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
847 SDL_SetAlpha(surface, 0, 0); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
848 } |
0 | 849 } |
850 | |
851 /* Copy over the image data */ | |
852 bounds.x = 0; | |
853 bounds.y = 0; | |
854 bounds.w = surface->w; | |
855 bounds.h = surface->h; | |
856 SDL_LowerBlit(surface, &bounds, convert, &bounds); | |
857 | |
858 /* Clean up the original surface, and update converted surface */ | |
859 if ( convert != NULL ) { | |
860 SDL_SetClipRect(convert, &surface->clip_rect); | |
861 } | |
862 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
863 Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK); | |
864 if ( convert != NULL ) { | |
865 Uint8 keyR, keyG, keyB; | |
866 | |
867 SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); | |
868 SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK), | |
869 SDL_MapRGB(convert->format, keyR, keyG, keyB)); | |
870 } | |
871 SDL_SetColorKey(surface, cflags, colorkey); | |
872 } | |
873 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
874 Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK); | |
875 if ( convert != NULL ) { | |
876 SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK), | |
877 alpha); | |
878 } | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
879 if ( format->Amask ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
880 surface->flags |= SDL_SRCALPHA; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
881 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
882 SDL_SetAlpha(surface, aflags, alpha); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
883 } |
0 | 884 } |
885 | |
886 /* We're ready to go! */ | |
887 return(convert); | |
888 } | |
889 | |
890 /* | |
891 * Free a surface created by the above function. | |
892 */ | |
893 void SDL_FreeSurface (SDL_Surface *surface) | |
894 { | |
895 /* Free anything that's not NULL, and not the screen surface */ | |
896 if ((surface == NULL) || | |
897 (current_video && | |
898 ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) { | |
899 return; | |
900 } | |
901 if ( --surface->refcount > 0 ) { | |
902 return; | |
903 } | |
904 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | |
905 SDL_UnRLESurface(surface, 0); | |
906 } | |
907 if ( surface->format ) { | |
908 SDL_FreeFormat(surface->format); | |
909 surface->format = NULL; | |
910 } | |
911 if ( surface->map != NULL ) { | |
912 SDL_FreeBlitMap(surface->map); | |
913 surface->map = NULL; | |
914 } | |
422
b1b9ee41be70
Memory leak fix for DirectX software surfaces
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
915 if ( surface->hwdata ) { |
0 | 916 SDL_VideoDevice *video = current_video; |
917 SDL_VideoDevice *this = current_video; | |
918 video->FreeHWSurface(this, surface); | |
919 } | |
920 if ( surface->pixels && | |
921 ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) { | |
922 free(surface->pixels); | |
923 } | |
924 free(surface); | |
925 #ifdef CHECK_LEAKS | |
926 --surfaces_allocated; | |
927 #endif | |
928 } |