comparison src/video/SDL_pixels.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 61c237f69076
children 8a162bfdc838
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
29 #include "SDL_blit.h" 29 #include "SDL_blit.h"
30 #include "SDL_pixels_c.h" 30 #include "SDL_pixels_c.h"
31 #include "SDL_RLEaccel_c.h" 31 #include "SDL_RLEaccel_c.h"
32 32
33 /* Helper functions */ 33 /* Helper functions */
34
35 SDL_bool
36 SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
37 Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
38 {
39 Uint32 masks[4];
40
41 /* Initialize the values here */
42 if (SDL_BITSPERPIXEL(format) == 24) {
43 *bpp = SDL_BYTESPERPIXEL(format) * 8;
44 } else {
45 *bpp = SDL_BITSPERPIXEL(format);
46 }
47 *Rmask = *Gmask = *Bmask = *Amask = 0;
48
49 if (SDL_PIXELTYPE(format) != SDL_PixelType_Packed8 &&
50 SDL_PIXELTYPE(format) != SDL_PixelType_Packed16 &&
51 SDL_PIXELTYPE(format) != SDL_PixelType_Packed32) {
52 /* Not a format that uses masks */
53 return SDL_TRUE;
54 }
55
56 switch (SDL_PIXELLAYOUT(format)) {
57 case SDL_PackedLayout_332:
58 masks[0] = 0x00000000;
59 masks[1] = 0x000000E0;
60 masks[2] = 0x0000001C;
61 masks[3] = 0x00000003;
62 break;
63 case SDL_PackedLayout_4444:
64 masks[0] = 0x0000F000;
65 masks[1] = 0x00000F00;
66 masks[2] = 0x000000F0;
67 masks[3] = 0x0000000F;
68 break;
69 case SDL_PackedLayout_1555:
70 masks[0] = 0x00008000;
71 masks[1] = 0x00007C00;
72 masks[2] = 0x000003E0;
73 masks[3] = 0x0000001F;
74 break;
75 case SDL_PackedLayout_565:
76 masks[0] = 0x00000000;
77 masks[1] = 0x0000F800;
78 masks[2] = 0x000007E0;
79 masks[3] = 0x0000001F;
80 break;
81 case SDL_PackedLayout_8888:
82 masks[0] = 0xFF000000;
83 masks[1] = 0x00FF0000;
84 masks[2] = 0x0000FF00;
85 masks[3] = 0x000000FF;
86 break;
87 case SDL_PackedLayout_2101010:
88 masks[0] = 0xC0000000;
89 masks[1] = 0x3FF00000;
90 masks[2] = 0x000FFC00;
91 masks[3] = 0x000003FF;
92 break;
93 default:
94 /* Unknown layout */
95 return SDL_FALSE;
96 }
97
98 switch (SDL_PIXELORDER(format)) {
99 case SDL_PackedOrder_XRGB:
100 *Rmask = masks[1];
101 *Gmask = masks[2];
102 *Bmask = masks[3];
103 break;
104 case SDL_PackedOrder_RGBX:
105 *Rmask = masks[0];
106 *Gmask = masks[1];
107 *Bmask = masks[2];
108 break;
109 case SDL_PackedOrder_ARGB:
110 *Amask = masks[0];
111 *Rmask = masks[1];
112 *Gmask = masks[2];
113 *Bmask = masks[3];
114 break;
115 case SDL_PackedOrder_RGBA:
116 *Rmask = masks[0];
117 *Gmask = masks[1];
118 *Bmask = masks[2];
119 *Amask = masks[3];
120 break;
121 case SDL_PackedOrder_XBGR:
122 *Bmask = masks[1];
123 *Gmask = masks[2];
124 *Rmask = masks[3];
125 break;
126 case SDL_PackedOrder_BGRX:
127 *Bmask = masks[0];
128 *Gmask = masks[1];
129 *Rmask = masks[2];
130 break;
131 case SDL_PackedOrder_BGRA:
132 *Bmask = masks[0];
133 *Gmask = masks[1];
134 *Rmask = masks[2];
135 *Amask = masks[3];
136 break;
137 case SDL_PackedOrder_ABGR:
138 *Amask = masks[0];
139 *Bmask = masks[1];
140 *Gmask = masks[2];
141 *Rmask = masks[3];
142 break;
143 default:
144 /* Unknown order */
145 return SDL_FALSE;
146 }
147 return SDL_TRUE;
148 }
149
150 Uint32
151 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
152 Uint32 Amask)
153 {
154 switch (bpp) {
155 case 8:
156 switch (Rmask) {
157 case 0:
158 return SDL_PixelFormat_Index8;
159 case 0xE0:
160 return SDL_PixelFormat_RGB332;
161 }
162 break;
163 case 12:
164 switch (Rmask) {
165 case 0x0F00:
166 return SDL_PixelFormat_RGB444;
167 }
168 break;
169 case 15:
170 switch (Rmask) {
171 case 0x7C00:
172 return SDL_PixelFormat_RGB555;
173 }
174 break;
175 case 16:
176 switch (Rmask) {
177 case 0x0F00:
178 return SDL_PixelFormat_ARGB4444;
179 case 0x7C00:
180 return SDL_PixelFormat_ARGB1555;
181 case 0xF800:
182 return SDL_PixelFormat_RGB565;
183 }
184 break;
185 case 32:
186 switch (Rmask) {
187 case 0xFF000000:
188 if (Amask == 0x000000FF) {
189 return SDL_PixelFormat_RGBA8888;
190 }
191 break;
192 case 0x00FF0000:
193 if (Amask == 0xFF000000) {
194 return SDL_PixelFormat_ARGB8888;
195 } else {
196 return SDL_PixelFormat_RGB888;
197 }
198 break;
199 case 0x0000FF00:
200 if (Amask == 0x000000FF) {
201 return SDL_PixelFormat_BGRA8888;
202 }
203 break;
204 case 0x000000FF:
205 if (Amask == 0xFF000000) {
206 return SDL_PixelFormat_ABGR8888;
207 } else {
208 return SDL_PixelFormat_BGR888;
209 }
210 break;
211 case 0x3FF00000:
212 return SDL_PixelFormat_ARGB2101010;
213 }
214 }
215 return SDL_PixelFormat_Unknown;
216 }
217
218
219 SDL_Palette *
220 SDL_AllocPalette(int ncolors)
221 {
222 SDL_Palette *palette;
223
224 palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
225 if (!palette) {
226 SDL_OutOfMemory();
227 return NULL;
228 }
229 palette->colors =
230 (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
231 if (!palette->colors) {
232 SDL_free(palette);
233 return NULL;
234 }
235 palette->ncolors = ncolors;
236 palette->watch = NULL;
237 palette->refcount = 1;
238
239 SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
240
241 return palette;
242 }
243
244 int
245 SDL_AddPaletteWatch(SDL_Palette * palette, SDL_PaletteChangedFunc callback,
246 void *userdata)
247 {
248 SDL_PaletteWatch *watch;
249
250 if (!palette) {
251 return -1;
252 }
253
254 watch = (SDL_PaletteWatch *) SDL_malloc(sizeof(*watch));
255 if (!watch) {
256 SDL_OutOfMemory();
257 return -1;
258 }
259
260 watch->callback = callback;
261 watch->userdata = userdata;
262 watch->next = palette->watch;
263 palette->watch = watch;
264 ++palette->refcount;
265 return 0;
266 }
267
268 void
269 SDL_DelPaletteWatch(SDL_Palette * palette, SDL_PaletteChangedFunc callback,
270 void *userdata)
271 {
272 SDL_PaletteWatch *prev, *watch;
273
274 if (!palette) {
275 return;
276 }
277
278 for (prev = NULL, watch = palette->watch; watch;
279 prev = watch, watch = watch->next) {
280 if (watch->callback == callback && watch->userdata == userdata) {
281 if (prev) {
282 prev->next = watch->next;
283 } else {
284 palette->watch = watch->next;
285 }
286 SDL_free(watch);
287 SDL_FreePalette(palette);
288 return;
289 }
290 }
291 }
292
293 int
294 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
295 int firstcolor, int ncolors)
296 {
297 SDL_PaletteWatch *watch;
298 int status = 0;
299
300 /* Verify the parameters */
301 if (!palette) {
302 return -1;
303 }
304 if (ncolors > (palette->ncolors - firstcolor)) {
305 ncolors = (palette->ncolors - firstcolor);
306 status = -1;
307 }
308
309 if (colors != (palette->colors + firstcolor)) {
310 SDL_memcpy(palette->colors + firstcolor, colors,
311 ncolors * sizeof(*colors));
312 }
313
314 for (watch = palette->watch; watch; watch = watch->next) {
315 if (watch->callback(watch->userdata, palette) < 0) {
316 status = -1;
317 }
318 }
319
320 return status;
321 }
322
323 void
324 SDL_FreePalette(SDL_Palette * palette)
325 {
326 if (!palette) {
327 return;
328 }
329 if (--palette->refcount > 0) {
330 return;
331 }
332 if (palette->colors) {
333 SDL_free(palette->colors);
334 }
335 SDL_free(palette);
336 }
337
34 /* 338 /*
35 * Allocate a pixel format structure and fill it according to the given info. 339 * Allocate a pixel format structure and fill it according to the given info.
36 */ 340 */
37 SDL_PixelFormat *SDL_AllocFormat(int bpp, 341 SDL_PixelFormat *
38 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) 342 SDL_AllocFormat(int bpp,
39 { 343 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
40 SDL_PixelFormat *format; 344 {
41 Uint32 mask; 345 SDL_PixelFormat *format;
42 346 Uint32 mask;
43 /* Allocate an empty pixel format structure */ 347
44 format = SDL_malloc(sizeof(*format)); 348 /* Allocate an empty pixel format structure */
45 if ( format == NULL ) { 349 format = SDL_malloc(sizeof(*format));
46 SDL_OutOfMemory(); 350 if (format == NULL) {
47 return(NULL); 351 SDL_OutOfMemory();
48 } 352 return (NULL);
49 SDL_memset(format, 0, sizeof(*format)); 353 }
50 format->alpha = SDL_ALPHA_OPAQUE; 354 SDL_memset(format, 0, sizeof(*format));
51 355 format->alpha = SDL_ALPHA_OPAQUE;
52 /* Set up the format */ 356
53 format->BitsPerPixel = bpp; 357 /* Set up the format */
54 format->BytesPerPixel = (bpp+7)/8; 358 format->BitsPerPixel = bpp;
55 if ( Rmask || Bmask || Gmask ) { /* Packed pixels with custom mask */ 359 format->BytesPerPixel = (bpp + 7) / 8;
56 format->palette = NULL; 360 if (Rmask || Bmask || Gmask) { /* Packed pixels with custom mask */
57 format->Rshift = 0; 361 format->Rshift = 0;
58 format->Rloss = 8; 362 format->Rloss = 8;
59 if ( Rmask ) { 363 if (Rmask) {
60 for ( mask = Rmask; !(mask&0x01); mask >>= 1 ) 364 for (mask = Rmask; !(mask & 0x01); mask >>= 1)
61 ++format->Rshift; 365 ++format->Rshift;
62 for ( ; (mask&0x01); mask >>= 1 ) 366 for (; (mask & 0x01); mask >>= 1)
63 --format->Rloss; 367 --format->Rloss;
64 } 368 }
65 format->Gshift = 0; 369 format->Gshift = 0;
66 format->Gloss = 8; 370 format->Gloss = 8;
67 if ( Gmask ) { 371 if (Gmask) {
68 for ( mask = Gmask; !(mask&0x01); mask >>= 1 ) 372 for (mask = Gmask; !(mask & 0x01); mask >>= 1)
69 ++format->Gshift; 373 ++format->Gshift;
70 for ( ; (mask&0x01); mask >>= 1 ) 374 for (; (mask & 0x01); mask >>= 1)
71 --format->Gloss; 375 --format->Gloss;
72 } 376 }
73 format->Bshift = 0; 377 format->Bshift = 0;
74 format->Bloss = 8; 378 format->Bloss = 8;
75 if ( Bmask ) { 379 if (Bmask) {
76 for ( mask = Bmask; !(mask&0x01); mask >>= 1 ) 380 for (mask = Bmask; !(mask & 0x01); mask >>= 1)
77 ++format->Bshift; 381 ++format->Bshift;
78 for ( ; (mask&0x01); mask >>= 1 ) 382 for (; (mask & 0x01); mask >>= 1)
79 --format->Bloss; 383 --format->Bloss;
80 } 384 }
81 format->Ashift = 0; 385 format->Ashift = 0;
82 format->Aloss = 8; 386 format->Aloss = 8;
83 if ( Amask ) { 387 if (Amask) {
84 for ( mask = Amask; !(mask&0x01); mask >>= 1 ) 388 for (mask = Amask; !(mask & 0x01); mask >>= 1)
85 ++format->Ashift; 389 ++format->Ashift;
86 for ( ; (mask&0x01); mask >>= 1 ) 390 for (; (mask & 0x01); mask >>= 1)
87 --format->Aloss; 391 --format->Aloss;
88 } 392 }
89 format->Rmask = Rmask; 393 format->Rmask = Rmask;
90 format->Gmask = Gmask; 394 format->Gmask = Gmask;
91 format->Bmask = Bmask; 395 format->Bmask = Bmask;
92 format->Amask = Amask; 396 format->Amask = Amask;
93 } else if ( bpp > 8 ) { /* Packed pixels with standard mask */ 397 } else if (bpp > 8) { /* Packed pixels with standard mask */
94 /* R-G-B */ 398 /* R-G-B */
95 if ( bpp > 24 ) 399 if (bpp > 24)
96 bpp = 24; 400 bpp = 24;
97 format->Rloss = 8-(bpp/3); 401 format->Rloss = 8 - (bpp / 3);
98 format->Gloss = 8-(bpp/3)-(bpp%3); 402 format->Gloss = 8 - (bpp / 3) - (bpp % 3);
99 format->Bloss = 8-(bpp/3); 403 format->Bloss = 8 - (bpp / 3);
100 format->Rshift = ((bpp/3)+(bpp%3))+(bpp/3); 404 format->Rshift = ((bpp / 3) + (bpp % 3)) + (bpp / 3);
101 format->Gshift = (bpp/3); 405 format->Gshift = (bpp / 3);
102 format->Bshift = 0; 406 format->Bshift = 0;
103 format->Rmask = ((0xFF>>format->Rloss)<<format->Rshift); 407 format->Rmask = ((0xFF >> format->Rloss) << format->Rshift);
104 format->Gmask = ((0xFF>>format->Gloss)<<format->Gshift); 408 format->Gmask = ((0xFF >> format->Gloss) << format->Gshift);
105 format->Bmask = ((0xFF>>format->Bloss)<<format->Bshift); 409 format->Bmask = ((0xFF >> format->Bloss) << format->Bshift);
106 } else { 410 } else {
107 /* Palettized formats have no mask info */ 411 /* Palettized formats have no mask info */
108 format->Rloss = 8; 412 format->Rloss = 8;
109 format->Gloss = 8; 413 format->Gloss = 8;
110 format->Bloss = 8; 414 format->Bloss = 8;
111 format->Aloss = 8; 415 format->Aloss = 8;
112 format->Rshift = 0; 416 format->Rshift = 0;
113 format->Gshift = 0; 417 format->Gshift = 0;
114 format->Bshift = 0; 418 format->Bshift = 0;
115 format->Ashift = 0; 419 format->Ashift = 0;
116 format->Rmask = 0; 420 format->Rmask = 0;
117 format->Gmask = 0; 421 format->Gmask = 0;
118 format->Bmask = 0; 422 format->Bmask = 0;
119 format->Amask = 0; 423 format->Amask = 0;
120 } 424 }
121 if ( bpp <= 8 ) { /* Palettized mode */ 425 format->palette = NULL;
122 int ncolors = 1<<bpp; 426
123 #ifdef DEBUG_PALETTE 427 return (format);
124 fprintf(stderr,"bpp=%d ncolors=%d\n",bpp,ncolors);
125 #endif
126 format->palette = (SDL_Palette *)SDL_malloc(sizeof(SDL_Palette));
127 if ( format->palette == NULL ) {
128 SDL_FreeFormat(format);
129 SDL_OutOfMemory();
130 return(NULL);
131 }
132 (format->palette)->ncolors = ncolors;
133 (format->palette)->colors = (SDL_Color *)SDL_malloc(
134 (format->palette)->ncolors*sizeof(SDL_Color));
135 if ( (format->palette)->colors == NULL ) {
136 SDL_FreeFormat(format);
137 SDL_OutOfMemory();
138 return(NULL);
139 }
140 if ( Rmask || Bmask || Gmask ) {
141 /* create palette according to masks */
142 int i;
143 int Rm=0,Gm=0,Bm=0;
144 int Rw=0,Gw=0,Bw=0;
145 #ifdef ENABLE_PALETTE_ALPHA
146 int Am=0,Aw=0;
147 #endif
148 if(Rmask)
149 {
150 Rw=8-format->Rloss;
151 for(i=format->Rloss;i>0;i-=Rw)
152 Rm|=1<<i;
153 }
154 #ifdef DEBUG_PALETTE
155 fprintf(stderr,"Rw=%d Rm=0x%02X\n",Rw,Rm);
156 #endif
157 if(Gmask)
158 {
159 Gw=8-format->Gloss;
160 for(i=format->Gloss;i>0;i-=Gw)
161 Gm|=1<<i;
162 }
163 #ifdef DEBUG_PALETTE
164 fprintf(stderr,"Gw=%d Gm=0x%02X\n",Gw,Gm);
165 #endif
166 if(Bmask)
167 {
168 Bw=8-format->Bloss;
169 for(i=format->Bloss;i>0;i-=Bw)
170 Bm|=1<<i;
171 }
172 #ifdef DEBUG_PALETTE
173 fprintf(stderr,"Bw=%d Bm=0x%02X\n",Bw,Bm);
174 #endif
175 #ifdef ENABLE_PALETTE_ALPHA
176 if(Amask)
177 {
178 Aw=8-format->Aloss;
179 for(i=format->Aloss;i>0;i-=Aw)
180 Am|=1<<i;
181 }
182 # ifdef DEBUG_PALETTE
183 fprintf(stderr,"Aw=%d Am=0x%02X\n",Aw,Am);
184 # endif
185 #endif
186 for(i=0; i < ncolors; ++i) {
187 int r,g,b;
188 r=(i&Rmask)>>format->Rshift;
189 r=(r<<format->Rloss)|((r*Rm)>>Rw);
190 format->palette->colors[i].r=r;
191
192 g=(i&Gmask)>>format->Gshift;
193 g=(g<<format->Gloss)|((g*Gm)>>Gw);
194 format->palette->colors[i].g=g;
195
196 b=(i&Bmask)>>format->Bshift;
197 b=(b<<format->Bloss)|((b*Bm)>>Bw);
198 format->palette->colors[i].b=b;
199
200 #ifdef ENABLE_PALETTE_ALPHA
201 a=(i&Amask)>>format->Ashift;
202 a=(a<<format->Aloss)|((a*Am)>>Aw);
203 format->palette->colors[i].unused=a;
204 #else
205 format->palette->colors[i].unused=0;
206 #endif
207 }
208 } else if ( ncolors == 2 ) {
209 /* Create a black and white bitmap palette */
210 format->palette->colors[0].r = 0xFF;
211 format->palette->colors[0].g = 0xFF;
212 format->palette->colors[0].b = 0xFF;
213 format->palette->colors[1].r = 0x00;
214 format->palette->colors[1].g = 0x00;
215 format->palette->colors[1].b = 0x00;
216 } else {
217 /* Create an empty palette */
218 SDL_memset((format->palette)->colors, 0,
219 (format->palette)->ncolors*sizeof(SDL_Color));
220 }
221 }
222 return(format);
223 }
224 SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp,
225 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
226 {
227 if ( surface->format ) {
228 SDL_FreeFormat(surface->format);
229 SDL_FormatChanged(surface);
230 }
231 surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
232 return surface->format;
233 } 428 }
234 429
235 /* 430 /*
236 * Change any previous mappings from/to the new surface format 431 * Change any previous mappings from/to the new surface format
237 */ 432 */
238 void SDL_FormatChanged(SDL_Surface *surface) 433 void
239 { 434 SDL_FormatChanged(SDL_Surface * surface)
240 static int format_version = 0; 435 {
241 ++format_version; 436 static int format_version = 0;
242 if ( format_version < 0 ) { /* It wrapped... */ 437 ++format_version;
243 format_version = 1; 438 if (format_version < 0) { /* It wrapped... */
244 } 439 format_version = 1;
245 surface->format_version = format_version; 440 }
246 SDL_InvalidateMap(surface->map); 441 surface->format_version = format_version;
247 } 442 SDL_InvalidateMap(surface->map);
443 }
444
248 /* 445 /*
249 * Free a previously allocated format structure 446 * Free a previously allocated format structure
250 */ 447 */
251 void SDL_FreeFormat(SDL_PixelFormat *format) 448 void
252 { 449 SDL_FreeFormat(SDL_PixelFormat * format)
253 if ( format ) { 450 {
254 if ( format->palette ) { 451 if (!format) {
255 if ( format->palette->colors ) { 452 return;
256 SDL_free(format->palette->colors); 453 }
257 } 454 SDL_free(format);
258 SDL_free(format->palette); 455 }
259 } 456
260 SDL_free(format);
261 }
262 }
263 /* 457 /*
264 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors 458 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
265 */ 459 */
266 void SDL_DitherColors(SDL_Color *colors, int bpp) 460 void
267 { 461 SDL_DitherColors(SDL_Color * colors, int bpp)
268 int i; 462 {
269 if(bpp != 8) 463 int i;
270 return; /* only 8bpp supported right now */ 464 if (bpp != 8)
271 465 return; /* only 8bpp supported right now */
272 for(i = 0; i < 256; i++) { 466
273 int r, g, b; 467 for (i = 0; i < 256; i++) {
274 /* map each bit field to the full [0, 255] interval, 468 int r, g, b;
275 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ 469 /* map each bit field to the full [0, 255] interval,
276 r = i & 0xe0; 470 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
277 r |= r >> 3 | r >> 6; 471 r = i & 0xe0;
278 colors[i].r = r; 472 r |= r >> 3 | r >> 6;
279 g = (i << 3) & 0xe0; 473 colors[i].r = r;
280 g |= g >> 3 | g >> 6; 474 g = (i << 3) & 0xe0;
281 colors[i].g = g; 475 g |= g >> 3 | g >> 6;
282 b = i & 0x3; 476 colors[i].g = g;
283 b |= b << 2; 477 b = i & 0x3;
284 b |= b << 4; 478 b |= b << 2;
285 colors[i].b = b; 479 b |= b << 4;
286 } 480 colors[i].b = b;
287 } 481 colors[i].unused = SDL_ALPHA_OPAQUE;
482 }
483 }
484
288 /* 485 /*
289 * Calculate the pad-aligned scanline width of a surface 486 * Calculate the pad-aligned scanline width of a surface
290 */ 487 */
291 Uint16 SDL_CalculatePitch(SDL_Surface *surface) 488 int
292 { 489 SDL_CalculatePitch(SDL_Surface * surface)
293 Uint16 pitch; 490 {
294 491 int pitch;
295 /* Surface should be 4-byte aligned for speed */ 492
296 pitch = surface->w*surface->format->BytesPerPixel; 493 /* Surface should be 4-byte aligned for speed */
297 switch (surface->format->BitsPerPixel) { 494 pitch = surface->w * surface->format->BytesPerPixel;
298 case 1: 495 switch (surface->format->BitsPerPixel) {
299 pitch = (pitch+7)/8; 496 case 1:
300 break; 497 pitch = (pitch + 7) / 8;
301 case 4: 498 break;
302 pitch = (pitch+1)/2; 499 case 4:
303 break; 500 pitch = (pitch + 1) / 2;
304 default: 501 break;
305 break; 502 default:
306 } 503 break;
307 pitch = (pitch + 3) & ~3; /* 4-byte aligning */ 504 }
308 return(pitch); 505 pitch = (pitch + 3) & ~3; /* 4-byte aligning */
309 } 506 return (pitch);
507 }
508
310 /* 509 /*
311 * Match an RGB value to a particular palette index 510 * Match an RGB value to a particular palette index
312 */ 511 */
313 Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b) 512 Uint8
314 { 513 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b)
315 /* Do colorspace distance matching */ 514 {
316 unsigned int smallest; 515 /* Do colorspace distance matching */
317 unsigned int distance; 516 unsigned int smallest;
318 int rd, gd, bd; 517 unsigned int distance;
319 int i; 518 int rd, gd, bd;
320 Uint8 pixel=0; 519 int i;
321 520 Uint8 pixel = 0;
322 smallest = ~0; 521
323 for ( i=0; i<pal->ncolors; ++i ) { 522 smallest = ~0;
324 rd = pal->colors[i].r - r; 523 for (i = 0; i < pal->ncolors; ++i) {
325 gd = pal->colors[i].g - g; 524 rd = pal->colors[i].r - r;
326 bd = pal->colors[i].b - b; 525 gd = pal->colors[i].g - g;
327 distance = (rd*rd)+(gd*gd)+(bd*bd); 526 bd = pal->colors[i].b - b;
328 if ( distance < smallest ) { 527 distance = (rd * rd) + (gd * gd) + (bd * bd);
329 pixel = i; 528 if (distance < smallest) {
330 if ( distance == 0 ) { /* Perfect match! */ 529 pixel = i;
331 break; 530 if (distance == 0) { /* Perfect match! */
332 } 531 break;
333 smallest = distance; 532 }
334 } 533 smallest = distance;
335 } 534 }
336 return(pixel); 535 }
536 return (pixel);
337 } 537 }
338 538
339 /* Find the opaque pixel value corresponding to an RGB triple */ 539 /* Find the opaque pixel value corresponding to an RGB triple */
340 Uint32 SDL_MapRGB(SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b) 540 Uint32
341 { 541 SDL_MapRGB(SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
342 if ( format->palette == NULL ) { 542 {
343 return (r >> format->Rloss) << format->Rshift 543 if (format->palette == NULL) {
344 | (g >> format->Gloss) << format->Gshift 544 return (r >> format->Rloss) << format->Rshift
345 | (b >> format->Bloss) << format->Bshift 545 | (g >> format->Gloss) << format->Gshift
346 | format->Amask; 546 | (b >> format->Bloss) << format->Bshift | format->Amask;
347 } else { 547 } else {
348 return SDL_FindColor(format->palette, r, g, b); 548 return SDL_FindColor(format->palette, r, g, b);
349 } 549 }
350 } 550 }
351 551
352 /* Find the pixel value corresponding to an RGBA quadruple */ 552 /* Find the pixel value corresponding to an RGBA quadruple */
353 Uint32 SDL_MapRGBA(SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 553 Uint32
354 { 554 SDL_MapRGBA(SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
355 if ( format->palette == NULL ) { 555 {
356 return (r >> format->Rloss) << format->Rshift 556 if (format->palette == NULL) {
357 | (g >> format->Gloss) << format->Gshift 557 return (r >> format->Rloss) << format->Rshift
358 | (b >> format->Bloss) << format->Bshift 558 | (g >> format->Gloss) << format->Gshift
359 | ((a >> format->Aloss) << format->Ashift & format->Amask); 559 | (b >> format->Bloss) << format->Bshift
360 } else { 560 | ((a >> format->Aloss) << format->Ashift & format->Amask);
361 return SDL_FindColor(format->palette, r, g, b); 561 } else {
362 } 562 return SDL_FindColor(format->palette, r, g, b);
363 } 563 }
364 564 }
365 void SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt, 565
366 Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) 566 void
367 { 567 SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat * fmt,
368 if ( fmt->palette == NULL ) { 568 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
369 /* 569 {
370 * This makes sure that the result is mapped to the 570 if (fmt->palette == NULL) {
371 * interval [0..255], and the maximum value for each 571 /*
372 * component is 255. This is important to make sure 572 * This makes sure that the result is mapped to the
373 * that white is indeed reported as (255, 255, 255), 573 * interval [0..255], and the maximum value for each
374 * and that opaque alpha is 255. 574 * component is 255. This is important to make sure
375 * This only works for RGB bit fields at least 4 bit 575 * that white is indeed reported as (255, 255, 255),
376 * wide, which is almost always the case. 576 * and that opaque alpha is 255.
377 */ 577 * This only works for RGB bit fields at least 4 bit
378 unsigned v; 578 * wide, which is almost always the case.
379 v = (pixel & fmt->Rmask) >> fmt->Rshift; 579 */
380 *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); 580 unsigned v;
381 v = (pixel & fmt->Gmask) >> fmt->Gshift; 581 v = (pixel & fmt->Rmask) >> fmt->Rshift;
382 *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); 582 *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1)));
383 v = (pixel & fmt->Bmask) >> fmt->Bshift; 583 v = (pixel & fmt->Gmask) >> fmt->Gshift;
384 *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); 584 *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1)));
385 if(fmt->Amask) { 585 v = (pixel & fmt->Bmask) >> fmt->Bshift;
386 v = (pixel & fmt->Amask) >> fmt->Ashift; 586 *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1)));
387 *a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); 587 if (fmt->Amask) {
388 } else { 588 v = (pixel & fmt->Amask) >> fmt->Ashift;
389 *a = SDL_ALPHA_OPAQUE; 589 *a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1)));
590 } else {
591 *a = SDL_ALPHA_OPAQUE;
592 }
593 } else {
594 *r = fmt->palette->colors[pixel].r;
595 *g = fmt->palette->colors[pixel].g;
596 *b = fmt->palette->colors[pixel].b;
597 *a = SDL_ALPHA_OPAQUE;
598 }
599 }
600
601 void
602 SDL_GetRGB(Uint32 pixel, SDL_PixelFormat * fmt, Uint8 * r, Uint8 * g,
603 Uint8 * b)
604 {
605 if (fmt->palette == NULL) {
606 /* the note for SDL_GetRGBA above applies here too */
607 unsigned v;
608 v = (pixel & fmt->Rmask) >> fmt->Rshift;
609 *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1)));
610 v = (pixel & fmt->Gmask) >> fmt->Gshift;
611 *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1)));
612 v = (pixel & fmt->Bmask) >> fmt->Bshift;
613 *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1)));
614 } else {
615 *r = fmt->palette->colors[pixel].r;
616 *g = fmt->palette->colors[pixel].g;
617 *b = fmt->palette->colors[pixel].b;
618 }
619 }
620
621 /* Apply gamma to a set of colors - this is easy. :) */
622 void
623 SDL_ApplyGamma(Uint16 * gamma, SDL_Color * colors, SDL_Color * output,
624 int ncolors)
625 {
626 int i;
627
628 for (i = 0; i < ncolors; ++i) {
629 output[i].r = gamma[0 * 256 + colors[i].r] >> 8;
630 output[i].g = gamma[1 * 256 + colors[i].g] >> 8;
631 output[i].b = gamma[2 * 256 + colors[i].b] >> 8;
632 }
633 }
634
635 /* Map from Palette to Palette */
636 static Uint8 *
637 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
638 {
639 Uint8 *map;
640 int i;
641
642 if (identical) {
643 if (src->ncolors <= dst->ncolors) {
644 /* If an identical palette, no need to map */
645 if (src == dst
646 ||
647 (SDL_memcmp
648 (src->colors, dst->colors,
649 src->ncolors * sizeof(SDL_Color)) == 0)) {
650 *identical = 1;
651 return (NULL);
652 }
653 }
654 *identical = 0;
655 }
656 map = (Uint8 *) SDL_malloc(src->ncolors);
657 if (map == NULL) {
658 SDL_OutOfMemory();
659 return (NULL);
660 }
661 for (i = 0; i < src->ncolors; ++i) {
662 map[i] = SDL_FindColor(dst,
663 src->colors[i].r, src->colors[i].g,
664 src->colors[i].b);
665 }
666 return (map);
667 }
668
669 /* Map from Palette to BitField */
670 static Uint8 *
671 Map1toN(SDL_PixelFormat * src, SDL_PixelFormat * dst)
672 {
673 Uint8 *map;
674 int i;
675 int bpp;
676 unsigned alpha;
677 SDL_Palette *pal = src->palette;
678
679 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
680 map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
681 if (map == NULL) {
682 SDL_OutOfMemory();
683 return (NULL);
684 }
685
686 alpha = dst->Amask ? src->alpha : 0;
687 /* We memory copy to the pixel map so the endianness is preserved */
688 for (i = 0; i < pal->ncolors; ++i) {
689 ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst,
690 pal->colors[i].r, pal->colors[i].g,
691 pal->colors[i].b, alpha);
692 }
693 return (map);
694 }
695
696 /* Map from BitField to Dithered-Palette to Palette */
697 static Uint8 *
698 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
699 {
700 /* Generate a 256 color dither palette */
701 SDL_Palette dithered;
702 SDL_Color colors[256];
703 SDL_Palette *pal = dst->palette;
704
705 dithered.ncolors = 256;
706 SDL_DitherColors(colors, 8);
707 dithered.colors = colors;
708 return (Map1to1(&dithered, pal, identical));
709 }
710
711 SDL_BlitMap *
712 SDL_AllocBlitMap(void)
713 {
714 SDL_BlitMap *map;
715
716 /* Allocate the empty map */
717 map = (SDL_BlitMap *) SDL_malloc(sizeof(*map));
718 if (map == NULL) {
719 SDL_OutOfMemory();
720 return (NULL);
721 }
722 SDL_memset(map, 0, sizeof(*map));
723
724 /* Allocate the software blit data */
725 map->sw_data =
726 (struct private_swaccel *) SDL_malloc(sizeof(*map->sw_data));
727 if (map->sw_data == NULL) {
728 SDL_FreeBlitMap(map);
729 SDL_OutOfMemory();
730 return (NULL);
731 }
732 SDL_memset(map->sw_data, 0, sizeof(*map->sw_data));
733
734 /* It's ready to go */
735 return (map);
736 }
737
738 void
739 SDL_InvalidateMap(SDL_BlitMap * map)
740 {
741 if (!map) {
742 return;
743 }
744 map->dst = NULL;
745 map->format_version = (unsigned int) -1;
746 if (map->table) {
747 SDL_free(map->table);
748 map->table = NULL;
749 }
750 }
751 int
752 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
753 {
754 SDL_PixelFormat *srcfmt;
755 SDL_PixelFormat *dstfmt;
756 SDL_BlitMap *map;
757
758 /* Clear out any previous mapping */
759 map = src->map;
760 if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
761 SDL_UnRLESurface(src, 1);
762 }
763 SDL_InvalidateMap(map);
764
765 /* Figure out what kind of mapping we're doing */
766 map->identity = 0;
767 srcfmt = src->format;
768 dstfmt = dst->format;
769 switch (srcfmt->BytesPerPixel) {
770 case 1:
771 switch (dstfmt->BytesPerPixel) {
772 case 1:
773 /* Palette --> Palette */
774 map->table =
775 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
776 if (!map->identity) {
777 if (map->table == NULL) {
778 return (-1);
390 } 779 }
391 } else { 780 }
392 *r = fmt->palette->colors[pixel].r; 781 if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
393 *g = fmt->palette->colors[pixel].g; 782 map->identity = 0;
394 *b = fmt->palette->colors[pixel].b; 783 break;
395 *a = SDL_ALPHA_OPAQUE; 784
396 } 785 default:
397 } 786 /* Palette --> BitField */
398 787 map->table = Map1toN(srcfmt, dstfmt);
399 void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r,Uint8 *g,Uint8 *b) 788 if (map->table == NULL) {
400 { 789 return (-1);
401 if ( fmt->palette == NULL ) { 790 }
402 /* the note for SDL_GetRGBA above applies here too */ 791 break;
403 unsigned v; 792 }
404 v = (pixel & fmt->Rmask) >> fmt->Rshift; 793 break;
405 *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); 794 default:
406 v = (pixel & fmt->Gmask) >> fmt->Gshift; 795 switch (dstfmt->BytesPerPixel) {
407 *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); 796 case 1:
408 v = (pixel & fmt->Bmask) >> fmt->Bshift; 797 /* BitField --> Palette */
409 *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); 798 map->table = MapNto1(srcfmt, dstfmt, &map->identity);
410 } else { 799 if (!map->identity) {
411 *r = fmt->palette->colors[pixel].r; 800 if (map->table == NULL) {
412 *g = fmt->palette->colors[pixel].g; 801 return (-1);
413 *b = fmt->palette->colors[pixel].b; 802 }
414 } 803 }
415 } 804 map->identity = 0; /* Don't optimize to copy */
416 805 break;
417 /* Apply gamma to a set of colors - this is easy. :) */ 806 default:
418 void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, 807 /* BitField --> BitField */
419 int ncolors) 808 if (FORMAT_EQUAL(srcfmt, dstfmt))
420 { 809 map->identity = 1;
421 int i; 810 break;
422 811 }
423 for ( i=0; i<ncolors; ++i ) { 812 break;
424 output[i].r = gamma[0*256 + colors[i].r] >> 8; 813 }
425 output[i].g = gamma[1*256 + colors[i].g] >> 8; 814
426 output[i].b = gamma[2*256 + colors[i].b] >> 8; 815 map->dst = dst;
427 } 816 map->format_version = dst->format_version;
428 } 817
429 818 /* Choose your blitters wisely */
430 /* Map from Palette to Palette */ 819 return (SDL_CalculateBlit(src));
431 static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) 820 }
432 { 821
433 Uint8 *map; 822 void
434 int i; 823 SDL_FreeBlitMap(SDL_BlitMap * map)
435 824 {
436 if ( identical ) { 825 if (map) {
437 if ( src->ncolors <= dst->ncolors ) { 826 SDL_InvalidateMap(map);
438 /* If an identical palette, no need to map */ 827 if (map->sw_data != NULL) {
439 if ( SDL_memcmp(src->colors, dst->colors, src->ncolors* 828 SDL_free(map->sw_data);
440 sizeof(SDL_Color)) == 0 ) { 829 }
441 *identical = 1; 830 SDL_free(map);
442 return(NULL); 831 }
443 } 832 }
444 } 833
445 *identical = 0; 834 /* vi: set ts=4 sw=4 expandtab: */
446 }
447 map = (Uint8 *)SDL_malloc(src->ncolors);
448 if ( map == NULL ) {
449 SDL_OutOfMemory();
450 return(NULL);
451 }
452 for ( i=0; i<src->ncolors; ++i ) {
453 map[i] = SDL_FindColor(dst,
454 src->colors[i].r, src->colors[i].g, src->colors[i].b);
455 }
456 return(map);
457 }
458 /* Map from Palette to BitField */
459 static Uint8 *Map1toN(SDL_PixelFormat *src, SDL_PixelFormat *dst)
460 {
461 Uint8 *map;
462 int i;
463 int bpp;
464 unsigned alpha;
465 SDL_Palette *pal = src->palette;
466
467 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
468 map = (Uint8 *)SDL_malloc(pal->ncolors*bpp);
469 if ( map == NULL ) {
470 SDL_OutOfMemory();
471 return(NULL);
472 }
473
474 alpha = dst->Amask ? src->alpha : 0;
475 /* We memory copy to the pixel map so the endianness is preserved */
476 for ( i=0; i<pal->ncolors; ++i ) {
477 ASSEMBLE_RGBA(&map[i*bpp], dst->BytesPerPixel, dst,
478 pal->colors[i].r, pal->colors[i].g,
479 pal->colors[i].b, alpha);
480 }
481 return(map);
482 }
483 /* Map from BitField to Dithered-Palette to Palette */
484 static Uint8 *MapNto1(SDL_PixelFormat *src, SDL_PixelFormat *dst, int *identical)
485 {
486 /* Generate a 256 color dither palette */
487 SDL_Palette dithered;
488 SDL_Color colors[256];
489 SDL_Palette *pal = dst->palette;
490
491 /* SDL_DitherColors does not initialize the 'unused' component of colors,
492 but Map1to1 compares it against pal, so we should initialize it. */
493 SDL_memset(colors, 0, sizeof(colors));
494
495 dithered.ncolors = 256;
496 SDL_DitherColors(colors, 8);
497 dithered.colors = colors;
498 return(Map1to1(&dithered, pal, identical));
499 }
500
501 SDL_BlitMap *SDL_AllocBlitMap(void)
502 {
503 SDL_BlitMap *map;
504
505 /* Allocate the empty map */
506 map = (SDL_BlitMap *)SDL_malloc(sizeof(*map));
507 if ( map == NULL ) {
508 SDL_OutOfMemory();
509 return(NULL);
510 }
511 SDL_memset(map, 0, sizeof(*map));
512
513 /* Allocate the software blit data */
514 map->sw_data = (struct private_swaccel *)SDL_malloc(sizeof(*map->sw_data));
515 if ( map->sw_data == NULL ) {
516 SDL_FreeBlitMap(map);
517 SDL_OutOfMemory();
518 return(NULL);
519 }
520 SDL_memset(map->sw_data, 0, sizeof(*map->sw_data));
521
522 /* It's ready to go */
523 return(map);
524 }
525 void SDL_InvalidateMap(SDL_BlitMap *map)
526 {
527 if ( ! map ) {
528 return;
529 }
530 map->dst = NULL;
531 map->format_version = (unsigned int)-1;
532 if ( map->table ) {
533 SDL_free(map->table);
534 map->table = NULL;
535 }
536 }
537 int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst)
538 {
539 SDL_PixelFormat *srcfmt;
540 SDL_PixelFormat *dstfmt;
541 SDL_BlitMap *map;
542
543 /* Clear out any previous mapping */
544 map = src->map;
545 if ( (src->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
546 SDL_UnRLESurface(src, 1);
547 }
548 SDL_InvalidateMap(map);
549
550 /* Figure out what kind of mapping we're doing */
551 map->identity = 0;
552 srcfmt = src->format;
553 dstfmt = dst->format;
554 switch (srcfmt->BytesPerPixel) {
555 case 1:
556 switch (dstfmt->BytesPerPixel) {
557 case 1:
558 /* Palette --> Palette */
559 /* If both SDL_HWSURFACE, assume have same palette */
560 if ( ((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
561 ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) ) {
562 map->identity = 1;
563 } else {
564 map->table = Map1to1(srcfmt->palette,
565 dstfmt->palette, &map->identity);
566 }
567 if ( ! map->identity ) {
568 if ( map->table == NULL ) {
569 return(-1);
570 }
571 }
572 if (srcfmt->BitsPerPixel!=dstfmt->BitsPerPixel)
573 map->identity = 0;
574 break;
575
576 default:
577 /* Palette --> BitField */
578 map->table = Map1toN(srcfmt, dstfmt);
579 if ( map->table == NULL ) {
580 return(-1);
581 }
582 break;
583 }
584 break;
585 default:
586 switch (dstfmt->BytesPerPixel) {
587 case 1:
588 /* BitField --> Palette */
589 map->table = MapNto1(srcfmt, dstfmt, &map->identity);
590 if ( ! map->identity ) {
591 if ( map->table == NULL ) {
592 return(-1);
593 }
594 }
595 map->identity = 0; /* Don't optimize to copy */
596 break;
597 default:
598 /* BitField --> BitField */
599 if ( FORMAT_EQUAL(srcfmt, dstfmt) )
600 map->identity = 1;
601 break;
602 }
603 break;
604 }
605
606 map->dst = dst;
607 map->format_version = dst->format_version;
608
609 /* Choose your blitters wisely */
610 return(SDL_CalculateBlit(src));
611 }
612 void SDL_FreeBlitMap(SDL_BlitMap *map)
613 {
614 if ( map ) {
615 SDL_InvalidateMap(map);
616 if ( map->sw_data != NULL ) {
617 SDL_free(map->sw_data);
618 }
619 SDL_free(map);
620 }
621 }