comparison src/video/SDL_pixels.c @ 1683:396a35389351 SDL-1.3

Finished palettized display handling. Added support for surface palette sharing.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 17 Jun 2006 06:45:14 +0000
parents 7ae8018b2e5d
children 1577404809f0
comparison
equal deleted inserted replaced
1682:7ae8018b2e5d 1683:396a35389351
213 } 213 }
214 } 214 }
215 return SDL_PixelFormat_Unknown; 215 return SDL_PixelFormat_Unknown;
216 } 216 }
217 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
218 /* 338 /*
219 * 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.
220 */ 340 */
221 SDL_PixelFormat * 341 SDL_PixelFormat *
222 SDL_AllocFormat(int bpp, 342 SDL_AllocFormat(int bpp,
236 356
237 /* Set up the format */ 357 /* Set up the format */
238 format->BitsPerPixel = bpp; 358 format->BitsPerPixel = bpp;
239 format->BytesPerPixel = (bpp + 7) / 8; 359 format->BytesPerPixel = (bpp + 7) / 8;
240 if (Rmask || Bmask || Gmask) { /* Packed pixels with custom mask */ 360 if (Rmask || Bmask || Gmask) { /* Packed pixels with custom mask */
241 format->palette = NULL;
242 format->Rshift = 0; 361 format->Rshift = 0;
243 format->Rloss = 8; 362 format->Rloss = 8;
244 if (Rmask) { 363 if (Rmask) {
245 for (mask = Rmask; !(mask & 0x01); mask >>= 1) 364 for (mask = Rmask; !(mask & 0x01); mask >>= 1)
246 ++format->Rshift; 365 ++format->Rshift;
301 format->Rmask = 0; 420 format->Rmask = 0;
302 format->Gmask = 0; 421 format->Gmask = 0;
303 format->Bmask = 0; 422 format->Bmask = 0;
304 format->Amask = 0; 423 format->Amask = 0;
305 } 424 }
306 if (bpp <= 8) { /* Palettized mode */ 425 format->palette = NULL;
307 int ncolors = 1 << bpp; 426
308 #ifdef DEBUG_PALETTE
309 fprintf(stderr, "bpp=%d ncolors=%d\n", bpp, ncolors);
310 #endif
311 format->palette = (SDL_Palette *) SDL_malloc(sizeof(SDL_Palette));
312 if (format->palette == NULL) {
313 SDL_FreeFormat(format);
314 SDL_OutOfMemory();
315 return (NULL);
316 }
317 (format->palette)->ncolors = ncolors;
318 (format->palette)->colors = (SDL_Color *) SDL_malloc((format->
319 palette)->
320 ncolors *
321 sizeof
322 (SDL_Color));
323 if ((format->palette)->colors == NULL) {
324 SDL_FreeFormat(format);
325 SDL_OutOfMemory();
326 return (NULL);
327 }
328 if (Rmask || Bmask || Gmask) {
329 /* create palette according to masks */
330 int i;
331 int Rm = 0, Gm = 0, Bm = 0;
332 int Rw = 0, Gw = 0, Bw = 0;
333 #ifdef ENABLE_PALETTE_ALPHA
334 int Am = 0, Aw = 0;
335 #endif
336 if (Rmask) {
337 Rw = 8 - format->Rloss;
338 for (i = format->Rloss; i > 0; i -= Rw)
339 Rm |= 1 << i;
340 }
341 #ifdef DEBUG_PALETTE
342 fprintf(stderr, "Rw=%d Rm=0x%02X\n", Rw, Rm);
343 #endif
344 if (Gmask) {
345 Gw = 8 - format->Gloss;
346 for (i = format->Gloss; i > 0; i -= Gw)
347 Gm |= 1 << i;
348 }
349 #ifdef DEBUG_PALETTE
350 fprintf(stderr, "Gw=%d Gm=0x%02X\n", Gw, Gm);
351 #endif
352 if (Bmask) {
353 Bw = 8 - format->Bloss;
354 for (i = format->Bloss; i > 0; i -= Bw)
355 Bm |= 1 << i;
356 }
357 #ifdef DEBUG_PALETTE
358 fprintf(stderr, "Bw=%d Bm=0x%02X\n", Bw, Bm);
359 #endif
360 #ifdef ENABLE_PALETTE_ALPHA
361 if (Amask) {
362 Aw = 8 - format->Aloss;
363 for (i = format->Aloss; i > 0; i -= Aw)
364 Am |= 1 << i;
365 }
366 # ifdef DEBUG_PALETTE
367 fprintf(stderr, "Aw=%d Am=0x%02X\n", Aw, Am);
368 # endif
369 #endif
370 for (i = 0; i < ncolors; ++i) {
371 int r, g, b;
372 r = (i & Rmask) >> format->Rshift;
373 r = (r << format->Rloss) | ((r * Rm) >> Rw);
374 format->palette->colors[i].r = r;
375
376 g = (i & Gmask) >> format->Gshift;
377 g = (g << format->Gloss) | ((g * Gm) >> Gw);
378 format->palette->colors[i].g = g;
379
380 b = (i & Bmask) >> format->Bshift;
381 b = (b << format->Bloss) | ((b * Bm) >> Bw);
382 format->palette->colors[i].b = b;
383
384 #ifdef ENABLE_PALETTE_ALPHA
385 a = (i & Amask) >> format->Ashift;
386 a = (a << format->Aloss) | ((a * Am) >> Aw);
387 format->palette->colors[i].unused = a;
388 #else
389 format->palette->colors[i].unused = SDL_ALPHA_OPAQUE;
390 #endif
391 }
392 } else if (ncolors == 2) {
393 /* Create a black and white bitmap palette */
394 format->palette->colors[0].r = 0xFF;
395 format->palette->colors[0].g = 0xFF;
396 format->palette->colors[0].b = 0xFF;
397 format->palette->colors[1].r = 0x00;
398 format->palette->colors[1].g = 0x00;
399 format->palette->colors[1].b = 0x00;
400 } else {
401 /* Create an empty palette */
402 SDL_memset((format->palette)->colors, 0xFF,
403 (format->palette)->ncolors * sizeof(SDL_Color));
404 }
405 }
406 return (format); 427 return (format);
407 }
408
409 SDL_PixelFormat *
410 SDL_ReallocFormat(SDL_Surface * surface, int bpp,
411 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
412 {
413 if (surface->format) {
414 SDL_FreeFormat(surface->format);
415 SDL_FormatChanged(surface);
416 }
417 surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
418 return surface->format;
419 } 428 }
420 429
421 /* 430 /*
422 * Change any previous mappings from/to the new surface format 431 * Change any previous mappings from/to the new surface format
423 */ 432 */
437 * Free a previously allocated format structure 446 * Free a previously allocated format structure
438 */ 447 */
439 void 448 void
440 SDL_FreeFormat(SDL_PixelFormat * format) 449 SDL_FreeFormat(SDL_PixelFormat * format)
441 { 450 {
442 if (format) { 451 if (!format) {
443 if (format->palette) { 452 return;
444 if (format->palette->colors) { 453 }
445 SDL_free(format->palette->colors); 454 SDL_free(format);
446 }
447 SDL_free(format->palette);
448 }
449 SDL_free(format);
450 }
451 } 455 }
452 456
453 /* 457 /*
454 * 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
455 */ 459 */
693 /* Generate a 256 color dither palette */ 697 /* Generate a 256 color dither palette */
694 SDL_Palette dithered; 698 SDL_Palette dithered;
695 SDL_Color colors[256]; 699 SDL_Color colors[256];
696 SDL_Palette *pal = dst->palette; 700 SDL_Palette *pal = dst->palette;
697 701
698 /* SDL_DitherColors does not initialize the 'unused' component of colors,
699 but Map1to1 compares it against pal, so we should initialize it. */
700 SDL_memset(colors, 0xFF, sizeof(colors));
701
702 dithered.ncolors = 256; 702 dithered.ncolors = 256;
703 SDL_DitherColors(colors, 8); 703 SDL_DitherColors(colors, 8);
704 dithered.colors = colors; 704 dithered.colors = colors;
705 return (Map1to1(&dithered, pal, identical)); 705 return (Map1to1(&dithered, pal, identical));
706 } 706 }
766 switch (srcfmt->BytesPerPixel) { 766 switch (srcfmt->BytesPerPixel) {
767 case 1: 767 case 1:
768 switch (dstfmt->BytesPerPixel) { 768 switch (dstfmt->BytesPerPixel) {
769 case 1: 769 case 1:
770 /* Palette --> Palette */ 770 /* Palette --> Palette */
771 /* If both SDL_HWSURFACE, assume have same palette */ 771 map->table =
772 if (((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && 772 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
773 ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE)) {
774 map->identity = 1;
775 } else {
776 map->table = Map1to1(srcfmt->palette,
777 dstfmt->palette, &map->identity);
778 }
779 if (!map->identity) { 773 if (!map->identity) {
780 if (map->table == NULL) { 774 if (map->table == NULL) {
781 return (-1); 775 return (-1);
782 } 776 }
783 } 777 }