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