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(&copydata);
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) {