Mercurial > sdl-ios-xcode
comparison src/video/SDL_renderer_sw.c @ 5145:c8e049de174c
Making the API simpler, the renderer present semantics are always having a backbuffer and then discarding it. This is best for hardware accelerated rendering.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 01 Feb 2011 12:19:46 -0800 |
parents | 31e7f523ab3d |
children | ad50b3db78bd |
comparison
equal
deleted
inserted
replaced
5144:31e7f523ab3d | 5145:c8e049de174c |
---|---|
79 | 79 |
80 SDL_RenderDriver SW_RenderDriver = { | 80 SDL_RenderDriver SW_RenderDriver = { |
81 SW_CreateRenderer, | 81 SW_CreateRenderer, |
82 { | 82 { |
83 "software", | 83 "software", |
84 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | | 84 (SDL_RENDERER_PRESENTVSYNC), |
85 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | | |
86 SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC), | |
87 14, | 85 14, |
88 { | 86 { |
89 SDL_PIXELFORMAT_INDEX8, | 87 SDL_PIXELFORMAT_INDEX8, |
90 SDL_PIXELFORMAT_RGB555, | 88 SDL_PIXELFORMAT_RGB555, |
91 SDL_PIXELFORMAT_RGB565, | 89 SDL_PIXELFORMAT_RGB565, |
106 | 104 |
107 typedef struct | 105 typedef struct |
108 { | 106 { |
109 Uint32 format; | 107 Uint32 format; |
110 SDL_bool updateSize; | 108 SDL_bool updateSize; |
111 int current_texture; | 109 SDL_Texture *texture; |
112 SDL_Texture *texture[3]; | |
113 SDL_Surface surface; | 110 SDL_Surface surface; |
114 SDL_Renderer *renderer; | 111 SDL_Renderer *renderer; |
115 SDL_DirtyRectList dirty; | 112 SDL_DirtyRectList dirty; |
116 } SW_RenderData; | 113 } SW_RenderData; |
117 | 114 |
148 | 145 |
149 static int | 146 static int |
150 DisplayPaletteChanged(void *userdata, SDL_Palette * palette) | 147 DisplayPaletteChanged(void *userdata, SDL_Palette * palette) |
151 { | 148 { |
152 SW_RenderData *data = (SW_RenderData *) userdata; | 149 SW_RenderData *data = (SW_RenderData *) userdata; |
153 int i; | 150 |
154 | 151 if (data->renderer->SetTexturePalette) { |
155 for (i = 0; i < SDL_arraysize(data->texture); ++i) { | 152 data->renderer->SetTexturePalette(data->renderer, data->texture, |
156 if (data->texture[i] && data->renderer->SetTexturePalette) { | 153 palette->colors, 0, |
157 data->renderer->SetTexturePalette(data->renderer, | 154 palette->ncolors); |
158 data->texture[i], | |
159 palette->colors, 0, | |
160 palette->ncolors); | |
161 } | |
162 } | 155 } |
163 return 0; | 156 return 0; |
164 } | 157 } |
165 | 158 |
166 void | 159 void |
235 renderer->info.flags = 0; | 228 renderer->info.flags = 0; |
236 renderer->window = window; | 229 renderer->window = window; |
237 renderer->driverdata = data; | 230 renderer->driverdata = data; |
238 Setup_SoftwareRenderer(renderer); | 231 Setup_SoftwareRenderer(renderer); |
239 | 232 |
240 if (flags & SDL_RENDERER_PRESENTFLIP2) { | 233 n = 1; |
241 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; | |
242 n = 2; | |
243 } else if (flags & SDL_RENDERER_PRESENTFLIP3) { | |
244 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; | |
245 n = 3; | |
246 } else { | |
247 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; | |
248 n = 1; | |
249 } | |
250 data->format = displayMode->format; | 234 data->format = displayMode->format; |
251 | 235 |
252 /* Find a render driver that we can use to display data */ | 236 /* Find a render driver that we can use to display data */ |
253 renderer_flags = (SDL_RENDERER_SINGLEBUFFER | | 237 renderer_flags = 0; |
254 SDL_RENDERER_PRESENTDISCARD); | |
255 if (flags & SDL_RENDERER_PRESENTVSYNC) { | 238 if (flags & SDL_RENDERER_PRESENTVSYNC) { |
256 renderer_flags |= SDL_RENDERER_PRESENTVSYNC; | 239 renderer_flags |= SDL_RENDERER_PRESENTVSYNC; |
257 } | 240 } |
258 desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER"); | 241 desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER"); |
259 for (i = 0; i < display->num_render_drivers; ++i) { | 242 for (i = 0; i < display->num_render_drivers; ++i) { |
278 if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { | 261 if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { |
279 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; | 262 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; |
280 } | 263 } |
281 | 264 |
282 /* Create the textures we'll use for display */ | 265 /* Create the textures we'll use for display */ |
283 for (i = 0; i < n; ++i) { | 266 data->texture = |
284 data->texture[i] = | 267 CreateTexture(data->renderer, data->format, window->w, window->h); |
285 CreateTexture(data->renderer, data->format, window->w, window->h); | 268 if (!data->texture) { |
286 if (!data->texture[i]) { | 269 SW_DestroyRenderer(renderer); |
287 SW_DestroyRenderer(renderer); | 270 return NULL; |
288 return NULL; | 271 } |
289 } | |
290 } | |
291 data->current_texture = 0; | |
292 | 272 |
293 /* Create a surface we'll use for rendering */ | 273 /* Create a surface we'll use for rendering */ |
294 data->surface.flags = SDL_PREALLOC; | 274 data->surface.flags = SDL_PREALLOC; |
295 data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); | 275 data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); |
296 if (!data->surface.format) { | 276 if (!data->surface.format) { |
319 return -1; | 299 return -1; |
320 } | 300 } |
321 } | 301 } |
322 if (data->updateSize) { | 302 if (data->updateSize) { |
323 /* Recreate the textures for the new window size */ | 303 /* Recreate the textures for the new window size */ |
324 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { | 304 if (data->texture) { |
325 n = 2; | 305 DestroyTexture(data->renderer, data->texture); |
326 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { | 306 data->texture = 0; |
327 n = 3; | 307 } |
328 } else { | 308 data->texture = CreateTexture(data->renderer, data->format, |
329 n = 1; | 309 window->w, window->h); |
330 } | 310 if (!data->texture) { |
331 for (i = 0; i < n; ++i) { | 311 return -1; |
332 if (data->texture[i]) { | |
333 DestroyTexture(data->renderer, data->texture[i]); | |
334 data->texture[i] = 0; | |
335 } | |
336 } | |
337 for (i = 0; i < n; ++i) { | |
338 data->texture[i] = | |
339 CreateTexture(data->renderer, data->format, window->w, | |
340 window->h); | |
341 if (!data->texture[i]) { | |
342 return -1; | |
343 } | |
344 } | 312 } |
345 data->updateSize = SDL_FALSE; | 313 data->updateSize = SDL_FALSE; |
346 } | 314 } |
347 return 0; | 315 return 0; |
348 } | 316 } |
526 static int | 494 static int |
527 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, | 495 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, |
528 int count) | 496 int count) |
529 { | 497 { |
530 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 498 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
531 SDL_Texture *texture = data->texture[data->current_texture]; | 499 SDL_Texture *texture = data->texture; |
532 SDL_Rect rect; | 500 SDL_Rect rect; |
533 int i; | 501 int i; |
534 int x, y; | 502 int x, y; |
535 int status = 0; | 503 int status = 0; |
536 | 504 |
542 if (!SDL_EnclosePoints(points, count, &rect, &rect)) { | 510 if (!SDL_EnclosePoints(points, count, &rect, &rect)) { |
543 /* Nothing to draw */ | 511 /* Nothing to draw */ |
544 return 0; | 512 return 0; |
545 } | 513 } |
546 | 514 |
547 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | |
548 SDL_AddDirtyRect(&data->dirty, &rect); | |
549 } | |
550 | |
551 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | 515 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, |
552 &data->surface.pixels, | 516 &data->surface.pixels, |
553 &data->surface.pitch) < 0) { | 517 &data->surface.pitch) < 0) { |
554 return -1; | 518 return -1; |
555 } | 519 } |
589 static int | 553 static int |
590 SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, | 554 SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, |
591 int count) | 555 int count) |
592 { | 556 { |
593 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 557 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
594 SDL_Texture *texture = data->texture[data->current_texture]; | 558 SDL_Texture *texture = data->texture; |
595 SDL_Rect clip, rect; | 559 SDL_Rect clip, rect; |
596 int i; | 560 int i; |
597 int x1, y1, x2, y2; | 561 int x1, y1, x2, y2; |
598 int status = 0; | 562 int status = 0; |
599 | 563 |
606 if (!SDL_IntersectRect(&rect, &clip, &rect)) { | 570 if (!SDL_IntersectRect(&rect, &clip, &rect)) { |
607 /* Nothing to draw */ | 571 /* Nothing to draw */ |
608 return 0; | 572 return 0; |
609 } | 573 } |
610 | 574 |
611 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | |
612 SDL_AddDirtyRect(&data->dirty, &rect); | |
613 } | |
614 | |
615 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | 575 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, |
616 &data->surface.pixels, | 576 &data->surface.pixels, |
617 &data->surface.pitch) < 0) { | 577 &data->surface.pitch) < 0) { |
618 return -1; | 578 return -1; |
619 } | 579 } |
657 static int | 617 static int |
658 SW_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, | 618 SW_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, |
659 int count) | 619 int count) |
660 { | 620 { |
661 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 621 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
662 SDL_Texture *texture = data->texture[data->current_texture]; | 622 SDL_Texture *texture = data->texture; |
663 SDL_Rect clip, rect; | 623 SDL_Rect clip, rect; |
664 Uint32 color = 0; | 624 Uint32 color = 0; |
665 int i; | 625 int i; |
666 int status = 0; | 626 int status = 0; |
667 | 627 |
679 for (i = 0; i < count; ++i) { | 639 for (i = 0; i < count; ++i) { |
680 /* FIXME: We don't want to draw clipped edges */ | 640 /* FIXME: We don't want to draw clipped edges */ |
681 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { | 641 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { |
682 /* Nothing to draw */ | 642 /* Nothing to draw */ |
683 continue; | 643 continue; |
684 } | |
685 | |
686 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | |
687 SDL_AddDirtyRect(&data->dirty, &rect); | |
688 } | 644 } |
689 | 645 |
690 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | 646 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, |
691 &data->surface.pixels, | 647 &data->surface.pixels, |
692 &data->surface.pitch) < 0) { | 648 &data->surface.pitch) < 0) { |
713 static int | 669 static int |
714 SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, | 670 SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, |
715 int count) | 671 int count) |
716 { | 672 { |
717 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 673 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
718 SDL_Texture *texture = data->texture[data->current_texture]; | 674 SDL_Texture *texture = data->texture; |
719 SDL_Rect clip, rect; | 675 SDL_Rect clip, rect; |
720 Uint32 color = 0; | 676 Uint32 color = 0; |
721 int i; | 677 int i; |
722 int status = 0; | 678 int status = 0; |
723 | 679 |
734 | 690 |
735 for (i = 0; i < count; ++i) { | 691 for (i = 0; i < count; ++i) { |
736 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { | 692 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { |
737 /* Nothing to draw */ | 693 /* Nothing to draw */ |
738 continue; | 694 continue; |
739 } | |
740 | |
741 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | |
742 SDL_AddDirtyRect(&data->dirty, &rect); | |
743 } | 695 } |
744 | 696 |
745 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | 697 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, |
746 &data->surface.pixels, | 698 &data->surface.pixels, |
747 &data->surface.pitch) < 0) { | 699 &data->surface.pitch) < 0) { |
770 const SDL_Rect * srcrect, const SDL_Rect * dstrect) | 722 const SDL_Rect * srcrect, const SDL_Rect * dstrect) |
771 { | 723 { |
772 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 724 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
773 int status; | 725 int status; |
774 | 726 |
775 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | 727 if (data->renderer->LockTexture(data->renderer, data->texture, |
776 SDL_AddDirtyRect(&data->dirty, dstrect); | |
777 } | |
778 | |
779 if (data->renderer->LockTexture(data->renderer, | |
780 data->texture[data->current_texture], | |
781 dstrect, 1, &data->surface.pixels, | 728 dstrect, 1, &data->surface.pixels, |
782 &data->surface.pitch) < 0) { | 729 &data->surface.pitch) < 0) { |
783 return -1; | 730 return -1; |
784 } | 731 } |
785 | 732 |
801 | 748 |
802 status = | 749 status = |
803 SDL_LowerBlit(surface, &real_srcrect, &data->surface, | 750 SDL_LowerBlit(surface, &real_srcrect, &data->surface, |
804 &real_dstrect); | 751 &real_dstrect); |
805 } | 752 } |
806 data->renderer->UnlockTexture(data->renderer, | 753 data->renderer->UnlockTexture(data->renderer, data->texture); |
807 data->texture[data->current_texture]); | |
808 return status; | 754 return status; |
809 } | 755 } |
810 | 756 |
811 static int | 757 static int |
812 SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, | 758 SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, |
813 Uint32 format, void * pixels, int pitch) | 759 Uint32 format, void * pixels, int pitch) |
814 { | 760 { |
815 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 761 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
816 | 762 |
817 if (data->renderer->LockTexture(data->renderer, | 763 if (data->renderer->LockTexture(data->renderer, data->texture, |
818 data->texture[data->current_texture], | |
819 rect, 0, &data->surface.pixels, | 764 rect, 0, &data->surface.pixels, |
820 &data->surface.pitch) < 0) { | 765 &data->surface.pitch) < 0) { |
821 return -1; | 766 return -1; |
822 } | 767 } |
823 | 768 |
824 SDL_ConvertPixels(rect->w, rect->h, | 769 SDL_ConvertPixels(rect->w, rect->h, |
825 data->format, data->surface.pixels, data->surface.pitch, | 770 data->format, data->surface.pixels, data->surface.pitch, |
826 format, pixels, pitch); | 771 format, pixels, pitch); |
827 | 772 |
828 data->renderer->UnlockTexture(data->renderer, | 773 data->renderer->UnlockTexture(data->renderer, data->texture); |
829 data->texture[data->current_texture]); | |
830 return 0; | 774 return 0; |
831 } | 775 } |
832 | 776 |
833 static int | 777 static int |
834 SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, | 778 SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, |
835 Uint32 format, const void * pixels, int pitch) | 779 Uint32 format, const void * pixels, int pitch) |
836 { | 780 { |
837 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 781 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
838 | 782 |
839 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | 783 if (data->renderer->LockTexture(data->renderer, data->texture, |
840 SDL_AddDirtyRect(&data->dirty, rect); | |
841 } | |
842 | |
843 if (data->renderer->LockTexture(data->renderer, | |
844 data->texture[data->current_texture], | |
845 rect, 1, &data->surface.pixels, | 784 rect, 1, &data->surface.pixels, |
846 &data->surface.pitch) < 0) { | 785 &data->surface.pitch) < 0) { |
847 return -1; | 786 return -1; |
848 } | 787 } |
849 | 788 |
850 SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch, | 789 SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch, |
851 data->format, data->surface.pixels, data->surface.pitch); | 790 data->format, data->surface.pixels, data->surface.pitch); |
852 | 791 |
853 data->renderer->UnlockTexture(data->renderer, | 792 data->renderer->UnlockTexture(data->renderer, data->texture); |
854 data->texture[data->current_texture]); | |
855 return 0; | 793 return 0; |
856 } | 794 } |
857 | 795 |
858 static void | 796 static void |
859 SW_RenderPresent(SDL_Renderer * renderer) | 797 SW_RenderPresent(SDL_Renderer * renderer) |
860 { | 798 { |
861 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | 799 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; |
862 SDL_Texture *texture = data->texture[data->current_texture]; | 800 SDL_Texture *texture = data->texture; |
801 SDL_Rect rect; | |
863 | 802 |
864 /* Send the data to the display */ | 803 /* Send the data to the display */ |
865 if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { | 804 rect.x = 0; |
866 SDL_DirtyRect *dirty; | 805 rect.y = 0; |
867 for (dirty = data->dirty.list; dirty; dirty = dirty->next) { | 806 rect.w = texture->w; |
868 data->renderer->RenderCopy(data->renderer, texture, &dirty->rect, | 807 rect.h = texture->h; |
869 &dirty->rect); | 808 data->renderer->RenderCopy(data->renderer, texture, &rect, &rect); |
870 } | |
871 SDL_ClearDirtyRects(&data->dirty); | |
872 } else { | |
873 SDL_Rect rect; | |
874 rect.x = 0; | |
875 rect.y = 0; | |
876 rect.w = texture->w; | |
877 rect.h = texture->h; | |
878 data->renderer->RenderCopy(data->renderer, texture, &rect, &rect); | |
879 } | |
880 data->renderer->RenderPresent(data->renderer); | 809 data->renderer->RenderPresent(data->renderer); |
881 | |
882 /* Update the flipping chain, if any */ | |
883 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { | |
884 data->current_texture = (data->current_texture + 1) % 2; | |
885 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { | |
886 data->current_texture = (data->current_texture + 1) % 3; | |
887 } | |
888 } | 810 } |
889 | 811 |
890 static void | 812 static void |
891 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 813 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
892 { | 814 { |
906 SDL_Window *window = renderer->window; | 828 SDL_Window *window = renderer->window; |
907 SDL_VideoDisplay *display = window->display; | 829 SDL_VideoDisplay *display = window->display; |
908 int i; | 830 int i; |
909 | 831 |
910 if (data) { | 832 if (data) { |
911 for (i = 0; i < SDL_arraysize(data->texture); ++i) { | 833 if (data->texture) { |
912 if (data->texture[i]) { | 834 DestroyTexture(data->renderer, data->texture); |
913 DestroyTexture(data->renderer, data->texture[i]); | |
914 } | |
915 } | 835 } |
916 if (data->surface.format) { | 836 if (data->surface.format) { |
917 SDL_SetSurfacePalette(&data->surface, NULL); | 837 SDL_SetSurfacePalette(&data->surface, NULL); |
918 SDL_FreeFormat(data->surface.format); | 838 SDL_FreeFormat(data->surface.format); |
919 } | 839 } |