Mercurial > sdl-ios-xcode
comparison src/video/SDL_surface.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | 84de7511f79f |
children | 8a162bfdc838 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 */ | 21 */ |
22 #include "SDL_config.h" | 22 #include "SDL_config.h" |
23 | 23 |
24 #include "SDL_video.h" | 24 #include "SDL_video.h" |
25 #include "SDL_compat.h" | |
25 #include "SDL_sysvideo.h" | 26 #include "SDL_sysvideo.h" |
26 #include "SDL_cursor_c.h" | |
27 #include "SDL_blit.h" | 27 #include "SDL_blit.h" |
28 #include "SDL_RLEaccel_c.h" | 28 #include "SDL_RLEaccel_c.h" |
29 #include "SDL_pixels_c.h" | 29 #include "SDL_pixels_c.h" |
30 #include "SDL_leaks.h" | 30 #include "SDL_leaks.h" |
31 | 31 |
32 | 32 |
33 /* Public routines */ | 33 /* Public routines */ |
34 /* | 34 /* |
35 * Create an empty RGB surface of the appropriate depth | 35 * Create an empty RGB surface of the appropriate depth |
36 */ | 36 */ |
37 SDL_Surface * SDL_CreateRGBSurface (Uint32 flags, | 37 SDL_Surface * |
38 int width, int height, int depth, | 38 SDL_CreateRGBSurface(Uint32 flags, |
39 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) | 39 int width, int height, int depth, |
40 { | 40 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) |
41 SDL_VideoDevice *video = current_video; | 41 { |
42 SDL_VideoDevice *this = current_video; | 42 SDL_Surface *surface; |
43 SDL_Surface *screen; | 43 |
44 SDL_Surface *surface; | 44 /* Allocate the surface */ |
45 | 45 surface = (SDL_Surface *) SDL_malloc(sizeof(*surface)); |
46 /* Make sure the size requested doesn't overflow our datatypes */ | 46 if (surface == NULL) { |
47 /* Next time I write a library like SDL, I'll use int for size. :) */ | 47 SDL_OutOfMemory(); |
48 if ( width >= 16384 || height >= 65536 ) { | 48 return NULL; |
49 SDL_SetError("Width or height is too large"); | 49 } |
50 return(NULL); | 50 SDL_zerop(surface); |
51 } | 51 |
52 | 52 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); |
53 /* Check to see if we desire the surface in video memory */ | 53 if (!surface->format) { |
54 if ( video ) { | 54 SDL_FreeSurface(surface); |
55 screen = SDL_PublicSurface; | 55 return NULL; |
56 } else { | 56 } |
57 screen = NULL; | 57 if (Amask) { |
58 } | 58 surface->flags |= SDL_SRCALPHA; |
59 if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) { | 59 } |
60 if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) { | 60 surface->w = width; |
61 flags |= SDL_HWSURFACE; | 61 surface->h = height; |
62 } | 62 surface->pitch = SDL_CalculatePitch(surface); |
63 if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | 63 SDL_SetClipRect(surface, NULL); |
64 if ( ! current_video->info.blit_hw_CC ) { | 64 |
65 flags &= ~SDL_HWSURFACE; | 65 if (surface->format->BitsPerPixel <= 8) { |
66 } | 66 SDL_Palette *palette = |
67 } | 67 SDL_AllocPalette((1 << surface->format->BitsPerPixel)); |
68 if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | 68 if (!palette) { |
69 if ( ! current_video->info.blit_hw_A ) { | 69 SDL_FreeSurface(surface); |
70 flags &= ~SDL_HWSURFACE; | 70 return NULL; |
71 } | 71 } |
72 } | 72 if (Rmask || Bmask || Gmask) { |
73 } else { | 73 const SDL_PixelFormat *format = surface->format; |
74 flags &= ~SDL_HWSURFACE; | 74 |
75 } | 75 /* create palette according to masks */ |
76 | 76 int i; |
77 /* Allocate the surface */ | 77 int Rm = 0, Gm = 0, Bm = 0; |
78 surface = (SDL_Surface *)SDL_malloc(sizeof(*surface)); | 78 int Rw = 0, Gw = 0, Bw = 0; |
79 if ( surface == NULL ) { | 79 |
80 SDL_OutOfMemory(); | 80 if (Rmask) { |
81 return(NULL); | 81 Rw = 8 - format->Rloss; |
82 } | 82 for (i = format->Rloss; i > 0; i -= Rw) |
83 surface->flags = SDL_SWSURFACE; | 83 Rm |= 1 << i; |
84 if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { | 84 } |
85 if ((Amask) && (video->displayformatalphapixel)) | 85 if (Gmask) { |
86 { | 86 Gw = 8 - format->Gloss; |
87 depth = video->displayformatalphapixel->BitsPerPixel; | 87 for (i = format->Gloss; i > 0; i -= Gw) |
88 Rmask = video->displayformatalphapixel->Rmask; | 88 Gm |= 1 << i; |
89 Gmask = video->displayformatalphapixel->Gmask; | 89 } |
90 Bmask = video->displayformatalphapixel->Bmask; | 90 if (Bmask) { |
91 Amask = video->displayformatalphapixel->Amask; | 91 Bw = 8 - format->Bloss; |
92 } | 92 for (i = format->Bloss; i > 0; i -= Bw) |
93 else | 93 Bm |= 1 << i; |
94 { | 94 } |
95 depth = screen->format->BitsPerPixel; | 95 for (i = 0; i < palette->ncolors; ++i) { |
96 Rmask = screen->format->Rmask; | 96 int r, g, b; |
97 Gmask = screen->format->Gmask; | 97 r = (i & Rmask) >> format->Rshift; |
98 Bmask = screen->format->Bmask; | 98 r = (r << format->Rloss) | ((r * Rm) >> Rw); |
99 Amask = screen->format->Amask; | 99 palette->colors[i].r = r; |
100 } | 100 |
101 } | 101 g = (i & Gmask) >> format->Gshift; |
102 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); | 102 g = (g << format->Gloss) | ((g * Gm) >> Gw); |
103 if ( surface->format == NULL ) { | 103 palette->colors[i].g = g; |
104 SDL_free(surface); | 104 |
105 return(NULL); | 105 b = (i & Bmask) >> format->Bshift; |
106 } | 106 b = (b << format->Bloss) | ((b * Bm) >> Bw); |
107 if ( Amask ) { | 107 palette->colors[i].b = b; |
108 surface->flags |= SDL_SRCALPHA; | 108 } |
109 } | 109 } else if (palette->ncolors == 2) { |
110 surface->w = width; | 110 /* Create a black and white bitmap palette */ |
111 surface->h = height; | 111 palette->colors[0].r = 0xFF; |
112 surface->pitch = SDL_CalculatePitch(surface); | 112 palette->colors[0].g = 0xFF; |
113 surface->pixels = NULL; | 113 palette->colors[0].b = 0xFF; |
114 surface->offset = 0; | 114 palette->colors[1].r = 0x00; |
115 surface->hwdata = NULL; | 115 palette->colors[1].g = 0x00; |
116 surface->locked = 0; | 116 palette->colors[1].b = 0x00; |
117 surface->map = NULL; | 117 } |
118 surface->unused1 = 0; | 118 SDL_SetSurfacePalette(surface, palette); |
119 SDL_SetClipRect(surface, NULL); | 119 SDL_FreePalette(palette); |
120 SDL_FormatChanged(surface); | 120 } |
121 | 121 |
122 /* Get the pixels */ | 122 /* Get the pixels */ |
123 if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || | 123 if (surface->w && surface->h) { |
124 (video->AllocHWSurface(this, surface) < 0) ) { | 124 surface->pixels = SDL_malloc(surface->h * surface->pitch); |
125 if ( surface->w && surface->h ) { | 125 if (!surface->pixels) { |
126 surface->pixels = SDL_malloc(surface->h*surface->pitch); | 126 SDL_FreeSurface(surface); |
127 if ( surface->pixels == NULL ) { | 127 SDL_OutOfMemory(); |
128 SDL_FreeSurface(surface); | 128 return NULL; |
129 SDL_OutOfMemory(); | 129 } |
130 return(NULL); | 130 /* This is important for bitmaps */ |
131 } | 131 SDL_memset(surface->pixels, 0, surface->h * surface->pitch); |
132 /* This is important for bitmaps */ | 132 } |
133 SDL_memset(surface->pixels, 0, surface->h*surface->pitch); | 133 |
134 } | 134 /* Allocate an empty mapping */ |
135 } | 135 surface->map = SDL_AllocBlitMap(); |
136 | 136 if (!surface->map) { |
137 /* Allocate an empty mapping */ | 137 SDL_FreeSurface(surface); |
138 surface->map = SDL_AllocBlitMap(); | 138 return NULL; |
139 if ( surface->map == NULL ) { | 139 } |
140 SDL_FreeSurface(surface); | 140 SDL_FormatChanged(surface); |
141 return(NULL); | 141 |
142 } | 142 /* The surface is ready to go */ |
143 | 143 surface->refcount = 1; |
144 /* The surface is ready to go */ | |
145 surface->refcount = 1; | |
146 #ifdef CHECK_LEAKS | 144 #ifdef CHECK_LEAKS |
147 ++surfaces_allocated; | 145 ++surfaces_allocated; |
148 #endif | 146 #endif |
149 return(surface); | 147 return surface; |
150 } | 148 } |
149 | |
151 /* | 150 /* |
152 * Create an RGB surface from an existing memory buffer | 151 * Create an RGB surface from an existing memory buffer |
153 */ | 152 */ |
154 SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels, | 153 SDL_Surface * |
155 int width, int height, int depth, int pitch, | 154 SDL_CreateRGBSurfaceFrom(void *pixels, |
156 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) | 155 int width, int height, int depth, int pitch, |
157 { | 156 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, |
158 SDL_Surface *surface; | 157 Uint32 Amask) |
159 | 158 { |
160 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth, | 159 SDL_Surface *surface; |
161 Rmask, Gmask, Bmask, Amask); | 160 |
162 if ( surface != NULL ) { | 161 surface = |
163 surface->flags |= SDL_PREALLOC; | 162 SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask); |
164 surface->pixels = pixels; | 163 if (surface != NULL) { |
165 surface->w = width; | 164 surface->flags |= SDL_PREALLOC; |
166 surface->h = height; | 165 surface->pixels = pixels; |
167 surface->pitch = pitch; | 166 surface->w = width; |
168 SDL_SetClipRect(surface, NULL); | 167 surface->h = height; |
169 } | 168 surface->pitch = pitch; |
170 return(surface); | 169 SDL_SetClipRect(surface, NULL); |
171 } | 170 } |
171 return surface; | |
172 } | |
173 | |
174 SDL_Surface * | |
175 SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID) | |
176 { | |
177 SDL_Surface *surface; | |
178 Uint32 format; | |
179 int w, h; | |
180 int bpp; | |
181 Uint32 Rmask, Gmask, Bmask, Amask; | |
182 void *pixels; | |
183 int pitch; | |
184 | |
185 if (SDL_QueryTexture(textureID, &format, NULL, &w, &h) < 0) { | |
186 return NULL; | |
187 } | |
188 | |
189 if (!SDL_PixelFormatEnumToMasks | |
190 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
191 SDL_SetError("Unknown texture format"); | |
192 return NULL; | |
193 } | |
194 | |
195 if (SDL_QueryTexturePixels(textureID, &pixels, &pitch) == 0) { | |
196 surface = | |
197 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask, Gmask, | |
198 Bmask, Amask); | |
199 } else { | |
200 surface = | |
201 SDL_CreateRGBSurface(0, 0, 0, bpp, Rmask, Gmask, Bmask, Amask); | |
202 if (surface) { | |
203 surface->flags |= SDL_HWSURFACE; | |
204 surface->w = w; | |
205 surface->h = h; | |
206 surface->pitch = SDL_CalculatePitch(surface); | |
207 SDL_SetClipRect(surface, NULL); | |
208 } | |
209 } | |
210 if (surface) { | |
211 surface->textureID = textureID; | |
212 } | |
213 | |
214 return surface; | |
215 } | |
216 | |
217 static int | |
218 SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette) | |
219 { | |
220 SDL_Surface *surface = (SDL_Surface *) userdata; | |
221 | |
222 if (surface->textureID) { | |
223 if (SDL_SetTexturePalette | |
224 (surface->textureID, palette->colors, 0, palette->ncolors) < 0) { | |
225 SDL_GetTexturePalette(surface->textureID, palette->colors, 0, | |
226 palette->ncolors); | |
227 return -1; | |
228 } | |
229 } | |
230 SDL_FormatChanged(surface); | |
231 | |
232 return 0; | |
233 } | |
234 | |
235 int | |
236 SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette) | |
237 { | |
238 if (!surface || !surface->format) { | |
239 SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface"); | |
240 return -1; | |
241 } | |
242 | |
243 if (palette && palette->ncolors != (1 << surface->format->BitsPerPixel)) { | |
244 SDL_SetError | |
245 ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format"); | |
246 return -1; | |
247 } | |
248 | |
249 if (surface->format->palette == palette) { | |
250 return 0; | |
251 } | |
252 | |
253 if (surface->format->palette) { | |
254 SDL_DelPaletteWatch(surface->format->palette, | |
255 SDL_SurfacePaletteChanged, surface); | |
256 } | |
257 | |
258 surface->format->palette = palette; | |
259 | |
260 if (surface->format->palette) { | |
261 SDL_AddPaletteWatch(surface->format->palette, | |
262 SDL_SurfacePaletteChanged, surface); | |
263 } | |
264 return 0; | |
265 } | |
266 | |
172 /* | 267 /* |
173 * Set the color key in a blittable surface | 268 * Set the color key in a blittable surface |
174 */ | 269 */ |
175 int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key) | 270 int |
176 { | 271 SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key) |
177 /* Sanity check the flag as it gets passed in */ | 272 { |
178 if ( flag & SDL_SRCCOLORKEY ) { | 273 /* Sanity check the flag as it gets passed in */ |
179 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { | 274 if (flag & SDL_SRCCOLORKEY) { |
180 flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); | 275 if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) { |
181 } else { | 276 flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); |
182 flag = SDL_SRCCOLORKEY; | 277 } else { |
183 } | 278 flag = SDL_SRCCOLORKEY; |
184 } else { | 279 } |
185 flag = 0; | 280 } else { |
186 } | 281 flag = 0; |
187 | 282 } |
188 /* Optimize away operations that don't change anything */ | 283 |
189 if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) && | 284 /* Optimize away operations that don't change anything */ |
190 (key == surface->format->colorkey) ) { | 285 if ((flag == (surface->flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK))) && |
191 return(0); | 286 (key == surface->format->colorkey)) { |
192 } | 287 return (0); |
193 | 288 } |
194 /* UnRLE surfaces before we change the colorkey */ | 289 |
195 if ( surface->flags & SDL_RLEACCEL ) { | 290 /* UnRLE surfaces before we change the colorkey */ |
196 SDL_UnRLESurface(surface, 1); | 291 if (surface->flags & SDL_RLEACCEL) { |
197 } | 292 SDL_UnRLESurface(surface, 1); |
198 | 293 } |
199 if ( flag ) { | 294 |
200 SDL_VideoDevice *video = current_video; | 295 if (flag) { |
201 SDL_VideoDevice *this = current_video; | 296 surface->flags |= SDL_SRCCOLORKEY; |
202 | 297 surface->format->colorkey = key; |
203 | 298 if (flag & SDL_RLEACCELOK) { |
204 surface->flags |= SDL_SRCCOLORKEY; | 299 surface->flags |= SDL_RLEACCELOK; |
205 surface->format->colorkey = key; | 300 } else { |
206 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { | 301 surface->flags &= ~SDL_RLEACCELOK; |
207 if ( (video->SetHWColorKey == NULL) || | 302 } |
208 (video->SetHWColorKey(this, surface, key) < 0) ) { | 303 } else { |
209 surface->flags &= ~SDL_HWACCEL; | 304 surface->flags &= ~(SDL_SRCCOLORKEY | SDL_RLEACCELOK); |
210 } | 305 surface->format->colorkey = 0; |
211 } | 306 } |
212 if ( flag & SDL_RLEACCELOK ) { | 307 SDL_InvalidateMap(surface->map); |
213 surface->flags |= SDL_RLEACCELOK; | 308 return (0); |
214 } else { | 309 } |
215 surface->flags &= ~SDL_RLEACCELOK; | 310 |
216 } | |
217 } else { | |
218 surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK); | |
219 surface->format->colorkey = 0; | |
220 } | |
221 SDL_InvalidateMap(surface->map); | |
222 return(0); | |
223 } | |
224 /* This function sets the alpha channel of a surface */ | 311 /* This function sets the alpha channel of a surface */ |
225 int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value) | 312 int |
226 { | 313 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value) |
227 Uint32 oldflags = surface->flags; | 314 { |
228 Uint32 oldalpha = surface->format->alpha; | 315 Uint32 oldflags = surface->flags; |
229 | 316 Uint32 oldalpha = surface->format->alpha; |
230 /* Sanity check the flag as it gets passed in */ | 317 |
231 if ( flag & SDL_SRCALPHA ) { | 318 /* Sanity check the flag as it gets passed in */ |
232 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { | 319 if (flag & SDL_SRCALPHA) { |
233 flag = (SDL_SRCALPHA | SDL_RLEACCELOK); | 320 if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) { |
234 } else { | 321 flag = (SDL_SRCALPHA | SDL_RLEACCELOK); |
235 flag = SDL_SRCALPHA; | 322 } else { |
236 } | 323 flag = SDL_SRCALPHA; |
237 } else { | 324 } |
238 flag = 0; | 325 } else { |
239 } | 326 flag = 0; |
240 | 327 } |
241 /* Optimize away operations that don't change anything */ | 328 |
242 if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) && | 329 /* Optimize away operations that don't change anything */ |
243 (!flag || value == oldalpha) ) { | 330 if ((flag == (surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK))) && |
244 return(0); | 331 (!flag || value == oldalpha)) { |
245 } | 332 return (0); |
246 | 333 } |
247 if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) | 334 |
248 SDL_UnRLESurface(surface, 1); | 335 if (!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) |
249 | 336 SDL_UnRLESurface(surface, 1); |
250 if ( flag ) { | 337 |
251 SDL_VideoDevice *video = current_video; | 338 if (flag) { |
252 SDL_VideoDevice *this = current_video; | 339 surface->flags |= SDL_SRCALPHA; |
253 | 340 surface->format->alpha = value; |
254 surface->flags |= SDL_SRCALPHA; | 341 if (flag & SDL_RLEACCELOK) { |
255 surface->format->alpha = value; | 342 surface->flags |= SDL_RLEACCELOK; |
256 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { | 343 } else { |
257 if ( (video->SetHWAlpha == NULL) || | 344 surface->flags &= ~SDL_RLEACCELOK; |
258 (video->SetHWAlpha(this, surface, value) < 0) ) { | 345 } |
259 surface->flags &= ~SDL_HWACCEL; | 346 } else { |
260 } | 347 surface->flags &= ~SDL_SRCALPHA; |
261 } | 348 surface->format->alpha = SDL_ALPHA_OPAQUE; |
262 if ( flag & SDL_RLEACCELOK ) { | 349 } |
263 surface->flags |= SDL_RLEACCELOK; | 350 /* |
264 } else { | 351 * The representation for software surfaces is independent of |
265 surface->flags &= ~SDL_RLEACCELOK; | 352 * per-surface alpha, so no need to invalidate the blit mapping |
266 } | 353 * if just the alpha value was changed. (If either is 255, we still |
267 } else { | 354 * need to invalidate.) |
268 surface->flags &= ~SDL_SRCALPHA; | 355 */ |
269 surface->format->alpha = SDL_ALPHA_OPAQUE; | 356 if (oldflags != surface->flags |
270 } | 357 || (((oldalpha + 1) ^ (value + 1)) & 0x100)) { |
271 /* | 358 SDL_InvalidateMap(surface->map); |
272 * The representation for software surfaces is independent of | 359 } |
273 * per-surface alpha, so no need to invalidate the blit mapping | 360 return (0); |
274 * if just the alpha value was changed. (If either is 255, we still | 361 } |
275 * need to invalidate.) | 362 |
276 */ | 363 int |
277 if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL | 364 SDL_SetAlphaChannel(SDL_Surface * surface, Uint8 value) |
278 || oldflags != surface->flags | 365 { |
279 || (((oldalpha + 1) ^ (value + 1)) & 0x100)) | 366 int row, col; |
280 SDL_InvalidateMap(surface->map); | 367 int offset; |
281 return(0); | 368 Uint8 *buf; |
282 } | 369 |
283 int SDL_SetAlphaChannel(SDL_Surface *surface, Uint8 value) | 370 if ((surface->format->Amask != 0xFF000000) && |
284 { | 371 (surface->format->Amask != 0x000000FF)) { |
285 int row, col; | 372 SDL_SetError("Unsupported surface alpha mask format"); |
286 int offset; | 373 return -1; |
287 Uint8 *buf; | 374 } |
288 | |
289 if ( (surface->format->Amask != 0xFF000000) && | |
290 (surface->format->Amask != 0x000000FF) ) { | |
291 SDL_SetError("Unsupported surface alpha mask format"); | |
292 return -1; | |
293 } | |
294 | |
295 #if SDL_BYTEORDER == SDL_LIL_ENDIAN | 375 #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
296 if ( surface->format->Amask == 0xFF000000 ) { | 376 if (surface->format->Amask == 0xFF000000) { |
297 offset = 3; | 377 offset = 3; |
298 } else { | 378 } else { |
299 offset = 0; | 379 offset = 0; |
300 } | 380 } |
301 #else | 381 #else |
302 if ( surface->format->Amask == 0xFF000000 ) { | 382 if (surface->format->Amask == 0xFF000000) { |
303 offset = 0; | 383 offset = 0; |
304 } else { | 384 } else { |
305 offset = 3; | 385 offset = 3; |
306 } | 386 } |
307 #endif /* Byte ordering */ | 387 #endif /* Byte ordering */ |
308 | 388 |
309 /* Quickly set the alpha channel of an RGBA or ARGB surface */ | 389 /* Quickly set the alpha channel of an RGBA or ARGB surface */ |
310 if ( SDL_MUSTLOCK(surface) ) { | 390 if (SDL_MUSTLOCK(surface)) { |
311 if ( SDL_LockSurface(surface) < 0 ) { | 391 if (SDL_LockSurface(surface) < 0) { |
312 return -1; | 392 return -1; |
313 } | 393 } |
314 } | 394 } |
315 row = surface->h; | 395 row = surface->h; |
316 while (row--) { | 396 while (row--) { |
317 col = surface->w; | 397 col = surface->w; |
318 buf = (Uint8 *)surface->pixels + row * surface->pitch + offset; | 398 buf = (Uint8 *) surface->pixels + row * surface->pitch + offset; |
319 while(col--) { | 399 while (col--) { |
320 *buf = value; | 400 *buf = value; |
321 buf += 4; | 401 buf += 4; |
322 } | 402 } |
323 } | 403 } |
324 if ( SDL_MUSTLOCK(surface) ) { | 404 if (SDL_MUSTLOCK(surface)) { |
325 SDL_UnlockSurface(surface); | 405 SDL_UnlockSurface(surface); |
326 } | 406 } |
327 return 0; | 407 return 0; |
328 } | 408 } |
329 | 409 |
330 /* | |
331 * A function to calculate the intersection of two rectangles: | |
332 * return true if the rectangles intersect, false otherwise | |
333 */ | |
334 static __inline__ | |
335 SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection) | |
336 { | |
337 int Amin, Amax, Bmin, Bmax; | |
338 | |
339 /* Horizontal intersection */ | |
340 Amin = A->x; | |
341 Amax = Amin + A->w; | |
342 Bmin = B->x; | |
343 Bmax = Bmin + B->w; | |
344 if(Bmin > Amin) | |
345 Amin = Bmin; | |
346 intersection->x = Amin; | |
347 if(Bmax < Amax) | |
348 Amax = Bmax; | |
349 intersection->w = Amax - Amin > 0 ? Amax - Amin : 0; | |
350 | |
351 /* Vertical intersection */ | |
352 Amin = A->y; | |
353 Amax = Amin + A->h; | |
354 Bmin = B->y; | |
355 Bmax = Bmin + B->h; | |
356 if(Bmin > Amin) | |
357 Amin = Bmin; | |
358 intersection->y = Amin; | |
359 if(Bmax < Amax) | |
360 Amax = Bmax; | |
361 intersection->h = Amax - Amin > 0 ? Amax - Amin : 0; | |
362 | |
363 return (intersection->w && intersection->h); | |
364 } | |
365 /* | 410 /* |
366 * Set the clipping rectangle for a blittable surface | 411 * Set the clipping rectangle for a blittable surface |
367 */ | 412 */ |
368 SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect) | 413 SDL_bool |
369 { | 414 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect) |
370 SDL_Rect full_rect; | 415 { |
371 | 416 SDL_Rect full_rect; |
372 /* Don't do anything if there's no surface to act on */ | 417 |
373 if ( ! surface ) { | 418 /* Don't do anything if there's no surface to act on */ |
374 return SDL_FALSE; | 419 if (!surface) { |
375 } | 420 return SDL_FALSE; |
376 | 421 } |
377 /* Set up the full surface rectangle */ | 422 |
378 full_rect.x = 0; | 423 /* Set up the full surface rectangle */ |
379 full_rect.y = 0; | 424 full_rect.x = 0; |
380 full_rect.w = surface->w; | 425 full_rect.y = 0; |
381 full_rect.h = surface->h; | 426 full_rect.w = surface->w; |
382 | 427 full_rect.h = surface->h; |
383 /* Set the clipping rectangle */ | 428 |
384 if ( ! rect ) { | 429 /* Set the clipping rectangle */ |
385 surface->clip_rect = full_rect; | 430 if (!rect) { |
386 return 1; | 431 surface->clip_rect = full_rect; |
387 } | 432 return 1; |
388 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); | 433 } |
389 } | 434 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); |
390 void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect) | 435 } |
391 { | 436 |
392 if ( surface && rect ) { | 437 void |
393 *rect = surface->clip_rect; | 438 SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect) |
394 } | 439 { |
395 } | 440 if (surface && rect) { |
441 *rect = surface->clip_rect; | |
442 } | |
443 } | |
444 | |
396 /* | 445 /* |
397 * Set up a blit between two surfaces -- split into three parts: | 446 * Set up a blit between two surfaces -- split into three parts: |
398 * The upper part, SDL_UpperBlit(), performs clipping and rectangle | 447 * The upper part, SDL_UpperBlit(), performs clipping and rectangle |
399 * verification. The lower part is a pointer to a low level | 448 * verification. The lower part is a pointer to a low level |
400 * accelerated blitting function. | 449 * accelerated blitting function. |
402 * These parts are separated out and each used internally by this | 451 * These parts are separated out and each used internally by this |
403 * library in the optimimum places. They are exported so that if | 452 * library in the optimimum places. They are exported so that if |
404 * you know exactly what you are doing, you can optimize your code | 453 * you know exactly what you are doing, you can optimize your code |
405 * by calling the one(s) you need. | 454 * by calling the one(s) you need. |
406 */ | 455 */ |
407 int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect, | 456 int |
408 SDL_Surface *dst, SDL_Rect *dstrect) | 457 SDL_LowerBlit(SDL_Surface * src, SDL_Rect * srcrect, |
409 { | 458 SDL_Surface * dst, SDL_Rect * dstrect) |
410 SDL_blit do_blit; | 459 { |
411 SDL_Rect hw_srcrect; | 460 /* Check to make sure the blit mapping is valid */ |
412 SDL_Rect hw_dstrect; | 461 if ((src->map->dst != dst) || |
413 | 462 (src->map->dst->format_version != src->map->format_version)) { |
414 /* Check to make sure the blit mapping is valid */ | 463 if (SDL_MapSurface(src, dst) < 0) { |
415 if ( (src->map->dst != dst) || | 464 return (-1); |
416 (src->map->dst->format_version != src->map->format_version) ) { | 465 } |
417 if ( SDL_MapSurface(src, dst) < 0 ) { | 466 } |
418 return(-1); | 467 return (src->map->sw_blit(src, srcrect, dst, dstrect)); |
419 } | 468 } |
420 } | 469 |
421 | 470 |
422 /* Figure out which blitter to use */ | 471 int |
423 if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) { | 472 SDL_UpperBlit(SDL_Surface * src, SDL_Rect * srcrect, |
424 if ( src == SDL_VideoSurface ) { | 473 SDL_Surface * dst, SDL_Rect * dstrect) |
425 hw_srcrect = *srcrect; | 474 { |
426 hw_srcrect.x += current_video->offset_x; | 475 SDL_Rect fulldst; |
427 hw_srcrect.y += current_video->offset_y; | 476 int srcx, srcy, w, h; |
428 srcrect = &hw_srcrect; | 477 |
429 } | 478 /* Make sure the surfaces aren't locked */ |
430 if ( dst == SDL_VideoSurface ) { | 479 if (!src || !dst) { |
431 hw_dstrect = *dstrect; | 480 SDL_SetError("SDL_UpperBlit: passed a NULL surface"); |
432 hw_dstrect.x += current_video->offset_x; | 481 return (-1); |
433 hw_dstrect.y += current_video->offset_y; | 482 } |
434 dstrect = &hw_dstrect; | 483 if (src->locked || dst->locked) { |
435 } | 484 SDL_SetError("Surfaces must not be locked during blit"); |
436 do_blit = src->map->hw_blit; | 485 return (-1); |
437 } else { | 486 } |
438 do_blit = src->map->sw_blit; | 487 |
439 } | 488 /* If the destination rectangle is NULL, use the entire dest surface */ |
440 return(do_blit(src, srcrect, dst, dstrect)); | 489 if (dstrect == NULL) { |
441 } | 490 fulldst.x = fulldst.y = 0; |
442 | 491 dstrect = &fulldst; |
443 | 492 } |
444 int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect, | 493 |
445 SDL_Surface *dst, SDL_Rect *dstrect) | 494 /* clip the source rectangle to the source surface */ |
446 { | 495 if (srcrect) { |
447 SDL_Rect fulldst; | 496 int maxw, maxh; |
448 int srcx, srcy, w, h; | 497 |
449 | 498 srcx = srcrect->x; |
450 /* Make sure the surfaces aren't locked */ | 499 w = srcrect->w; |
451 if ( ! src || ! dst ) { | 500 if (srcx < 0) { |
452 SDL_SetError("SDL_UpperBlit: passed a NULL surface"); | 501 w += srcx; |
453 return(-1); | 502 dstrect->x -= srcx; |
454 } | 503 srcx = 0; |
455 if ( src->locked || dst->locked ) { | 504 } |
456 SDL_SetError("Surfaces must not be locked during blit"); | 505 maxw = src->w - srcx; |
457 return(-1); | 506 if (maxw < w) |
458 } | 507 w = maxw; |
459 | 508 |
460 /* If the destination rectangle is NULL, use the entire dest surface */ | 509 srcy = srcrect->y; |
461 if ( dstrect == NULL ) { | 510 h = srcrect->h; |
462 fulldst.x = fulldst.y = 0; | 511 if (srcy < 0) { |
463 dstrect = &fulldst; | 512 h += srcy; |
464 } | 513 dstrect->y -= srcy; |
465 | 514 srcy = 0; |
466 /* clip the source rectangle to the source surface */ | 515 } |
467 if(srcrect) { | 516 maxh = src->h - srcy; |
468 int maxw, maxh; | 517 if (maxh < h) |
469 | 518 h = maxh; |
470 srcx = srcrect->x; | 519 |
471 w = srcrect->w; | 520 } else { |
472 if(srcx < 0) { | 521 srcx = srcy = 0; |
473 w += srcx; | 522 w = src->w; |
474 dstrect->x -= srcx; | 523 h = src->h; |
475 srcx = 0; | 524 } |
476 } | 525 |
477 maxw = src->w - srcx; | 526 /* clip the destination rectangle against the clip rectangle */ |
478 if(maxw < w) | 527 { |
479 w = maxw; | 528 SDL_Rect *clip = &dst->clip_rect; |
480 | 529 int dx, dy; |
481 srcy = srcrect->y; | 530 |
482 h = srcrect->h; | 531 dx = clip->x - dstrect->x; |
483 if(srcy < 0) { | 532 if (dx > 0) { |
484 h += srcy; | 533 w -= dx; |
485 dstrect->y -= srcy; | 534 dstrect->x += dx; |
486 srcy = 0; | 535 srcx += dx; |
487 } | 536 } |
488 maxh = src->h - srcy; | 537 dx = dstrect->x + w - clip->x - clip->w; |
489 if(maxh < h) | 538 if (dx > 0) |
490 h = maxh; | 539 w -= dx; |
491 | 540 |
492 } else { | 541 dy = clip->y - dstrect->y; |
493 srcx = srcy = 0; | 542 if (dy > 0) { |
494 w = src->w; | 543 h -= dy; |
495 h = src->h; | 544 dstrect->y += dy; |
496 } | 545 srcy += dy; |
497 | 546 } |
498 /* clip the destination rectangle against the clip rectangle */ | 547 dy = dstrect->y + h - clip->y - clip->h; |
499 { | 548 if (dy > 0) |
500 SDL_Rect *clip = &dst->clip_rect; | 549 h -= dy; |
501 int dx, dy; | 550 } |
502 | 551 |
503 dx = clip->x - dstrect->x; | 552 if (w > 0 && h > 0) { |
504 if(dx > 0) { | 553 SDL_Rect sr; |
505 w -= dx; | 554 sr.x = srcx; |
506 dstrect->x += dx; | 555 sr.y = srcy; |
507 srcx += dx; | 556 sr.w = dstrect->w = w; |
508 } | 557 sr.h = dstrect->h = h; |
509 dx = dstrect->x + w - clip->x - clip->w; | 558 return SDL_LowerBlit(src, &sr, dst, dstrect); |
510 if(dx > 0) | 559 } |
511 w -= dx; | 560 dstrect->w = dstrect->h = 0; |
512 | 561 return 0; |
513 dy = clip->y - dstrect->y; | 562 } |
514 if(dy > 0) { | 563 |
515 h -= dy; | 564 static int |
516 dstrect->y += dy; | 565 SDL_FillRect1(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color) |
517 srcy += dy; | 566 { |
518 } | 567 /* FIXME: We have to worry about packing order.. *sigh* */ |
519 dy = dstrect->y + h - clip->y - clip->h; | 568 SDL_SetError("1-bpp rect fill not yet implemented"); |
520 if(dy > 0) | 569 return -1; |
521 h -= dy; | 570 } |
522 } | 571 |
523 | 572 static int |
524 if(w > 0 && h > 0) { | 573 SDL_FillRect4(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color) |
525 SDL_Rect sr; | 574 { |
526 sr.x = srcx; | 575 /* FIXME: We have to worry about packing order.. *sigh* */ |
527 sr.y = srcy; | 576 SDL_SetError("4-bpp rect fill not yet implemented"); |
528 sr.w = dstrect->w = w; | 577 return -1; |
529 sr.h = dstrect->h = h; | |
530 return SDL_LowerBlit(src, &sr, dst, dstrect); | |
531 } | |
532 dstrect->w = dstrect->h = 0; | |
533 return 0; | |
534 } | |
535 | |
536 static int SDL_FillRect1(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) | |
537 { | |
538 /* FIXME: We have to worry about packing order.. *sigh* */ | |
539 SDL_SetError("1-bpp rect fill not yet implemented"); | |
540 return -1; | |
541 } | |
542 | |
543 static int SDL_FillRect4(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) | |
544 { | |
545 /* FIXME: We have to worry about packing order.. *sigh* */ | |
546 SDL_SetError("4-bpp rect fill not yet implemented"); | |
547 return -1; | |
548 } | 578 } |
549 | 579 |
550 /* | 580 /* |
551 * This function performs a fast fill of the given rectangle with 'color' | 581 * This function performs a fast fill of the given rectangle with 'color' |
552 */ | 582 */ |
553 int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) | 583 int |
554 { | 584 SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color) |
555 SDL_VideoDevice *video = current_video; | 585 { |
556 SDL_VideoDevice *this = current_video; | 586 int x, y; |
557 int x, y; | 587 Uint8 *row; |
558 Uint8 *row; | 588 |
559 | 589 /* This function doesn't work on surfaces < 8 bpp */ |
560 /* This function doesn't work on surfaces < 8 bpp */ | 590 if (dst->format->BitsPerPixel < 8) { |
561 if ( dst->format->BitsPerPixel < 8 ) { | 591 switch (dst->format->BitsPerPixel) { |
562 switch(dst->format->BitsPerPixel) { | 592 case 1: |
563 case 1: | 593 return SDL_FillRect1(dst, dstrect, color); |
564 return SDL_FillRect1(dst, dstrect, color); | 594 break; |
565 break; | 595 case 4: |
566 case 4: | 596 return SDL_FillRect4(dst, dstrect, color); |
567 return SDL_FillRect4(dst, dstrect, color); | 597 break; |
568 break; | 598 default: |
569 default: | 599 SDL_SetError("Fill rect on unsupported surface format"); |
570 SDL_SetError("Fill rect on unsupported surface format"); | 600 return (-1); |
571 return(-1); | 601 break; |
572 break; | 602 } |
573 } | 603 } |
574 } | 604 |
575 | 605 /* If 'dstrect' == NULL, then fill the whole surface */ |
576 /* If 'dstrect' == NULL, then fill the whole surface */ | 606 if (dstrect) { |
577 if ( dstrect ) { | 607 /* Perform clipping */ |
578 /* Perform clipping */ | 608 if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) { |
579 if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) { | 609 return (0); |
580 return(0); | 610 } |
581 } | 611 } else { |
582 } else { | 612 dstrect = &dst->clip_rect; |
583 dstrect = &dst->clip_rect; | 613 } |
584 } | 614 |
585 | 615 /* Perform software fill */ |
586 /* Check for hardware acceleration */ | 616 if (SDL_LockSurface(dst) != 0) { |
587 if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && | 617 return (-1); |
588 video->info.blit_fill ) { | 618 } |
589 SDL_Rect hw_rect; | 619 row = (Uint8 *) dst->pixels + dstrect->y * dst->pitch + |
590 if ( dst == SDL_VideoSurface ) { | 620 dstrect->x * dst->format->BytesPerPixel; |
591 hw_rect = *dstrect; | 621 if (dst->format->palette || (color == 0)) { |
592 hw_rect.x += current_video->offset_x; | 622 x = dstrect->w * dst->format->BytesPerPixel; |
593 hw_rect.y += current_video->offset_y; | 623 if (!color && !((uintptr_t) row & 3) && !(x & 3) |
594 dstrect = &hw_rect; | 624 && !(dst->pitch & 3)) { |
595 } | 625 int n = x >> 2; |
596 return(video->FillHWRect(this, dst, dstrect, color)); | 626 for (y = dstrect->h; y; --y) { |
597 } | 627 SDL_memset4(row, 0, n); |
598 | 628 row += dst->pitch; |
599 /* Perform software fill */ | 629 } |
600 if ( SDL_LockSurface(dst) != 0 ) { | 630 } else { |
601 return(-1); | |
602 } | |
603 row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+ | |
604 dstrect->x*dst->format->BytesPerPixel; | |
605 if ( dst->format->palette || (color == 0) ) { | |
606 x = dstrect->w*dst->format->BytesPerPixel; | |
607 if ( !color && !((uintptr_t)row&3) && !(x&3) && !(dst->pitch&3) ) { | |
608 int n = x >> 2; | |
609 for ( y=dstrect->h; y; --y ) { | |
610 SDL_memset4(row, 0, n); | |
611 row += dst->pitch; | |
612 } | |
613 } else { | |
614 #ifdef __powerpc__ | 631 #ifdef __powerpc__ |
615 /* | 632 /* |
616 * SDL_memset() on PPC (both glibc and codewarrior) uses | 633 * SDL_memset() on PPC (both glibc and codewarrior) uses |
617 * the dcbz (Data Cache Block Zero) instruction, which | 634 * the dcbz (Data Cache Block Zero) instruction, which |
618 * causes an alignment exception if the destination is | 635 * causes an alignment exception if the destination is |
619 * uncachable, so only use it on software surfaces | 636 * uncachable, so only use it on software surfaces |
620 */ | 637 */ |
621 if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { | 638 if (dst->flags & SDL_HWSURFACE) { |
622 if(dstrect->w >= 8) { | 639 if (dstrect->w >= 8) { |
623 /* | 640 /* |
624 * 64-bit stores are probably most | 641 * 64-bit stores are probably most |
625 * efficient to uncached video memory | 642 * efficient to uncached video memory |
626 */ | 643 */ |
627 double fill; | 644 double fill; |
628 SDL_memset(&fill, color, (sizeof fill)); | 645 SDL_memset(&fill, color, (sizeof fill)); |
629 for(y = dstrect->h; y; y--) { | 646 for (y = dstrect->h; y; y--) { |
630 Uint8 *d = row; | 647 Uint8 *d = row; |
631 unsigned n = x; | 648 unsigned n = x; |
632 unsigned nn; | 649 unsigned nn; |
633 Uint8 c = color; | 650 Uint8 c = color; |
634 double f = fill; | 651 double f = fill; |
635 while((unsigned long)d | 652 while ((unsigned long) d & (sizeof(double) - 1)) { |
636 & (sizeof(double) - 1)) { | 653 *d++ = c; |
637 *d++ = c; | 654 n--; |
638 n--; | 655 } |
639 } | 656 nn = n / (sizeof(double) * 4); |
640 nn = n / (sizeof(double) * 4); | 657 while (nn) { |
641 while(nn) { | 658 ((double *) d)[0] = f; |
642 ((double *)d)[0] = f; | 659 ((double *) d)[1] = f; |
643 ((double *)d)[1] = f; | 660 ((double *) d)[2] = f; |
644 ((double *)d)[2] = f; | 661 ((double *) d)[3] = f; |
645 ((double *)d)[3] = f; | 662 d += 4 * sizeof(double); |
646 d += 4*sizeof(double); | 663 nn--; |
647 nn--; | 664 } |
648 } | 665 n &= ~(sizeof(double) * 4 - 1); |
649 n &= ~(sizeof(double) * 4 - 1); | 666 nn = n / sizeof(double); |
650 nn = n / sizeof(double); | 667 while (nn) { |
651 while(nn) { | 668 *(double *) d = f; |
652 *(double *)d = f; | 669 d += sizeof(double); |
653 d += sizeof(double); | 670 nn--; |
654 nn--; | 671 } |
655 } | 672 n &= ~(sizeof(double) - 1); |
656 n &= ~(sizeof(double) - 1); | 673 while (n) { |
657 while(n) { | 674 *d++ = c; |
658 *d++ = c; | 675 n--; |
659 n--; | 676 } |
660 } | 677 row += dst->pitch; |
661 row += dst->pitch; | 678 } |
662 } | 679 } else { |
663 } else { | 680 /* narrow boxes */ |
664 /* narrow boxes */ | 681 for (y = dstrect->h; y; y--) { |
665 for(y = dstrect->h; y; y--) { | 682 Uint8 *d = row; |
666 Uint8 *d = row; | 683 Uint8 c = color; |
667 Uint8 c = color; | 684 int n = x; |
668 int n = x; | 685 while (n) { |
669 while(n) { | 686 *d++ = c; |
670 *d++ = c; | 687 n--; |
671 n--; | 688 } |
672 } | 689 row += dst->pitch; |
673 row += dst->pitch; | 690 } |
674 } | 691 } |
675 } | 692 } else |
676 } else | |
677 #endif /* __powerpc__ */ | 693 #endif /* __powerpc__ */ |
678 { | 694 { |
679 for(y = dstrect->h; y; y--) { | 695 for (y = dstrect->h; y; y--) { |
680 SDL_memset(row, color, x); | 696 SDL_memset(row, color, x); |
681 row += dst->pitch; | 697 row += dst->pitch; |
682 } | 698 } |
683 } | 699 } |
684 } | 700 } |
685 } else { | 701 } else { |
686 switch (dst->format->BytesPerPixel) { | 702 switch (dst->format->BytesPerPixel) { |
687 case 2: | 703 case 2: |
688 for ( y=dstrect->h; y; --y ) { | 704 for (y = dstrect->h; y; --y) { |
689 Uint16 *pixels = (Uint16 *)row; | 705 Uint16 *pixels = (Uint16 *) row; |
690 Uint16 c = (Uint16)color; | 706 Uint16 c = (Uint16) color; |
691 Uint32 cc = (Uint32)c << 16 | c; | 707 Uint32 cc = (Uint32) c << 16 | c; |
692 int n = dstrect->w; | 708 int n = dstrect->w; |
693 if((uintptr_t)pixels & 3) { | 709 if ((uintptr_t) pixels & 3) { |
694 *pixels++ = c; | 710 *pixels++ = c; |
695 n--; | 711 n--; |
696 } | 712 } |
697 if(n >> 1) | 713 if (n >> 1) |
698 SDL_memset4(pixels, cc, n >> 1); | 714 SDL_memset4(pixels, cc, n >> 1); |
699 if(n & 1) | 715 if (n & 1) |
700 pixels[n - 1] = c; | 716 pixels[n - 1] = c; |
701 row += dst->pitch; | 717 row += dst->pitch; |
702 } | 718 } |
703 break; | 719 break; |
704 | 720 |
705 case 3: | 721 case 3: |
706 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | 722 #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
707 color <<= 8; | 723 color <<= 8; |
708 #endif | 724 #endif |
709 for ( y=dstrect->h; y; --y ) { | 725 for (y = dstrect->h; y; --y) { |
710 Uint8 *pixels = row; | 726 Uint8 *pixels = row; |
711 for ( x=dstrect->w; x; --x ) { | 727 for (x = dstrect->w; x; --x) { |
712 SDL_memcpy(pixels, &color, 3); | 728 SDL_memcpy(pixels, &color, 3); |
713 pixels += 3; | 729 pixels += 3; |
714 } | 730 } |
715 row += dst->pitch; | 731 row += dst->pitch; |
716 } | 732 } |
717 break; | 733 break; |
718 | 734 |
719 case 4: | 735 case 4: |
720 for(y = dstrect->h; y; --y) { | 736 for (y = dstrect->h; y; --y) { |
721 SDL_memset4(row, color, dstrect->w); | 737 SDL_memset4(row, color, dstrect->w); |
722 row += dst->pitch; | 738 row += dst->pitch; |
723 } | 739 } |
724 break; | 740 break; |
725 } | 741 } |
726 } | 742 } |
727 SDL_UnlockSurface(dst); | 743 SDL_UnlockSurface(dst); |
728 | 744 |
729 /* We're done! */ | 745 /* We're done! */ |
730 return(0); | 746 return (0); |
731 } | 747 } |
732 | 748 |
733 /* | 749 /* |
734 * Lock a surface to directly access the pixels | 750 * Lock a surface to directly access the pixels |
735 */ | 751 */ |
736 int SDL_LockSurface (SDL_Surface *surface) | 752 int |
737 { | 753 SDL_LockSurface(SDL_Surface * surface) |
738 if ( ! surface->locked ) { | 754 { |
739 /* Perform the lock */ | 755 if (!surface->locked) { |
740 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { | 756 /* Perform the lock */ |
741 SDL_VideoDevice *video = current_video; | 757 if (surface->flags & SDL_HWSURFACE) { |
742 SDL_VideoDevice *this = current_video; | 758 if (SDL_LockTexture |
743 if ( video->LockHWSurface(this, surface) < 0 ) { | 759 (surface->textureID, NULL, 1, &surface->pixels, |
744 return(-1); | 760 &surface->pitch) < 0) { |
745 } | 761 return (-1); |
746 } | 762 } |
747 if ( surface->flags & SDL_RLEACCEL ) { | 763 } |
748 SDL_UnRLESurface(surface, 1); | 764 if (surface->flags & SDL_RLEACCEL) { |
749 surface->flags |= SDL_RLEACCEL; /* save accel'd state */ | 765 SDL_UnRLESurface(surface, 1); |
750 } | 766 surface->flags |= SDL_RLEACCEL; /* save accel'd state */ |
751 /* This needs to be done here in case pixels changes value */ | 767 } |
752 surface->pixels = (Uint8 *)surface->pixels + surface->offset; | 768 } |
753 } | 769 |
754 | 770 /* Increment the surface lock count, for recursive locks */ |
755 /* Increment the surface lock count, for recursive locks */ | 771 ++surface->locked; |
756 ++surface->locked; | 772 |
757 | 773 /* Ready to go.. */ |
758 /* Ready to go.. */ | 774 return (0); |
759 return(0); | 775 } |
760 } | 776 |
761 /* | 777 /* |
762 * Unlock a previously locked surface | 778 * Unlock a previously locked surface |
763 */ | 779 */ |
764 void SDL_UnlockSurface (SDL_Surface *surface) | 780 void |
765 { | 781 SDL_UnlockSurface(SDL_Surface * surface) |
766 /* Only perform an unlock if we are locked */ | 782 { |
767 if ( ! surface->locked || (--surface->locked > 0) ) { | 783 /* Only perform an unlock if we are locked */ |
768 return; | 784 if (!surface->locked || (--surface->locked > 0)) { |
769 } | 785 return; |
770 | 786 } |
771 /* Perform the unlock */ | 787 |
772 surface->pixels = (Uint8 *)surface->pixels - surface->offset; | 788 /* Unlock hardware or accelerated surfaces */ |
773 | 789 if (surface->flags & SDL_HWSURFACE) { |
774 /* Unlock hardware or accelerated surfaces */ | 790 SDL_UnlockTexture(surface->textureID); |
775 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { | 791 } |
776 SDL_VideoDevice *video = current_video; | 792 |
777 SDL_VideoDevice *this = current_video; | 793 /* Update RLE encoded surface with new data */ |
778 video->UnlockHWSurface(this, surface); | 794 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { |
779 } else { | 795 surface->flags &= ~SDL_RLEACCEL; /* stop lying */ |
780 /* Update RLE encoded surface with new data */ | 796 SDL_RLESurface(surface); |
781 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | 797 } |
782 surface->flags &= ~SDL_RLEACCEL; /* stop lying */ | |
783 SDL_RLESurface(surface); | |
784 } | |
785 } | |
786 } | 798 } |
787 | 799 |
788 /* | 800 /* |
789 * Convert a surface into the specified pixel format. | 801 * Convert a surface into the specified pixel format. |
790 */ | 802 */ |
791 SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface, | 803 SDL_Surface * |
792 SDL_PixelFormat *format, Uint32 flags) | 804 SDL_ConvertSurface(SDL_Surface * surface, |
793 { | 805 SDL_PixelFormat * format, Uint32 flags) |
794 SDL_Surface *convert; | 806 { |
795 Uint32 colorkey = 0; | 807 SDL_Surface *convert; |
796 Uint8 alpha = 0; | 808 Uint32 colorkey = 0; |
797 Uint32 surface_flags; | 809 Uint8 alpha = 0; |
798 SDL_Rect bounds; | 810 Uint32 surface_flags; |
799 | 811 SDL_Rect bounds; |
800 /* Check for empty destination palette! (results in empty image) */ | 812 |
801 if ( format->palette != NULL ) { | 813 /* Check for empty destination palette! (results in empty image) */ |
802 int i; | 814 if (format->palette != NULL) { |
803 for ( i=0; i<format->palette->ncolors; ++i ) { | 815 int i; |
804 if ( (format->palette->colors[i].r != 0) || | 816 for (i = 0; i < format->palette->ncolors; ++i) { |
805 (format->palette->colors[i].g != 0) || | 817 if ((format->palette->colors[i].r != 0xFF) || |
806 (format->palette->colors[i].b != 0) ) | 818 (format->palette->colors[i].g != 0xFF) || |
807 break; | 819 (format->palette->colors[i].b != 0xFF)) |
808 } | 820 break; |
809 if ( i == format->palette->ncolors ) { | 821 } |
810 SDL_SetError("Empty destination palette"); | 822 if (i == format->palette->ncolors) { |
811 return(NULL); | 823 SDL_SetError("Empty destination palette"); |
812 } | 824 return (NULL); |
813 } | 825 } |
814 | 826 } |
815 /* Only create hw surfaces with alpha channel if hw alpha blits | 827 |
816 are supported */ | 828 /* Create a new surface with the desired format */ |
817 if(format->Amask != 0 && (flags & SDL_HWSURFACE)) { | 829 convert = SDL_CreateRGBSurface(flags, |
818 const SDL_VideoInfo *vi = SDL_GetVideoInfo(); | 830 surface->w, surface->h, |
819 if(!vi || !vi->blit_hw_A) | 831 format->BitsPerPixel, format->Rmask, |
820 flags &= ~SDL_HWSURFACE; | 832 format->Gmask, format->Bmask, |
821 } | 833 format->Amask); |
822 | 834 if (convert == NULL) { |
823 /* Create a new surface with the desired format */ | 835 return (NULL); |
824 convert = SDL_CreateRGBSurface(flags, | 836 } |
825 surface->w, surface->h, format->BitsPerPixel, | 837 |
826 format->Rmask, format->Gmask, format->Bmask, format->Amask); | 838 /* Copy the palette if any */ |
827 if ( convert == NULL ) { | 839 if (format->palette && convert->format->palette) { |
828 return(NULL); | 840 SDL_memcpy(convert->format->palette->colors, |
829 } | 841 format->palette->colors, |
830 | 842 format->palette->ncolors * sizeof(SDL_Color)); |
831 /* Copy the palette if any */ | 843 convert->format->palette->ncolors = format->palette->ncolors; |
832 if ( format->palette && convert->format->palette ) { | 844 } |
833 SDL_memcpy(convert->format->palette->colors, | 845 |
834 format->palette->colors, | 846 /* Save the original surface color key and alpha */ |
835 format->palette->ncolors*sizeof(SDL_Color)); | 847 surface_flags = surface->flags; |
836 convert->format->palette->ncolors = format->palette->ncolors; | 848 if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { |
837 } | 849 /* Convert colourkeyed surfaces to RGBA if requested */ |
838 | 850 if ((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY && format->Amask) { |
839 /* Save the original surface color key and alpha */ | 851 surface_flags &= ~SDL_SRCCOLORKEY; |
840 surface_flags = surface->flags; | 852 } else { |
841 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | 853 colorkey = surface->format->colorkey; |
842 /* Convert colourkeyed surfaces to RGBA if requested */ | 854 SDL_SetColorKey(surface, 0, 0); |
843 if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY | 855 } |
844 && format->Amask) { | 856 } |
845 surface_flags &= ~SDL_SRCCOLORKEY; | 857 if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { |
846 } else { | 858 /* Copy over the alpha channel to RGBA if requested */ |
847 colorkey = surface->format->colorkey; | 859 if (format->Amask) { |
848 SDL_SetColorKey(surface, 0, 0); | 860 surface->flags &= ~SDL_SRCALPHA; |
849 } | 861 } else { |
850 } | 862 alpha = surface->format->alpha; |
851 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | 863 SDL_SetAlpha(surface, 0, 0); |
852 /* Copy over the alpha channel to RGBA if requested */ | 864 } |
853 if ( format->Amask ) { | 865 } |
854 surface->flags &= ~SDL_SRCALPHA; | 866 |
855 } else { | 867 /* Copy over the image data */ |
856 alpha = surface->format->alpha; | 868 bounds.x = 0; |
857 SDL_SetAlpha(surface, 0, 0); | 869 bounds.y = 0; |
858 } | 870 bounds.w = surface->w; |
859 } | 871 bounds.h = surface->h; |
860 | 872 SDL_LowerBlit(surface, &bounds, convert, &bounds); |
861 /* Copy over the image data */ | 873 |
862 bounds.x = 0; | 874 /* Clean up the original surface, and update converted surface */ |
863 bounds.y = 0; | 875 if (convert != NULL) { |
864 bounds.w = surface->w; | 876 SDL_SetClipRect(convert, &surface->clip_rect); |
865 bounds.h = surface->h; | 877 } |
866 SDL_LowerBlit(surface, &bounds, convert, &bounds); | 878 if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { |
867 | 879 Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK); |
868 /* Clean up the original surface, and update converted surface */ | 880 if (convert != NULL) { |
869 if ( convert != NULL ) { | 881 Uint8 keyR, keyG, keyB; |
870 SDL_SetClipRect(convert, &surface->clip_rect); | 882 |
871 } | 883 SDL_GetRGB(colorkey, surface->format, &keyR, &keyG, &keyB); |
872 if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | 884 SDL_SetColorKey(convert, cflags | (flags & SDL_RLEACCELOK), |
873 Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK); | 885 SDL_MapRGB(convert->format, keyR, keyG, keyB)); |
874 if ( convert != NULL ) { | 886 } |
875 Uint8 keyR, keyG, keyB; | 887 SDL_SetColorKey(surface, cflags, colorkey); |
876 | 888 } |
877 SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); | 889 if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { |
878 SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK), | 890 Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); |
879 SDL_MapRGB(convert->format, keyR, keyG, keyB)); | 891 if (convert != NULL) { |
880 } | 892 SDL_SetAlpha(convert, aflags | (flags & SDL_RLEACCELOK), alpha); |
881 SDL_SetColorKey(surface, cflags, colorkey); | 893 } |
882 } | 894 if (format->Amask) { |
883 if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | 895 surface->flags |= SDL_SRCALPHA; |
884 Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK); | 896 } else { |
885 if ( convert != NULL ) { | 897 SDL_SetAlpha(surface, aflags, alpha); |
886 SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK), | 898 } |
887 alpha); | 899 } |
888 } | 900 |
889 if ( format->Amask ) { | 901 /* We're ready to go! */ |
890 surface->flags |= SDL_SRCALPHA; | 902 return (convert); |
891 } else { | |
892 SDL_SetAlpha(surface, aflags, alpha); | |
893 } | |
894 } | |
895 | |
896 /* We're ready to go! */ | |
897 return(convert); | |
898 } | 903 } |
899 | 904 |
900 /* | 905 /* |
901 * Free a surface created by the above function. | 906 * Free a surface created by the above function. |
902 */ | 907 */ |
903 void SDL_FreeSurface (SDL_Surface *surface) | 908 void |
904 { | 909 SDL_FreeSurface(SDL_Surface * surface) |
905 /* Free anything that's not NULL, and not the screen surface */ | 910 { |
906 if ((surface == NULL) || | 911 if (surface == NULL) { |
907 (current_video && | 912 return; |
908 ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) { | 913 } |
909 return; | 914 if (--surface->refcount > 0) { |
910 } | 915 return; |
911 if ( --surface->refcount > 0 ) { | 916 } |
912 return; | 917 while (surface->locked > 0) { |
913 } | 918 SDL_UnlockSurface(surface); |
914 while ( surface->locked > 0 ) { | 919 } |
915 SDL_UnlockSurface(surface); | 920 if (surface->flags & SDL_RLEACCEL) { |
916 } | 921 SDL_UnRLESurface(surface, 0); |
917 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | 922 } |
918 SDL_UnRLESurface(surface, 0); | 923 if (surface->format) { |
919 } | 924 SDL_SetSurfacePalette(surface, NULL); |
920 if ( surface->format ) { | 925 SDL_FreeFormat(surface->format); |
921 SDL_FreeFormat(surface->format); | 926 surface->format = NULL; |
922 surface->format = NULL; | 927 } |
923 } | 928 if (surface->map != NULL) { |
924 if ( surface->map != NULL ) { | 929 SDL_FreeBlitMap(surface->map); |
925 SDL_FreeBlitMap(surface->map); | 930 surface->map = NULL; |
926 surface->map = NULL; | 931 } |
927 } | 932 /* Should we destroy the texture too? |
928 if ( surface->hwdata ) { | 933 if (surface->textureID) { |
929 SDL_VideoDevice *video = current_video; | 934 SDL_DestroyTexture(surface->textureID); |
930 SDL_VideoDevice *this = current_video; | 935 } |
931 video->FreeHWSurface(this, surface); | 936 */ |
932 } | 937 if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) { |
933 if ( surface->pixels && | 938 SDL_free(surface->pixels); |
934 ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) { | 939 } |
935 SDL_free(surface->pixels); | 940 SDL_free(surface); |
936 } | |
937 SDL_free(surface); | |
938 #ifdef CHECK_LEAKS | 941 #ifdef CHECK_LEAKS |
939 --surfaces_allocated; | 942 --surfaces_allocated; |
940 #endif | 943 #endif |
941 } | 944 } |
945 | |
946 /* vi: set ts=4 sw=4 expandtab: */ |