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: */