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: */