Mercurial > sdl-ios-xcode
annotate src/video/win32/SDL_gapirender.c @ 3583:65f66674b7fb
Allocate memory only if we're going to overwrite an environment variable
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 16 Dec 2009 16:08:17 +0000 |
parents | 83518f8fcd61 |
children | ce7d4942d18b |
rev | line source |
---|---|
3168 | 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 { | |
3520
83518f8fcd61
Fixed calls to SDL_AddRenderDriver()
Sam Lantinga <slouken@libsdl.org>
parents:
3168
diff
changeset
|
95 int i; |
83518f8fcd61
Fixed calls to SDL_AddRenderDriver()
Sam Lantinga <slouken@libsdl.org>
parents:
3168
diff
changeset
|
96 |
3168 | 97 /* TODO: should we check for support of GetRawFramebuffer here? |
98 */ | |
99 #if USE_GAPI_EMU | |
100 g_hGapiLib = LoadLibrary(L"GAPI_Emu.dll"); | |
101 #else | |
102 g_hGapiLib = LoadLibrary(L"\\Windows\\gx.dll"); | |
103 #endif | |
104 | |
105 if (g_hGapiLib) { | |
106 #define LINK(name,import) gx.name = (PFN##name)GetProcAddress( g_hGapiLib, L##import ); | |
107 | |
108 LINK(GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z") | |
109 LINK(GXCloseDisplay, "?GXCloseDisplay@@YAHXZ") | |
110 LINK(GXBeginDraw, "?GXBeginDraw@@YAPAXXZ") | |
111 LINK(GXEndDraw, "?GXEndDraw@@YAHXZ") | |
112 LINK(GXOpenInput, "?GXOpenInput@@YAHXZ") | |
113 LINK(GXCloseInput, "?GXCloseInput@@YAHXZ") | |
114 LINK(GXGetDisplayProperties, | |
115 "?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") | |
116 LINK(GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z") | |
117 LINK(GXSuspend, "?GXSuspend@@YAHXZ") | |
118 LINK(GXResume, "?GXResume@@YAHXZ") | |
119 LINK(GXSetViewport, "?GXSetViewport@@YAHKKKK@Z") | |
120 LINK(GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ") | |
121 | |
122 /* wrong gapi.dll */ | |
123 if (!gx.GXOpenDisplay) { | |
124 FreeLibrary(g_hGapiLib); | |
125 g_hGapiLib = 0; | |
126 } | |
127 #undef LINK | |
128 } | |
129 | |
3520
83518f8fcd61
Fixed calls to SDL_AddRenderDriver()
Sam Lantinga <slouken@libsdl.org>
parents:
3168
diff
changeset
|
130 for (i = 0; i < _this->num_displays; ++i) { |
83518f8fcd61
Fixed calls to SDL_AddRenderDriver()
Sam Lantinga <slouken@libsdl.org>
parents:
3168
diff
changeset
|
131 SDL_AddRenderDriver(&_this->displays[i], &GAPI_RenderDriver); |
83518f8fcd61
Fixed calls to SDL_AddRenderDriver()
Sam Lantinga <slouken@libsdl.org>
parents:
3168
diff
changeset
|
132 } |
3168 | 133 } |
134 | |
135 typedef enum | |
136 { | |
137 USAGE_GX_FUNCS = 0x0001, /* enable to use GXOpen/GXClose/GXBeginDraw... */ | |
138 USAGE_DATA_PTR_CONSTANT = 0x0002 /* the framebuffer is at a constant location, don't use values from GXBeginDraw() */ | |
139 } GAPI_UsageFlags; | |
140 | |
141 | |
142 | |
143 typedef struct | |
144 { | |
145 int w; | |
146 int h; | |
147 int xPitch; /* bytes to move to go to the next pixel */ | |
148 int yPitch; /* bytes to move to go to the next line */ | |
149 int offset; /* data offset, to add to the data returned from GetFramebuffer, before processing */ | |
150 | |
151 void *data; | |
152 Uint32 usageFlags; /* these flags contain options to define screen handling and to reliably workarounds */ | |
153 | |
154 Uint32 format; /* pixel format as defined in SDL_pixels.h */ | |
155 | |
156 } GAPI_RenderData; | |
157 | |
158 | |
159 static Uint32 | |
160 GuessPixelFormatFromBpp(int bpp) | |
161 { | |
162 switch (bpp) { | |
163 case 15: | |
164 return SDL_PIXELFORMAT_RGB555; | |
165 case 16: | |
166 return SDL_PIXELFORMAT_RGB565; | |
167 default: | |
168 return SDL_PIXELFORMAT_UNKNOWN; | |
169 break; | |
170 } | |
171 } | |
172 | |
173 static GAPI_RenderData * | |
174 FillRenderDataRawFramebuffer(SDL_Window * window) | |
175 { | |
176 RawFrameBufferInfo rbi; | |
177 GAPI_RenderData *renderdata; | |
178 HDC hdc; | |
179 | |
180 //TODO should we use the hdc of the window? | |
181 hdc = GetDC(NULL); | |
182 int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, | |
183 sizeof(RawFrameBufferInfo), | |
184 (char *) &rbi); | |
185 ReleaseDC(NULL, hdc); | |
186 | |
187 if (!(result > 0)) { | |
188 return NULL; | |
189 } | |
190 | |
191 /* Asus A696 returns wrong results so we do a sanity check | |
192 See: | |
193 http://groups.google.com/group/microsoft.public.smartphone.developer/browse_thread/thread/4fde5bddd477de81 | |
194 */ | |
195 if (rbi.cxPixels <= 0 || | |
196 rbi.cyPixels <= 0 || | |
197 rbi.cxStride == 0 || rbi.cyStride == 0 || rbi.pFramePointer == 0) { | |
198 return NULL; | |
199 } | |
200 | |
201 | |
202 renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(*renderdata)); | |
203 if (!renderdata) { | |
204 SDL_OutOfMemory(); | |
205 return NULL; | |
206 } | |
207 //Try to match the window size | |
208 //TODO add rotation support | |
209 if (rbi.cxPixels != window->w || rbi.cyPixels != window->h) { | |
210 SDL_free(renderdata); | |
211 return NULL; | |
212 } | |
213 //Check that the display uses a known display format | |
214 switch (rbi.wFormat) { | |
215 case FORMAT_565: | |
216 renderdata->format = SDL_PIXELFORMAT_RGB565; | |
217 break; | |
218 case FORMAT_555: | |
219 renderdata->format = SDL_PIXELFORMAT_RGB555; | |
220 break; | |
221 default: | |
222 //TODO we should add support for other formats | |
223 SDL_free(renderdata); | |
224 return NULL; | |
225 } | |
226 | |
227 renderdata->usageFlags = USAGE_DATA_PTR_CONSTANT; | |
228 renderdata->data = rbi.pFramePointer; | |
229 renderdata->w = rbi.cxPixels; | |
230 renderdata->h = rbi.cyPixels; | |
231 renderdata->xPitch = rbi.cxStride; | |
232 renderdata->yPitch = rbi.cyStride; | |
233 | |
234 return renderdata; | |
235 | |
236 } | |
237 | |
238 | |
239 static GAPI_RenderData * | |
240 FillRenderDataGAPI(SDL_Window * window) | |
241 { | |
242 GAPI_RenderData *renderdata; | |
243 struct GXDisplayProperties gxdp; | |
244 int tmp; | |
245 | |
246 #ifdef _ARM_ | |
247 WCHAR oemstr[100]; | |
248 #endif | |
249 | |
250 if (!g_hGapiLib) { | |
251 return NULL; | |
252 } | |
253 | |
254 renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(GAPI_RenderData)); | |
255 if (!renderdata) { | |
256 SDL_OutOfMemory(); | |
257 return NULL; | |
258 } | |
259 | |
260 gxdp = gx.GXGetDisplayProperties(); | |
261 renderdata->usageFlags = USAGE_GX_FUNCS; | |
262 renderdata->w = gxdp.cxWidth; | |
263 renderdata->h = gxdp.cyHeight; | |
264 renderdata->xPitch = gxdp.cbxPitch; | |
265 renderdata->yPitch = gxdp.cbyPitch; | |
266 | |
267 //Check that the display uses a known display format | |
268 if (gxdp.ffFormat & kfDirect565) { | |
269 renderdata->format = SDL_PIXELFORMAT_RGB565; | |
270 } else if (gxdp.ffFormat & kfDirect555) { | |
271 renderdata->format = SDL_PIXELFORMAT_RGB555; | |
272 } else { | |
273 renderdata->format = SDL_PIXELFORMAT_UNKNOWN; | |
274 } | |
275 | |
276 /* apply some device specific corrections */ | |
277 #ifdef _ARM_ | |
278 SystemParametersInfo(SPI_GETOEMINFO, sizeof(oemstr), oemstr, 0); | |
279 | |
280 // buggy iPaq38xx | |
281 if ((oemstr[12] == 'H') && (oemstr[13] == '3') | |
282 && (oemstr[14] == '8') | |
283 && (gxdp.cbxPitch > 0)) { | |
284 renderdata->data = (void *) 0xac0755a0; | |
285 renderdata->xPitch = -640; | |
286 renderdata->yPitch = 2; | |
287 } | |
288 #if (EMULATE_AXIM_X30 == 0) | |
289 // buggy Dell Axim X30 | |
290 if (_tcsncmp(oemstr, L"Dell Axim X30", 13) == 0) | |
291 #endif | |
292 { | |
293 GXDeviceInfo gxInfo = { 0 }; | |
294 HDC hdc = GetDC(NULL); | |
295 int result; | |
296 | |
297 gxInfo.Version = 100; | |
298 result = | |
299 ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), | |
300 (char *) &gxInfo); | |
301 if (result > 0) { | |
302 renderdata->usageFlags = USAGE_DATA_PTR_CONSTANT; /* no more GAPI usage from now */ | |
303 renderdata->data = gxInfo.pvFrameBuffer; | |
304 this->hidden->needUpdate = 0; | |
305 renderdata->xPitch = 2; | |
306 renderdata->yPitch = 480; | |
307 renderdata->w = gxInfo.cxWidth; | |
308 renderdata->h = gxInfo.cyHeight; | |
309 | |
310 //Check that the display uses a known display format | |
311 switch (rbi->wFormat) { | |
312 case FORMAT_565: | |
313 renderdata->format = SDL_PIXELFORMAT_RGB565; | |
314 break; | |
315 case FORMAT_555: | |
316 renderdata->format = SDL_PIXELFORMAT_RGB555; | |
317 break; | |
318 default: | |
319 //TODO we should add support for other formats | |
320 SDL_free(renderdata); | |
321 return NULL; | |
322 } | |
323 } | |
324 } | |
325 #endif | |
326 | |
327 | |
328 if (renderdata->format == SDL_PIXELFORMAT_UNKNOWN) { | |
329 SDL_SetError("Gapi Pixelformat is unknown"); | |
330 SDL_free(renderdata); | |
331 return NULL; | |
332 } | |
333 | |
334 /* Gapi always returns values in standard orientation, so we manually apply | |
335 the current orientation | |
336 */ | |
337 | |
338 DEVMODE settings; | |
339 SDL_memset(&settings, 0, sizeof(DEVMODE)); | |
340 settings.dmSize = sizeof(DEVMODE); | |
341 | |
342 settings.dmFields = DM_DISPLAYORIENTATION; | |
343 ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL); | |
344 | |
345 if (settings.dmDisplayOrientation == DMDO_90) { | |
346 | |
347 tmp = renderdata->w; | |
348 renderdata->w = renderdata->h; | |
349 renderdata->h = tmp; | |
350 | |
351 tmp = renderdata->xPitch; | |
352 renderdata->xPitch = -renderdata->yPitch; | |
353 renderdata->yPitch = tmp; | |
354 | |
355 renderdata->offset = -renderdata->w * renderdata->xPitch; | |
356 | |
357 } else if (settings.dmDisplayOrientation == DMDO_180) { | |
358 | |
359 renderdata->xPitch = -renderdata->xPitch; | |
360 renderdata->yPitch = -renderdata->yPitch; | |
361 | |
362 renderdata->offset = -renderdata->h * renderdata->yPitch | |
363 - renderdata->w * renderdata->xPitch; | |
364 | |
365 } else if (settings.dmDisplayOrientation == DMDO_270) { | |
366 | |
367 tmp = renderdata->w; | |
368 renderdata->w = renderdata->h; | |
369 renderdata->h = tmp; | |
370 | |
371 tmp = renderdata->xPitch; | |
372 renderdata->xPitch = renderdata->yPitch; | |
373 renderdata->yPitch = -tmp; | |
374 | |
375 renderdata->offset = -renderdata->h * renderdata->yPitch; | |
376 | |
377 } | |
378 | |
379 if (renderdata->w != window->w || renderdata->h != window->h) { | |
380 GAPI_LOG("GAPI open failed, wrong size %i %i %i %i\n", renderdata->w, | |
381 renderdata->h, renderdata->xPitch, renderdata->yPitch); | |
382 SDL_free(renderdata); | |
383 return NULL; | |
384 } | |
385 | |
386 return renderdata; | |
387 | |
388 } | |
389 | |
390 | |
391 /* This function does the whole encapsulation of Gapi/RAWFRAMEBUFFER | |
392 it should handle all the device dependent details and fill the device INDEPENDENT | |
393 RenderData structure. | |
394 */ | |
395 GAPI_RenderData * | |
396 FillRenderData(SDL_Window * window) | |
397 { | |
398 /* We try to match the requested window to the modes available by GAPI and RAWFRAMEBUFFER. | |
399 First RAWFRAMEBUFFER is tried, as it is the most reliable one | |
400 Look here for detailed discussions: | |
401 http://pdaphonehome.com/forums/samsung-i700/28087-just-saw.html | |
402 http://blogs.msdn.com/windowsmobile/archive/2007/08/13/have-you-migrated-to-directdraw-yet.aspx | |
403 */ | |
404 | |
405 GAPI_RenderData *res; | |
406 | |
407 res = FillRenderDataRawFramebuffer(window); | |
408 GAPI_LOG("FillRenderDataRawFramebuffer: %p\n", res); | |
409 if (res) { | |
410 return res; | |
411 } | |
412 //Now we try gapi | |
413 res = FillRenderDataGAPI(window); | |
414 GAPI_LOG("FillRenderDataGAPI: %p\n", res); | |
415 | |
416 return res; | |
417 } | |
418 | |
419 void * | |
420 GetFramebuffer() | |
421 { | |
422 | |
423 } | |
424 | |
425 | |
426 SDL_Renderer * | |
427 GAPI_CreateRenderer(SDL_Window * window, Uint32 flags) | |
428 { | |
429 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | |
430 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; | |
431 SDL_DisplayMode *displayMode = &display->current_mode; | |
432 SDL_Renderer *renderer; | |
433 GAPI_RenderData *data; | |
434 int i, n; | |
435 int bpp; | |
436 Uint32 Rmask, Gmask, Bmask, Amask; | |
437 | |
438 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { | |
439 SDL_SetError("Gapi supports only fullscreen windows"); | |
440 return NULL; | |
441 } | |
442 | |
443 if (!SDL_PixelFormatEnumToMasks | |
444 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
445 SDL_SetError("Unknown display format"); | |
446 return NULL; | |
447 } | |
448 | |
449 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); | |
450 if (!renderer) { | |
451 SDL_OutOfMemory(); | |
452 return NULL; | |
453 } | |
454 | |
455 data = FillRenderData(window); | |
456 if (!data) { | |
457 GAPI_DestroyRenderer(renderer); | |
458 SDL_OutOfMemory(); | |
459 return NULL; | |
460 } | |
461 | |
462 renderer->RenderPoint = GAPI_RenderPoint; | |
463 renderer->RenderLine = GAPI_RenderLine; | |
464 renderer->RenderFill = GAPI_RenderFill; | |
465 renderer->RenderCopy = GAPI_RenderCopy; | |
466 renderer->RenderPresent = GAPI_RenderPresent; | |
467 renderer->DestroyRenderer = GAPI_DestroyRenderer; | |
468 renderer->info.name = GAPI_RenderDriver.info.name; | |
469 renderer->info.flags = 0; | |
470 renderer->window = window->id; | |
471 renderer->driverdata = data; | |
472 | |
473 /* Gapi provides only a framebuffer so lets use software implementation */ | |
474 Setup_SoftwareRenderer(renderer); | |
475 | |
476 #ifdef GAPI_RENDERER_DEBUG | |
477 printf("Created gapi renderer\n"); | |
478 printf("use GX functions: %i\n", data->usageFlags & USAGE_GX_FUNCS); | |
479 printf("framebuffer is constant: %i\n", | |
480 data->usageFlags & USAGE_DATA_PTR_CONSTANT); | |
481 printf("w: %i h: %i\n", data->w, data->h); | |
482 printf("data ptr: %p\n", data->data); /* this can be 0 in case of GAPI usage */ | |
483 printf("xPitch: %i\n", data->xPitch); | |
484 printf("yPitch: %i\n", data->yPitch); | |
485 printf("offset: %i\n", data->offset); | |
486 printf("format: %x\n", data->format); | |
487 #endif | |
488 | |
489 if (data->usageFlags & USAGE_GX_FUNCS) { | |
490 if (gx.GXOpenDisplay(windowdata->hwnd, GX_FULLSCREEN) == 0) { | |
491 GAPI_DestroyRenderer(renderer); | |
492 return NULL; | |
493 } | |
494 } | |
495 | |
496 return renderer; | |
497 } | |
498 | |
499 static int | |
500 GAPI_RenderPoint(SDL_Renderer * renderer, int x, int y) | |
501 { | |
502 //TODO implement | |
503 return -1; | |
504 } | |
505 | |
506 static int | |
507 GAPI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) | |
508 { | |
509 //TODO implement | |
510 return -11; | |
511 } | |
512 | |
513 static int | |
514 GAPI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) | |
515 { | |
516 //TODO implement | |
517 return -1; | |
518 } | |
519 | |
520 /* Video memory is very slow so lets optimize as much as possible */ | |
521 static void | |
522 updateLine16to16(char *src, int srcXPitch, int srcYPitch, | |
523 char *dst, int dstXPitch, int dstYPitch, int width, | |
524 int height) | |
525 { | |
526 char *srcLine, *dstLine; | |
527 char *srcPix, *dstPix; | |
528 | |
529 int x, y; | |
530 | |
531 //First dumb solution | |
532 if (srcXPitch == 2 && dstXPitch == 2) { | |
533 srcLine = src; | |
534 dstLine = dst; | |
535 y = height; | |
536 while (y--) { | |
537 SDL_memcpy(dstLine, srcLine, width * sizeof(Uint16)); | |
538 srcLine += srcYPitch; | |
539 dstLine += dstYPitch; | |
540 } | |
541 } else { | |
542 //printf("GAPI uses slow blit path %i, %i\n", dstXPitch, dstYPitch); | |
543 srcLine = src; | |
544 dstLine = dst; | |
545 y = height; | |
546 while (y--) { | |
547 srcPix = srcLine; | |
548 dstPix = dstLine; | |
549 x = width; | |
550 while (x--) { | |
551 *((Uint16 *) dstPix) = *((Uint16 *) srcPix); | |
552 dstPix += dstXPitch; | |
553 srcPix += srcXPitch; | |
554 } | |
555 srcLine += srcYPitch; | |
556 dstLine += dstYPitch; | |
557 } | |
558 } | |
559 } | |
560 | |
561 static int | |
562 GAPI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
563 const SDL_Rect * srcrect, const SDL_Rect * dstrect) | |
564 { | |
565 GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; | |
566 int bpp; | |
567 int bytespp; | |
568 int status; | |
569 Uint32 Rmask, Gmask, Bmask, Amask; | |
570 | |
571 if (texture->format != data->format) { | |
572 SDL_SetError("Gapi got wrong texture"); | |
573 return -1; | |
574 } | |
575 | |
576 GAPI_LOG("GAPI_RenderCopy\n"); | |
577 | |
578 if (data->usageFlags & USAGE_GX_FUNCS) { | |
579 char *buffer; | |
580 buffer = gx.GXBeginDraw(); | |
581 if (!(data->usageFlags & USAGE_DATA_PTR_CONSTANT)) { | |
582 data->data = buffer; | |
583 } | |
584 } | |
585 | |
586 GAPI_LOG("GAPI_RenderCopy blit\n"); | |
587 /* If our framebuffer has an xPitch which matches the pixelsize, we | |
588 can convert the framebuffer to a SDL_surface and blit there, | |
589 otherwise, we have to use our own blitting routine | |
590 */ | |
591 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, | |
592 &Amask); | |
593 bytespp = bpp >> 3; | |
594 if (data->xPitch == bytespp && 0) { | |
595 SDL_Surface *screen = | |
596 SDL_CreateRGBSurfaceFrom(data->data, data->w, data->h, | |
597 bpp, data->yPitch, Rmask, Gmask, Bmask, | |
598 Amask); | |
599 status = | |
600 SDL_UpperBlit((SDL_Surface *) texture->driverdata, srcrect, | |
601 screen, dstrect); | |
602 SDL_FreeSurface(screen); | |
603 } else { /* screen is rotated, we have to blit on our own */ | |
604 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
605 | |
606 char *src, *dst; | |
607 src = surface->pixels; | |
608 src += srcrect->y * surface->pitch + srcrect->x * 2; | |
609 | |
610 dst = data->data + data->offset; | |
611 dst += dstrect->y * data->yPitch + dstrect->x * data->xPitch; | |
612 | |
613 updateLine16to16(src, 2, surface->pitch, | |
614 dst, data->xPitch, data->yPitch, | |
615 srcrect->w, srcrect->h); | |
616 | |
617 } | |
618 | |
619 Uint32 ticks = SDL_GetTicks(); | |
620 if (data->usageFlags & USAGE_GX_FUNCS) { | |
621 gx.GXEndDraw(); | |
622 } | |
623 GAPI_LOG("GAPI_RenderCopy %i\n", SDL_GetTicks() - ticks); | |
624 return status; | |
625 } | |
626 | |
627 static void | |
628 GAPI_RenderPresent(SDL_Renderer * renderer) | |
629 { | |
630 /* Nothing todo as we rendered directly to the screen on RenderCopy */ | |
631 } | |
632 | |
633 static void | |
634 GAPI_DestroyRenderer(SDL_Renderer * renderer) | |
635 { | |
636 GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; | |
637 | |
638 if (data->usageFlags & USAGE_GX_FUNCS) { | |
639 gx.GXCloseDisplay(); | |
640 } | |
641 | |
642 if (data) { | |
643 SDL_free(data); | |
644 } | |
645 SDL_free(renderer); | |
646 } | |
647 | |
648 #endif /* SDL_VIDEO_RENDER_GAPI */ | |
649 | |
650 /* vi: set ts=4 sw=4 expandtab: */ |