Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
    SDL - Simple DirectMedia Layer
3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
4
 
5
    This library is free software; you can redistribute it and/or
6
    modify it under the terms of the GNU Library General Public
7
    License as published by the Free Software Foundation; either
8
    version 2 of the License, or (at your option) any later version.
9
 
10
    This library is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
    Library General Public License for more details.
14
 
15
    You should have received a copy of the GNU Library General Public
16
    License along with this library; if not, write to the Free
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
19
    Sam Lantinga
20
    slouken@devolution.com
21
*/
22
 
23
 
24
#include 
25
#include 
26
#include 
27
 
28
#include "SDL_error.h"
29
#include "SDL_video.h"
30
#include "SDL_sysvideo.h"
31
#include "SDL_cursor_c.h"
32
#include "SDL_blit.h"
33
#include "SDL_RLEaccel_c.h"
34
#include "SDL_pixels_c.h"
35
#include "SDL_memops.h"
36
#include "SDL_leaks.h"
37
 
38
/* Public routines */
39
/*
40
 * Create an empty RGB surface of the appropriate depth
41
 */
42
SDL_Surface * SDL_CreateRGBSurface (Uint32 flags,
43
			int width, int height, int depth,
44
			Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
45
{
46
	SDL_VideoDevice *video = current_video;
47
	SDL_VideoDevice *this  = current_video;
48
	SDL_Surface *screen;
49
	SDL_Surface *surface;
50
 
51
	/* Check to see if we desire the surface in video memory */
52
	if ( video ) {
53
		screen = SDL_PublicSurface;
54
	} else {
55
		screen = NULL;
56
	}
57
	if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) {
58
		if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) {
59
			flags |= SDL_HWSURFACE;
60
		}
61
		if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
62
			if ( ! current_video->info.blit_hw_CC ) {
63
				flags &= ~SDL_HWSURFACE;
64
			}
65
		}
66
		if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
67
			if ( ! current_video->info.blit_hw_A ) {
68
				flags &= ~SDL_HWSURFACE;
69
			}
70
		}
71
	} else {
72
		flags &= ~SDL_HWSURFACE;
73
	}
74
 
75
	/* Allocate the surface */
76
	surface = (SDL_Surface *)malloc(sizeof(*surface));
77
	if ( surface == NULL ) {
78
		SDL_OutOfMemory();
79
		return(NULL);
80
	}
81
	surface->flags = SDL_SWSURFACE;
82
	if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
83
		depth = screen->format->BitsPerPixel;
84
		Rmask = screen->format->Rmask;
85
		Gmask = screen->format->Gmask;
86
		Bmask = screen->format->Bmask;
87
		Amask = screen->format->Amask;
88
	}
89
	surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
90
	if ( surface->format == NULL ) {
91
		free(surface);
92
		return(NULL);
93
	}
94
	if ( Amask ) {
95
		surface->flags |= SDL_SRCALPHA;
96
	}
97
	surface->w = width;
98
	surface->h = height;
99
	surface->pitch = SDL_CalculatePitch(surface);
100
	surface->pixels = NULL;
101
	surface->offset = 0;
102
	surface->hwdata = NULL;
103
	surface->locked = 0;
104
	surface->map = NULL;
105
	surface->format_version = 0;
106
	SDL_SetClipRect(surface, NULL);
107
 
108
	/* Get the pixels */
109
	if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) ||
110
				(video->AllocHWSurface(this, surface) < 0) ) {
111
		if ( surface->w && surface->h ) {
112
			surface->pixels = malloc(surface->h*surface->pitch);
113
			if ( surface->pixels == NULL ) {
114
				SDL_FreeSurface(surface);
115
				SDL_OutOfMemory();
116
				return(NULL);
117
			}
118
			/* This is important for bitmaps */
119
			memset(surface->pixels, 0, surface->h*surface->pitch);
120
		}
121
	}
122
 
123
	/* Allocate an empty mapping */
124
	surface->map = SDL_AllocBlitMap();
125
	if ( surface->map == NULL ) {
126
		SDL_FreeSurface(surface);
127
		return(NULL);
128
	}
129
 
130
	/* The surface is ready to go */
131
	surface->refcount = 1;
132
#ifdef CHECK_LEAKS
133
	++surfaces_allocated;
134
#endif
135
	return(surface);
136
}
137
/*
138
 * Create an RGB surface from an existing memory buffer
139
 */
140
SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels,
141
			int width, int height, int depth, int pitch,
142
			Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
143
{
144
	SDL_Surface *surface;
145
 
146
	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth,
147
	                               Rmask, Gmask, Bmask, Amask);
148
	if ( surface != NULL ) {
149
		surface->flags |= SDL_PREALLOC;
150
		surface->pixels = pixels;
151
		surface->w = width;
152
		surface->h = height;
153
		surface->pitch = pitch;
154
		SDL_SetClipRect(surface, NULL);
155
	}
156
	return(surface);
157
}
158
/*
159
 * Set the color key in a blittable surface
160
 */
161
int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key)
162
{
163
	/* Sanity check the flag as it gets passed in */
164
	if ( flag & SDL_SRCCOLORKEY ) {
165
		if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
166
			flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
167
		} else {
168
			flag = SDL_SRCCOLORKEY;
169
		}
170
	} else {
171
		flag = 0;
172
	}
173
 
174
	/* Optimize away operations that don't change anything */
175
	if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) &&
176
	     (key == surface->format->colorkey) ) {
177
		return(0);
178
	}
179
 
180
	/* UnRLE surfaces before we change the colorkey */
181
	if ( surface->flags & SDL_RLEACCEL ) {
182
	        SDL_UnRLESurface(surface, 1);
183
	}
184
 
185
	if ( flag ) {
186
		SDL_VideoDevice *video = current_video;
187
		SDL_VideoDevice *this  = current_video;
188
 
189
 
190
		surface->flags |= SDL_SRCCOLORKEY;
191
		surface->format->colorkey = key;
192
		if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
193
			if ( (video->SetHWColorKey == NULL) ||
194
			     (video->SetHWColorKey(this, surface, key) < 0) ) {
195
				surface->flags &= ~SDL_HWACCEL;
196
			}
197
		}
198
		if ( flag & SDL_RLEACCELOK ) {
199
			surface->flags |= SDL_RLEACCELOK;
200
		} else {
201
			surface->flags &= ~SDL_RLEACCELOK;
202
		}
203
	} else {
204
		surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
205
		surface->format->colorkey = 0;
206
	}
207
	SDL_InvalidateMap(surface->map);
208
	return(0);
209
}
210
int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value)
211
{
212
	Uint32 oldflags = surface->flags;
213
	Uint32 oldalpha = surface->format->alpha;
214
 
215
	/* Sanity check the flag as it gets passed in */
216
	if ( flag & SDL_SRCALPHA ) {
217
		if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
218
			flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
219
		} else {
220
			flag = SDL_SRCALPHA;
221
		}
222
	} else {
223
		flag = 0;
224
	}
225
 
226
	/* Optimize away operations that don't change anything */
227
	if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) &&
228
	     (!flag || value == oldalpha) ) {
229
		return(0);
230
	}
231
 
232
	if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
233
		SDL_UnRLESurface(surface, 1);
234
 
235
	if ( flag ) {
236
		SDL_VideoDevice *video = current_video;
237
		SDL_VideoDevice *this  = current_video;
238
 
239
		surface->flags |= SDL_SRCALPHA;
240
		surface->format->alpha = value;
241
		if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
242
			if ( (video->SetHWAlpha == NULL) ||
243
			     (video->SetHWAlpha(this, surface, value) < 0) ) {
244
				surface->flags &= ~SDL_HWACCEL;
245
			}
246
		}
247
		if ( flag & SDL_RLEACCELOK ) {
248
		        surface->flags |= SDL_RLEACCELOK;
249
		} else {
250
		        surface->flags &= ~SDL_RLEACCELOK;
251
		}
252
	} else {
253
		surface->flags &= ~SDL_SRCALPHA;
254
		surface->format->alpha = SDL_ALPHA_OPAQUE;
255
	}
256
	/*
257
	 * The representation for software surfaces is independent of
258
	 * per-surface alpha, so no need to invalidate the blit mapping
259
	 * if just the alpha value was changed. (If either is 255, we still
260
	 * need to invalidate.)
261
	 */
262
	if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL
263
	   || oldflags != surface->flags
264
	   || (((oldalpha + 1) ^ (value + 1)) & 0x100))
265
		SDL_InvalidateMap(surface->map);
266
	return(0);
267
}
268
 
269
/*
270
 * A function to calculate the intersection of two rectangles:
271
 * return true if the rectangles intersect, false otherwise
272
 */
273
static __inline__
274
SDL_bool SDL_IntersectRect(SDL_Rect *A, SDL_Rect *B, SDL_Rect *intersection)
275
{
276
	int Amin, Amax, Bmin, Bmax;
277
 
278
	/* Horizontal intersection */
279
	Amin = A->x;
280
	Amax = Amin + A->w;
281
	Bmin = B->x;
282
	Bmax = Bmin + B->w;
283
	if(Bmin > Amin)
284
	        Amin = Bmin;
285
	intersection->x = Amin;
286
	if(Bmax < Amax)
287
	        Amax = Bmax;
288
	intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
289
 
290
	/* Vertical intersection */
291
	Amin = A->y;
292
	Amax = Amin + A->h;
293
	Bmin = B->y;
294
	Bmax = Bmin + B->h;
295
	if(Bmin > Amin)
296
	        Amin = Bmin;
297
	intersection->y = Amin;
298
	if(Bmax < Amax)
299
	        Amax = Bmax;
300
	intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
301
 
302
	return (intersection->w && intersection->h);
303
}
304
/*
305
 * Set the clipping rectangle for a blittable surface
306
 */
307
SDL_bool SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect)
308
{
309
	SDL_Rect full_rect;
310
 
311
	/* Don't do anything if there's no surface to act on */
312
	if ( ! surface ) {
313
		return SDL_FALSE;
314
	}
315
 
316
	/* Set up the full surface rectangle */
317
	full_rect.x = 0;
318
	full_rect.y = 0;
319
	full_rect.w = surface->w;
320
	full_rect.h = surface->h;
321
 
322
	/* Set the clipping rectangle */
323
	if ( ! rect ) {
324
		surface->clip_rect = full_rect;
325
		return 1;
326
	}
327
	return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
328
}
329
void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
330
{
331
	if ( surface && rect ) {
332
		*rect = surface->clip_rect;
333
	}
334
}
335
/*
336
 * Set up a blit between two surfaces -- split into three parts:
337
 * The upper part, SDL_UpperBlit(), performs clipping and rectangle
338
 * verification.  The lower part is a pointer to a low level
339
 * accelerated blitting function.
340
 *
341
 * These parts are separated out and each used internally by this
342
 * library in the optimimum places.  They are exported so that if
343
 * you know exactly what you are doing, you can optimize your code
344
 * by calling the one(s) you need.
345
 */
346
int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect,
347
				SDL_Surface *dst, SDL_Rect *dstrect)
348
{
349
	SDL_blit do_blit;
350
 
351
	/* Check to make sure the blit mapping is valid */
352
	if ( (src->map->dst != dst) ||
353
             (src->map->dst->format_version != src->map->format_version) ) {
354
		if ( SDL_MapSurface(src, dst) < 0 ) {
355
			return(-1);
356
		}
357
	}
358
 
359
	/* Figure out which blitter to use */
360
	if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
361
		do_blit = src->map->hw_blit;
362
	} else {
363
		do_blit = src->map->sw_blit;
364
	}
365
	return(do_blit(src, srcrect, dst, dstrect));
366
}
367
 
368
 
369
int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect,
370
		   SDL_Surface *dst, SDL_Rect *dstrect)
371
{
372
        SDL_Rect fulldst;
373
	int srcx, srcy, w, h;
374
 
375
	/* Make sure the surfaces aren't locked */
376
	if ( ! src || ! dst ) {
377
		SDL_SetError("SDL_UpperBlit: passed a NULL surface");
378
		return(-1);
379
	}
380
	if ( src->locked || dst->locked ) {
381
		SDL_SetError("Surfaces must not be locked during blit");
382
		return(-1);
383
	}
384
 
385
	/* If the destination rectangle is NULL, use the entire dest surface */
386
	if ( dstrect == NULL ) {
387
	        fulldst.x = fulldst.y = 0;
388
		dstrect = &fulldst;
389
	}
390
 
391
	/* clip the source rectangle to the source surface */
392
	if(srcrect) {
393
	        int maxw, maxh;
394
 
395
		srcx = srcrect->x;
396
		w = srcrect->w;
397
		if(srcx < 0) {
398
		        w += srcx;
399
			dstrect->x -= srcx;
400
			srcx = 0;
401
		}
402
		maxw = src->w - srcx;
403
		if(maxw < w)
404
			w = maxw;
405
 
406
		srcy = srcrect->y;
407
		h = srcrect->h;
408
		if(srcy < 0) {
409
		        h += srcy;
410
			dstrect->y -= srcy;
411
			srcy = 0;
412
		}
413
		maxh = src->h - srcy;
414
		if(maxh < h)
415
			h = maxh;
416
 
417
	} else {
418
	        srcx = srcy = 0;
419
		w = src->w;
420
		h = src->h;
421
	}
422
 
423
	/* clip the destination rectangle against the clip rectangle */
424
	{
425
	        SDL_Rect *clip = &dst->clip_rect;
426
		int dx, dy;
427
 
428
		dx = clip->x - dstrect->x;
429
		if(dx > 0) {
430
			w -= dx;
431
			dstrect->x += dx;
432
			srcx += dx;
433
		}
434
		dx = dstrect->x + w - clip->x - clip->w;
435
		if(dx > 0)
436
			w -= dx;
437
 
438
		dy = clip->y - dstrect->y;
439
		if(dy > 0) {
440
			h -= dy;
441
			dstrect->y += dy;
442
			srcy += dy;
443
		}
444
		dy = dstrect->y + h - clip->y - clip->h;
445
		if(dy > 0)
446
			h -= dy;
447
	}
448
 
449
	if(w > 0 && h > 0) {
450
	        SDL_Rect sr;
451
	        sr.x = srcx;
452
		sr.y = srcy;
453
		sr.w = dstrect->w = w;
454
		sr.h = dstrect->h = h;
455
		return SDL_LowerBlit(src, &sr, dst, dstrect);
456
	}
457
	dstrect->w = dstrect->h = 0;
458
	return 0;
459
}
460
 
461
/*
462
 * This function performs a fast fill of the given rectangle with 'color'
463
 */
464
int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
465
{
466
	SDL_VideoDevice *video = current_video;
467
	SDL_VideoDevice *this  = current_video;
468
	int x, y;
469
	Uint8 *row;
470
 
471
	/* If 'dstrect' == NULL, then fill the whole surface */
472
	if ( dstrect ) {
473
		/* Perform clipping */
474
		if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) {
475
			return(0);
476
		}
477
	} else {
478
		dstrect = &dst->clip_rect;
479
	}
480
 
481
	/* Check for hardware acceleration */
482
	if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
483
					video->info.blit_fill ) {
484
		return(video->FillHWRect(this, dst, dstrect, color));
485
	}
486
 
487
	/* Perform software fill */
488
	if ( SDL_LockSurface(dst) != 0 ) {
489
		return(-1);
490
	}
491
	row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+
492
			dstrect->x*dst->format->BytesPerPixel;
493
	if ( dst->format->palette || (color == 0) ) {
494
		x = dstrect->w*dst->format->BytesPerPixel;
495
		if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) {
496
			int n = x >> 2;
497
			for ( y=dstrect->h; y; --y ) {
498
				SDL_memset4(row, 0, n);
499
				row += dst->pitch;
500
			}
501
		} else {
502
#ifdef __powerpc__
503
			/*
504
			 * memset() on PPC (both glibc and codewarrior) uses
505
			 * the dcbz (Data Cache Block Zero) instruction, which
506
			 * causes an alignment exception if the destination is
507
			 * uncachable, so only use it on software surfaces
508
			 */
509
			if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
510
				if(dstrect->w >= 8) {
511
					/*
512
					 * 64-bit stores are probably most
513
					 * efficient to uncached video memory
514
					 */
515
					double fill;
516
					memset(&fill, color, (sizeof fill));
517
					for(y = dstrect->h; y; y--) {
518
						Uint8 *d = row;
519
						unsigned n = x;
520
						unsigned nn;
521
						Uint8 c = color;
522
						double f = fill;
523
						while((unsigned long)d
524
						      & (sizeof(double) - 1)) {
525
							*d++ = c;
526
							n--;
527
						}
528
						nn = n / (sizeof(double) * 4);
529
						while(nn) {
530
							((double *)d)[0] = f;
531
							((double *)d)[1] = f;
532
							((double *)d)[2] = f;
533
							((double *)d)[3] = f;
534
							d += 4*sizeof(double);
535
							nn--;
536
						}
537
						n &= ~(sizeof(double) * 4 - 1);
538
						nn = n / sizeof(double);
539
						while(nn) {
540
							*(double *)d = f;
541
							d += sizeof(double);
542
							nn--;
543
						}
544
						n &= ~(sizeof(double) - 1);
545
						while(n) {
546
							*d++ = c;
547
							n--;
548
						}
549
						row += dst->pitch;
550
					}
551
				} else {
552
					/* narrow boxes */
553
					for(y = dstrect->h; y; y--) {
554
						Uint8 *d = row;
555
						Uint8 c = color;
556
						int n = x;
557
						while(n) {
558
							*d++ = c;
559
							n--;
560
						}
561
						row += dst->pitch;
562
					}
563
				}
564
			} else
565
#endif /* __powerpc__ */
566
			{
567
				for(y = dstrect->h; y; y--) {
568
					memset(row, color, x);
569
					row += dst->pitch;
570
				}
571
			}
572
		}
573
	} else {
574
		switch (dst->format->BytesPerPixel) {
575
		    case 2:
576
			for ( y=dstrect->h; y; --y ) {
577
				Uint16 *pixels = (Uint16 *)row;
578
				Uint16 c = color;
579
				Uint32 cc = (Uint32)c << 16 | c;
580
				int n = dstrect->w;
581
				if((unsigned long)pixels & 3) {
582
					*pixels++ = c;
583
					n--;
584
				}
585
				if(n >> 1)
586
					SDL_memset4(pixels, cc, n >> 1);
587
				if(n & 1)
588
					pixels[n - 1] = c;
589
				row += dst->pitch;
590
			}
591
			break;
592
 
593
		    case 3:
594
			if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
595
				color <<= 8;
596
			for ( y=dstrect->h; y; --y ) {
597
				Uint8 *pixels = row;
598
				for ( x=dstrect->w; x; --x ) {
599
					memcpy(pixels, &color, 3);
600
					pixels += 3;
601
				}
602
				row += dst->pitch;
603
			}
604
			break;
605
 
606
		    case 4:
607
			for(y = dstrect->h; y; --y) {
608
				SDL_memset4(row, color, dstrect->w);
609
				row += dst->pitch;
610
			}
611
			break;
612
		}
613
	}
614
	SDL_UnlockSurface(dst);
615
 
616
	/* We're done! */
617
	return(0);
618
}
619
 
620
/*
621
 * Lock a surface to directly access the pixels
622
 * -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
623
 *    Instead, use:
624
 *    if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
625
 *               video->LockHWSurface(video, surface);
626
 */
627
int SDL_LockSurface (SDL_Surface *surface)
628
{
629
	if ( ! surface->locked ) {
630
		/* Perform the lock */
631
		if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
632
			SDL_VideoDevice *video = current_video;
633
			SDL_VideoDevice *this  = current_video;
634
			if ( video->LockHWSurface(this, surface) < 0 ) {
635
				return(-1);
636
			}
637
		}
638
		if ( surface->flags & SDL_RLEACCEL ) {
639
			SDL_UnRLESurface(surface, 1);
640
			surface->flags |= SDL_RLEACCEL;	/* save accel'd state */
641
		}
642
		/* This needs to be done here in case pixels changes value */
643
		surface->pixels = (Uint8 *)surface->pixels + surface->offset;
644
	}
645
 
646
	/* Increment the surface lock count, for recursive locks */
647
	++surface->locked;
648
 
649
	/* Ready to go.. */
650
	return(0);
651
}
652
/*
653
 * Unlock a previously locked surface
654
 * -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
655
 *    Instead, use:
656
 *    if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
657
 *               video->UnlockHWSurface(video, surface);
658
 */
659
void SDL_UnlockSurface (SDL_Surface *surface)
660
{
661
	/* Only perform an unlock if we are locked */
662
	if ( ! surface->locked || (--surface->locked > 0) ) {
663
		return;
664
	}
665
 
666
	/* Perform the unlock */
667
	surface->pixels = (Uint8 *)surface->pixels - surface->offset;
668
 
669
	/* Unlock hardware or accelerated surfaces */
670
	if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
671
		SDL_VideoDevice *video = current_video;
672
		SDL_VideoDevice *this  = current_video;
673
		video->UnlockHWSurface(this, surface);
674
	} else {
675
		/* Update RLE encoded surface with new data */
676
		if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
677
		        surface->flags &= ~SDL_RLEACCEL; /* stop lying */
678
			SDL_RLESurface(surface);
679
		}
680
	}
681
}
682
 
683
/*
684
 * Convert a surface into the specified pixel format.
685
 */
686
SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface,
687
					SDL_PixelFormat *format, Uint32 flags)
688
{
689
	SDL_Surface *convert;
690
	Uint32 colorkey = 0;
691
	Uint8 alpha = 0;
692
	Uint32 surface_flags;
693
	SDL_Rect bounds;
694
 
695
	/* Check for empty destination palette! (results in empty image) */
696
	if ( format->palette != NULL ) {
697
		int i;
698
		for ( i=0; ipalette->ncolors; ++i ) {
699
			if ( (format->palette->colors[i].r != 0) ||
700
			     (format->palette->colors[i].g != 0) ||
701
			     (format->palette->colors[i].b != 0) )
702
				break;
703
		}
704
		if ( i == format->palette->ncolors ) {
705
			SDL_SetError("Empty destination palette");
706
			return(NULL);
707
		}
708
	}
709
 
710
	/* Create a new surface with the desired format */
711
	convert = SDL_CreateRGBSurface(flags,
712
				surface->w, surface->h, format->BitsPerPixel,
713
		format->Rmask, format->Gmask, format->Bmask, format->Amask);
714
	if ( convert == NULL ) {
715
		return(NULL);
716
	}
717
 
718
	/* Copy the palette if any */
719
	if ( format->palette && convert->format->palette ) {
720
		memcpy(convert->format->palette->colors,
721
				format->palette->colors,
722
				format->palette->ncolors*sizeof(SDL_Color));
723
		convert->format->palette->ncolors = format->palette->ncolors;
724
	}
725
 
726
	/* Save the original surface color key and alpha */
727
	surface_flags = surface->flags;
728
	if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
729
		/* Convert colourkeyed surfaces to RGBA if requested */
730
		if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY
731
		   && format->Amask) {
732
			surface_flags &= ~SDL_SRCCOLORKEY;
733
		} else {
734
			colorkey = surface->format->colorkey;
735
			SDL_SetColorKey(surface, 0, 0);
736
		}
737
	}
738
	if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
739
		alpha = surface->format->alpha;
740
		SDL_SetAlpha(surface, 0, 0);
741
	}
742
 
743
	/* Copy over the image data */
744
	bounds.x = 0;
745
	bounds.y = 0;
746
	bounds.w = surface->w;
747
	bounds.h = surface->h;
748
	SDL_LowerBlit(surface, &bounds, convert, &bounds);
749
 
750
	/* Clean up the original surface, and update converted surface */
751
	if ( convert != NULL ) {
752
		SDL_SetClipRect(convert, &surface->clip_rect);
753
	}
754
	if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
755
		Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
756
		if ( convert != NULL ) {
757
			Uint8 keyR, keyG, keyB;
758
 
759
			SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
760
			SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK),
761
				SDL_MapRGB(convert->format, keyR, keyG, keyB));
762
		}
763
		SDL_SetColorKey(surface, cflags, colorkey);
764
	}
765
	if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
766
		Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
767
		if ( convert != NULL ) {
768
		        SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK),
769
				alpha);
770
		}
771
		SDL_SetAlpha(surface, aflags, alpha);
772
	}
773
 
774
	/* We're ready to go! */
775
	return(convert);
776
}
777
 
778
/*
779
 * Free a surface created by the above function.
780
 */
781
void SDL_FreeSurface (SDL_Surface *surface)
782
{
783
	/* Free anything that's not NULL, and not the screen surface */
784
	if ((surface == NULL) ||
785
	    (current_video &&
786
	    ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) {
787
		return;
788
	}
789
	if ( --surface->refcount > 0 ) {
790
		return;
791
	}
792
	if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
793
	        SDL_UnRLESurface(surface, 0);
794
	}
795
	if ( surface->format ) {
796
		SDL_FreeFormat(surface->format);
797
		surface->format = NULL;
798
	}
799
	if ( surface->map != NULL ) {
800
		SDL_FreeBlitMap(surface->map);
801
		surface->map = NULL;
802
	}
803
	if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
804
		SDL_VideoDevice *video = current_video;
805
		SDL_VideoDevice *this  = current_video;
806
		video->FreeHWSurface(this, surface);
807
	}
808
	if ( surface->pixels &&
809
	     ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) {
810
		free(surface->pixels);
811
	}
812
	free(surface);
813
#ifdef CHECK_LEAKS
814
	--surfaces_allocated;
815
#endif
816
}