Mercurial > sdl-ios-xcode
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: */ |