comparison src/video/win32/SDL_dibrender.c @ 1724:6c63fc2bd986 SDL-1.3

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