Mercurial > sdl-ios-xcode
comparison src/video/SDL_renderer_sw.c @ 1985:8055185ae4ed
Added source color and alpha modulation support.
Added perl script to generate optimized render copy functions.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 28 Aug 2006 03:17:39 +0000 |
parents | a0e278364188 |
children | 5b5f5de5433f |
comparison
equal
deleted
inserted
replaced
1984:b910bcabec26 | 1985:8055185ae4ed |
---|---|
24 #include "SDL_video.h" | 24 #include "SDL_video.h" |
25 #include "SDL_sysvideo.h" | 25 #include "SDL_sysvideo.h" |
26 #include "SDL_pixels_c.h" | 26 #include "SDL_pixels_c.h" |
27 #include "SDL_rect_c.h" | 27 #include "SDL_rect_c.h" |
28 #include "SDL_yuv_sw_c.h" | 28 #include "SDL_yuv_sw_c.h" |
29 #include "SDL_rendercopy.h" | |
29 | 30 |
30 | 31 |
31 /* SDL surface based renderer implementation */ | 32 /* SDL surface based renderer implementation */ |
32 | 33 |
33 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags); | 34 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags); |
42 const SDL_Color * colors, int firstcolor, | 43 const SDL_Color * colors, int firstcolor, |
43 int ncolors); | 44 int ncolors); |
44 static int SW_GetTexturePalette(SDL_Renderer * renderer, | 45 static int SW_GetTexturePalette(SDL_Renderer * renderer, |
45 SDL_Texture * texture, SDL_Color * colors, | 46 SDL_Texture * texture, SDL_Color * colors, |
46 int firstcolor, int ncolors); | 47 int firstcolor, int ncolors); |
47 static int SW_UpdateTexture(SDL_Renderer * renderer, | 48 static int SW_SetTextureColorMod(SDL_Renderer * renderer, |
48 SDL_Texture * texture, const SDL_Rect * rect, | 49 SDL_Texture * texture); |
49 const void *pixels, int pitch); | 50 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer, |
51 SDL_Texture * texture); | |
52 static int SW_SetTextureBlendMode(SDL_Renderer * renderer, | |
53 SDL_Texture * texture); | |
54 static int SW_SetTextureScaleMode(SDL_Renderer * renderer, | |
55 SDL_Texture * texture); | |
56 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
57 const SDL_Rect * rect, const void *pixels, | |
58 int pitch); | |
50 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | 59 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, |
51 const SDL_Rect * rect, int markDirty, | 60 const SDL_Rect * rect, int markDirty, void **pixels, |
52 void **pixels, int *pitch); | 61 int *pitch); |
53 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); | 62 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); |
54 static void SW_DirtyTexture(SDL_Renderer * renderer, | 63 static void SW_DirtyTexture(SDL_Renderer * renderer, |
55 SDL_Texture * texture, int numrects, | 64 SDL_Texture * texture, int numrects, |
56 const SDL_Rect * rects); | 65 const SDL_Rect * rects); |
57 static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, | 66 static int SW_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, |
58 Uint32 color); | 67 Uint8 a, const SDL_Rect * rect); |
59 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | 68 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, |
60 const SDL_Rect * srcrect, | 69 const SDL_Rect * srcrect, const SDL_Rect * dstrect); |
61 const SDL_Rect * dstrect, int blendMode, | |
62 int scaleMode); | |
63 static void SW_RenderPresent(SDL_Renderer * renderer); | 70 static void SW_RenderPresent(SDL_Renderer * renderer); |
64 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); | 71 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); |
65 static void SW_DestroyRenderer(SDL_Renderer * renderer); | 72 static void SW_DestroyRenderer(SDL_Renderer * renderer); |
66 | 73 |
67 | 74 |
70 { | 77 { |
71 "software", | 78 "software", |
72 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | | 79 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | |
73 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | | 80 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | |
74 SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC), | 81 SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC), |
82 (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR | | |
83 SDL_TEXTUREMODULATE_ALPHA), | |
75 (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK | | 84 (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK | |
76 SDL_TEXTUREBLENDMODE_BLEND), | 85 SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD | |
86 SDL_TEXTUREBLENDMODE_MOD), | |
77 (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST), | 87 (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST), |
78 11, | 88 11, |
79 { | 89 { |
80 SDL_PIXELFORMAT_INDEX8, | 90 SDL_PIXELFORMAT_INDEX8, |
81 SDL_PIXELFORMAT_RGB555, | 91 SDL_PIXELFORMAT_RGB555, |
186 renderer->DisplayModeChanged = SW_DisplayModeChanged; | 196 renderer->DisplayModeChanged = SW_DisplayModeChanged; |
187 renderer->CreateTexture = SW_CreateTexture; | 197 renderer->CreateTexture = SW_CreateTexture; |
188 renderer->QueryTexturePixels = SW_QueryTexturePixels; | 198 renderer->QueryTexturePixels = SW_QueryTexturePixels; |
189 renderer->SetTexturePalette = SW_SetTexturePalette; | 199 renderer->SetTexturePalette = SW_SetTexturePalette; |
190 renderer->GetTexturePalette = SW_GetTexturePalette; | 200 renderer->GetTexturePalette = SW_GetTexturePalette; |
201 renderer->SetTextureColorMod = SW_SetTextureColorMod; | |
202 renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod; | |
203 renderer->SetTextureBlendMode = SW_SetTextureBlendMode; | |
204 renderer->SetTextureScaleMode = SW_SetTextureScaleMode; | |
191 renderer->UpdateTexture = SW_UpdateTexture; | 205 renderer->UpdateTexture = SW_UpdateTexture; |
192 renderer->LockTexture = SW_LockTexture; | 206 renderer->LockTexture = SW_LockTexture; |
193 renderer->UnlockTexture = SW_UnlockTexture; | 207 renderer->UnlockTexture = SW_UnlockTexture; |
194 renderer->DirtyTexture = SW_DirtyTexture; | 208 renderer->DirtyTexture = SW_DirtyTexture; |
195 renderer->RenderFill = SW_RenderFill; | 209 renderer->RenderFill = SW_RenderFill; |
331 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 345 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
332 { | 346 { |
333 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | 347 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { |
334 texture->driverdata = SDL_SW_CreateYUVTexture(texture); | 348 texture->driverdata = SDL_SW_CreateYUVTexture(texture); |
335 } else { | 349 } else { |
350 SDL_Surface *surface; | |
336 int bpp; | 351 int bpp; |
337 Uint32 Rmask, Gmask, Bmask, Amask; | 352 Uint32 Rmask, Gmask, Bmask, Amask; |
338 | 353 |
339 if (!SDL_PixelFormatEnumToMasks | 354 if (!SDL_PixelFormatEnumToMasks |
340 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | 355 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { |
395 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | 410 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; |
396 | 411 |
397 SDL_memcpy(colors, &surface->format->palette->colors[firstcolor], | 412 SDL_memcpy(colors, &surface->format->palette->colors[firstcolor], |
398 ncolors * sizeof(*colors)); | 413 ncolors * sizeof(*colors)); |
399 return 0; | 414 return 0; |
415 } | |
416 } | |
417 | |
418 static void | |
419 SW_UpdateRenderCopyFunc(SDL_Renderer * renderer, SDL_Texture * texture) | |
420 { | |
421 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
422 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
423 | |
424 surface->userdata = | |
425 SDL_GetRenderCopyFunc(texture->format, data->format, texture->modMode, | |
426 texture->blendMode, texture->scaleMode); | |
427 } | |
428 | |
429 static int | |
430 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) | |
431 { | |
432 SW_UpdateRenderCopyFunc(renderer, texture); | |
433 return 0; | |
434 } | |
435 | |
436 static int | |
437 SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) | |
438 { | |
439 SW_UpdateRenderCopyFunc(renderer, texture); | |
440 return 0; | |
441 } | |
442 | |
443 static int | |
444 SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) | |
445 { | |
446 switch (texture->blendMode) { | |
447 case SDL_TEXTUREBLENDMODE_NONE: | |
448 case SDL_TEXTUREBLENDMODE_MASK: | |
449 case SDL_TEXTUREBLENDMODE_BLEND: | |
450 case SDL_TEXTUREBLENDMODE_ADD: | |
451 case SDL_TEXTUREBLENDMODE_MOD: | |
452 SW_UpdateRenderCopyFunc(renderer, texture); | |
453 return 0; | |
454 default: | |
455 SDL_Unsupported(); | |
456 texture->blendMode = SDL_TEXTUREBLENDMODE_NONE; | |
457 SW_UpdateRenderCopyFunc(renderer, texture); | |
458 return -1; | |
459 } | |
460 } | |
461 | |
462 static int | |
463 SW_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) | |
464 { | |
465 switch (texture->scaleMode) { | |
466 case SDL_TEXTURESCALEMODE_NONE: | |
467 case SDL_TEXTURESCALEMODE_FAST: | |
468 SW_UpdateRenderCopyFunc(renderer, texture); | |
469 return 0; | |
470 case SDL_TEXTURESCALEMODE_SLOW: | |
471 case SDL_TEXTURESCALEMODE_BEST: | |
472 SDL_Unsupported(); | |
473 texture->scaleMode = SDL_TEXTURESCALEMODE_FAST; | |
474 SW_UpdateRenderCopyFunc(renderer, texture); | |
475 return -1; | |
476 default: | |
477 SDL_Unsupported(); | |
478 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; | |
479 SW_UpdateRenderCopyFunc(renderer, texture); | |
480 return -1; | |
400 } | 481 } |
401 } | 482 } |
402 | 483 |
403 static int | 484 static int |
404 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | 485 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, |
460 int numrects, const SDL_Rect * rects) | 541 int numrects, const SDL_Rect * rects) |
461 { | 542 { |
462 } | 543 } |
463 | 544 |
464 static int | 545 static int |
465 SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 color) | 546 SW_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a, |
547 const SDL_Rect * rect) | |
466 { | 548 { |
467 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 549 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
468 Uint8 r, g, b, a; | 550 Uint32 color; |
469 SDL_Rect real_rect; | 551 SDL_Rect real_rect; |
470 int status; | 552 int status; |
471 | 553 |
472 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | 554 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { |
473 SDL_AddDirtyRect(&data->dirty, rect); | 555 SDL_AddDirtyRect(&data->dirty, rect); |
474 } | 556 } |
475 | 557 |
476 a = (Uint8) ((color >> 24) & 0xFF); | |
477 r = (Uint8) ((color >> 16) & 0xFF); | |
478 g = (Uint8) ((color >> 8) & 0xFF); | |
479 b = (Uint8) (color & 0xFF); | |
480 color = SDL_MapRGBA(data->surface.format, r, g, b, a); | 558 color = SDL_MapRGBA(data->surface.format, r, g, b, a); |
481 | 559 |
482 if (data->renderer-> | 560 if (data->renderer-> |
483 LockTexture(data->renderer, data->texture[data->current_texture], | 561 LockTexture(data->renderer, data->texture[data->current_texture], |
484 rect, 1, &data->surface.pixels, | 562 rect, 1, &data->surface.pixels, |
498 return status; | 576 return status; |
499 } | 577 } |
500 | 578 |
501 static int | 579 static int |
502 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | 580 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, |
503 const SDL_Rect * srcrect, const SDL_Rect * dstrect, | 581 const SDL_Rect * srcrect, const SDL_Rect * dstrect) |
504 int blendMode, int scaleMode) | |
505 { | 582 { |
506 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 583 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
507 SDL_Window *window = SDL_GetWindowFromID(renderer->window); | 584 SDL_Window *window = SDL_GetWindowFromID(renderer->window); |
508 int status; | 585 int status; |
509 | 586 |
523 SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | 600 SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, |
524 srcrect, data->format, dstrect->w, dstrect->h, | 601 srcrect, data->format, dstrect->w, dstrect->h, |
525 data->surface.pixels, data->surface.pitch); | 602 data->surface.pixels, data->surface.pitch); |
526 } else { | 603 } else { |
527 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | 604 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; |
528 SDL_Rect real_srcrect = *srcrect; | 605 SDL_RenderCopyFunc copyfunc = (SDL_RenderCopyFunc) surface->userdata; |
529 SDL_Rect real_dstrect; | 606 |
530 | 607 if (copyfunc) { |
531 data->surface.w = dstrect->w; | 608 SDL_RenderCopyData copydata; |
532 data->surface.h = dstrect->h; | 609 |
533 data->surface.clip_rect.w = dstrect->w; | 610 copydata.src = |
534 data->surface.clip_rect.h = dstrect->h; | 611 (Uint8 *) surface->pixels + srcrect->y * surface->pitch + |
535 real_dstrect = data->surface.clip_rect; | 612 srcrect->x * surface->format->BytesPerPixel; |
536 | 613 copydata.src_w = srcrect->w; |
537 if (blendMode & | 614 copydata.src_h = srcrect->h; |
538 (SDL_TEXTUREBLENDMODE_MASK | SDL_TEXTUREBLENDMODE_BLEND)) { | 615 copydata.src_pitch = surface->pitch; |
539 SDL_SetAlpha(surface, SDL_SRCALPHA, 0); | 616 copydata.dst = (Uint8 *) data->surface.pixels; |
617 copydata.dst_w = dstrect->w; | |
618 copydata.dst_h = dstrect->h; | |
619 copydata.dst_pitch = data->surface.pitch; | |
620 copydata.flags = 0; | |
621 if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { | |
622 copydata.flags |= SDL_RENDERCOPY_MODULATE_COLOR; | |
623 copydata.r = texture->r; | |
624 copydata.g = texture->g; | |
625 copydata.b = texture->b; | |
626 } | |
627 if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) { | |
628 copydata.flags |= SDL_RENDERCOPY_MODULATE_ALPHA; | |
629 copydata.a = texture->a; | |
630 } | |
631 if (texture-> | |
632 blendMode & (SDL_TEXTUREBLENDMODE_MASK | | |
633 SDL_TEXTUREBLENDMODE_BLEND)) { | |
634 copydata.flags |= SDL_RENDERCOPY_BLEND; | |
635 } else if (texture->blendMode & SDL_TEXTUREBLENDMODE_ADD) { | |
636 copydata.flags |= SDL_RENDERCOPY_ADD; | |
637 } else if (texture->blendMode & SDL_TEXTUREBLENDMODE_MOD) { | |
638 copydata.flags |= SDL_RENDERCOPY_MOD; | |
639 } | |
640 if (texture->scaleMode) { | |
641 copydata.flags |= SDL_RENDERCOPY_NEAREST; | |
642 } | |
643 status = copyfunc(©data); | |
540 } else { | 644 } else { |
541 SDL_SetAlpha(surface, 0, 0); | 645 SDL_Rect real_srcrect = *srcrect; |
542 } | 646 SDL_Rect real_dstrect; |
543 if (scaleMode != SDL_TEXTURESCALEMODE_NONE && | 647 |
544 (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) { | 648 data->surface.w = dstrect->w; |
545 status = | 649 data->surface.h = dstrect->h; |
546 SDL_SoftStretch(surface, &real_srcrect, &data->surface, | 650 data->surface.clip_rect.w = dstrect->w; |
547 &real_dstrect); | 651 data->surface.clip_rect.h = dstrect->h; |
548 } else { | 652 real_dstrect = data->surface.clip_rect; |
653 | |
549 status = | 654 status = |
550 SDL_LowerBlit(surface, &real_srcrect, &data->surface, | 655 SDL_LowerBlit(surface, &real_srcrect, &data->surface, |
551 &real_dstrect); | 656 &real_dstrect); |
552 } | 657 } |
553 } | 658 } |
565 /* Send the data to the display */ | 670 /* Send the data to the display */ |
566 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | 671 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { |
567 SDL_DirtyRect *dirty; | 672 SDL_DirtyRect *dirty; |
568 for (dirty = data->dirty.list; dirty; dirty = dirty->next) { | 673 for (dirty = data->dirty.list; dirty; dirty = dirty->next) { |
569 data->renderer->RenderCopy(data->renderer, texture, &dirty->rect, | 674 data->renderer->RenderCopy(data->renderer, texture, &dirty->rect, |
570 &dirty->rect, | 675 &dirty->rect); |
571 SDL_TEXTUREBLENDMODE_NONE, | |
572 SDL_TEXTURESCALEMODE_NONE); | |
573 } | 676 } |
574 SDL_ClearDirtyRects(&data->dirty); | 677 SDL_ClearDirtyRects(&data->dirty); |
575 } else { | 678 } else { |
576 SDL_Rect rect; | 679 SDL_Rect rect; |
577 rect.x = 0; | 680 rect.x = 0; |
578 rect.y = 0; | 681 rect.y = 0; |
579 rect.w = texture->w; | 682 rect.w = texture->w; |
580 rect.h = texture->h; | 683 rect.h = texture->h; |
581 data->renderer->RenderCopy(data->renderer, texture, &rect, &rect, | 684 data->renderer->RenderCopy(data->renderer, texture, &rect, &rect); |
582 SDL_TEXTUREBLENDMODE_NONE, | |
583 SDL_TEXTURESCALEMODE_NONE); | |
584 } | 685 } |
585 data->renderer->RenderPresent(data->renderer); | 686 data->renderer->RenderPresent(data->renderer); |
586 | 687 |
587 /* Update the flipping chain, if any */ | 688 /* Update the flipping chain, if any */ |
588 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { | 689 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { |