comparison src/video/win32/SDL_gdirender.c @ 1730:e70477157db9 SDL-1.3

Starting support for Direct3D render driver.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 08 Jul 2006 18:06:02 +0000
parents
children c2a27da60b18
comparison
equal deleted inserted replaced
1729:0ef52d56e8bb 1730:e70477157db9
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #if SDL_VIDEO_RENDER_GDI
25
26 #include "SDL_win32video.h"
27 #include "../SDL_yuv_sw_c.h"
28
29 /* GDI renderer implementation */
30
31 static SDL_Renderer *SDL_GDI_CreateRenderer(SDL_Window * window,
32 Uint32 flags);
33 static int SDL_GDI_CreateTexture(SDL_Renderer * renderer,
34 SDL_Texture * texture);
35 static int SDL_GDI_QueryTexturePixels(SDL_Renderer * renderer,
36 SDL_Texture * texture, void **pixels,
37 int *pitch);
38 static int SDL_GDI_SetTexturePalette(SDL_Renderer * renderer,
39 SDL_Texture * texture,
40 const SDL_Color * colors, int firstcolor,
41 int ncolors);
42 static int SDL_GDI_GetTexturePalette(SDL_Renderer * renderer,
43 SDL_Texture * texture,
44 SDL_Color * colors, int firstcolor,
45 int ncolors);
46 static int SDL_GDI_UpdateTexture(SDL_Renderer * renderer,
47 SDL_Texture * texture, const SDL_Rect * rect,
48 const void *pixels, int pitch);
49 static int SDL_GDI_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
50 const SDL_Rect * rect, int markDirty,
51 void **pixels, int *pitch);
52 static void SDL_GDI_UnlockTexture(SDL_Renderer * renderer,
53 SDL_Texture * texture);
54 static void SDL_GDI_DirtyTexture(SDL_Renderer * renderer,
55 SDL_Texture * texture, int numrects,
56 const SDL_Rect * rects);
57 static void SDL_GDI_SelectRenderTexture(SDL_Renderer * renderer,
58 SDL_Texture * texture);
59 static int SDL_GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
60 Uint32 color);
61 static int SDL_GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
62 const SDL_Rect * srcrect,
63 const SDL_Rect * dstrect, int blendMode,
64 int scaleMode);
65 static int SDL_GDI_RenderReadPixels(SDL_Renderer * renderer,
66 const SDL_Rect * rect, void *pixels,
67 int pitch);
68 static int SDL_GDI_RenderWritePixels(SDL_Renderer * renderer,
69 const SDL_Rect * rect,
70 const void *pixels, int pitch);
71 static void SDL_GDI_RenderPresent(SDL_Renderer * renderer);
72 static void SDL_GDI_DestroyTexture(SDL_Renderer * renderer,
73 SDL_Texture * texture);
74 static void SDL_GDI_DestroyRenderer(SDL_Renderer * renderer);
75
76
77 SDL_RenderDriver SDL_GDI_RenderDriver = {
78 SDL_GDI_CreateRenderer,
79 {
80 "gdi",
81 (SDL_Renderer_PresentDiscard |
82 SDL_Renderer_PresentCopy | SDL_Renderer_RenderTarget),
83 (SDL_TextureBlendMode_None |
84 SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend),
85 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
86 11,
87 {
88 SDL_PixelFormat_Index8,
89 SDL_PixelFormat_RGB555,
90 SDL_PixelFormat_RGB565,
91 SDL_PixelFormat_RGB888,
92 SDL_PixelFormat_BGR888,
93 SDL_PixelFormat_ARGB8888,
94 SDL_PixelFormat_RGBA8888,
95 SDL_PixelFormat_ABGR8888,
96 SDL_PixelFormat_BGRA8888,
97 SDL_PixelFormat_YUY2,
98 SDL_PixelFormat_UYVY},
99 0,
100 0}
101 };
102
103 typedef struct
104 {
105 HWND hwnd;
106 HDC window_hdc;
107 HDC render_hdc;
108 HDC memory_hdc;
109 HDC current_hdc;
110 LPBITMAPINFO bmi;
111 HBITMAP window_bmp;
112 void *window_pixels;
113 int window_pitch;
114 } SDL_GDI_RenderData;
115
116 typedef struct
117 {
118 SDL_SW_YUVTexture *yuv;
119 Uint32 format;
120 HPALETTE hpal;
121 HBITMAP hbm;
122 void *pixels;
123 int pitch;
124 } SDL_GDI_TextureData;
125
126 static void
127 UpdateYUVTextureData(SDL_Texture * texture)
128 {
129 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
130 SDL_Rect rect;
131
132 rect.x = 0;
133 rect.y = 0;
134 rect.w = texture->w;
135 rect.h = texture->h;
136 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
137 texture->h, data->pixels, data->pitch);
138 }
139
140 void
141 GDI_AddRenderDriver(_THIS)
142 {
143 SDL_AddRenderDriver(0, &SDL_GDI_RenderDriver);
144 }
145
146 SDL_Renderer *
147 SDL_GDI_CreateRenderer(SDL_Window * window, Uint32 flags)
148 {
149 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
150 SDL_Renderer *renderer;
151 SDL_GDI_RenderData *data;
152 int bmi_size;
153 HBITMAP hbm;
154
155 renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer));
156 if (!renderer) {
157 SDL_OutOfMemory();
158 return NULL;
159 }
160 SDL_zerop(renderer);
161
162 data = (SDL_GDI_RenderData *) SDL_malloc(sizeof(*data));
163 if (!data) {
164 SDL_GDI_DestroyRenderer(renderer);
165 SDL_OutOfMemory();
166 return NULL;
167 }
168 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
192 renderer->CreateTexture = SDL_GDI_CreateTexture;
193 renderer->QueryTexturePixels = SDL_GDI_QueryTexturePixels;
194 renderer->SetTexturePalette = SDL_GDI_SetTexturePalette;
195 renderer->GetTexturePalette = SDL_GDI_GetTexturePalette;
196 renderer->UpdateTexture = SDL_GDI_UpdateTexture;
197 renderer->LockTexture = SDL_GDI_LockTexture;
198 renderer->UnlockTexture = SDL_GDI_UnlockTexture;
199 renderer->DirtyTexture = SDL_GDI_DirtyTexture;
200 renderer->SelectRenderTexture = SDL_GDI_SelectRenderTexture;
201 renderer->RenderFill = SDL_GDI_RenderFill;
202 renderer->RenderCopy = SDL_GDI_RenderCopy;
203 renderer->RenderReadPixels = SDL_GDI_RenderReadPixels;
204 renderer->RenderWritePixels = SDL_GDI_RenderWritePixels;
205 renderer->RenderPresent = SDL_GDI_RenderPresent;
206 renderer->DestroyTexture = SDL_GDI_DestroyTexture;
207 renderer->DestroyRenderer = SDL_GDI_DestroyRenderer;
208 renderer->info = SDL_GDI_RenderDriver.info;
209 renderer->window = window->id;
210 renderer->driverdata = data;
211
212 renderer->info.flags = SDL_Renderer_RenderTarget;
213
214 return renderer;
215 }
216
217 static int
218 SDL_GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
219 {
220 SDL_GDI_RenderData *renderdata =
221 (SDL_GDI_RenderData *) renderer->driverdata;
222 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
223 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
224 SDL_GDI_TextureData *data;
225
226 data = (SDL_GDI_TextureData *) SDL_malloc(sizeof(*data));
227 if (!data) {
228 SDL_OutOfMemory();
229 return -1;
230 }
231 SDL_zerop(data);
232
233 texture->driverdata = data;
234
235 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
236 if (texture->access == SDL_TextureAccess_Render) {
237 SDL_SetError("Rendering to YUV format textures is not supported");
238 return -1;
239 }
240 data->yuv = SDL_SW_CreateYUVTexture(texture);
241 if (!data->yuv) {
242 SDL_GDI_DestroyTexture(renderer, texture);
243 return -1;
244 }
245 data->format = display->current_mode.format;
246 } else {
247 data->format = texture->format;
248 }
249 data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
250
251 if (data->yuv || texture->access == SDL_TextureAccess_Local
252 || texture->format != SDL_GetCurrentDisplayMode()->format) {
253 int bmi_size;
254 LPBITMAPINFO bmi;
255
256 bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
257 bmi = (LPBITMAPINFO) SDL_malloc(bmi_size);
258 if (!bmi) {
259 SDL_GDI_DestroyTexture(renderer, texture);
260 SDL_OutOfMemory();
261 return -1;
262 }
263 SDL_memset(bmi, 0, bmi_size);
264 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
265 bmi->bmiHeader.biWidth = texture->w;
266 bmi->bmiHeader.biHeight = -texture->h; /* topdown bitmap */
267 bmi->bmiHeader.biPlanes = 1;
268 bmi->bmiHeader.biSizeImage = texture->h * data->pitch;
269 bmi->bmiHeader.biXPelsPerMeter = 0;
270 bmi->bmiHeader.biYPelsPerMeter = 0;
271 bmi->bmiHeader.biClrUsed = 0;
272 bmi->bmiHeader.biClrImportant = 0;
273 bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(data->format) * 8;
274 if (SDL_ISPIXELFORMAT_INDEXED(data->format)) {
275 int i, ncolors;
276 LOGPALETTE *palette;
277
278 bmi->bmiHeader.biCompression = BI_RGB;
279 ncolors = (1 << SDL_BITSPERPIXEL(data->format));
280 palette =
281 (LOGPALETTE *) SDL_malloc(sizeof(*palette) +
282 ncolors * sizeof(PALETTEENTRY));
283 if (!palette) {
284 SDL_free(bmi);
285 SDL_GDI_DestroyTexture(renderer, texture);
286 SDL_OutOfMemory();
287 return -1;
288 }
289 palette->palVersion = 0x300;
290 palette->palNumEntries = ncolors;
291 for (i = 0; i < ncolors; ++i) {
292 palette->palPalEntry[i].peRed = 0xFF;
293 palette->palPalEntry[i].peGreen = 0xFF;
294 palette->palPalEntry[i].peBlue = 0xFF;
295 palette->palPalEntry[i].peFlags = 0;
296 }
297 data->hpal = CreatePalette(palette);
298 SDL_free(palette);
299 } else {
300 int bpp;
301 Uint32 Rmask, Gmask, Bmask, Amask;
302
303 bmi->bmiHeader.biCompression = BI_BITFIELDS;
304 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask,
305 &Bmask, &Amask);
306 ((Uint32 *) bmi->bmiColors)[0] = Rmask;
307 ((Uint32 *) bmi->bmiColors)[1] = Gmask;
308 ((Uint32 *) bmi->bmiColors)[2] = Bmask;
309 data->hpal = NULL;
310 }
311 data->hbm =
312 CreateDIBSection(renderdata->memory_hdc, bmi, DIB_RGB_COLORS,
313 &data->pixels, NULL, 0);
314 } else {
315 data->hbm =
316 CreateCompatibleBitmap(renderdata->window_hdc, texture->w,
317 texture->h);
318 data->pixels = NULL;
319 }
320 if (!data->hbm) {
321 SDL_GDI_DestroyTexture(renderer, texture);
322 WIN_SetError("Couldn't create bitmap");
323 return -1;
324 }
325 return 0;
326 }
327
328 static int
329 SDL_GDI_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
330 void **pixels, int *pitch)
331 {
332 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
333
334 if (data->yuv) {
335 return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
336 } else {
337 *pixels = data->pixels;
338 *pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
339 return 0;
340 }
341 }
342
343 static int
344 SDL_GDI_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
345 const SDL_Color * colors, int firstcolor,
346 int ncolors)
347 {
348 SDL_GDI_RenderData *renderdata =
349 (SDL_GDI_RenderData *) renderer->driverdata;
350 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
351
352 if (data->yuv) {
353 SDL_SetError("YUV textures don't have a palette");
354 return -1;
355 } else {
356 PALETTEENTRY entries[256];
357 int i;
358
359 for (i = 0; i < ncolors; ++i) {
360 entries[i].peRed = colors[i].r;
361 entries[i].peGreen = colors[i].g;
362 entries[i].peBlue = colors[i].b;
363 entries[i].peFlags = 0;
364 }
365 if (!SetPaletteEntries(data->hpal, firstcolor, ncolors, entries)) {
366 WIN_SetError("SetPaletteEntries()");
367 return -1;
368 }
369 return 0;
370 }
371 }
372
373 static int
374 SDL_GDI_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
375 SDL_Color * colors, int firstcolor, int ncolors)
376 {
377 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
378
379 if (data->yuv) {
380 SDL_SetError("YUV textures don't have a palette");
381 return -1;
382 } else {
383 PALETTEENTRY entries[256];
384 int i;
385
386 if (!GetPaletteEntries(data->hpal, firstcolor, ncolors, entries)) {
387 WIN_SetError("GetPaletteEntries()");
388 return -1;
389 }
390 for (i = 0; i < ncolors; ++i) {
391 colors[i].r = entries[i].peRed;
392 colors[i].g = entries[i].peGreen;
393 colors[i].b = entries[i].peBlue;
394 }
395 return 0;
396 }
397 }
398
399 static int
400 SDL_GDI_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
401 const SDL_Rect * rect, const void *pixels, int pitch)
402 {
403 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
404
405 if (data->yuv) {
406 if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
407 return -1;
408 }
409 UpdateYUVTextureData(texture);
410 return 0;
411 } else {
412 SDL_GDI_RenderData *renderdata =
413 (SDL_GDI_RenderData *) renderer->driverdata;
414
415 if (data->pixels) {
416 Uint8 *src, *dst;
417 int row;
418 size_t length;
419
420 src = (Uint8 *) pixels;
421 dst =
422 (Uint8 *) data->pixels + rect->y * data->pitch +
423 rect->x * SDL_BYTESPERPIXEL(texture->format);
424 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
425 for (row = 0; row < rect->h; ++row) {
426 SDL_memcpy(dst, src, length);
427 src += pitch;
428 dst += data->pitch;
429 }
430 } else if (rect->w == texture->w && pitch == data->pitch) {
431 if (!SetDIBits
432 (renderdata->window_hdc, data->hbm, rect->y, rect->h, pixels,
433 renderdata->bmi, DIB_RGB_COLORS)) {
434 WIN_SetError("SetDIBits()");
435 return -1;
436 }
437 } else {
438 SDL_SetError
439 ("FIXME: Need to allocate temporary memory and do GetDIBits() followed by SetDIBits(), since we can only set blocks of scanlines at a time");
440 return -1;
441 }
442 return 0;
443 }
444 }
445
446 static int
447 SDL_GDI_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
448 const SDL_Rect * rect, int markDirty, void **pixels,
449 int *pitch)
450 {
451 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
452
453 if (data->yuv) {
454 return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
455 pitch);
456 } else {
457 GdiFlush();
458 *pixels =
459 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
460 rect->x * SDL_BYTESPERPIXEL(texture->format));
461 *pitch = data->pitch;
462 return 0;
463 }
464 }
465
466 static void
467 SDL_GDI_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
468 {
469 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
470
471 if (data->yuv) {
472 SDL_SW_UnlockYUVTexture(data->yuv);
473 UpdateYUVTextureData(texture);
474 }
475 }
476
477 static void
478 SDL_GDI_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
479 int numrects, const SDL_Rect * rects)
480 {
481 }
482
483 static void
484 SDL_GDI_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture)
485 {
486 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
487
488 if (texture) {
489 SDL_GDI_TextureData *texturedata =
490 (SDL_GDI_TextureData *) texture->driverdata;
491 SelectObject(data->render_hdc, texturedata->hbm);
492 if (texturedata->hpal) {
493 SelectPalette(data->render_hdc, texturedata->hpal, TRUE);
494 RealizePalette(data->render_hdc);
495 }
496 data->current_hdc = data->render_hdc;
497 } else {
498 data->current_hdc = data->current_hdc;
499 }
500 }
501
502 static int
503 SDL_GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
504 Uint32 color)
505 {
506 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
507 Uint8 r, g, b;
508 RECT rc;
509 static HBRUSH brush;
510 int status;
511
512 r = (Uint8) ((color >> 16) & 0xFF);
513 g = (Uint8) ((color >> 8) & 0xFF);
514 b = (Uint8) (color & 0xFF);
515
516 rc.left = rect->x;
517 rc.top = rect->y;
518 rc.right = rect->x + rect->w + 1;
519 rc.bottom = rect->y + rect->h + 1;
520
521 /* Should we cache the brushes? .. it looks like GDI does for us. :) */
522 brush = CreateSolidBrush(RGB(r, g, b));
523 SelectObject(data->current_hdc, brush);
524 status = FillRect(data->current_hdc, &rc, brush);
525 DeleteObject(brush);
526
527 if (!status) {
528 WIN_SetError("FillRect()");
529 return -1;
530 }
531 return 0;
532 }
533
534 static int
535 SDL_GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
536 const SDL_Rect * srcrect, const SDL_Rect * dstrect,
537 int blendMode, int scaleMode)
538 {
539 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
540 SDL_GDI_TextureData *texturedata =
541 (SDL_GDI_TextureData *) texture->driverdata;
542
543 SelectObject(data->memory_hdc, texturedata->hbm);
544 if (texturedata->hpal) {
545 SelectPalette(data->memory_hdc, texturedata->hpal, TRUE);
546 RealizePalette(data->memory_hdc);
547 }
548 if (blendMode & (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) {
549 static BLENDFUNCTION blendFunc = {
550 AC_SRC_OVER,
551 0,
552 255,
553 AC_SRC_ALPHA
554 };
555 /* FIXME: GDI uses premultiplied alpha! */
556 if (!AlphaBlend
557 (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
558 dstrect->h, data->memory_hdc, srcrect->x, srcrect->y, srcrect->w,
559 srcrect->h, blendFunc)) {
560 WIN_SetError("AlphaBlend()");
561 return -1;
562 }
563 } else {
564 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
565 if (!BitBlt
566 (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
567 srcrect->h, data->memory_hdc, srcrect->x, srcrect->y,
568 SRCCOPY)) {
569 WIN_SetError("BitBlt()");
570 return -1;
571 }
572 } else {
573 if (!StretchBlt
574 (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
575 dstrect->h, data->memory_hdc, srcrect->x, srcrect->y,
576 srcrect->w, srcrect->h, SRCCOPY)) {
577 WIN_SetError("StretchBlt()");
578 return -1;
579 }
580 }
581 }
582 return 0;
583 }
584
585 static int
586 CreateWindowDIB(SDL_GDI_RenderData * data, SDL_Window * window)
587 {
588 data->window_pitch = window->w * (data->bmi->bmiHeader.biBitCount / 8);
589 data->bmi->bmiHeader.biWidth = window->w;
590 data->bmi->bmiHeader.biHeight = -window->h;
591 data->bmi->bmiHeader.biSizeImage =
592 window->h * (data->bmi->bmiHeader.biBitCount / 8);
593 data->window_bmp =
594 CreateDIBSection(data->window_hdc, data->bmi, DIB_RGB_COLORS,
595 &data->window_pixels, NULL, 0);
596 if (!data->window_bmp) {
597 WIN_SetError("CreateDIBSection()");
598 return -1;
599 }
600 return 0;
601 }
602
603 static int
604 SDL_GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
605 void *pixels, int pitch)
606 {
607 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
608 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
609
610 if (!data->window_bmp) {
611 if (CreateWindowDIB(data, window) < 0) {
612 return -1;
613 }
614 }
615
616 SelectObject(data->memory_hdc, data->window_bmp);
617 BitBlt(data->memory_hdc, rect->x, rect->y, rect->w, rect->h,
618 data->window_hdc, rect->x, rect->y, SRCCOPY);
619
620 {
621 int bpp = data->bmi->bmiHeader.biBitCount / 8;
622 Uint8 *src =
623 (Uint8 *) data->window_pixels + rect->y * data->window_pitch +
624 rect->x * bpp;
625 Uint8 *dst = (Uint8 *) pixels;
626 int row;
627
628 for (row = 0; row < rect->h; ++row) {
629 SDL_memcpy(dst, src, rect->w * bpp);
630 src += data->window_pitch;
631 dst += pitch;
632 }
633 }
634
635 return 0;
636 }
637
638 static int
639 SDL_GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
640 const void *pixels, int pitch)
641 {
642 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
643 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
644
645 if (!data->window_bmp) {
646 if (CreateWindowDIB(data, window) < 0) {
647 return -1;
648 }
649 }
650
651 {
652 int bpp = data->bmi->bmiHeader.biBitCount / 8;
653 Uint8 *src = (Uint8 *) pixels;
654 Uint8 *dst =
655 (Uint8 *) data->window_pixels + rect->y * data->window_pitch +
656 rect->x * bpp;
657 int row;
658
659 for (row = 0; row < rect->h; ++row) {
660 SDL_memcpy(dst, src, rect->w * bpp);
661 src += pitch;
662 dst += data->window_pitch;
663 }
664 }
665
666 SelectObject(data->memory_hdc, data->window_bmp);
667 BitBlt(data->window_hdc, rect->x, rect->y, rect->w, rect->h,
668 data->memory_hdc, rect->x, rect->y, SRCCOPY);
669
670 return 0;
671 }
672
673 static void
674 SDL_GDI_RenderPresent(SDL_Renderer * renderer)
675 {
676 }
677
678 static void
679 SDL_GDI_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
680 {
681 SDL_GDI_TextureData *data = (SDL_GDI_TextureData *) texture->driverdata;
682
683 if (!data) {
684 return;
685 }
686 if (data->yuv) {
687 SDL_SW_DestroyYUVTexture(data->yuv);
688 }
689 if (data->hpal) {
690 DeleteObject(data->hpal);
691 }
692 if (data->hbm) {
693 DeleteObject(data->hbm);
694 }
695 SDL_free(data);
696 texture->driverdata = NULL;
697 }
698
699 void
700 SDL_GDI_DestroyRenderer(SDL_Renderer * renderer)
701 {
702 SDL_GDI_RenderData *data = (SDL_GDI_RenderData *) renderer->driverdata;
703
704 if (data) {
705 ReleaseDC(data->hwnd, data->window_hdc);
706 DeleteDC(data->render_hdc);
707 DeleteDC(data->memory_hdc);
708 if (data->bmi) {
709 SDL_free(data->bmi);
710 }
711 if (data->window_bmp) {
712 DeleteObject(data->window_bmp);
713 }
714 SDL_free(data);
715 }
716 SDL_free(renderer);
717 }
718
719 #endif /* SDL_VIDEO_RENDER_GDI */
720
721 /* vi: set ts=4 sw=4 expandtab: */