Mercurial > sdl-ios-xcode
comparison src/video/win32/SDL_gapirender.c @ 3168:6338b7f2d024
Hi,
I have prepared a set of patches to readd WindowsCE support to SDL 1.3.
I've created a new GAPI/Rawframebuffer and a DirectDraw renderer.
Both renderers are work in progress and there are several unimplemented
cases. (Notably
RenderLine/RenderPoint/RenderFill/QueryTexturePixels/UpdateTexture and
texture blending )
Nevertheless I am successfully using these renderers together with the
SDL software renderer. (On most devices the SDL software renderer will
be much faster as there are only badly optimized vendor drivers available)
I send these patches now in this unpolished state because there seems to
be some interest in win ce and someone has to start supporting SDL 1.3
Now on to the patches:
wince_events_window_fixes.patch
fixes some wince incompatibilities and adds fullscreen support via
SHFullScreen. NOTE: This patch shouldn't have any side effects on
Windows, but I have NOT tested it on Windows, so please double-check.
This patch doesn't dependent on the following ones.
wince_renderers_system.patch
This patch does all necessary modifications to the SDL system.
- it adds the renderers to the configure system
- it adds the renderers to win32video
SDL_ceddrawrender.c
SDL_ceddrawrender.h
SDL_gapirender_c.h
SDL_gapirender.c
SDL_gapirender.h
these files add the new render drivers and should be placed in
src/video/win32
Some notes to people who want to test this:
- I have only compiled sdl with ming32ce, so the VisualC files are not
up to date
- As mingw32ce has no ddraw.h this file must be taken from the MS SDK
and modified to work with gcc
- I had to modify line 2611 in configure.in to
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lcoredll -lcommctrl -lmmtimer
-Wl,--image-base -Wl,0x10000"
otherwise GetCPinfo wouldn't link. If someone knows whats causing this
I'd be happy to hear about it.
It would be great if these patches could make their way into SVN as this
would make collaboration much much easier.
I'm out of office for the next week and therefore will be unavailable
via email.
Regards
Stefan
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 07 Jun 2009 02:44:46 +0000 |
parents | |
children | 83518f8fcd61 |
comparison
equal
deleted
inserted
replaced
3167:0c85abc61e47 | 3168:6338b7f2d024 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2009 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 Stefan Klug | |
23 klug.stefan@gmx.de | |
24 */ | |
25 #include "SDL_config.h" | |
26 | |
27 #if SDL_VIDEO_RENDER_GAPI | |
28 | |
29 #include "SDL_win32video.h" | |
30 //#include "../SDL_sysvideo.h" | |
31 #include "../SDL_yuv_sw_c.h" | |
32 #include "../SDL_renderer_sw.h" | |
33 | |
34 #include "SDL_gapirender_c.h" | |
35 | |
36 #define GAPI_RENDERER_DEBUG 1 | |
37 | |
38 /* GAPI renderer implementation */ | |
39 | |
40 static SDL_Renderer *GAPI_CreateRenderer(SDL_Window * window, Uint32 flags); | |
41 static int GAPI_RenderPoint(SDL_Renderer * renderer, int x, int y); | |
42 static int GAPI_RenderLine(SDL_Renderer * renderer, int x1, int y1, | |
43 int x2, int y2); | |
44 static int GAPI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); | |
45 static int GAPI_RenderCopy(SDL_Renderer * renderer, | |
46 SDL_Texture * texture, | |
47 const SDL_Rect * srcrect, | |
48 const SDL_Rect * dstrect); | |
49 static void GAPI_RenderPresent(SDL_Renderer * renderer); | |
50 static void GAPI_DestroyRenderer(SDL_Renderer * renderer); | |
51 | |
52 | |
53 SDL_RenderDriver GAPI_RenderDriver = { | |
54 GAPI_CreateRenderer, | |
55 { | |
56 "gapi", | |
57 (SDL_RENDERER_SINGLEBUFFER), | |
58 } | |
59 }; | |
60 | |
61 static HMODULE g_hGapiLib = 0; | |
62 | |
63 // for testing with GapiEmu | |
64 #define USE_GAPI_EMU 0 | |
65 #define EMULATE_AXIM_X30 0 | |
66 | |
67 #if 0 | |
68 #define GAPI_LOG(...) printf(__VA_ARGS__) | |
69 #else | |
70 #define GAPI_LOG(...) | |
71 #endif | |
72 | |
73 | |
74 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO | |
75 #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") | |
76 #endif | |
77 | |
78 | |
79 static void | |
80 GAPI_SetError(const char *prefix, HRESULT result) | |
81 { | |
82 const char *error; | |
83 | |
84 switch (result) { | |
85 default: | |
86 error = "UNKNOWN"; | |
87 break; | |
88 } | |
89 SDL_SetError("%s: %s", prefix, error); | |
90 } | |
91 | |
92 void | |
93 GAPI_AddRenderDriver(_THIS) | |
94 { | |
95 /* TODO: should we check for support of GetRawFramebuffer here? | |
96 */ | |
97 #if USE_GAPI_EMU | |
98 g_hGapiLib = LoadLibrary(L"GAPI_Emu.dll"); | |
99 #else | |
100 g_hGapiLib = LoadLibrary(L"\\Windows\\gx.dll"); | |
101 #endif | |
102 | |
103 if (g_hGapiLib) { | |
104 #define LINK(name,import) gx.name = (PFN##name)GetProcAddress( g_hGapiLib, L##import ); | |
105 | |
106 LINK(GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z") | |
107 LINK(GXCloseDisplay, "?GXCloseDisplay@@YAHXZ") | |
108 LINK(GXBeginDraw, "?GXBeginDraw@@YAPAXXZ") | |
109 LINK(GXEndDraw, "?GXEndDraw@@YAHXZ") | |
110 LINK(GXOpenInput, "?GXOpenInput@@YAHXZ") | |
111 LINK(GXCloseInput, "?GXCloseInput@@YAHXZ") | |
112 LINK(GXGetDisplayProperties, | |
113 "?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") | |
114 LINK(GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z") | |
115 LINK(GXSuspend, "?GXSuspend@@YAHXZ") | |
116 LINK(GXResume, "?GXResume@@YAHXZ") | |
117 LINK(GXSetViewport, "?GXSetViewport@@YAHKKKK@Z") | |
118 LINK(GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ") | |
119 | |
120 /* wrong gapi.dll */ | |
121 if (!gx.GXOpenDisplay) { | |
122 FreeLibrary(g_hGapiLib); | |
123 g_hGapiLib = 0; | |
124 } | |
125 #undef LINK | |
126 } | |
127 | |
128 SDL_AddRenderDriver(0, &GAPI_RenderDriver); | |
129 } | |
130 | |
131 typedef enum | |
132 { | |
133 USAGE_GX_FUNCS = 0x0001, /* enable to use GXOpen/GXClose/GXBeginDraw... */ | |
134 USAGE_DATA_PTR_CONSTANT = 0x0002 /* the framebuffer is at a constant location, don't use values from GXBeginDraw() */ | |
135 } GAPI_UsageFlags; | |
136 | |
137 | |
138 | |
139 typedef struct | |
140 { | |
141 int w; | |
142 int h; | |
143 int xPitch; /* bytes to move to go to the next pixel */ | |
144 int yPitch; /* bytes to move to go to the next line */ | |
145 int offset; /* data offset, to add to the data returned from GetFramebuffer, before processing */ | |
146 | |
147 void *data; | |
148 Uint32 usageFlags; /* these flags contain options to define screen handling and to reliably workarounds */ | |
149 | |
150 Uint32 format; /* pixel format as defined in SDL_pixels.h */ | |
151 | |
152 } GAPI_RenderData; | |
153 | |
154 | |
155 static Uint32 | |
156 GuessPixelFormatFromBpp(int bpp) | |
157 { | |
158 switch (bpp) { | |
159 case 15: | |
160 return SDL_PIXELFORMAT_RGB555; | |
161 case 16: | |
162 return SDL_PIXELFORMAT_RGB565; | |
163 default: | |
164 return SDL_PIXELFORMAT_UNKNOWN; | |
165 break; | |
166 } | |
167 } | |
168 | |
169 static GAPI_RenderData * | |
170 FillRenderDataRawFramebuffer(SDL_Window * window) | |
171 { | |
172 RawFrameBufferInfo rbi; | |
173 GAPI_RenderData *renderdata; | |
174 HDC hdc; | |
175 | |
176 //TODO should we use the hdc of the window? | |
177 hdc = GetDC(NULL); | |
178 int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, | |
179 sizeof(RawFrameBufferInfo), | |
180 (char *) &rbi); | |
181 ReleaseDC(NULL, hdc); | |
182 | |
183 if (!(result > 0)) { | |
184 return NULL; | |
185 } | |
186 | |
187 /* Asus A696 returns wrong results so we do a sanity check | |
188 See: | |
189 http://groups.google.com/group/microsoft.public.smartphone.developer/browse_thread/thread/4fde5bddd477de81 | |
190 */ | |
191 if (rbi.cxPixels <= 0 || | |
192 rbi.cyPixels <= 0 || | |
193 rbi.cxStride == 0 || rbi.cyStride == 0 || rbi.pFramePointer == 0) { | |
194 return NULL; | |
195 } | |
196 | |
197 | |
198 renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(*renderdata)); | |
199 if (!renderdata) { | |
200 SDL_OutOfMemory(); | |
201 return NULL; | |
202 } | |
203 //Try to match the window size | |
204 //TODO add rotation support | |
205 if (rbi.cxPixels != window->w || rbi.cyPixels != window->h) { | |
206 SDL_free(renderdata); | |
207 return NULL; | |
208 } | |
209 //Check that the display uses a known display format | |
210 switch (rbi.wFormat) { | |
211 case FORMAT_565: | |
212 renderdata->format = SDL_PIXELFORMAT_RGB565; | |
213 break; | |
214 case FORMAT_555: | |
215 renderdata->format = SDL_PIXELFORMAT_RGB555; | |
216 break; | |
217 default: | |
218 //TODO we should add support for other formats | |
219 SDL_free(renderdata); | |
220 return NULL; | |
221 } | |
222 | |
223 renderdata->usageFlags = USAGE_DATA_PTR_CONSTANT; | |
224 renderdata->data = rbi.pFramePointer; | |
225 renderdata->w = rbi.cxPixels; | |
226 renderdata->h = rbi.cyPixels; | |
227 renderdata->xPitch = rbi.cxStride; | |
228 renderdata->yPitch = rbi.cyStride; | |
229 | |
230 return renderdata; | |
231 | |
232 } | |
233 | |
234 | |
235 static GAPI_RenderData * | |
236 FillRenderDataGAPI(SDL_Window * window) | |
237 { | |
238 GAPI_RenderData *renderdata; | |
239 struct GXDisplayProperties gxdp; | |
240 int tmp; | |
241 | |
242 #ifdef _ARM_ | |
243 WCHAR oemstr[100]; | |
244 #endif | |
245 | |
246 if (!g_hGapiLib) { | |
247 return NULL; | |
248 } | |
249 | |
250 renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(GAPI_RenderData)); | |
251 if (!renderdata) { | |
252 SDL_OutOfMemory(); | |
253 return NULL; | |
254 } | |
255 | |
256 gxdp = gx.GXGetDisplayProperties(); | |
257 renderdata->usageFlags = USAGE_GX_FUNCS; | |
258 renderdata->w = gxdp.cxWidth; | |
259 renderdata->h = gxdp.cyHeight; | |
260 renderdata->xPitch = gxdp.cbxPitch; | |
261 renderdata->yPitch = gxdp.cbyPitch; | |
262 | |
263 //Check that the display uses a known display format | |
264 if (gxdp.ffFormat & kfDirect565) { | |
265 renderdata->format = SDL_PIXELFORMAT_RGB565; | |
266 } else if (gxdp.ffFormat & kfDirect555) { | |
267 renderdata->format = SDL_PIXELFORMAT_RGB555; | |
268 } else { | |
269 renderdata->format = SDL_PIXELFORMAT_UNKNOWN; | |
270 } | |
271 | |
272 /* apply some device specific corrections */ | |
273 #ifdef _ARM_ | |
274 SystemParametersInfo(SPI_GETOEMINFO, sizeof(oemstr), oemstr, 0); | |
275 | |
276 // buggy iPaq38xx | |
277 if ((oemstr[12] == 'H') && (oemstr[13] == '3') | |
278 && (oemstr[14] == '8') | |
279 && (gxdp.cbxPitch > 0)) { | |
280 renderdata->data = (void *) 0xac0755a0; | |
281 renderdata->xPitch = -640; | |
282 renderdata->yPitch = 2; | |
283 } | |
284 #if (EMULATE_AXIM_X30 == 0) | |
285 // buggy Dell Axim X30 | |
286 if (_tcsncmp(oemstr, L"Dell Axim X30", 13) == 0) | |
287 #endif | |
288 { | |
289 GXDeviceInfo gxInfo = { 0 }; | |
290 HDC hdc = GetDC(NULL); | |
291 int result; | |
292 | |
293 gxInfo.Version = 100; | |
294 result = | |
295 ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), | |
296 (char *) &gxInfo); | |
297 if (result > 0) { | |
298 renderdata->usageFlags = USAGE_DATA_PTR_CONSTANT; /* no more GAPI usage from now */ | |
299 renderdata->data = gxInfo.pvFrameBuffer; | |
300 this->hidden->needUpdate = 0; | |
301 renderdata->xPitch = 2; | |
302 renderdata->yPitch = 480; | |
303 renderdata->w = gxInfo.cxWidth; | |
304 renderdata->h = gxInfo.cyHeight; | |
305 | |
306 //Check that the display uses a known display format | |
307 switch (rbi->wFormat) { | |
308 case FORMAT_565: | |
309 renderdata->format = SDL_PIXELFORMAT_RGB565; | |
310 break; | |
311 case FORMAT_555: | |
312 renderdata->format = SDL_PIXELFORMAT_RGB555; | |
313 break; | |
314 default: | |
315 //TODO we should add support for other formats | |
316 SDL_free(renderdata); | |
317 return NULL; | |
318 } | |
319 } | |
320 } | |
321 #endif | |
322 | |
323 | |
324 if (renderdata->format == SDL_PIXELFORMAT_UNKNOWN) { | |
325 SDL_SetError("Gapi Pixelformat is unknown"); | |
326 SDL_free(renderdata); | |
327 return NULL; | |
328 } | |
329 | |
330 /* Gapi always returns values in standard orientation, so we manually apply | |
331 the current orientation | |
332 */ | |
333 | |
334 DEVMODE settings; | |
335 SDL_memset(&settings, 0, sizeof(DEVMODE)); | |
336 settings.dmSize = sizeof(DEVMODE); | |
337 | |
338 settings.dmFields = DM_DISPLAYORIENTATION; | |
339 ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL); | |
340 | |
341 if (settings.dmDisplayOrientation == DMDO_90) { | |
342 | |
343 tmp = renderdata->w; | |
344 renderdata->w = renderdata->h; | |
345 renderdata->h = tmp; | |
346 | |
347 tmp = renderdata->xPitch; | |
348 renderdata->xPitch = -renderdata->yPitch; | |
349 renderdata->yPitch = tmp; | |
350 | |
351 renderdata->offset = -renderdata->w * renderdata->xPitch; | |
352 | |
353 } else if (settings.dmDisplayOrientation == DMDO_180) { | |
354 | |
355 renderdata->xPitch = -renderdata->xPitch; | |
356 renderdata->yPitch = -renderdata->yPitch; | |
357 | |
358 renderdata->offset = -renderdata->h * renderdata->yPitch | |
359 - renderdata->w * renderdata->xPitch; | |
360 | |
361 } else if (settings.dmDisplayOrientation == DMDO_270) { | |
362 | |
363 tmp = renderdata->w; | |
364 renderdata->w = renderdata->h; | |
365 renderdata->h = tmp; | |
366 | |
367 tmp = renderdata->xPitch; | |
368 renderdata->xPitch = renderdata->yPitch; | |
369 renderdata->yPitch = -tmp; | |
370 | |
371 renderdata->offset = -renderdata->h * renderdata->yPitch; | |
372 | |
373 } | |
374 | |
375 if (renderdata->w != window->w || renderdata->h != window->h) { | |
376 GAPI_LOG("GAPI open failed, wrong size %i %i %i %i\n", renderdata->w, | |
377 renderdata->h, renderdata->xPitch, renderdata->yPitch); | |
378 SDL_free(renderdata); | |
379 return NULL; | |
380 } | |
381 | |
382 return renderdata; | |
383 | |
384 } | |
385 | |
386 | |
387 /* This function does the whole encapsulation of Gapi/RAWFRAMEBUFFER | |
388 it should handle all the device dependent details and fill the device INDEPENDENT | |
389 RenderData structure. | |
390 */ | |
391 GAPI_RenderData * | |
392 FillRenderData(SDL_Window * window) | |
393 { | |
394 /* We try to match the requested window to the modes available by GAPI and RAWFRAMEBUFFER. | |
395 First RAWFRAMEBUFFER is tried, as it is the most reliable one | |
396 Look here for detailed discussions: | |
397 http://pdaphonehome.com/forums/samsung-i700/28087-just-saw.html | |
398 http://blogs.msdn.com/windowsmobile/archive/2007/08/13/have-you-migrated-to-directdraw-yet.aspx | |
399 */ | |
400 | |
401 GAPI_RenderData *res; | |
402 | |
403 res = FillRenderDataRawFramebuffer(window); | |
404 GAPI_LOG("FillRenderDataRawFramebuffer: %p\n", res); | |
405 if (res) { | |
406 return res; | |
407 } | |
408 //Now we try gapi | |
409 res = FillRenderDataGAPI(window); | |
410 GAPI_LOG("FillRenderDataGAPI: %p\n", res); | |
411 | |
412 return res; | |
413 } | |
414 | |
415 void * | |
416 GetFramebuffer() | |
417 { | |
418 | |
419 } | |
420 | |
421 | |
422 SDL_Renderer * | |
423 GAPI_CreateRenderer(SDL_Window * window, Uint32 flags) | |
424 { | |
425 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | |
426 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; | |
427 SDL_DisplayMode *displayMode = &display->current_mode; | |
428 SDL_Renderer *renderer; | |
429 GAPI_RenderData *data; | |
430 int i, n; | |
431 int bpp; | |
432 Uint32 Rmask, Gmask, Bmask, Amask; | |
433 | |
434 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { | |
435 SDL_SetError("Gapi supports only fullscreen windows"); | |
436 return NULL; | |
437 } | |
438 | |
439 if (!SDL_PixelFormatEnumToMasks | |
440 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
441 SDL_SetError("Unknown display format"); | |
442 return NULL; | |
443 } | |
444 | |
445 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); | |
446 if (!renderer) { | |
447 SDL_OutOfMemory(); | |
448 return NULL; | |
449 } | |
450 | |
451 data = FillRenderData(window); | |
452 if (!data) { | |
453 GAPI_DestroyRenderer(renderer); | |
454 SDL_OutOfMemory(); | |
455 return NULL; | |
456 } | |
457 | |
458 renderer->RenderPoint = GAPI_RenderPoint; | |
459 renderer->RenderLine = GAPI_RenderLine; | |
460 renderer->RenderFill = GAPI_RenderFill; | |
461 renderer->RenderCopy = GAPI_RenderCopy; | |
462 renderer->RenderPresent = GAPI_RenderPresent; | |
463 renderer->DestroyRenderer = GAPI_DestroyRenderer; | |
464 renderer->info.name = GAPI_RenderDriver.info.name; | |
465 renderer->info.flags = 0; | |
466 renderer->window = window->id; | |
467 renderer->driverdata = data; | |
468 | |
469 /* Gapi provides only a framebuffer so lets use software implementation */ | |
470 Setup_SoftwareRenderer(renderer); | |
471 | |
472 #ifdef GAPI_RENDERER_DEBUG | |
473 printf("Created gapi renderer\n"); | |
474 printf("use GX functions: %i\n", data->usageFlags & USAGE_GX_FUNCS); | |
475 printf("framebuffer is constant: %i\n", | |
476 data->usageFlags & USAGE_DATA_PTR_CONSTANT); | |
477 printf("w: %i h: %i\n", data->w, data->h); | |
478 printf("data ptr: %p\n", data->data); /* this can be 0 in case of GAPI usage */ | |
479 printf("xPitch: %i\n", data->xPitch); | |
480 printf("yPitch: %i\n", data->yPitch); | |
481 printf("offset: %i\n", data->offset); | |
482 printf("format: %x\n", data->format); | |
483 #endif | |
484 | |
485 if (data->usageFlags & USAGE_GX_FUNCS) { | |
486 if (gx.GXOpenDisplay(windowdata->hwnd, GX_FULLSCREEN) == 0) { | |
487 GAPI_DestroyRenderer(renderer); | |
488 return NULL; | |
489 } | |
490 } | |
491 | |
492 return renderer; | |
493 } | |
494 | |
495 static int | |
496 GAPI_RenderPoint(SDL_Renderer * renderer, int x, int y) | |
497 { | |
498 //TODO implement | |
499 return -1; | |
500 } | |
501 | |
502 static int | |
503 GAPI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) | |
504 { | |
505 //TODO implement | |
506 return -11; | |
507 } | |
508 | |
509 static int | |
510 GAPI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) | |
511 { | |
512 //TODO implement | |
513 return -1; | |
514 } | |
515 | |
516 /* Video memory is very slow so lets optimize as much as possible */ | |
517 static void | |
518 updateLine16to16(char *src, int srcXPitch, int srcYPitch, | |
519 char *dst, int dstXPitch, int dstYPitch, int width, | |
520 int height) | |
521 { | |
522 char *srcLine, *dstLine; | |
523 char *srcPix, *dstPix; | |
524 | |
525 int x, y; | |
526 | |
527 //First dumb solution | |
528 if (srcXPitch == 2 && dstXPitch == 2) { | |
529 srcLine = src; | |
530 dstLine = dst; | |
531 y = height; | |
532 while (y--) { | |
533 SDL_memcpy(dstLine, srcLine, width * sizeof(Uint16)); | |
534 srcLine += srcYPitch; | |
535 dstLine += dstYPitch; | |
536 } | |
537 } else { | |
538 //printf("GAPI uses slow blit path %i, %i\n", dstXPitch, dstYPitch); | |
539 srcLine = src; | |
540 dstLine = dst; | |
541 y = height; | |
542 while (y--) { | |
543 srcPix = srcLine; | |
544 dstPix = dstLine; | |
545 x = width; | |
546 while (x--) { | |
547 *((Uint16 *) dstPix) = *((Uint16 *) srcPix); | |
548 dstPix += dstXPitch; | |
549 srcPix += srcXPitch; | |
550 } | |
551 srcLine += srcYPitch; | |
552 dstLine += dstYPitch; | |
553 } | |
554 } | |
555 } | |
556 | |
557 static int | |
558 GAPI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
559 const SDL_Rect * srcrect, const SDL_Rect * dstrect) | |
560 { | |
561 GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; | |
562 int bpp; | |
563 int bytespp; | |
564 int status; | |
565 Uint32 Rmask, Gmask, Bmask, Amask; | |
566 | |
567 if (texture->format != data->format) { | |
568 SDL_SetError("Gapi got wrong texture"); | |
569 return -1; | |
570 } | |
571 | |
572 GAPI_LOG("GAPI_RenderCopy\n"); | |
573 | |
574 if (data->usageFlags & USAGE_GX_FUNCS) { | |
575 char *buffer; | |
576 buffer = gx.GXBeginDraw(); | |
577 if (!(data->usageFlags & USAGE_DATA_PTR_CONSTANT)) { | |
578 data->data = buffer; | |
579 } | |
580 } | |
581 | |
582 GAPI_LOG("GAPI_RenderCopy blit\n"); | |
583 /* If our framebuffer has an xPitch which matches the pixelsize, we | |
584 can convert the framebuffer to a SDL_surface and blit there, | |
585 otherwise, we have to use our own blitting routine | |
586 */ | |
587 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, | |
588 &Amask); | |
589 bytespp = bpp >> 3; | |
590 if (data->xPitch == bytespp && 0) { | |
591 SDL_Surface *screen = | |
592 SDL_CreateRGBSurfaceFrom(data->data, data->w, data->h, | |
593 bpp, data->yPitch, Rmask, Gmask, Bmask, | |
594 Amask); | |
595 status = | |
596 SDL_UpperBlit((SDL_Surface *) texture->driverdata, srcrect, | |
597 screen, dstrect); | |
598 SDL_FreeSurface(screen); | |
599 } else { /* screen is rotated, we have to blit on our own */ | |
600 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
601 | |
602 char *src, *dst; | |
603 src = surface->pixels; | |
604 src += srcrect->y * surface->pitch + srcrect->x * 2; | |
605 | |
606 dst = data->data + data->offset; | |
607 dst += dstrect->y * data->yPitch + dstrect->x * data->xPitch; | |
608 | |
609 updateLine16to16(src, 2, surface->pitch, | |
610 dst, data->xPitch, data->yPitch, | |
611 srcrect->w, srcrect->h); | |
612 | |
613 } | |
614 | |
615 Uint32 ticks = SDL_GetTicks(); | |
616 if (data->usageFlags & USAGE_GX_FUNCS) { | |
617 gx.GXEndDraw(); | |
618 } | |
619 GAPI_LOG("GAPI_RenderCopy %i\n", SDL_GetTicks() - ticks); | |
620 return status; | |
621 } | |
622 | |
623 static void | |
624 GAPI_RenderPresent(SDL_Renderer * renderer) | |
625 { | |
626 /* Nothing todo as we rendered directly to the screen on RenderCopy */ | |
627 } | |
628 | |
629 static void | |
630 GAPI_DestroyRenderer(SDL_Renderer * renderer) | |
631 { | |
632 GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; | |
633 | |
634 if (data->usageFlags & USAGE_GX_FUNCS) { | |
635 gx.GXCloseDisplay(); | |
636 } | |
637 | |
638 if (data) { | |
639 SDL_free(data); | |
640 } | |
641 SDL_free(renderer); | |
642 } | |
643 | |
644 #endif /* SDL_VIDEO_RENDER_GAPI */ | |
645 | |
646 /* vi: set ts=4 sw=4 expandtab: */ |