Mercurial > sdl-ios-xcode
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 } |