Mercurial > sdl-ios-xcode
annotate src/video/SDL_surface.c @ 1192:54aa9aa32327
To: sdl@libsdl.org
From: Christian Walther <cwalther@gmx.ch>
Date: Fri, 18 Nov 2005 23:39:02 +0100
Subject: [SDL] Mouse position bugs on Mac OS X
The attached patch fixes a few bugs in SDL related to the mouse position
in windowed mode on Mac OS X, reproduced using the attached minimal test
program - at least here on 10.3.9, with SDL CVS from today. Could anyone
test whether the bugs exist and are fixed by the patch on 10.2 and 10.4?
1. When using OpenGL, the vertical mouse positions obtained through
events or SDL_GetMouseState() are off by one.
2. When using OpenGL, SDL_WarpMouse() inverts the y coordinate.
3. Clicks on the topmost pixel row of the window are not recognized.
1 and 2 do not occur in non-OpenGL mode, while 3 does. All three only
occur in windowed mode, not in fullscreen.
The cause for 1 and 3 is that in Cocoa, "the location of the mouse"
seems to be defined as "the location of the top left corner of the mouse
pointer's hot pixel" (this is not documented, it's just what I found out
here), which together with the fact that Cocoa's usual y coordinates
start at the bottom and increase upwards means that the y coordinate of
the mouse runs from 1 to h, not from 0 to h-1, in a window of height h.
If it does work on 10.2 and 10.4 (I'll try to test it as soon as I can,
but at the moment all I have at hand is 10.3.9), can this be applied to
the CVS?
-Christian
To: sdl@libsdl.org
From: Christian Walther <cwalther@gmx.ch>
Date: Mon, 28 Nov 2005 10:41:51 +0100
Subject: [SDL] Re: Mouse position bugs on Mac OS X
I wrote:
> I'll try to test it as soon as I can, but at the moment all I have at hand is 10.3.9
So, here are the results of my tests (with patched and unpatched
frameworks compiled with Xcode 1.5 (gcc 3.3) on 10.3.9):
On 10.1.5, my test program doesn't run because of "Undefined symbols:
SDL undefined reference to _CGMainDisplayID expected to be defined in
Carbon". I guess not supporting 10.1 was a deliberate decision then and
that's OK with me.
On 10.2.8, 10.3.9, and 10.4.0, the bugs exist as described in my
original post and are fixed by my patch. That is, there is no difference
between pre/post 10.3 and the patched version works correctly in all
combinations of GL/non-GL and windowed/fullscreen.
I therefore recommend the patch for inclusion.
-Christian
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Mon, 28 Nov 2005 13:58:26 +0000 |
parents | 91569ec25acd |
children | 86d0d01290ea |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
532
diff
changeset
|
3 Copyright (C) 1997-2004 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 | |
940
bb1588ebe47b
Date: Sat, 10 Jul 2004 21:02:33 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
915
diff
changeset
|
55 /* Make sure the size requested doesn't overflow our datatypes */ |
bb1588ebe47b
Date: Sat, 10 Jul 2004 21:02:33 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
915
diff
changeset
|
56 /* Next time I write a library like SDL, I'll use int for size. :) */ |
1017
c2f2370ac1e5
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
940
diff
changeset
|
57 if ( width >= 16384 || height >= 65536 ) { |
940
bb1588ebe47b
Date: Sat, 10 Jul 2004 21:02:33 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
915
diff
changeset
|
58 SDL_SetError("Width or height is too large"); |
bb1588ebe47b
Date: Sat, 10 Jul 2004 21:02:33 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
915
diff
changeset
|
59 return(NULL); |
bb1588ebe47b
Date: Sat, 10 Jul 2004 21:02:33 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
915
diff
changeset
|
60 } |
bb1588ebe47b
Date: Sat, 10 Jul 2004 21:02:33 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
915
diff
changeset
|
61 |
0 | 62 /* Check to see if we desire the surface in video memory */ |
63 if ( video ) { | |
64 screen = SDL_PublicSurface; | |
65 } else { | |
66 screen = NULL; | |
67 } | |
68 if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) { | |
69 if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) { | |
70 flags |= SDL_HWSURFACE; | |
71 } | |
72 if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
73 if ( ! current_video->info.blit_hw_CC ) { | |
74 flags &= ~SDL_HWSURFACE; | |
75 } | |
76 } | |
77 if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
78 if ( ! current_video->info.blit_hw_A ) { | |
79 flags &= ~SDL_HWSURFACE; | |
80 } | |
81 } | |
82 } else { | |
83 flags &= ~SDL_HWSURFACE; | |
84 } | |
85 | |
86 /* Allocate the surface */ | |
87 surface = (SDL_Surface *)malloc(sizeof(*surface)); | |
88 if ( surface == NULL ) { | |
89 SDL_OutOfMemory(); | |
90 return(NULL); | |
91 } | |
92 surface->flags = SDL_SWSURFACE; | |
93 if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { | |
1052
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
94 if ((Amask) && (video->displayformatalphapixel)) |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
95 { |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
96 depth = video->displayformatalphapixel->BitsPerPixel; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
97 Rmask = video->displayformatalphapixel->Rmask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
98 Gmask = video->displayformatalphapixel->Gmask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
99 Bmask = video->displayformatalphapixel->Bmask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
100 Amask = video->displayformatalphapixel->Amask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
101 } |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
102 else |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
103 { |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
104 depth = screen->format->BitsPerPixel; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
105 Rmask = screen->format->Rmask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
106 Gmask = screen->format->Gmask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
107 Bmask = screen->format->Bmask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
108 Amask = screen->format->Amask; |
68f607298ca9
Some work on using accelerated alpha blits with hardware surfaces.
Ryan C. Gordon <icculus@icculus.org>
parents:
1017
diff
changeset
|
109 } |
0 | 110 } |
111 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); | |
112 if ( surface->format == NULL ) { | |
113 free(surface); | |
114 return(NULL); | |
115 } | |
116 if ( Amask ) { | |
117 surface->flags |= SDL_SRCALPHA; | |
118 } | |
119 surface->w = width; | |
120 surface->h = height; | |
121 surface->pitch = SDL_CalculatePitch(surface); | |
122 surface->pixels = NULL; | |
123 surface->offset = 0; | |
124 surface->hwdata = NULL; | |
125 surface->locked = 0; | |
126 surface->map = NULL; | |
441
598b25b9bffe
Zeroed out SDL_Surface::unused1 so glSDL will work on stock SDL
Sam Lantinga <slouken@libsdl.org>
parents:
431
diff
changeset
|
127 surface->unused1 = 0; |
0 | 128 SDL_SetClipRect(surface, NULL); |
845
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
129 SDL_FormatChanged(surface); |
0 | 130 |
131 /* Get the pixels */ | |
132 if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || | |
133 (video->AllocHWSurface(this, surface) < 0) ) { | |
134 if ( surface->w && surface->h ) { | |
135 surface->pixels = malloc(surface->h*surface->pitch); | |
136 if ( surface->pixels == NULL ) { | |
137 SDL_FreeSurface(surface); | |
138 SDL_OutOfMemory(); | |
139 return(NULL); | |
140 } | |
141 /* This is important for bitmaps */ | |
142 memset(surface->pixels, 0, surface->h*surface->pitch); | |
143 } | |
144 } | |
145 | |
146 /* Allocate an empty mapping */ | |
147 surface->map = SDL_AllocBlitMap(); | |
148 if ( surface->map == NULL ) { | |
149 SDL_FreeSurface(surface); | |
150 return(NULL); | |
151 } | |
152 | |
153 /* The surface is ready to go */ | |
154 surface->refcount = 1; | |
155 #ifdef CHECK_LEAKS | |
156 ++surfaces_allocated; | |
157 #endif | |
158 return(surface); | |
159 } | |
160 /* | |
161 * Create an RGB surface from an existing memory buffer | |
162 */ | |
163 SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels, | |
164 int width, int height, int depth, int pitch, | |
165 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) | |
166 { | |
167 SDL_Surface *surface; | |
168 | |
169 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth, | |
170 Rmask, Gmask, Bmask, Amask); | |
171 if ( surface != NULL ) { | |
172 surface->flags |= SDL_PREALLOC; | |
173 surface->pixels = pixels; | |
174 surface->w = width; | |
175 surface->h = height; | |
176 surface->pitch = pitch; | |
177 SDL_SetClipRect(surface, NULL); | |
178 } | |
179 return(surface); | |
180 } | |
181 /* | |
182 * Set the color key in a blittable surface | |
183 */ | |
184 int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key) | |
185 { | |
186 /* Sanity check the flag as it gets passed in */ | |
187 if ( flag & SDL_SRCCOLORKEY ) { | |
188 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { | |
189 flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); | |
190 } else { | |
191 flag = SDL_SRCCOLORKEY; | |
192 } | |
193 } else { | |
194 flag = 0; | |
195 } | |
196 | |
197 /* Optimize away operations that don't change anything */ | |
198 if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) && | |
199 (key == surface->format->colorkey) ) { | |
200 return(0); | |
201 } | |
202 | |
203 /* UnRLE surfaces before we change the colorkey */ | |
204 if ( surface->flags & SDL_RLEACCEL ) { | |
205 SDL_UnRLESurface(surface, 1); | |
206 } | |
207 | |
208 if ( flag ) { | |
209 SDL_VideoDevice *video = current_video; | |
210 SDL_VideoDevice *this = current_video; | |
211 | |
212 | |
213 surface->flags |= SDL_SRCCOLORKEY; | |
214 surface->format->colorkey = key; | |
215 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { | |
216 if ( (video->SetHWColorKey == NULL) || | |
217 (video->SetHWColorKey(this, surface, key) < 0) ) { | |
218 surface->flags &= ~SDL_HWACCEL; | |
219 } | |
220 } | |
221 if ( flag & SDL_RLEACCELOK ) { | |
222 surface->flags |= SDL_RLEACCELOK; | |
223 } else { | |
224 surface->flags &= ~SDL_RLEACCELOK; | |
225 } | |
226 } else { | |
227 surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK); | |
228 surface->format->colorkey = 0; | |
229 } | |
230 SDL_InvalidateMap(surface->map); | |
231 return(0); | |
232 } | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
233 /* This function sets the alpha channel of a surface */ |
0 | 234 int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value) |
235 { | |
236 Uint32 oldflags = surface->flags; | |
237 Uint32 oldalpha = surface->format->alpha; | |
238 | |
239 /* Sanity check the flag as it gets passed in */ | |
240 if ( flag & SDL_SRCALPHA ) { | |
241 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { | |
242 flag = (SDL_SRCALPHA | SDL_RLEACCELOK); | |
243 } else { | |
244 flag = SDL_SRCALPHA; | |
245 } | |
246 } else { | |
247 flag = 0; | |
248 } | |
249 | |
250 /* Optimize away operations that don't change anything */ | |
251 if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) && | |
252 (!flag || value == oldalpha) ) { | |
253 return(0); | |
254 } | |
255 | |
256 if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) | |
257 SDL_UnRLESurface(surface, 1); | |
258 | |
259 if ( flag ) { | |
260 SDL_VideoDevice *video = current_video; | |
261 SDL_VideoDevice *this = current_video; | |
262 | |
263 surface->flags |= SDL_SRCALPHA; | |
264 surface->format->alpha = value; | |
265 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { | |
266 if ( (video->SetHWAlpha == NULL) || | |
267 (video->SetHWAlpha(this, surface, value) < 0) ) { | |
268 surface->flags &= ~SDL_HWACCEL; | |
269 } | |
270 } | |
271 if ( flag & SDL_RLEACCELOK ) { | |
272 surface->flags |= SDL_RLEACCELOK; | |
273 } else { | |
274 surface->flags &= ~SDL_RLEACCELOK; | |
275 } | |
276 } else { | |
277 surface->flags &= ~SDL_SRCALPHA; | |
278 surface->format->alpha = SDL_ALPHA_OPAQUE; | |
279 } | |
280 /* | |
281 * The representation for software surfaces is independent of | |
282 * per-surface alpha, so no need to invalidate the blit mapping | |
283 * if just the alpha value was changed. (If either is 255, we still | |
284 * need to invalidate.) | |
285 */ | |
286 if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL | |
287 || oldflags != surface->flags | |
288 || (((oldalpha + 1) ^ (value + 1)) & 0x100)) | |
289 SDL_InvalidateMap(surface->map); | |
290 return(0); | |
291 } | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
292 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
|
293 { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
294 int row, col; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
295 int offset; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
296 Uint8 *buf; |
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 if ( (surface->format->Amask != 0xFF000000) && |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
299 (surface->format->Amask != 0x000000FF) ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
300 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
|
301 return -1; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
302 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
303 |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
304 #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
305 if ( surface->format->Amask == 0xFF000000 ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
306 offset = 3; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
307 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
308 offset = 0; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
309 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
310 #else |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
311 if ( surface->format->Amask == 0xFF000000 ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
312 offset = 0; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
313 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
314 offset = 3; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
315 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
316 #endif /* Byte ordering */ |
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 /* 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
|
319 if ( SDL_MUSTLOCK(surface) ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
320 if ( SDL_LockSurface(surface) < 0 ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
321 return -1; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
322 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
323 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
324 row = surface->h; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
325 while (row--) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
326 col = surface->w; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
327 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
|
328 while(col--) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
329 *buf = value; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
330 buf += 4; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
331 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
332 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
333 if ( SDL_MUSTLOCK(surface) ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
334 SDL_UnlockSurface(surface); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
335 } |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
336 return 0; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
337 } |
0 | 338 |
339 /* | |
340 * A function to calculate the intersection of two rectangles: | |
341 * return true if the rectangles intersect, false otherwise | |
342 */ | |
343 static __inline__ | |
130
14af14ff7c19
The rectangle argument to SDL_SetClipRect is really const
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
344 SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection) |
0 | 345 { |
346 int Amin, Amax, Bmin, Bmax; | |
347 | |
348 /* Horizontal intersection */ | |
349 Amin = A->x; | |
350 Amax = Amin + A->w; | |
351 Bmin = B->x; | |
352 Bmax = Bmin + B->w; | |
353 if(Bmin > Amin) | |
354 Amin = Bmin; | |
355 intersection->x = Amin; | |
356 if(Bmax < Amax) | |
357 Amax = Bmax; | |
358 intersection->w = Amax - Amin > 0 ? Amax - Amin : 0; | |
359 | |
360 /* Vertical intersection */ | |
361 Amin = A->y; | |
362 Amax = Amin + A->h; | |
363 Bmin = B->y; | |
364 Bmax = Bmin + B->h; | |
365 if(Bmin > Amin) | |
366 Amin = Bmin; | |
367 intersection->y = Amin; | |
368 if(Bmax < Amax) | |
369 Amax = Bmax; | |
370 intersection->h = Amax - Amin > 0 ? Amax - Amin : 0; | |
371 | |
372 return (intersection->w && intersection->h); | |
373 } | |
374 /* | |
375 * Set the clipping rectangle for a blittable surface | |
376 */ | |
130
14af14ff7c19
The rectangle argument to SDL_SetClipRect is really const
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
377 SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect) |
0 | 378 { |
379 SDL_Rect full_rect; | |
380 | |
381 /* Don't do anything if there's no surface to act on */ | |
382 if ( ! surface ) { | |
383 return SDL_FALSE; | |
384 } | |
385 | |
386 /* Set up the full surface rectangle */ | |
387 full_rect.x = 0; | |
388 full_rect.y = 0; | |
389 full_rect.w = surface->w; | |
390 full_rect.h = surface->h; | |
391 | |
392 /* Set the clipping rectangle */ | |
393 if ( ! rect ) { | |
394 surface->clip_rect = full_rect; | |
395 return 1; | |
396 } | |
397 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); | |
398 } | |
399 void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect) | |
400 { | |
401 if ( surface && rect ) { | |
402 *rect = surface->clip_rect; | |
403 } | |
404 } | |
405 /* | |
406 * Set up a blit between two surfaces -- split into three parts: | |
407 * The upper part, SDL_UpperBlit(), performs clipping and rectangle | |
408 * verification. The lower part is a pointer to a low level | |
409 * accelerated blitting function. | |
410 * | |
411 * These parts are separated out and each used internally by this | |
412 * library in the optimimum places. They are exported so that if | |
413 * you know exactly what you are doing, you can optimize your code | |
414 * by calling the one(s) you need. | |
415 */ | |
416 int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect, | |
417 SDL_Surface *dst, SDL_Rect *dstrect) | |
418 { | |
419 SDL_blit do_blit; | |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
420 SDL_Rect hw_srcrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
421 SDL_Rect hw_dstrect; |
0 | 422 |
423 /* Check to make sure the blit mapping is valid */ | |
424 if ( (src->map->dst != dst) || | |
425 (src->map->dst->format_version != src->map->format_version) ) { | |
426 if ( SDL_MapSurface(src, dst) < 0 ) { | |
427 return(-1); | |
428 } | |
429 } | |
430 | |
431 /* Figure out which blitter to use */ | |
432 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
|
433 if ( src == SDL_VideoSurface ) { |
519
c7da0cd5ae5e
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
462
diff
changeset
|
434 hw_srcrect = *srcrect; |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
435 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
|
436 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
|
437 srcrect = &hw_srcrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
438 } |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
439 if ( dst == SDL_VideoSurface ) { |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
440 hw_dstrect = *dstrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
441 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
|
442 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
|
443 dstrect = &hw_dstrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
444 } |
0 | 445 do_blit = src->map->hw_blit; |
446 } else { | |
447 do_blit = src->map->sw_blit; | |
448 } | |
449 return(do_blit(src, srcrect, dst, dstrect)); | |
450 } | |
451 | |
452 | |
453 int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect, | |
454 SDL_Surface *dst, SDL_Rect *dstrect) | |
455 { | |
456 SDL_Rect fulldst; | |
457 int srcx, srcy, w, h; | |
458 | |
459 /* Make sure the surfaces aren't locked */ | |
460 if ( ! src || ! dst ) { | |
461 SDL_SetError("SDL_UpperBlit: passed a NULL surface"); | |
462 return(-1); | |
463 } | |
464 if ( src->locked || dst->locked ) { | |
465 SDL_SetError("Surfaces must not be locked during blit"); | |
466 return(-1); | |
467 } | |
468 | |
469 /* If the destination rectangle is NULL, use the entire dest surface */ | |
470 if ( dstrect == NULL ) { | |
471 fulldst.x = fulldst.y = 0; | |
472 dstrect = &fulldst; | |
473 } | |
474 | |
475 /* clip the source rectangle to the source surface */ | |
476 if(srcrect) { | |
477 int maxw, maxh; | |
478 | |
479 srcx = srcrect->x; | |
480 w = srcrect->w; | |
481 if(srcx < 0) { | |
482 w += srcx; | |
483 dstrect->x -= srcx; | |
484 srcx = 0; | |
485 } | |
486 maxw = src->w - srcx; | |
487 if(maxw < w) | |
488 w = maxw; | |
489 | |
490 srcy = srcrect->y; | |
491 h = srcrect->h; | |
492 if(srcy < 0) { | |
493 h += srcy; | |
494 dstrect->y -= srcy; | |
495 srcy = 0; | |
496 } | |
497 maxh = src->h - srcy; | |
498 if(maxh < h) | |
499 h = maxh; | |
500 | |
501 } else { | |
502 srcx = srcy = 0; | |
503 w = src->w; | |
504 h = src->h; | |
505 } | |
506 | |
507 /* clip the destination rectangle against the clip rectangle */ | |
508 { | |
509 SDL_Rect *clip = &dst->clip_rect; | |
510 int dx, dy; | |
511 | |
512 dx = clip->x - dstrect->x; | |
513 if(dx > 0) { | |
514 w -= dx; | |
515 dstrect->x += dx; | |
516 srcx += dx; | |
517 } | |
518 dx = dstrect->x + w - clip->x - clip->w; | |
519 if(dx > 0) | |
520 w -= dx; | |
521 | |
522 dy = clip->y - dstrect->y; | |
523 if(dy > 0) { | |
524 h -= dy; | |
525 dstrect->y += dy; | |
526 srcy += dy; | |
527 } | |
528 dy = dstrect->y + h - clip->y - clip->h; | |
529 if(dy > 0) | |
530 h -= dy; | |
531 } | |
532 | |
533 if(w > 0 && h > 0) { | |
534 SDL_Rect sr; | |
535 sr.x = srcx; | |
536 sr.y = srcy; | |
537 sr.w = dstrect->w = w; | |
538 sr.h = dstrect->h = h; | |
539 return SDL_LowerBlit(src, &sr, dst, dstrect); | |
540 } | |
541 dstrect->w = dstrect->h = 0; | |
542 return 0; | |
543 } | |
544 | |
532
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
545 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
|
546 { |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
547 /* 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
|
548 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
|
549 return -1; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
550 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
551 |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
552 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
|
553 { |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
554 /* 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
|
555 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
|
556 return -1; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
557 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
558 |
0 | 559 /* |
560 * This function performs a fast fill of the given rectangle with 'color' | |
561 */ | |
562 int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) | |
563 { | |
564 SDL_VideoDevice *video = current_video; | |
565 SDL_VideoDevice *this = current_video; | |
566 int x, y; | |
567 Uint8 *row; | |
568 | |
532
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
569 /* 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
|
570 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
|
571 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
|
572 case 1: |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
573 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
|
574 break; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
575 case 4: |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
576 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
|
577 break; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
578 default: |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
579 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
|
580 return(-1); |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
581 break; |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
582 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
583 } |
058d47b7a3b4
Return an error with color fills on less than 8 bpp surfaces.
Sam Lantinga <slouken@libsdl.org>
parents:
526
diff
changeset
|
584 |
0 | 585 /* If 'dstrect' == NULL, then fill the whole surface */ |
586 if ( dstrect ) { | |
587 /* Perform clipping */ | |
588 if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) { | |
589 return(0); | |
590 } | |
591 } else { | |
592 dstrect = &dst->clip_rect; | |
593 } | |
594 | |
595 /* Check for hardware acceleration */ | |
596 if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && | |
597 video->info.blit_fill ) { | |
462
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
598 SDL_Rect hw_rect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
599 if ( dst == SDL_VideoSurface ) { |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
600 hw_rect = *dstrect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
601 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
|
602 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
|
603 dstrect = &hw_rect; |
1be0cdaf8092
Fixed offset bug in hardware accelerated fills and blits
Sam Lantinga <slouken@libsdl.org>
parents:
441
diff
changeset
|
604 } |
0 | 605 return(video->FillHWRect(this, dst, dstrect, color)); |
606 } | |
607 | |
608 /* Perform software fill */ | |
609 if ( SDL_LockSurface(dst) != 0 ) { | |
610 return(-1); | |
611 } | |
612 row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+ | |
613 dstrect->x*dst->format->BytesPerPixel; | |
614 if ( dst->format->palette || (color == 0) ) { | |
615 x = dstrect->w*dst->format->BytesPerPixel; | |
616 if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) { | |
617 int n = x >> 2; | |
618 for ( y=dstrect->h; y; --y ) { | |
619 SDL_memset4(row, 0, n); | |
620 row += dst->pitch; | |
621 } | |
622 } else { | |
623 #ifdef __powerpc__ | |
624 /* | |
625 * memset() on PPC (both glibc and codewarrior) uses | |
626 * the dcbz (Data Cache Block Zero) instruction, which | |
627 * causes an alignment exception if the destination is | |
628 * uncachable, so only use it on software surfaces | |
629 */ | |
630 if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { | |
631 if(dstrect->w >= 8) { | |
632 /* | |
633 * 64-bit stores are probably most | |
634 * efficient to uncached video memory | |
635 */ | |
636 double fill; | |
637 memset(&fill, color, (sizeof fill)); | |
638 for(y = dstrect->h; y; y--) { | |
639 Uint8 *d = row; | |
640 unsigned n = x; | |
641 unsigned nn; | |
642 Uint8 c = color; | |
643 double f = fill; | |
644 while((unsigned long)d | |
645 & (sizeof(double) - 1)) { | |
646 *d++ = c; | |
647 n--; | |
648 } | |
649 nn = n / (sizeof(double) * 4); | |
650 while(nn) { | |
651 ((double *)d)[0] = f; | |
652 ((double *)d)[1] = f; | |
653 ((double *)d)[2] = f; | |
654 ((double *)d)[3] = f; | |
655 d += 4*sizeof(double); | |
656 nn--; | |
657 } | |
658 n &= ~(sizeof(double) * 4 - 1); | |
659 nn = n / sizeof(double); | |
660 while(nn) { | |
661 *(double *)d = f; | |
662 d += sizeof(double); | |
663 nn--; | |
664 } | |
665 n &= ~(sizeof(double) - 1); | |
666 while(n) { | |
667 *d++ = c; | |
668 n--; | |
669 } | |
670 row += dst->pitch; | |
671 } | |
672 } else { | |
673 /* narrow boxes */ | |
674 for(y = dstrect->h; y; y--) { | |
675 Uint8 *d = row; | |
676 Uint8 c = color; | |
677 int n = x; | |
678 while(n) { | |
679 *d++ = c; | |
680 n--; | |
681 } | |
682 row += dst->pitch; | |
683 } | |
684 } | |
685 } else | |
686 #endif /* __powerpc__ */ | |
687 { | |
688 for(y = dstrect->h; y; y--) { | |
689 memset(row, color, x); | |
690 row += dst->pitch; | |
691 } | |
692 } | |
693 } | |
694 } else { | |
695 switch (dst->format->BytesPerPixel) { | |
696 case 2: | |
697 for ( y=dstrect->h; y; --y ) { | |
698 Uint16 *pixels = (Uint16 *)row; | |
699 Uint16 c = color; | |
700 Uint32 cc = (Uint32)c << 16 | c; | |
701 int n = dstrect->w; | |
702 if((unsigned long)pixels & 3) { | |
703 *pixels++ = c; | |
704 n--; | |
705 } | |
706 if(n >> 1) | |
707 SDL_memset4(pixels, cc, n >> 1); | |
708 if(n & 1) | |
709 pixels[n - 1] = c; | |
710 row += dst->pitch; | |
711 } | |
712 break; | |
713 | |
714 case 3: | |
1155
91569ec25acd
Fixed some compiler warnings about "unreachable code" on Watcom C.
Ryan C. Gordon <icculus@icculus.org>
parents:
1052
diff
changeset
|
715 #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
0 | 716 color <<= 8; |
1155
91569ec25acd
Fixed some compiler warnings about "unreachable code" on Watcom C.
Ryan C. Gordon <icculus@icculus.org>
parents:
1052
diff
changeset
|
717 #endif |
0 | 718 for ( y=dstrect->h; y; --y ) { |
719 Uint8 *pixels = row; | |
720 for ( x=dstrect->w; x; --x ) { | |
721 memcpy(pixels, &color, 3); | |
722 pixels += 3; | |
723 } | |
724 row += dst->pitch; | |
725 } | |
726 break; | |
727 | |
728 case 4: | |
729 for(y = dstrect->h; y; --y) { | |
730 SDL_memset4(row, color, dstrect->w); | |
731 row += dst->pitch; | |
732 } | |
733 break; | |
734 } | |
735 } | |
736 SDL_UnlockSurface(dst); | |
737 | |
738 /* We're done! */ | |
739 return(0); | |
740 } | |
741 | |
742 /* | |
743 * Lock a surface to directly access the pixels | |
744 */ | |
745 int SDL_LockSurface (SDL_Surface *surface) | |
746 { | |
747 if ( ! surface->locked ) { | |
748 /* Perform the lock */ | |
749 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { | |
750 SDL_VideoDevice *video = current_video; | |
751 SDL_VideoDevice *this = current_video; | |
752 if ( video->LockHWSurface(this, surface) < 0 ) { | |
753 return(-1); | |
754 } | |
755 } | |
756 if ( surface->flags & SDL_RLEACCEL ) { | |
757 SDL_UnRLESurface(surface, 1); | |
758 surface->flags |= SDL_RLEACCEL; /* save accel'd state */ | |
759 } | |
760 /* This needs to be done here in case pixels changes value */ | |
761 surface->pixels = (Uint8 *)surface->pixels + surface->offset; | |
762 } | |
763 | |
764 /* Increment the surface lock count, for recursive locks */ | |
765 ++surface->locked; | |
766 | |
767 /* Ready to go.. */ | |
768 return(0); | |
769 } | |
770 /* | |
771 * Unlock a previously locked surface | |
772 */ | |
773 void SDL_UnlockSurface (SDL_Surface *surface) | |
774 { | |
775 /* Only perform an unlock if we are locked */ | |
776 if ( ! surface->locked || (--surface->locked > 0) ) { | |
777 return; | |
778 } | |
779 | |
780 /* Perform the unlock */ | |
781 surface->pixels = (Uint8 *)surface->pixels - surface->offset; | |
782 | |
783 /* Unlock hardware or accelerated surfaces */ | |
784 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { | |
785 SDL_VideoDevice *video = current_video; | |
786 SDL_VideoDevice *this = current_video; | |
787 video->UnlockHWSurface(this, surface); | |
788 } else { | |
789 /* Update RLE encoded surface with new data */ | |
790 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | |
791 surface->flags &= ~SDL_RLEACCEL; /* stop lying */ | |
792 SDL_RLESurface(surface); | |
793 } | |
794 } | |
795 } | |
796 | |
797 /* | |
798 * Convert a surface into the specified pixel format. | |
799 */ | |
800 SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface, | |
801 SDL_PixelFormat *format, Uint32 flags) | |
802 { | |
803 SDL_Surface *convert; | |
804 Uint32 colorkey = 0; | |
805 Uint8 alpha = 0; | |
806 Uint32 surface_flags; | |
807 SDL_Rect bounds; | |
808 | |
809 /* Check for empty destination palette! (results in empty image) */ | |
810 if ( format->palette != NULL ) { | |
811 int i; | |
812 for ( i=0; i<format->palette->ncolors; ++i ) { | |
813 if ( (format->palette->colors[i].r != 0) || | |
814 (format->palette->colors[i].g != 0) || | |
815 (format->palette->colors[i].b != 0) ) | |
816 break; | |
817 } | |
818 if ( i == format->palette->ncolors ) { | |
819 SDL_SetError("Empty destination palette"); | |
820 return(NULL); | |
821 } | |
822 } | |
823 | |
264
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
824 /* Only create hw surfaces with alpha channel if hw alpha blits |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
825 are supported */ |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
826 if(format->Amask != 0 && (flags & SDL_HWSURFACE)) { |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
827 const SDL_VideoInfo *vi = SDL_GetVideoInfo(); |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
828 if(!vi || !vi->blit_hw_A) |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
829 flags &= ~SDL_HWSURFACE; |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
830 } |
c9cd3b564e4b
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
831 |
0 | 832 /* Create a new surface with the desired format */ |
833 convert = SDL_CreateRGBSurface(flags, | |
834 surface->w, surface->h, format->BitsPerPixel, | |
835 format->Rmask, format->Gmask, format->Bmask, format->Amask); | |
836 if ( convert == NULL ) { | |
837 return(NULL); | |
838 } | |
839 | |
840 /* Copy the palette if any */ | |
841 if ( format->palette && convert->format->palette ) { | |
842 memcpy(convert->format->palette->colors, | |
843 format->palette->colors, | |
844 format->palette->ncolors*sizeof(SDL_Color)); | |
845 convert->format->palette->ncolors = format->palette->ncolors; | |
846 } | |
847 | |
848 /* Save the original surface color key and alpha */ | |
849 surface_flags = surface->flags; | |
850 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
851 /* Convert colourkeyed surfaces to RGBA if requested */ | |
852 if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY | |
853 && format->Amask) { | |
854 surface_flags &= ~SDL_SRCCOLORKEY; | |
855 } else { | |
856 colorkey = surface->format->colorkey; | |
857 SDL_SetColorKey(surface, 0, 0); | |
858 } | |
859 } | |
860 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
|
861 /* 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
|
862 if ( format->Amask ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
863 surface->flags &= ~SDL_SRCALPHA; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
864 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
865 alpha = surface->format->alpha; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
866 SDL_SetAlpha(surface, 0, 0); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
867 } |
0 | 868 } |
869 | |
870 /* Copy over the image data */ | |
871 bounds.x = 0; | |
872 bounds.y = 0; | |
873 bounds.w = surface->w; | |
874 bounds.h = surface->h; | |
875 SDL_LowerBlit(surface, &bounds, convert, &bounds); | |
876 | |
877 /* Clean up the original surface, and update converted surface */ | |
878 if ( convert != NULL ) { | |
879 SDL_SetClipRect(convert, &surface->clip_rect); | |
880 } | |
881 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
882 Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK); | |
883 if ( convert != NULL ) { | |
884 Uint8 keyR, keyG, keyB; | |
885 | |
886 SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); | |
887 SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK), | |
888 SDL_MapRGB(convert->format, keyR, keyG, keyB)); | |
889 } | |
890 SDL_SetColorKey(surface, cflags, colorkey); | |
891 } | |
892 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
893 Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK); | |
894 if ( convert != NULL ) { | |
895 SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK), | |
896 alpha); | |
897 } | |
431
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
898 if ( format->Amask ) { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
899 surface->flags |= SDL_SRCALPHA; |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
900 } else { |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
901 SDL_SetAlpha(surface, aflags, alpha); |
41cadcba32e8
Fixed SDL_DisplayFormatAlpha() on RGB surfaces with alpha
Sam Lantinga <slouken@libsdl.org>
parents:
422
diff
changeset
|
902 } |
0 | 903 } |
904 | |
905 /* We're ready to go! */ | |
906 return(convert); | |
907 } | |
908 | |
909 /* | |
910 * Free a surface created by the above function. | |
911 */ | |
912 void SDL_FreeSurface (SDL_Surface *surface) | |
913 { | |
914 /* Free anything that's not NULL, and not the screen surface */ | |
915 if ((surface == NULL) || | |
916 (current_video && | |
917 ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) { | |
918 return; | |
919 } | |
920 if ( --surface->refcount > 0 ) { | |
921 return; | |
922 } | |
915
01cddd0f2efb
You can't free locked surfaces!
Sam Lantinga <slouken@libsdl.org>
parents:
845
diff
changeset
|
923 while ( surface->locked > 0 ) { |
01cddd0f2efb
You can't free locked surfaces!
Sam Lantinga <slouken@libsdl.org>
parents:
845
diff
changeset
|
924 SDL_UnlockSurface(surface); |
01cddd0f2efb
You can't free locked surfaces!
Sam Lantinga <slouken@libsdl.org>
parents:
845
diff
changeset
|
925 } |
0 | 926 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { |
927 SDL_UnRLESurface(surface, 0); | |
928 } | |
929 if ( surface->format ) { | |
930 SDL_FreeFormat(surface->format); | |
931 surface->format = NULL; | |
932 } | |
933 if ( surface->map != NULL ) { | |
934 SDL_FreeBlitMap(surface->map); | |
935 surface->map = NULL; | |
936 } | |
422
b1b9ee41be70
Memory leak fix for DirectX software surfaces
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
937 if ( surface->hwdata ) { |
0 | 938 SDL_VideoDevice *video = current_video; |
939 SDL_VideoDevice *this = current_video; | |
940 video->FreeHWSurface(this, surface); | |
941 } | |
942 if ( surface->pixels && | |
943 ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) { | |
944 free(surface->pixels); | |
945 } | |
946 free(surface); | |
947 #ifdef CHECK_LEAKS | |
948 --surfaces_allocated; | |
949 #endif | |
950 } |