Mercurial > sdl-ios-xcode
comparison src/video/SDL_surface.c @ 2266:e61ad15a205f
More work in progress integrating SDL_Surface and the new SDL_Texture API
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 18 Aug 2007 01:44:21 +0000 |
parents | 202ddfd1cfb1 |
children | c785543d1843 |
comparison
equal
deleted
inserted
replaced
2265:265bb136af92 | 2266:e61ad15a205f |
---|---|
210 SDL_SurfacePaletteChanged, surface); | 210 SDL_SurfacePaletteChanged, surface); |
211 } | 211 } |
212 return 0; | 212 return 0; |
213 } | 213 } |
214 | 214 |
215 /* | 215 int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag) |
216 * Set the color key in a blittable surface | 216 { |
217 */ | 217 Uint32 flags; |
218 int | 218 |
219 SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key) | 219 if (!surface) { |
220 { | 220 return -1; |
221 /* Sanity check the flag as it gets passed in */ | 221 } |
222 if (flag & SDL_SRCCOLORKEY) { | 222 |
223 if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) { | 223 if (flag) { |
224 flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); | 224 surface->flags |= SDL_RLEACCELOK; |
225 } else { | |
226 flag = SDL_SRCCOLORKEY; | |
227 } | |
228 } else { | 225 } else { |
229 flag = 0; | 226 surface->flags &= ~SDL_RLEACCELOK; |
230 } | 227 } |
231 | 228 if (surface->flags != flags) { |
232 /* Optimize away operations that don't change anything */ | 229 SDL_InvalidateMap(surface->map); |
233 if ((flag == (surface->flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK))) && | 230 } |
234 (key == surface->map->ckey)) { | 231 return 0; |
235 return (0); | 232 } |
236 } | 233 |
237 | 234 int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key) |
238 /* UnRLE surfaces before we change the colorkey */ | 235 { |
239 if (surface->flags & SDL_RLEACCEL) { | 236 int flags; |
240 SDL_UnRLESurface(surface, 1); | 237 |
241 } | 238 if (!surface) { |
242 | 239 return -1; |
240 } | |
241 | |
242 if (flag & SDL_RLEACCEL) { | |
243 SDL_SetSurfaceRLE(surface, 1); | |
244 } | |
245 | |
246 flags = surface->map->info.flags; | |
243 if (flag) { | 247 if (flag) { |
244 surface->flags |= SDL_SRCCOLORKEY; | 248 surface->map->info.flags |= SDL_COPY_COLORKEY; |
245 surface->map->ckey = key; | 249 surface->map->info.colorkey = key; |
246 if (flag & SDL_RLEACCELOK) { | |
247 surface->flags |= SDL_RLEACCELOK; | |
248 } else { | |
249 surface->flags &= ~SDL_RLEACCELOK; | |
250 } | |
251 } else { | 250 } else { |
252 surface->flags &= ~(SDL_SRCCOLORKEY | SDL_RLEACCELOK); | 251 surface->map->info.flags &= ~SDL_COPY_COLORKEY; |
253 surface->map->ckey = 0; | 252 } |
254 } | 253 if (surface->map->info.flags != flags) { |
255 SDL_InvalidateMap(surface->map); | 254 SDL_InvalidateMap(surface->map); |
256 return (0); | 255 } |
257 } | 256 return 0; |
258 | 257 } |
259 /* This function sets the alpha channel of a surface */ | 258 |
260 int | 259 int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) |
261 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value) | 260 { |
262 { | 261 int flags; |
263 Uint32 oldflags = surface->flags; | 262 |
264 Uint32 oldalpha = (surface->map->cmod >> 24); | 263 if (!surface) { |
265 | 264 return -1; |
266 /* Sanity check the flag as it gets passed in */ | 265 } |
267 if (flag & SDL_SRCALPHA) { | 266 |
268 if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) { | 267 surface->map->info.r = r; |
269 flag = (SDL_SRCALPHA | SDL_RLEACCELOK); | 268 surface->map->info.g = g; |
270 } else { | 269 surface->map->info.b = b; |
271 flag = SDL_SRCALPHA; | 270 |
272 } | 271 flags = surface->map->info.flags; |
272 if (r != 0xFF || g != 0xFF || b != 0xFF) { | |
273 surface->map->info.flags |= SDL_COPY_MODULATE_COLOR; | |
273 } else { | 274 } else { |
274 flag = 0; | 275 surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR; |
275 } | 276 } |
276 | 277 if (surface->map->info.flags != flags) { |
277 /* Optimize away operations that don't change anything */ | 278 SDL_InvalidateMap(surface->map); |
278 if ((flag == (surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK))) && | 279 } |
279 (!flag || value == oldalpha)) { | 280 return 0; |
280 return (0); | 281 } |
281 } | 282 |
282 | 283 |
283 if (!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) | 284 int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 * r, Uint8 * g, Uint8 * b) |
284 SDL_UnRLESurface(surface, 1); | 285 { |
285 | 286 if (!surface) { |
286 if (flag) { | 287 return -1; |
287 surface->flags |= SDL_SRCALPHA; | 288 } |
288 surface->map->cmod &= 0x00FFFFFF; | 289 |
289 surface->map->cmod |= ((Uint32) value << 24); | 290 if (r) { |
290 if (flag & SDL_RLEACCELOK) { | 291 *r = surface->map->info.r; |
291 surface->flags |= SDL_RLEACCELOK; | 292 } |
292 } else { | 293 if (g) { |
293 surface->flags &= ~SDL_RLEACCELOK; | 294 *g = surface->map->info.g; |
294 } | 295 } |
296 if (b) { | |
297 *b = surface->map->info.b; | |
298 } | |
299 return 0; | |
300 } | |
301 | |
302 int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) | |
303 { | |
304 int flags; | |
305 | |
306 if (!surface) { | |
307 return -1; | |
308 } | |
309 | |
310 surface->map->info.a = alpha; | |
311 | |
312 flags = surface->map->info.flags; | |
313 if (alpha != 0xFF) { | |
314 surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA; | |
295 } else { | 315 } else { |
296 surface->flags &= ~SDL_SRCALPHA; | 316 surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA; |
297 surface->map->cmod |= 0xFF000000; | 317 } |
298 } | 318 if (surface->map->info.flags != flags) { |
299 /* | |
300 * The representation for software surfaces is independent of | |
301 * per-surface alpha, so no need to invalidate the blit mapping | |
302 * if just the alpha value was changed. (If either is 255, we still | |
303 * need to invalidate.) | |
304 */ | |
305 if (oldflags != surface->flags | |
306 || (((oldalpha + 1) ^ (value + 1)) & 0x100)) { | |
307 SDL_InvalidateMap(surface->map); | 319 SDL_InvalidateMap(surface->map); |
308 } | 320 } |
309 return (0); | 321 return 0; |
310 } | 322 } |
311 | 323 |
312 int | 324 int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 * alpha) |
313 SDL_SetAlphaChannel(SDL_Surface * surface, Uint8 value) | 325 { |
314 { | 326 if (!surface) { |
315 int row, col; | 327 return -1; |
316 int offset; | 328 } |
317 Uint8 *buf; | 329 |
318 | 330 if (alpha) { |
319 if ((surface->format->Amask != 0xFF000000) && | 331 *alpha = surface->map->info.a; |
320 (surface->format->Amask != 0x000000FF)) { | 332 } |
321 SDL_SetError("Unsupported surface alpha mask format"); | 333 return 0; |
322 return -1; | 334 } |
323 } | 335 |
324 #if SDL_BYTEORDER == SDL_LIL_ENDIAN | 336 int SDL_SetSurfaceBlendMode(SDL_Surface *surface, int blendMode) |
325 if (surface->format->Amask == 0xFF000000) { | 337 { |
326 offset = 3; | 338 int flags, status; |
327 } else { | 339 |
328 offset = 0; | 340 if (!surface) { |
329 } | 341 return -1; |
330 #else | 342 } |
331 if (surface->format->Amask == 0xFF000000) { | 343 |
332 offset = 0; | 344 status = 0; |
333 } else { | 345 flags = surface->map->info.flags; |
334 offset = 3; | 346 surface->map->info.flags &= ~(SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD); |
335 } | 347 switch (blendMode) { |
336 #endif /* Byte ordering */ | 348 case SDL_TEXTUREBLENDMODE_NONE: |
337 | 349 break; |
338 /* Quickly set the alpha channel of an RGBA or ARGB surface */ | 350 case SDL_TEXTUREBLENDMODE_MASK: |
339 if (SDL_MUSTLOCK(surface)) { | 351 surface->map->info.flags |= SDL_COPY_MASK; |
340 if (SDL_LockSurface(surface) < 0) { | 352 break; |
341 return -1; | 353 case SDL_TEXTUREBLENDMODE_BLEND: |
342 } | 354 surface->map->info.flags |= SDL_COPY_BLEND; |
343 } | 355 break; |
344 row = surface->h; | 356 case SDL_TEXTUREBLENDMODE_ADD: |
345 while (row--) { | 357 surface->map->info.flags |= SDL_COPY_ADD; |
346 col = surface->w; | 358 break; |
347 buf = (Uint8 *) surface->pixels + row * surface->pitch + offset; | 359 case SDL_TEXTUREBLENDMODE_MOD: |
348 while (col--) { | 360 surface->map->info.flags |= SDL_COPY_MOD; |
349 *buf = value; | 361 break; |
350 buf += 4; | 362 default: |
351 } | 363 SDL_Unsupported(); |
352 } | 364 status = -1; |
353 if (SDL_MUSTLOCK(surface)) { | 365 break; |
354 SDL_UnlockSurface(surface); | 366 } |
355 } | 367 |
356 return 0; | 368 if (surface->map->info.flags != flags) { |
357 } | 369 SDL_InvalidateMap(surface->map); |
358 | 370 } |
359 /* | 371 return status; |
360 * Set the clipping rectangle for a blittable surface | 372 } |
361 */ | 373 |
374 int SDL_GetSurfaceBlendMode(SDL_Surface *surface, int *blendMode) | |
375 { | |
376 if (!surface) { | |
377 return -1; | |
378 } | |
379 | |
380 if (!blendMode) { | |
381 return 0; | |
382 } | |
383 | |
384 switch(surface->map->info.flags & (SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) { | |
385 case SDL_COPY_MASK: | |
386 *blendMode = SDL_TEXTUREBLENDMODE_MASK: | |
387 break; | |
388 case SDL_COPY_BLEND: | |
389 *blendMode = SDL_TEXTUREBLENDMODE_BLEND: | |
390 break; | |
391 case SDL_COPY_ADD: | |
392 *blendMode = SDL_TEXTUREBLENDMODE_ADD: | |
393 break; | |
394 case SDL_COPY_MOD: | |
395 *blendMode = SDL_TEXTUREBLENDMODE_MOD: | |
396 break; | |
397 default: | |
398 *blendMode = SDL_TEXTUREBLENDMODE_NONE: | |
399 break; | |
400 } | |
401 return 0; | |
402 } | |
403 | |
404 int SDL_SetSurfaceScaleMode(SDL_Surface *surface, int scaleMode) | |
405 { | |
406 int flags, status; | |
407 | |
408 if (!surface) { | |
409 return -1; | |
410 } | |
411 | |
412 status = 0; | |
413 flags = surface->map->info.flags; | |
414 surface->map->info.flags &= ~(SDL_COPY_NEAREST); | |
415 switch (scaleMode) { | |
416 case SDL_TEXTURESCALEMODE_NONE: | |
417 break; | |
418 case SDL_TEXTURESCALEMODE_FAST: | |
419 surface->map->info.flags |= SDL_COPY_NEAREST; | |
420 break; | |
421 case SDL_TEXTURESCALEMODE_SLOW: | |
422 case SDL_TEXTURESCALEMODE_BEST: | |
423 SDL_Unsupported(); | |
424 surface->map->info.flags |= SDL_COPY_NEAREST; | |
425 status = -1; | |
426 break; | |
427 default: | |
428 SDL_Unsupported(); | |
429 status = -1; | |
430 break; | |
431 } | |
432 | |
433 if (surface->map->info.flags != flags) { | |
434 SDL_InvalidateMap(surface->map); | |
435 } | |
436 return status; | |
437 } | |
438 | |
439 int SDL_GetSurfaceScaleMode(SDL_Surface *surface, int *scaleMode) | |
440 { | |
441 if (!surface) { | |
442 return -1; | |
443 } | |
444 | |
445 if (!scaleMode) { | |
446 return 0; | |
447 } | |
448 | |
449 switch(surface->map->info.flags & (SDL_COPY_LINEAR)) { | |
450 case SDL_COPY_LINEAR: | |
451 *scaleMode = SDL_TEXTURESCALEMODE_FAST: | |
452 break; | |
453 default: | |
454 *scaleMode = SDL_TEXTURESCALEMODE_NONE: | |
455 break; | |
456 } | |
457 return 0; | |
458 } | |
459 | |
362 SDL_bool | 460 SDL_bool |
363 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect) | 461 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect) |
364 { | 462 { |
365 SDL_Rect full_rect; | 463 SDL_Rect full_rect; |
366 | 464 |
555 SDL_Surface * | 653 SDL_Surface * |
556 SDL_ConvertSurface(SDL_Surface * surface, | 654 SDL_ConvertSurface(SDL_Surface * surface, |
557 SDL_PixelFormat * format, Uint32 flags) | 655 SDL_PixelFormat * format, Uint32 flags) |
558 { | 656 { |
559 SDL_Surface *convert; | 657 SDL_Surface *convert; |
560 Uint32 colorkey = 0; | 658 Uint32 copy_flags; |
561 Uint8 alpha = 0; | |
562 Uint32 surface_flags; | |
563 SDL_Rect bounds; | 659 SDL_Rect bounds; |
564 | 660 |
565 /* Check for empty destination palette! (results in empty image) */ | 661 /* Check for empty destination palette! (results in empty image) */ |
566 if (format->palette != NULL) { | 662 if (format->palette != NULL) { |
567 int i; | 663 int i; |
576 return (NULL); | 672 return (NULL); |
577 } | 673 } |
578 } | 674 } |
579 | 675 |
580 /* Create a new surface with the desired format */ | 676 /* Create a new surface with the desired format */ |
581 convert = SDL_CreateRGBSurface(flags, | 677 convert = SDL_CreateRGBSurface(0, surface->w, surface->h, |
582 surface->w, surface->h, | |
583 format->BitsPerPixel, format->Rmask, | 678 format->BitsPerPixel, format->Rmask, |
584 format->Gmask, format->Bmask, | 679 format->Gmask, format->Bmask, |
585 format->Amask); | 680 format->Amask); |
586 if (convert == NULL) { | 681 if (convert == NULL) { |
587 return (NULL); | 682 return (NULL); |
593 format->palette->colors, | 688 format->palette->colors, |
594 format->palette->ncolors * sizeof(SDL_Color)); | 689 format->palette->ncolors * sizeof(SDL_Color)); |
595 convert->format->palette->ncolors = format->palette->ncolors; | 690 convert->format->palette->ncolors = format->palette->ncolors; |
596 } | 691 } |
597 | 692 |
598 /* Save the original surface color key and alpha */ | 693 /* Save the original copy flags */ |
599 surface_flags = surface->flags; | 694 copy_flags = surface->map->info.flags; |
600 if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { | 695 surface->map->info.flags = 0; |
601 /* Convert colourkeyed surfaces to RGBA if requested */ | |
602 if ((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY && format->Amask) { | |
603 surface_flags &= ~SDL_SRCCOLORKEY; | |
604 } else { | |
605 colorkey = surface->map->ckey; | |
606 SDL_SetColorKey(surface, 0, 0); | |
607 } | |
608 } | |
609 if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { | |
610 /* Copy over the alpha channel to RGBA if requested */ | |
611 if (format->Amask) { | |
612 surface->flags &= ~SDL_SRCALPHA; | |
613 } else { | |
614 alpha = (Uint8) (surface->map->cmod >> 24); | |
615 SDL_SetAlpha(surface, 0, 0); | |
616 } | |
617 } | |
618 | 696 |
619 /* Copy over the image data */ | 697 /* Copy over the image data */ |
620 bounds.x = 0; | 698 bounds.x = 0; |
621 bounds.y = 0; | 699 bounds.y = 0; |
622 bounds.w = surface->w; | 700 bounds.w = surface->w; |
623 bounds.h = surface->h; | 701 bounds.h = surface->h; |
624 SDL_LowerBlit(surface, &bounds, convert, &bounds); | 702 SDL_LowerBlit(surface, &bounds, convert, &bounds); |
625 | 703 |
626 /* Clean up the original surface, and update converted surface */ | 704 /* Clean up the original surface, and update converted surface */ |
627 if (convert != NULL) { | 705 SDL_SetClipRect(convert, &surface->clip_rect); |
628 SDL_SetClipRect(convert, &surface->clip_rect); | 706 if (copy_flags & SDL_COPY_COLORKEY) { |
629 } | 707 Uint8 keyR, keyG, keyB, keyA; |
630 if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { | 708 |
631 Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK); | 709 SDL_GetRGBA(colorkey, surface->format, &keyR, &keyG, &keyB, &keyA); |
632 if (convert != NULL) { | 710 SDL_SetColorKey(convert, 1, |
633 Uint8 keyR, keyG, keyB; | 711 SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA)); |
634 | 712 } |
635 SDL_GetRGB(colorkey, surface->format, &keyR, &keyG, &keyB); | 713 convert->map->info.r = surface->map->info.r; |
636 SDL_SetColorKey(convert, cflags | (flags & SDL_RLEACCELOK), | 714 convert->map->info.g = surface->map->info.g; |
637 SDL_MapRGB(convert->format, keyR, keyG, keyB)); | 715 convert->map->info.b = surface->map->info.b; |
638 } | 716 convert->map->info.a = surface->map->info.a; |
639 SDL_SetColorKey(surface, cflags, colorkey); | 717 convert->map->info.flags = copy_flags; |
640 } | 718 surface->map->info.flags = copy_flags; |
641 if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { | 719 |
642 Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); | 720 /* Enable alpha blending by default if the new surface has an |
643 if (convert != NULL) { | 721 * alpha channel or alpha modulation */ |
644 SDL_SetAlpha(convert, aflags | (flags & SDL_RLEACCELOK), alpha); | 722 if (format->Amask || (copy_flags & SDL_COPY_MODULATE_ALPHA)) { |
645 } | 723 SDL_SetSurfaceBlendMode(convert, SDL_TEXTUREBLENDMODE_BLEND); |
646 if (format->Amask) { | |
647 surface->flags |= SDL_SRCALPHA; | |
648 } else { | |
649 SDL_SetAlpha(surface, aflags, alpha); | |
650 } | |
651 } | 724 } |
652 | 725 |
653 /* We're ready to go! */ | 726 /* We're ready to go! */ |
654 return (convert); | 727 return (convert); |
655 } | 728 } |