comparison src/video/win32/SDL_gdirender.c @ 1897:c2a27da60b18

Solved the performance problems by introducing the concept of a single-buffered display, which is a fast path used for the whole-surface SDL 1.2 API. Solved the flicker problems by implementing a backbuffer in the GDI renderer. Unfortunately, now using the GDI renderer with a backbuffer and HBITMAPs is significantly slower than SDL's surface code. *sigh*
author Sam Lantinga <slouken@libsdl.org>
date Wed, 12 Jul 2006 06:39:26 +0000
parents c121d94672cb
children f89e49e51e89
comparison
equal deleted inserted replaced
1896:4a74fa359e7e 1897:c2a27da60b18
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 #if SDL_VIDEO_RENDER_GDI 24 #if SDL_VIDEO_RENDER_GDI
25 25
26 #include "SDL_win32video.h" 26 #include "SDL_win32video.h"
27 #include "../SDL_rect_c.h"
27 #include "../SDL_yuv_sw_c.h" 28 #include "../SDL_yuv_sw_c.h"
28 29
29 /* GDI renderer implementation */ 30 /* GDI renderer implementation */
30 31
31 static SDL_Renderer *SDL_GDI_CreateRenderer(SDL_Window * window, 32 static SDL_Renderer *SDL_GDI_CreateRenderer(SDL_Window * window,
76 77
77 SDL_RenderDriver SDL_GDI_RenderDriver = { 78 SDL_RenderDriver SDL_GDI_RenderDriver = {
78 SDL_GDI_CreateRenderer, 79 SDL_GDI_CreateRenderer,
79 { 80 {
80 "gdi", 81 "gdi",
81 (SDL_Renderer_PresentDiscard | 82 (SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy |
82 SDL_Renderer_PresentCopy | SDL_Renderer_RenderTarget), 83 SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 |
83 (SDL_TextureBlendMode_None | 84 SDL_Renderer_PresentDiscard | SDL_Renderer_RenderTarget),
84 SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend), 85 (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask |
86 SDL_TextureBlendMode_Blend),
85 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast), 87 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
86 11, 88 11,
87 { 89 {
88 SDL_PixelFormat_Index8, 90 SDL_PixelFormat_Index8,
89 SDL_PixelFormat_RGB555, 91 SDL_PixelFormat_RGB555,
106 HDC window_hdc; 108 HDC window_hdc;
107 HDC render_hdc; 109 HDC render_hdc;
108 HDC memory_hdc; 110 HDC memory_hdc;
109 HDC current_hdc; 111 HDC current_hdc;
110 LPBITMAPINFO bmi; 112 LPBITMAPINFO bmi;
111 HBITMAP window_bmp; 113 HBITMAP hbm[3];
114 int current_hbm;
115 SDL_DirtyRectList dirty;
116 SDL_bool makedirty;
117 HBITMAP window_dib;
112 void *window_pixels; 118 void *window_pixels;
113 int window_pitch; 119 int window_pitch;
114 } SDL_GDI_RenderData; 120 } SDL_GDI_RenderData;
115 121
116 typedef struct 122 typedef struct
149 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; 155 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
150 SDL_Renderer *renderer; 156 SDL_Renderer *renderer;
151 SDL_GDI_RenderData *data; 157 SDL_GDI_RenderData *data;
152 int bmi_size; 158 int bmi_size;
153 HBITMAP hbm; 159 HBITMAP hbm;
160 int i, n;
154 161
155 renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer)); 162 renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer));
156 if (!renderer) { 163 if (!renderer) {
157 SDL_OutOfMemory(); 164 SDL_OutOfMemory();
158 return NULL; 165 return NULL;
164 SDL_GDI_DestroyRenderer(renderer); 171 SDL_GDI_DestroyRenderer(renderer);
165 SDL_OutOfMemory(); 172 SDL_OutOfMemory();
166 return NULL; 173 return NULL;
167 } 174 }
168 SDL_zerop(data); 175 SDL_zerop(data);
169
170 data->hwnd = windowdata->hwnd;
171 data->window_hdc = GetDC(data->hwnd);
172 data->render_hdc = CreateCompatibleDC(data->window_hdc);
173 data->memory_hdc = CreateCompatibleDC(data->window_hdc);
174 data->current_hdc = data->window_hdc;
175
176 /* Fill in the compatible bitmap info */
177 bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
178 data->bmi = (LPBITMAPINFO) SDL_malloc(bmi_size);
179 if (!data->bmi) {
180 SDL_GDI_DestroyRenderer(renderer);
181 SDL_OutOfMemory();
182 return NULL;
183 }
184 SDL_memset(data->bmi, 0, bmi_size);
185 data->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
186
187 hbm = CreateCompatibleBitmap(data->window_hdc, 1, 1);
188 GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
189 GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
190 DeleteObject(hbm);
191 176
192 renderer->CreateTexture = SDL_GDI_CreateTexture; 177 renderer->CreateTexture = SDL_GDI_CreateTexture;
193 renderer->QueryTexturePixels = SDL_GDI_QueryTexturePixels; 178 renderer->QueryTexturePixels = SDL_GDI_QueryTexturePixels;
194 renderer->SetTexturePalette = SDL_GDI_SetTexturePalette; 179 renderer->SetTexturePalette = SDL_GDI_SetTexturePalette;
195 renderer->GetTexturePalette = SDL_GDI_GetTexturePalette; 180 renderer->GetTexturePalette = SDL_GDI_GetTexturePalette;
208 renderer->info = SDL_GDI_RenderDriver.info; 193 renderer->info = SDL_GDI_RenderDriver.info;
209 renderer->window = window->id; 194 renderer->window = window->id;
210 renderer->driverdata = data; 195 renderer->driverdata = data;
211 196
212 renderer->info.flags = SDL_Renderer_RenderTarget; 197 renderer->info.flags = SDL_Renderer_RenderTarget;
198
199 data->hwnd = windowdata->hwnd;
200 data->window_hdc = GetDC(data->hwnd);
201 data->render_hdc = CreateCompatibleDC(data->window_hdc);
202 data->memory_hdc = CreateCompatibleDC(data->window_hdc);
203
204 /* Fill in the compatible bitmap info */
205 bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
206 data->bmi = (LPBITMAPINFO) SDL_malloc(bmi_size);
207 if (!data->bmi) {
208 SDL_GDI_DestroyRenderer(renderer);
209 SDL_OutOfMemory();
210 return NULL;
211 }
212 SDL_memset(data->bmi, 0, bmi_size);
213 data->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
214
215 hbm = CreateCompatibleBitmap(data->window_hdc, 1, 1);
216 GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
217 GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
218 DeleteObject(hbm);
219
220 if (flags & SDL_Renderer_SingleBuffer) {
221 renderer->info.flags |= SDL_Renderer_SingleBuffer;
222 n = 0;
223 } else if (flags & SDL_Renderer_PresentFlip2) {
224 renderer->info.flags |= SDL_Renderer_PresentFlip2;
225 n = 2;
226 } else if (flags & SDL_Renderer_PresentFlip3) {
227 renderer->info.flags |= SDL_Renderer_PresentFlip3;
228 n = 3;
229 } else {
230 renderer->info.flags |= SDL_Renderer_PresentCopy;
231 n = 1;
232 }
233 for (i = 0; i < n; ++i) {
234 data->hbm[i] =
235 CreateCompatibleBitmap(data->window_hdc, window->w, window->h);
236 if (!data->hbm[i]) {
237 SDL_GDI_DestroyRenderer(renderer);
238 WIN_SetError("CreateCompatibleBitmap()");
239 return NULL;
240 }
241 }
242 if (n > 0) {
243 SelectObject(data->render_hdc, data->hbm[0]);
244 data->current_hdc = data->render_hdc;
245 data->makedirty = SDL_TRUE;
246 } else {
247 data->current_hdc = data->window_hdc;
248 data->makedirty = SDL_FALSE;
249 }
250 data->current_hbm = 0;
213 251
214 return renderer; 252 return renderer;
215 } 253 }
216 254
217 static int 255 static int
333 371
334 if (data->yuv) { 372 if (data->yuv) {
335 return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch); 373 return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
336 } else { 374 } else {
337 *pixels = data->pixels; 375 *pixels = data->pixels;
338 *pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); 376 *pitch = data->pitch;
339 return 0; 377 return 0;
340 } 378 }
341 } 379 }
342 380
343 static int 381 static int
492 if (texturedata->hpal) { 530 if (texturedata->hpal) {
493 SelectPalette(data->render_hdc, texturedata->hpal, TRUE); 531 SelectPalette(data->render_hdc, texturedata->hpal, TRUE);
494 RealizePalette(data->render_hdc); 532 RealizePalette(data->render_hdc);
495 } 533 }
496 data->current_hdc = data->render_hdc; 534 data->current_hdc = data->render_hdc;
497 } else { 535 data->makedirty = SDL_FALSE;
498 data->current_hdc = data->current_hdc; 536 } else if (renderer->info.flags & SDL_Renderer_SingleBuffer) {
537 data->current_hdc = data->window_hdc;
538 data->makedirty = SDL_FALSE;
539 } else {
540 SelectObject(data->render_hdc, data->hbm[data->current_hbm]);
541 data->current_hdc = data->render_hdc;
542 data->makedirty = SDL_TRUE;
499 } 543 }
500 } 544 }
501 545
502 static int 546 static int
503 SDL_GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, 547 SDL_GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
507 Uint8 r, g, b; 551 Uint8 r, g, b;
508 RECT rc; 552 RECT rc;
509 static HBRUSH brush; 553 static HBRUSH brush;
510 int status; 554 int status;
511 555
556 if (data->makedirty) {
557 SDL_AddDirtyRect(&data->dirty, rect);
558 }
559
512 r = (Uint8) ((color >> 16) & 0xFF); 560 r = (Uint8) ((color >> 16) & 0xFF);
513 g = (Uint8) ((color >> 8) & 0xFF); 561 g = (Uint8) ((color >> 8) & 0xFF);
514 b = (Uint8) (color & 0xFF); 562 b = (Uint8) (color & 0xFF);
515 563
516 rc.left = rect->x; 564 rc.left = rect->x;
537 int blendMode, int scaleMode) 585 int blendMode, int scaleMode)
538 { 586 {
539 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata; 587 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
540 SDL_GDI_TextureData *texturedata = 588 SDL_GDI_TextureData *texturedata =
541 (SDL_GDI_TextureData *) texture->driverdata; 589 (SDL_GDI_TextureData *) texture->driverdata;
590
591 if (data->makedirty) {
592 SDL_AddDirtyRect(&data->dirty, dstrect);
593 }
542 594
543 SelectObject(data->memory_hdc, texturedata->hbm); 595 SelectObject(data->memory_hdc, texturedata->hbm);
544 if (texturedata->hpal) { 596 if (texturedata->hpal) {
545 SelectPalette(data->memory_hdc, texturedata->hpal, TRUE); 597 SelectPalette(data->memory_hdc, texturedata->hpal, TRUE);
546 RealizePalette(data->memory_hdc); 598 RealizePalette(data->memory_hdc);
588 data->window_pitch = window->w * (data->bmi->bmiHeader.biBitCount / 8); 640 data->window_pitch = window->w * (data->bmi->bmiHeader.biBitCount / 8);
589 data->bmi->bmiHeader.biWidth = window->w; 641 data->bmi->bmiHeader.biWidth = window->w;
590 data->bmi->bmiHeader.biHeight = -window->h; 642 data->bmi->bmiHeader.biHeight = -window->h;
591 data->bmi->bmiHeader.biSizeImage = 643 data->bmi->bmiHeader.biSizeImage =
592 window->h * (data->bmi->bmiHeader.biBitCount / 8); 644 window->h * (data->bmi->bmiHeader.biBitCount / 8);
593 data->window_bmp = 645 data->window_dib =
594 CreateDIBSection(data->window_hdc, data->bmi, DIB_RGB_COLORS, 646 CreateDIBSection(data->window_hdc, data->bmi, DIB_RGB_COLORS,
595 &data->window_pixels, NULL, 0); 647 &data->window_pixels, NULL, 0);
596 if (!data->window_bmp) { 648 if (!data->window_dib) {
597 WIN_SetError("CreateDIBSection()"); 649 WIN_SetError("CreateDIBSection()");
598 return -1; 650 return -1;
599 } 651 }
600 return 0; 652 return 0;
601 } 653 }
605 void *pixels, int pitch) 657 void *pixels, int pitch)
606 { 658 {
607 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 659 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
608 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata; 660 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
609 661
610 if (!data->window_bmp) { 662 if (!data->window_dib) {
611 if (CreateWindowDIB(data, window) < 0) { 663 if (CreateWindowDIB(data, window) < 0) {
612 return -1; 664 return -1;
613 } 665 }
614 } 666 }
615 667
616 SelectObject(data->memory_hdc, data->window_bmp); 668 SelectObject(data->memory_hdc, data->window_dib);
617 BitBlt(data->memory_hdc, rect->x, rect->y, rect->w, rect->h, 669 BitBlt(data->memory_hdc, rect->x, rect->y, rect->w, rect->h,
618 data->window_hdc, rect->x, rect->y, SRCCOPY); 670 data->current_hdc, rect->x, rect->y, SRCCOPY);
619 671
620 { 672 {
621 int bpp = data->bmi->bmiHeader.biBitCount / 8; 673 int bpp = data->bmi->bmiHeader.biBitCount / 8;
622 Uint8 *src = 674 Uint8 *src =
623 (Uint8 *) data->window_pixels + rect->y * data->window_pitch + 675 (Uint8 *) data->window_pixels + rect->y * data->window_pitch +
640 const void *pixels, int pitch) 692 const void *pixels, int pitch)
641 { 693 {
642 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 694 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
643 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata; 695 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
644 696
645 if (!data->window_bmp) { 697 if (data->makedirty) {
698 SDL_AddDirtyRect(&data->dirty, rect);
699 }
700
701 if (!data->window_dib) {
646 if (CreateWindowDIB(data, window) < 0) { 702 if (CreateWindowDIB(data, window) < 0) {
647 return -1; 703 return -1;
648 } 704 }
649 } 705 }
650 706
661 src += pitch; 717 src += pitch;
662 dst += data->window_pitch; 718 dst += data->window_pitch;
663 } 719 }
664 } 720 }
665 721
666 SelectObject(data->memory_hdc, data->window_bmp); 722 SelectObject(data->memory_hdc, data->window_dib);
667 BitBlt(data->window_hdc, rect->x, rect->y, rect->w, rect->h, 723 BitBlt(data->current_hdc, rect->x, rect->y, rect->w, rect->h,
668 data->memory_hdc, rect->x, rect->y, SRCCOPY); 724 data->memory_hdc, rect->x, rect->y, SRCCOPY);
669 725
670 return 0; 726 return 0;
671 } 727 }
672 728
673 static void 729 static void
674 SDL_GDI_RenderPresent(SDL_Renderer * renderer) 730 SDL_GDI_RenderPresent(SDL_Renderer * renderer)
675 { 731 {
732 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
733 SDL_DirtyRect *dirty;
734 int new_hbm;
735
736 /* Send the data to the display */
737 /*
738 if (!(renderer->info.flags & SDL_Renderer_SingleBuffer)) {
739 for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
740 const SDL_Rect *rect = &dirty->rect;
741 BitBlt(data->window_hdc, rect->x, rect->y, rect->w, rect->h,
742 data->render_hdc, rect->x, rect->y, SRCCOPY);
743 }
744 SDL_ClearDirtyRects(&data->dirty);
745 }
746 */
747 BitBlt(data->window_hdc, 0, 0, 640, 480, data->render_hdc, 0, 0, SRCCOPY);
748
749 /* Update the flipping chain, if any */
750 if (renderer->info.flags & SDL_Renderer_PresentFlip2) {
751 data->current_hbm = (data->current_hbm + 1) % 2;
752 SelectObject(data->render_hdc, data->hbm[data->current_hbm]);
753 } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) {
754 data->current_hbm = (data->current_hbm + 1) % 3;
755 SelectObject(data->render_hdc, data->hbm[data->current_hbm]);
756 }
676 } 757 }
677 758
678 static void 759 static void
679 SDL_GDI_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 760 SDL_GDI_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
680 { 761 {
698 779
699 void 780 void
700 SDL_GDI_DestroyRenderer(SDL_Renderer * renderer) 781 SDL_GDI_DestroyRenderer(SDL_Renderer * renderer)
701 { 782 {
702 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata; 783 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
784 int i;
703 785
704 if (data) { 786 if (data) {
705 ReleaseDC(data->hwnd, data->window_hdc); 787 ReleaseDC(data->hwnd, data->window_hdc);
706 DeleteDC(data->render_hdc); 788 DeleteDC(data->render_hdc);
707 DeleteDC(data->memory_hdc); 789 DeleteDC(data->memory_hdc);
708 if (data->bmi) { 790 if (data->bmi) {
709 SDL_free(data->bmi); 791 SDL_free(data->bmi);
710 } 792 }
711 if (data->window_bmp) { 793 for (i = 0; i < SDL_arraysize(data->hbm); ++i) {
712 DeleteObject(data->window_bmp); 794 if (data->hbm[i]) {
795 DeleteObject(data->hbm[i]);
796 }
797 }
798 SDL_FreeDirtyRects(&data->dirty);
799 if (data->window_dib) {
800 DeleteObject(data->window_dib);
713 } 801 }
714 SDL_free(data); 802 SDL_free(data);
715 } 803 }
716 SDL_free(renderer); 804 SDL_free(renderer);
717 } 805 }