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 }