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 }