diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/gapi')
-rw-r--r-- | apps/plugins/sdl/src/video/gapi/SDL_gapivideo.c | 1287 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/gapi/SDL_gapivideo.h | 160 |
2 files changed, 0 insertions, 1447 deletions
diff --git a/apps/plugins/sdl/src/video/gapi/SDL_gapivideo.c b/apps/plugins/sdl/src/video/gapi/SDL_gapivideo.c deleted file mode 100644 index 86deadc75b..0000000000 --- a/apps/plugins/sdl/src/video/gapi/SDL_gapivideo.c +++ /dev/null | |||
@@ -1,1287 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | /* Pocket PC GAPI SDL video driver implementation; | ||
25 | Implemented by Dmitry Yakimov - support@activekitten.com | ||
26 | Inspired by http://arisme.free.fr/ports/SDL.php | ||
27 | */ | ||
28 | |||
29 | // TODO: copy surface on window when lost focus | ||
30 | // TODO: test buttons rotation | ||
31 | // TODO: test on be300 and HPC ( check WinDib fullscreen keys catching ) | ||
32 | // TODO: test on smartphones | ||
33 | // TODO: windib on SH3 PPC2000 landscape test | ||
34 | // TODO: optimize 8bpp landscape mode | ||
35 | |||
36 | // there is some problems in runnings apps from a device landscape mode | ||
37 | // due to WinCE bugs. Some works and some - does not. | ||
38 | // TODO: finish Axim Dell X30 and user landscape mode, device landscape mode | ||
39 | // TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion | ||
40 | // TODO: fix running GAPI apps from landscape mode - | ||
41 | // wince goes to portrait mode, but does not update video memory | ||
42 | |||
43 | |||
44 | #include "SDL.h" | ||
45 | #include "SDL_error.h" | ||
46 | #include "SDL_video.h" | ||
47 | #include "SDL_mouse.h" | ||
48 | #include "../SDL_sysvideo.h" | ||
49 | #include "../SDL_pixels_c.h" | ||
50 | #include "../../events/SDL_events_c.h" | ||
51 | #include "../wincommon/SDL_syswm_c.h" | ||
52 | #include "../wincommon/SDL_sysmouse_c.h" | ||
53 | #include "../windib/SDL_dibevents_c.h" | ||
54 | |||
55 | #include "../windib/SDL_gapidibvideo.h" | ||
56 | #include "SDL_gapivideo.h" | ||
57 | |||
58 | #define gapi this->hidden->gapiInfo | ||
59 | |||
60 | #define GAPIVID_DRIVER_NAME "gapi" | ||
61 | |||
62 | #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG) | ||
63 | #define REPORT_VIDEO_INFO 1 | ||
64 | #else | ||
65 | #define REPORT_VIDEO_INFO 0 | ||
66 | #endif | ||
67 | |||
68 | // for testing with GapiEmu | ||
69 | #define USE_GAPI_EMU 0 | ||
70 | #define EMULATE_AXIM_X30 0 | ||
71 | #define WITHOUT_GAPI 0 | ||
72 | |||
73 | #if USE_GAPI_EMU && !REPORT_VIDEO_INFO | ||
74 | #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") | ||
75 | #endif | ||
76 | |||
77 | #ifndef _T | ||
78 | #define _T(x) L##x | ||
79 | #endif | ||
80 | |||
81 | #ifndef ASSERT | ||
82 | #define ASSERT(x) | ||
83 | #endif | ||
84 | |||
85 | // defined and used in SDL_sysevents.c | ||
86 | extern HINSTANCE aygshell; | ||
87 | extern void SDL_UnregisterApp(); | ||
88 | extern int DIB_AddMode(_THIS, int bpp, int w, int h); | ||
89 | |||
90 | /* Initialization/Query functions */ | ||
91 | static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); | ||
92 | static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | ||
93 | static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | ||
94 | static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | ||
95 | static void GAPI_VideoQuit(_THIS); | ||
96 | |||
97 | /* Hardware surface functions */ | ||
98 | static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); | ||
99 | static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); | ||
100 | static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); | ||
101 | static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); | ||
102 | |||
103 | /* Windows message handling functions, will not be processed */ | ||
104 | static void GAPI_Activate(_THIS, BOOL active, BOOL minimized); | ||
105 | static void GAPI_RealizePalette(_THIS); | ||
106 | static void GAPI_PaletteChanged(_THIS, HWND window); | ||
107 | static void GAPI_WinPAINT(_THIS, HDC hdc); | ||
108 | |||
109 | /* etc. */ | ||
110 | static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); | ||
111 | |||
112 | static HMODULE g_hGapiLib = 0; | ||
113 | #define LINK(type,name,import) \ | ||
114 | if( g_hGapiLib ) \ | ||
115 | name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); | ||
116 | |||
117 | static char g_bRawBufferAvailable = 0; | ||
118 | |||
119 | /* GAPI driver bootstrap functions */ | ||
120 | |||
121 | /* hi res definitions */ | ||
122 | typedef struct _RawFrameBufferInfo | ||
123 | { | ||
124 | WORD wFormat; | ||
125 | WORD wBPP; | ||
126 | VOID *pFramePointer; | ||
127 | int cxStride; | ||
128 | int cyStride; | ||
129 | int cxPixels; | ||
130 | int cyPixels; | ||
131 | } RawFrameBufferInfo; | ||
132 | |||
133 | static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0}; | ||
134 | |||
135 | #define GETRAWFRAMEBUFFER 0x00020001 | ||
136 | |||
137 | #define FORMAT_565 1 | ||
138 | #define FORMAT_555 2 | ||
139 | #define FORMAT_OTHER 3 | ||
140 | |||
141 | /* Dell Axim x30 hangs when we use GAPI from landscape, | ||
142 | so lets avoid using GxOpenDisplay there via GETGXINFO trick | ||
143 | It seems that GAPI subsystem use the same ExtEscape code. | ||
144 | */ | ||
145 | #define GETGXINFO 0x00020000 | ||
146 | |||
147 | typedef struct GXDeviceInfo | ||
148 | { | ||
149 | long Version; //00 (should filled with 100 before calling ExtEscape) | ||
150 | void * pvFrameBuffer; //04 | ||
151 | unsigned long cbStride; //08 | ||
152 | unsigned long cxWidth; //0c | ||
153 | unsigned long cyHeight; //10 | ||
154 | unsigned long cBPP; //14 | ||
155 | unsigned long ffFormat; //18 | ||
156 | char Unused[0x84-7*4]; | ||
157 | } GXDeviceInfo; | ||
158 | |||
159 | static int GAPI_Available(void) | ||
160 | { | ||
161 | // try to use VGA display, even on emulator | ||
162 | HDC hdc = GetDC(NULL); | ||
163 | int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo); | ||
164 | ReleaseDC(NULL, hdc); | ||
165 | g_bRawBufferAvailable = result > 0; | ||
166 | |||
167 | //My Asus MyPAL 696 reports the RAWFRAMEBUFFER as available, but with a size of 0 x 0 | ||
168 | if(g_RawFrameBufferInfo.cxPixels <= 0 || g_RawFrameBufferInfo.cyPixels <= 0){ | ||
169 | g_bRawBufferAvailable = 0; | ||
170 | } | ||
171 | |||
172 | #if WITHOUT_GAPI | ||
173 | return g_bRawBufferAvailable; | ||
174 | #endif | ||
175 | |||
176 | #if USE_GAPI_EMU | ||
177 | g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll")); | ||
178 | if( !g_hGapiLib ) | ||
179 | { | ||
180 | SDL_SetError("Gapi Emu not found!"); | ||
181 | } | ||
182 | return g_hGapiLib != 0; | ||
183 | #endif | ||
184 | |||
185 | // try to find gx.dll | ||
186 | g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll")); | ||
187 | if( !g_hGapiLib ) | ||
188 | { | ||
189 | g_hGapiLib = LoadLibrary(_T("gx.dll")); | ||
190 | if( !g_hGapiLib ) return g_bRawBufferAvailable; | ||
191 | } | ||
192 | |||
193 | return(1); | ||
194 | } | ||
195 | |||
196 | static int cmpmodes(const void *va, const void *vb) | ||
197 | { | ||
198 | SDL_Rect *a = *(SDL_Rect **)va; | ||
199 | SDL_Rect *b = *(SDL_Rect **)vb; | ||
200 | if ( a->w == b->w ) | ||
201 | return b->h - a->h; | ||
202 | else | ||
203 | return b->w - a->w; | ||
204 | } | ||
205 | |||
206 | static int GAPI_AddMode(_THIS, int bpp, int w, int h) | ||
207 | { | ||
208 | SDL_Rect *mode; | ||
209 | int i, index; | ||
210 | int next_mode; | ||
211 | |||
212 | /* Check to see if we already have this mode */ | ||
213 | if ( bpp < 8 ) { /* Not supported */ | ||
214 | return(0); | ||
215 | } | ||
216 | index = ((bpp+7)/8)-1; | ||
217 | for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) { | ||
218 | mode = gapi->SDL_modelist[index][i]; | ||
219 | if ( (mode->w == w) && (mode->h == h) ) { | ||
220 | return(0); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | /* Set up the new video mode rectangle */ | ||
225 | mode = (SDL_Rect *)SDL_malloc(sizeof *mode); | ||
226 | if ( mode == NULL ) { | ||
227 | SDL_OutOfMemory(); | ||
228 | return(-1); | ||
229 | } | ||
230 | mode->x = 0; | ||
231 | mode->y = 0; | ||
232 | mode->w = w; | ||
233 | mode->h = h; | ||
234 | |||
235 | /* Allocate the new list of modes, and fill in the new mode */ | ||
236 | next_mode = gapi->SDL_nummodes[index]; | ||
237 | gapi->SDL_modelist[index] = (SDL_Rect **) | ||
238 | SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); | ||
239 | if ( gapi->SDL_modelist[index] == NULL ) { | ||
240 | SDL_OutOfMemory(); | ||
241 | gapi->SDL_nummodes[index] = 0; | ||
242 | SDL_free(mode); | ||
243 | return(-1); | ||
244 | } | ||
245 | gapi->SDL_modelist[index][next_mode] = mode; | ||
246 | gapi->SDL_modelist[index][next_mode+1] = NULL; | ||
247 | gapi->SDL_nummodes[index]++; | ||
248 | |||
249 | return(0); | ||
250 | } | ||
251 | |||
252 | static void GAPI_DeleteDevice(SDL_VideoDevice *device) | ||
253 | { | ||
254 | if( g_hGapiLib ) | ||
255 | { | ||
256 | FreeLibrary(g_hGapiLib); | ||
257 | g_hGapiLib = 0; | ||
258 | } | ||
259 | SDL_free(device->hidden->gapiInfo); | ||
260 | SDL_free(device->hidden); | ||
261 | SDL_free(device); | ||
262 | } | ||
263 | |||
264 | static SDL_VideoDevice *GAPI_CreateDevice(int devindex) | ||
265 | { | ||
266 | SDL_VideoDevice *device; | ||
267 | |||
268 | if( !g_hGapiLib && !g_bRawBufferAvailable) | ||
269 | { | ||
270 | if( !GAPI_Available() ) | ||
271 | { | ||
272 | SDL_SetError("GAPI dll is not found and VGA mode is not available!"); | ||
273 | return 0; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | /* Initialize all variables that we clean on shutdown */ | ||
278 | device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); | ||
279 | if ( device ) { | ||
280 | SDL_memset(device, 0, (sizeof *device)); | ||
281 | device->hidden = (struct SDL_PrivateVideoData *) | ||
282 | SDL_malloc((sizeof *device->hidden)); | ||
283 | if(device->hidden){ | ||
284 | SDL_memset(device->hidden, 0, (sizeof *device->hidden)); | ||
285 | device->hidden->gapiInfo = (GapiInfo *)SDL_malloc((sizeof(GapiInfo))); | ||
286 | if(device->hidden->gapiInfo == NULL) | ||
287 | { | ||
288 | SDL_free(device->hidden); | ||
289 | device->hidden = NULL; | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | if ( (device == NULL) || (device->hidden == NULL) ) { | ||
294 | SDL_OutOfMemory(); | ||
295 | if ( device ) { | ||
296 | SDL_free(device); | ||
297 | } | ||
298 | return(0); | ||
299 | } | ||
300 | SDL_memset(device->hidden->gapiInfo, 0, (sizeof *device->hidden->gapiInfo)); | ||
301 | |||
302 | /* Set the function pointers */ | ||
303 | device->VideoInit = GAPI_VideoInit; | ||
304 | device->ListModes = GAPI_ListModes; | ||
305 | device->SetVideoMode = GAPI_SetVideoMode; | ||
306 | device->UpdateMouse = WIN_UpdateMouse; | ||
307 | device->CreateYUVOverlay = NULL; | ||
308 | device->SetColors = GAPI_SetColors; | ||
309 | device->UpdateRects = GAPI_UpdateRects; | ||
310 | device->VideoQuit = GAPI_VideoQuit; | ||
311 | device->AllocHWSurface = GAPI_AllocHWSurface; | ||
312 | device->CheckHWBlit = NULL; | ||
313 | device->FillHWRect = NULL; | ||
314 | device->SetHWColorKey = NULL; | ||
315 | device->SetHWAlpha = NULL; | ||
316 | device->LockHWSurface = GAPI_LockHWSurface; | ||
317 | device->UnlockHWSurface = GAPI_UnlockHWSurface; | ||
318 | device->FlipHWSurface = NULL; | ||
319 | device->FreeHWSurface = GAPI_FreeHWSurface; | ||
320 | device->SetCaption = WIN_SetWMCaption; | ||
321 | device->SetIcon = WIN_SetWMIcon; | ||
322 | device->IconifyWindow = WIN_IconifyWindow; | ||
323 | device->GrabInput = WIN_GrabInput; | ||
324 | device->GetWMInfo = WIN_GetWMInfo; | ||
325 | device->FreeWMCursor = WIN_FreeWMCursor; | ||
326 | device->CreateWMCursor = WIN_CreateWMCursor; | ||
327 | device->ShowWMCursor = WIN_ShowWMCursor; | ||
328 | device->WarpWMCursor = WIN_WarpWMCursor; | ||
329 | device->CheckMouseMode = WIN_CheckMouseMode; | ||
330 | device->InitOSKeymap = DIB_InitOSKeymap; | ||
331 | device->PumpEvents = DIB_PumpEvents; | ||
332 | |||
333 | /* Set up the windows message handling functions */ | ||
334 | WIN_Activate = GAPI_Activate; | ||
335 | WIN_RealizePalette = GAPI_RealizePalette; | ||
336 | WIN_PaletteChanged = GAPI_PaletteChanged; | ||
337 | WIN_WinPAINT = GAPI_WinPAINT; | ||
338 | HandleMessage = DIB_HandleMessage; | ||
339 | |||
340 | device->free = GAPI_DeleteDevice; | ||
341 | |||
342 | /* Load gapi library */ | ||
343 | #define gx device->hidden->gapiInfo->gxFunc | ||
344 | |||
345 | LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" ) | ||
346 | LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" ) | ||
347 | LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" ) | ||
348 | LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" ) | ||
349 | LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" ) | ||
350 | LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" ) | ||
351 | LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" ) | ||
352 | LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" ) | ||
353 | LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" ) | ||
354 | LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" ) | ||
355 | LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" ) | ||
356 | LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" ) | ||
357 | |||
358 | /* wrong gapi.dll */ | ||
359 | if( !gx.GXOpenDisplay ) | ||
360 | { | ||
361 | if( g_hGapiLib ) | ||
362 | { | ||
363 | FreeLibrary(g_hGapiLib); | ||
364 | g_hGapiLib = 0; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | if( !gx.GXOpenDisplay && !g_bRawBufferAvailable) | ||
369 | { | ||
370 | SDL_SetError("Error: damaged or unknown gapi.dll!\n"); | ||
371 | GAPI_DeleteDevice(device); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | return device; | ||
376 | } | ||
377 | |||
378 | VideoBootStrap GAPI_bootstrap = { | ||
379 | GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", | ||
380 | GAPI_Available, GAPI_CreateDevice | ||
381 | }; | ||
382 | |||
383 | static void FillStructs(_THIS, BOOL useVga) | ||
384 | { | ||
385 | #ifdef _ARM_ | ||
386 | WCHAR oemstr[100]; | ||
387 | #endif | ||
388 | /* fill a device properties */ | ||
389 | |||
390 | if( !useVga ) | ||
391 | { | ||
392 | gapi->gxProperties = gapi->gxFunc.GXGetDisplayProperties(); | ||
393 | gapi->needUpdate = 1; | ||
394 | gapi->hiresFix = 0; | ||
395 | gapi->useVga = 0; | ||
396 | gapi->useGXOpenDisplay = 1; | ||
397 | |||
398 | #ifdef _ARM_ | ||
399 | /* check some devices and extract addition info */ | ||
400 | SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 ); | ||
401 | |||
402 | // buggy iPaq38xx | ||
403 | if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (gapi->gxProperties.cbxPitch > 0)) | ||
404 | { | ||
405 | gapi->videoMem = (PIXEL*)0xac0755a0; | ||
406 | gapi->gxProperties.cbxPitch = -640; | ||
407 | gapi->gxProperties.cbyPitch = 2; | ||
408 | gapi->needUpdate = 0; | ||
409 | } | ||
410 | #if (EMULATE_AXIM_X30 == 0) | ||
411 | // buggy Dell Axim X30 | ||
412 | if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 ) | ||
413 | #endif | ||
414 | { | ||
415 | GXDeviceInfo gxInfo = {0}; | ||
416 | HDC hdc = GetDC(NULL); | ||
417 | int result; | ||
418 | |||
419 | gxInfo.Version = 100; | ||
420 | result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo); | ||
421 | if( result > 0 ) | ||
422 | { | ||
423 | gapi->useGXOpenDisplay = 0; | ||
424 | gapi->videoMem = gxInfo.pvFrameBuffer; | ||
425 | gapi->needUpdate = 0; | ||
426 | gapi->gxProperties.cbxPitch = 2; | ||
427 | gapi->gxProperties.cbyPitch = 480; | ||
428 | gapi->gxProperties.cxWidth = gxInfo.cxWidth; | ||
429 | gapi->gxProperties.cyHeight = gxInfo.cyHeight; | ||
430 | gapi->gxProperties.ffFormat = gxInfo.ffFormat; | ||
431 | } | ||
432 | } | ||
433 | #endif | ||
434 | } else | ||
435 | { | ||
436 | gapi->needUpdate = 0; | ||
437 | gapi->hiresFix = 0; | ||
438 | gapi->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP; | ||
439 | gapi->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride; | ||
440 | gapi->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride; | ||
441 | gapi->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels; | ||
442 | gapi->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels; | ||
443 | gapi->videoMem = g_RawFrameBufferInfo.pFramePointer; | ||
444 | gapi->useVga = 1; | ||
445 | |||
446 | switch( g_RawFrameBufferInfo.wFormat ) | ||
447 | { | ||
448 | case FORMAT_565: | ||
449 | gapi->gxProperties.ffFormat = kfDirect565; | ||
450 | break; | ||
451 | case FORMAT_555: | ||
452 | gapi->gxProperties.ffFormat = kfDirect555; | ||
453 | break; | ||
454 | default: | ||
455 | /* unknown pixel format, try define by BPP! */ | ||
456 | switch( g_RawFrameBufferInfo.wBPP ) | ||
457 | { | ||
458 | case 4: | ||
459 | case 8: | ||
460 | gapi->gxProperties.ffFormat = kfDirect; | ||
461 | case 16: | ||
462 | gapi->gxProperties.ffFormat = kfDirect565; | ||
463 | default: | ||
464 | gapi->gxProperties.ffFormat = kfDirect; | ||
465 | break; | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | |||
470 | if( gapi->gxProperties.cBPP != 16 ) | ||
471 | { | ||
472 | gapi->gapiOrientation = SDL_ORIENTATION_UP; | ||
473 | } else | ||
474 | if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch > 0 )) | ||
475 | { | ||
476 | gapi->gapiOrientation = SDL_ORIENTATION_UP; | ||
477 | } else | ||
478 | if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch < 0 )) | ||
479 | { | ||
480 | gapi->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660 | ||
481 | } else | ||
482 | if( (gapi->gxProperties.cbxPitch < 0) && (gapi->gxProperties.cbyPitch > 0 )) | ||
483 | { | ||
484 | gapi->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800 | ||
485 | } | ||
486 | } | ||
487 | |||
488 | static void GAPI_CreatePalette(int ncolors, SDL_Color *colors) | ||
489 | { | ||
490 | // Setup a custom color palette | ||
491 | BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ]; | ||
492 | int i; | ||
493 | LOGPALETTE* pLogical = (LOGPALETTE*)buffer; | ||
494 | PALETTEENTRY* entries = pLogical->palPalEntry; | ||
495 | HPALETTE hPalette; | ||
496 | HDC hdc; | ||
497 | |||
498 | for (i = 0; i < ncolors; ++i) | ||
499 | { | ||
500 | // Find intensity by replicating the bit patterns over a byte | ||
501 | entries[i].peRed = colors[i].r; | ||
502 | entries[i].peGreen = colors[i].g; | ||
503 | entries[i].peBlue = colors[i].b; | ||
504 | entries[i].peFlags = 0; | ||
505 | } | ||
506 | |||
507 | // Create the GDI palette object | ||
508 | pLogical->palVersion = 0x0300; | ||
509 | pLogical->palNumEntries = ncolors; | ||
510 | |||
511 | hPalette = CreatePalette( pLogical ); | ||
512 | ASSERT(hPalette); | ||
513 | |||
514 | |||
515 | // Realize the palette | ||
516 | hdc = GetDC(0); | ||
517 | |||
518 | SelectPalette( hdc, hPalette, FALSE ); | ||
519 | RealizePalette( hdc ); | ||
520 | |||
521 | ReleaseDC( 0, hdc ); | ||
522 | DeleteObject( hPalette ); | ||
523 | } | ||
524 | |||
525 | int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat) | ||
526 | { | ||
527 | int i,bpp; | ||
528 | |||
529 | /* Create the window */ | ||
530 | if ( DIB_CreateWindow(this) < 0 ) { | ||
531 | return(-1); | ||
532 | } | ||
533 | |||
534 | if( g_hGapiLib ) | ||
535 | { | ||
536 | FillStructs(this, 0); | ||
537 | |||
538 | // SDL does not supports 2/4bpp mode, so use 16 bpp | ||
539 | bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; | ||
540 | |||
541 | /* set up normal and landscape mode */ | ||
542 | GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); | ||
543 | GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); | ||
544 | } | ||
545 | |||
546 | /* add hi-res mode */ | ||
547 | if( g_bRawBufferAvailable && | ||
548 | !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels))) | ||
549 | { | ||
550 | FillStructs(this, 1); | ||
551 | |||
552 | // SDL does not supports 2/4bpp mode, so use 16 bpp | ||
553 | bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; | ||
554 | |||
555 | /* set up normal and landscape mode */ | ||
556 | GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); | ||
557 | GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); | ||
558 | } | ||
559 | |||
560 | /* Determine the current screen size. | ||
561 | * This is NOT necessarily the size of the Framebuffer or GAPI, as they return | ||
562 | * the displaysize in ORIENTATION_UP */ | ||
563 | this->info.current_w = GetSystemMetrics(SM_CXSCREEN); | ||
564 | this->info.current_h = GetSystemMetrics(SM_CYSCREEN); | ||
565 | |||
566 | /* Sort the mode lists */ | ||
567 | for ( i=0; i<NUM_MODELISTS; ++i ) { | ||
568 | if ( gapi->SDL_nummodes[i] > 0 ) { | ||
569 | SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | vformat->BitsPerPixel = gapi->gxProperties.cBPP < 8 ? 16 : (unsigned char)gapi->gxProperties.cBPP; | ||
574 | |||
575 | // Get color mask | ||
576 | if (gapi->gxProperties.ffFormat & kfDirect565) { | ||
577 | vformat->BitsPerPixel = 16; | ||
578 | vformat->Rmask = 0x0000f800; | ||
579 | vformat->Gmask = 0x000007e0; | ||
580 | vformat->Bmask = 0x0000001f; | ||
581 | gapi->videoMode = GAPI_DIRECT_565; | ||
582 | } | ||
583 | else | ||
584 | if (gapi->gxProperties.ffFormat & kfDirect555) { | ||
585 | vformat->BitsPerPixel = 16; | ||
586 | vformat->Rmask = 0x00007c00; | ||
587 | vformat->Gmask = 0x000003e0; | ||
588 | vformat->Bmask = 0x0000001f; | ||
589 | gapi->videoMode = GAPI_DIRECT_555; | ||
590 | } | ||
591 | else | ||
592 | if ((gapi->gxProperties.ffFormat & kfDirect) && (gapi->gxProperties.cBPP < 8)) { | ||
593 | // We'll perform the conversion | ||
594 | vformat->BitsPerPixel = 16; | ||
595 | vformat->Rmask = 0x0000f800; // 16 bit 565 | ||
596 | vformat->Gmask = 0x000007e0; | ||
597 | vformat->Bmask = 0x0000001f; | ||
598 | if (gapi->gxProperties.ffFormat & kfDirectInverted) | ||
599 | gapi->invert = (1 << gapi->gxProperties.cBPP) - 1; | ||
600 | gapi->colorscale = gapi->gxProperties.cBPP < 8 ? 8 - gapi->gxProperties.cBPP : 0; | ||
601 | gapi->videoMode = GAPI_MONO; | ||
602 | } | ||
603 | else | ||
604 | if (gapi->gxProperties.ffFormat & kfPalette) { | ||
605 | gapi->videoMode = GAPI_PALETTE; | ||
606 | } | ||
607 | |||
608 | /* We're done! */ | ||
609 | return(0); | ||
610 | } | ||
611 | |||
612 | SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | ||
613 | { | ||
614 | return(gapi->SDL_modelist[((format->BitsPerPixel+7)/8)-1]); | ||
615 | // return (SDL_Rect **) -1; | ||
616 | } | ||
617 | |||
618 | SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, | ||
619 | int width, int height, int bpp, Uint32 flags) | ||
620 | { | ||
621 | SDL_Surface *video; | ||
622 | Uint32 Rmask, Gmask, Bmask; | ||
623 | DWORD style; | ||
624 | SDL_Rect allScreen; | ||
625 | |||
626 | if( bpp < 4 ) | ||
627 | { | ||
628 | SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!"); | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | /* Recalculate bitmasks if necessary */ | ||
633 | if (bpp == current->format->BitsPerPixel) { | ||
634 | video = current; | ||
635 | } | ||
636 | else { | ||
637 | switch(bpp) { | ||
638 | case 8: | ||
639 | Rmask = 0; | ||
640 | Gmask = 0; | ||
641 | Bmask = 0; | ||
642 | break; | ||
643 | case 15: | ||
644 | case 16: | ||
645 | /* Default is 565 unless the display is specifically 555 */ | ||
646 | if (gapi->gxProperties.ffFormat & kfDirect555) { | ||
647 | Rmask = 0x00007c00; | ||
648 | Gmask = 0x000003e0; | ||
649 | Bmask = 0x0000001f; | ||
650 | } | ||
651 | else { | ||
652 | Rmask = 0x0000f800; | ||
653 | Gmask = 0x000007e0; | ||
654 | Bmask = 0x0000001f; | ||
655 | } | ||
656 | break; | ||
657 | case 24: | ||
658 | case 32: | ||
659 | Rmask = 0x00ff0000; | ||
660 | Gmask = 0x0000ff00; | ||
661 | Bmask = 0x000000ff; | ||
662 | break; | ||
663 | default: | ||
664 | SDL_SetError("Unsupported Bits Per Pixel format requested"); | ||
665 | return NULL; | ||
666 | } | ||
667 | video = SDL_CreateRGBSurface(SDL_SWSURFACE, | ||
668 | 0, 0, bpp, Rmask, Gmask, Bmask, 0); | ||
669 | if ( video == NULL ) { | ||
670 | SDL_OutOfMemory(); | ||
671 | return(NULL); | ||
672 | } | ||
673 | } | ||
674 | |||
675 | gapi->userOrientation = SDL_ORIENTATION_UP; | ||
676 | gapi->systemOrientation = SDL_ORIENTATION_UP; | ||
677 | video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */ | ||
678 | |||
679 | /* GAPI or VGA? */ | ||
680 | if( g_hGapiLib ) | ||
681 | { | ||
682 | FillStructs(this, 0); | ||
683 | if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight)) | ||
684 | && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth))) | ||
685 | FillStructs(this, 1); // gapi is found but we use VGA resolution | ||
686 | } else | ||
687 | FillStructs(this, 1); | ||
688 | |||
689 | if ( !gapi->needUpdate && !gapi->videoMem) { | ||
690 | SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug"); | ||
691 | return(NULL); | ||
692 | } | ||
693 | |||
694 | /* detect user landscape mode */ | ||
695 | if( (width > height) && (gapi->gxProperties.cxWidth < gapi->gxProperties.cyHeight)) | ||
696 | gapi->userOrientation = SDL_ORIENTATION_RIGHT; | ||
697 | |||
698 | if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN)) | ||
699 | gapi->systemOrientation = SDL_ORIENTATION_RIGHT; | ||
700 | |||
701 | gapi->hiresFix = 0; | ||
702 | |||
703 | /* check hires */ | ||
704 | if(GetSystemMetrics(SM_CXSCREEN) < width && GetSystemMetrics(SM_CYSCREEN) < height) | ||
705 | { | ||
706 | gapi->hiresFix = 1; | ||
707 | } | ||
708 | |||
709 | switch( gapi->userOrientation ) | ||
710 | { | ||
711 | case SDL_ORIENTATION_UP: | ||
712 | gapi->startOffset = 0; | ||
713 | gapi->dstLineStep = gapi->gxProperties.cbyPitch; | ||
714 | gapi->dstPixelStep = gapi->gxProperties.cbxPitch; | ||
715 | break; | ||
716 | case SDL_ORIENTATION_RIGHT: | ||
717 | switch( gapi->gapiOrientation ) | ||
718 | { | ||
719 | case SDL_ORIENTATION_UP: | ||
720 | case SDL_ORIENTATION_RIGHT: | ||
721 | case SDL_ORIENTATION_LEFT: | ||
722 | if( (gapi->videoMode == GAPI_MONO) ) | ||
723 | gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode | ||
724 | else | ||
725 | gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1); | ||
726 | |||
727 | gapi->dstLineStep = gapi->gxProperties.cbxPitch; | ||
728 | gapi->dstPixelStep = -gapi->gxProperties.cbyPitch; | ||
729 | break; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | video->w = gapi->w = width; | ||
734 | video->h = gapi->h = height; | ||
735 | video->pitch = SDL_CalculatePitch(video); | ||
736 | |||
737 | /* Small fix for WinCE/Win32 - when activating window | ||
738 | SDL_VideoSurface is equal to zero, so activating code | ||
739 | is not called properly for fullscreen windows because | ||
740 | macros WINDIB_FULLSCREEN uses SDL_VideoSurface | ||
741 | */ | ||
742 | SDL_VideoSurface = video; | ||
743 | |||
744 | /* GAPI is always fullscreen, title bar is useless */ | ||
745 | style = 0; | ||
746 | |||
747 | if (!SDL_windowid) | ||
748 | SetWindowLong(SDL_Window, GWL_STYLE, style); | ||
749 | |||
750 | /* Allocate bitmap */ | ||
751 | if( gapi->buffer ) | ||
752 | { | ||
753 | SDL_free( gapi->buffer ); | ||
754 | gapi->buffer = NULL; | ||
755 | } | ||
756 | gapi->buffer = SDL_malloc(video->h * video->pitch); | ||
757 | video->pixels = gapi->buffer; | ||
758 | |||
759 | if ( ! gapi->buffer ) { | ||
760 | SDL_SetError("Couldn't allocate buffer for requested mode"); | ||
761 | return(NULL); | ||
762 | } | ||
763 | |||
764 | SDL_memset(gapi->buffer, 255, video->h * video->pitch); | ||
765 | MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE); | ||
766 | ShowWindow(SDL_Window, SW_SHOW); | ||
767 | SetForegroundWindow(SDL_Window); | ||
768 | |||
769 | /* JC 14 Mar 2006 | ||
770 | Flush the message loop or this can cause big problems later | ||
771 | Especially if the user decides to use dialog boxes or assert()! | ||
772 | */ | ||
773 | WIN_FlushMessageQueue(); | ||
774 | |||
775 | /* Open GAPI display */ | ||
776 | if( !gapi->useVga && gapi->useGXOpenDisplay && !gapi->alreadyGXOpened ) | ||
777 | { | ||
778 | #if REPORT_VIDEO_INFO | ||
779 | printf("system display width (orig): %d\n", GetSystemMetrics(SM_CXSCREEN)); | ||
780 | printf("system display height (orig): %d\n", GetSystemMetrics(SM_CYSCREEN)); | ||
781 | #endif | ||
782 | gapi->alreadyGXOpened = 1; | ||
783 | if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) ) | ||
784 | { | ||
785 | SDL_SetError("Couldn't initialize GAPI"); | ||
786 | return(NULL); | ||
787 | } | ||
788 | } | ||
789 | |||
790 | if(gapi->useVga) | ||
791 | gapi->coordinateTransform = (4 - gapi->systemOrientation + gapi->userOrientation) % 4; | ||
792 | else | ||
793 | gapi->coordinateTransform = gapi->userOrientation; | ||
794 | |||
795 | #if REPORT_VIDEO_INFO | ||
796 | printf("Video properties:\n"); | ||
797 | printf("display bpp: %d\n", gapi->gxProperties.cBPP); | ||
798 | printf("display width: %d\n", gapi->gxProperties.cxWidth); | ||
799 | printf("display height: %d\n", gapi->gxProperties.cyHeight); | ||
800 | printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN)); | ||
801 | printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN)); | ||
802 | printf("x pitch: %d\n", gapi->gxProperties.cbxPitch); | ||
803 | printf("y pitch: %d\n", gapi->gxProperties.cbyPitch); | ||
804 | printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat); | ||
805 | printf("user orientation: %d\n", gapi->userOrientation); | ||
806 | printf("system orientation: %d\n", gapi->systemOrientation); | ||
807 | printf("gapi orientation: %d\n", gapi->gapiOrientation); | ||
808 | |||
809 | |||
810 | if( !gapi->useVga && gapi->useGXOpenDisplay && gapi->needUpdate) | ||
811 | { | ||
812 | gapi->videoMem = gapi->gxFunc.GXBeginDraw(); | ||
813 | gapi->gxFunc.GXEndDraw(); | ||
814 | } | ||
815 | |||
816 | printf("video memory: 0x%x\n", gapi->videoMem); | ||
817 | printf("need update: %d\n", gapi->needUpdate); | ||
818 | printf("hi-res fix: %d\n", gapi->hiresFix); | ||
819 | printf("VGA is available on the device: %d\n", g_bRawBufferAvailable); | ||
820 | printf("use raw framebuffer: %d\n", gapi->useVga); | ||
821 | printf("video surface bpp: %d\n", video->format->BitsPerPixel); | ||
822 | printf("video surface width: %d\n", video->w); | ||
823 | printf("video surface height: %d\n", video->h); | ||
824 | printf("mouse/arrows transformation angle: %d\n", gapi->coordinateTransform); | ||
825 | #endif | ||
826 | |||
827 | |||
828 | /* Blank screen */ | ||
829 | allScreen.x = allScreen.y = 0; | ||
830 | allScreen.w = video->w - 1; | ||
831 | allScreen.h = video->h - 1; | ||
832 | GAPI_UpdateRects(this, 1, &allScreen); | ||
833 | |||
834 | /* We're done */ | ||
835 | return(video); | ||
836 | } | ||
837 | |||
838 | /* We don't actually allow hardware surfaces other than the main one */ | ||
839 | static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) | ||
840 | { | ||
841 | return(-1); | ||
842 | } | ||
843 | static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) | ||
844 | { | ||
845 | return; | ||
846 | } | ||
847 | |||
848 | /* We need to wait for vertical retrace on page flipped displays */ | ||
849 | static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) | ||
850 | { | ||
851 | return(0); | ||
852 | } | ||
853 | |||
854 | static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) | ||
855 | { | ||
856 | return; | ||
857 | } | ||
858 | |||
859 | static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines) | ||
860 | { | ||
861 | if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */ | ||
862 | { | ||
863 | SDL_memcpy(destPointer, srcPointer, width); | ||
864 | return 1; | ||
865 | } else | ||
866 | { | ||
867 | // TODO: read 4 pixels, write DWORD | ||
868 | int step = gapi->dstPixelStep; | ||
869 | while(width--) | ||
870 | { | ||
871 | *destPointer = *srcPointer++; | ||
872 | destPointer += step; | ||
873 | } | ||
874 | } | ||
875 | return 1; | ||
876 | } | ||
877 | |||
878 | /* Video memory is very slow so lets optimize as much as possible */ | ||
879 | static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines) | ||
880 | { | ||
881 | PIXEL *line1, *line2; | ||
882 | int step = gapi->dstPixelStep / 2; | ||
883 | |||
884 | if( step == 1 ) /* optimized blitting on most devices */ | ||
885 | { | ||
886 | SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL)); | ||
887 | return 1; | ||
888 | } | ||
889 | else | ||
890 | { | ||
891 | if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) && | ||
892 | (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up | ||
893 | { | ||
894 | // to prevent data misalignment copy only one line | ||
895 | if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) | ||
896 | || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT)) | ||
897 | || (lines == 1) ) | ||
898 | { | ||
899 | while(width--) | ||
900 | { | ||
901 | *destPointer = *srcPointer++; | ||
902 | destPointer += step; | ||
903 | } | ||
904 | return 1; | ||
905 | } | ||
906 | |||
907 | /* read two lines at the same time, write DWORD */ | ||
908 | line1 = srcPointer; | ||
909 | line2 = srcPointer + SDL_VideoSurface->pitch / 2; | ||
910 | |||
911 | if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) | ||
912 | while(width--) // iPaq 3800 | ||
913 | { | ||
914 | *(DWORD*)destPointer =(*line2++ << 16) | *line1++; | ||
915 | destPointer += step; | ||
916 | } | ||
917 | else | ||
918 | { | ||
919 | destPointer += gapi->gxProperties.cbyPitch / 2; | ||
920 | |||
921 | while(width--) // iPaq 3660 | ||
922 | { | ||
923 | *(DWORD*)destPointer =(*line1++ << 16) | *line2++; | ||
924 | destPointer += step; | ||
925 | } | ||
926 | } | ||
927 | return 2; | ||
928 | } else | ||
929 | { | ||
930 | // iPaq 3800 and user orientation landscape | ||
931 | if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) | ||
932 | { | ||
933 | int w1; | ||
934 | |||
935 | // to prevent data misalignment copy only one pixel | ||
936 | if( (((unsigned)destPointer & 3) == 0) && (width > 0)) | ||
937 | { | ||
938 | *destPointer-- = *srcPointer++; | ||
939 | width--; | ||
940 | } | ||
941 | |||
942 | destPointer--; | ||
943 | |||
944 | w1 = width / 2; | ||
945 | |||
946 | while(w1--) | ||
947 | { | ||
948 | DWORD p = *(DWORD*)srcPointer; | ||
949 | *((DWORD*)destPointer) = (p << 16) | (p >> 16); | ||
950 | destPointer -= 2; | ||
951 | srcPointer += 2; | ||
952 | } | ||
953 | |||
954 | if( width & 1 ) // copy the last pixel | ||
955 | { | ||
956 | destPointer++; | ||
957 | *destPointer = *srcPointer; | ||
958 | } | ||
959 | |||
960 | return 1; | ||
961 | } | ||
962 | |||
963 | // modern iPaqs and user orientation landscape | ||
964 | // read two pixels, write DWORD | ||
965 | |||
966 | line1 = srcPointer; | ||
967 | line2 = srcPointer + SDL_VideoSurface->pitch / 2; | ||
968 | |||
969 | if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) | ||
970 | { | ||
971 | while(width--) | ||
972 | { | ||
973 | *destPointer = *srcPointer++; | ||
974 | destPointer += step; | ||
975 | } | ||
976 | return 1; | ||
977 | } | ||
978 | |||
979 | while(width--) | ||
980 | { | ||
981 | *(DWORD*)destPointer =(*line2++ << 16) | *line1++; | ||
982 | destPointer -= gapi->gxProperties.cbyPitch / 2; | ||
983 | } | ||
984 | return 2; | ||
985 | } | ||
986 | } | ||
987 | } | ||
988 | |||
989 | // Color component masks for 565 | ||
990 | #define REDMASK (31<<11) | ||
991 | #define GREENMASK (63<<5) | ||
992 | #define BLUEMASK (31) | ||
993 | |||
994 | |||
995 | static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble) | ||
996 | { | ||
997 | PIXEL *line1, *line2; | ||
998 | int step = gapi->dstPixelStep; | ||
999 | |||
1000 | if( gapi->userOrientation == SDL_ORIENTATION_UP ) | ||
1001 | { | ||
1002 | if( yNibble ) // copy bottom half of a line | ||
1003 | { | ||
1004 | while(width--) | ||
1005 | { | ||
1006 | PIXEL c1 = *srcPointer++; | ||
1007 | c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | ||
1008 | *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); | ||
1009 | destPointer += step; | ||
1010 | } | ||
1011 | return 1; | ||
1012 | } | ||
1013 | |||
1014 | // either 1 pixel picture or tail, anyway this is the last line | ||
1015 | if( lines == 1 ) | ||
1016 | { | ||
1017 | while(width--) | ||
1018 | { | ||
1019 | PIXEL c1 = *srcPointer++; | ||
1020 | c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | ||
1021 | *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); | ||
1022 | destPointer += step; | ||
1023 | } | ||
1024 | return 1; | ||
1025 | } | ||
1026 | |||
1027 | line1 = srcPointer; | ||
1028 | line2 = srcPointer + SDL_VideoSurface->pitch / 2; | ||
1029 | |||
1030 | while(width--) | ||
1031 | { | ||
1032 | PIXEL c1 = *line1++; | ||
1033 | PIXEL c2 = *line2++; | ||
1034 | c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | ||
1035 | c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); | ||
1036 | *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4)); | ||
1037 | destPointer += step; | ||
1038 | } | ||
1039 | return 2; | ||
1040 | } else | ||
1041 | { | ||
1042 | int w1; | ||
1043 | w1 = width / 2; | ||
1044 | |||
1045 | if( xNibble ) | ||
1046 | { | ||
1047 | // copy one pixel | ||
1048 | PIXEL c1 = *srcPointer++; | ||
1049 | c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | ||
1050 | *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); | ||
1051 | destPointer++; | ||
1052 | } | ||
1053 | |||
1054 | while(w1--) | ||
1055 | { | ||
1056 | PIXEL c1 = *srcPointer; | ||
1057 | PIXEL c2 = *(srcPointer + 1); | ||
1058 | c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | ||
1059 | c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); | ||
1060 | *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4)); | ||
1061 | srcPointer += 2; | ||
1062 | } | ||
1063 | |||
1064 | // copy tail | ||
1065 | if( (width & 1) && !xNibble ) | ||
1066 | { | ||
1067 | PIXEL c1 = *srcPointer; | ||
1068 | c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | ||
1069 | *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); | ||
1070 | } | ||
1071 | |||
1072 | return 1; | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects) | ||
1077 | { | ||
1078 | int i, height; | ||
1079 | int linesProcessed; | ||
1080 | int xNibble, yNibble; | ||
1081 | |||
1082 | for (i=0; i<numrects; i++) | ||
1083 | { | ||
1084 | unsigned char *destPointer; | ||
1085 | unsigned char *srcPointer; | ||
1086 | |||
1087 | if( gapi->userOrientation == SDL_ORIENTATION_UP ) | ||
1088 | destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep; | ||
1089 | else | ||
1090 | destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep; | ||
1091 | |||
1092 | srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2; | ||
1093 | yNibble = rects[i].y & 1; // TODO: only for 4 bpp | ||
1094 | xNibble = rects[i].x & 1; | ||
1095 | height = rects[i].h; | ||
1096 | while (height > 0) | ||
1097 | { | ||
1098 | switch(gapi->gxProperties.cBPP) | ||
1099 | { | ||
1100 | case 2: // TODO | ||
1101 | case 4: | ||
1102 | linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble); | ||
1103 | yNibble = 0; | ||
1104 | } | ||
1105 | height -= linesProcessed; | ||
1106 | if( gapi->userOrientation == SDL_ORIENTATION_UP ) | ||
1107 | destPointer--; // always fill 1 byte | ||
1108 | else destPointer += gapi->dstLineStep; | ||
1109 | srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes | ||
1110 | } | ||
1111 | } | ||
1112 | } | ||
1113 | |||
1114 | static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects) | ||
1115 | { | ||
1116 | int i, height; | ||
1117 | int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8; | ||
1118 | int linesProcessed; | ||
1119 | for (i=0; i<numrects; i++) { | ||
1120 | unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep; | ||
1121 | unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel; | ||
1122 | height = rects[i].h; | ||
1123 | |||
1124 | // fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h); | ||
1125 | // fflush(stderr); | ||
1126 | linesProcessed = height; | ||
1127 | |||
1128 | while (height > 0) { | ||
1129 | switch(bytesPerPixel) | ||
1130 | { | ||
1131 | case 1: | ||
1132 | linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height); | ||
1133 | break; | ||
1134 | case 2: | ||
1135 | #pragma warning(disable: 4133) | ||
1136 | linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height); | ||
1137 | break; | ||
1138 | } | ||
1139 | height -= linesProcessed; | ||
1140 | destPointer += gapi->dstLineStep * linesProcessed; | ||
1141 | srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes | ||
1142 | } | ||
1143 | // fprintf(stderr, "End of rect\n"); | ||
1144 | // fflush(stderr); | ||
1145 | } | ||
1146 | } | ||
1147 | |||
1148 | |||
1149 | static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects) | ||
1150 | { | ||
1151 | // we do not want to corrupt video memory | ||
1152 | if( gapi->suspended ) return; | ||
1153 | |||
1154 | if( gapi->needUpdate ) | ||
1155 | gapi->videoMem = gapi->gxFunc.GXBeginDraw(); | ||
1156 | |||
1157 | if( gapi->gxProperties.cBPP < 8 ) | ||
1158 | GAPI_UpdateRectsMono(this, numrects, rects); | ||
1159 | else | ||
1160 | GAPI_UpdateRectsColor(this, numrects, rects); | ||
1161 | |||
1162 | if( gapi->needUpdate ) | ||
1163 | gapi->gxFunc.GXEndDraw(); | ||
1164 | } | ||
1165 | |||
1166 | /* Note: If we are terminated, this could be called in the middle of | ||
1167 | another SDL video routine -- notably UpdateRects. | ||
1168 | */ | ||
1169 | void GAPI_VideoQuit(_THIS) | ||
1170 | { | ||
1171 | int i, j; | ||
1172 | /* Destroy the window and everything associated with it */ | ||
1173 | if ( SDL_Window ) | ||
1174 | { | ||
1175 | if ((g_hGapiLib != 0) && this && gapi && gapi->gxFunc.GXCloseDisplay && !gapi->useVga) | ||
1176 | gapi->gxFunc.GXCloseDisplay(); | ||
1177 | |||
1178 | if (this->screen->pixels != NULL) | ||
1179 | { | ||
1180 | SDL_free(this->screen->pixels); | ||
1181 | this->screen->pixels = NULL; | ||
1182 | } | ||
1183 | if ( screen_icn ) { | ||
1184 | DestroyIcon(screen_icn); | ||
1185 | screen_icn = NULL; | ||
1186 | } | ||
1187 | |||
1188 | DIB_DestroyWindow(this); | ||
1189 | SDL_UnregisterApp(); | ||
1190 | |||
1191 | SDL_Window = NULL; | ||
1192 | #if defined(_WIN32_WCE) | ||
1193 | |||
1194 | // Unload wince aygshell library to prevent leak | ||
1195 | if( aygshell ) | ||
1196 | { | ||
1197 | FreeLibrary(aygshell); | ||
1198 | aygshell = NULL; | ||
1199 | } | ||
1200 | #endif | ||
1201 | |||
1202 | /* Free video mode lists */ | ||
1203 | for ( i=0; i<NUM_MODELISTS; ++i ) { | ||
1204 | if ( gapi->SDL_modelist[i] != NULL ) { | ||
1205 | for ( j=0; gapi->SDL_modelist[i][j]; ++j ) | ||
1206 | SDL_free(gapi->SDL_modelist[i][j]); | ||
1207 | SDL_free(gapi->SDL_modelist[i]); | ||
1208 | gapi->SDL_modelist[i] = NULL; | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | } | ||
1213 | |||
1214 | } | ||
1215 | |||
1216 | static void GAPI_Activate(_THIS, BOOL active, BOOL minimized) | ||
1217 | { | ||
1218 | //Nothing to do here (as far as I know) | ||
1219 | } | ||
1220 | |||
1221 | static void GAPI_RealizePalette(_THIS) | ||
1222 | { | ||
1223 | OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); | ||
1224 | } | ||
1225 | |||
1226 | static void GAPI_PaletteChanged(_THIS, HWND window) | ||
1227 | { | ||
1228 | OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); | ||
1229 | } | ||
1230 | |||
1231 | static void GAPI_WinPAINT(_THIS, HDC hdc) | ||
1232 | { | ||
1233 | // draw current offscreen buffer on hdc | ||
1234 | |||
1235 | int bpp = 16; // we always use either 8 or 16 bpp internally | ||
1236 | HGDIOBJ prevObject; | ||
1237 | unsigned short *bitmapData; | ||
1238 | HBITMAP hb; | ||
1239 | HDC srcDC; | ||
1240 | |||
1241 | // Create a DIB | ||
1242 | BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0}; | ||
1243 | BITMAPINFO* pBMI = (BITMAPINFO*)buffer; | ||
1244 | BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader; | ||
1245 | DWORD* pColors = (DWORD*)&pBMI->bmiColors; | ||
1246 | |||
1247 | // CreateDIBSection does not support 332 pixel format on wce | ||
1248 | if( gapi->gxProperties.cBPP == 8 ) return; | ||
1249 | |||
1250 | // DIB Header | ||
1251 | pHeader->biSize = sizeof(BITMAPINFOHEADER); | ||
1252 | pHeader->biWidth = gapi->w; | ||
1253 | pHeader->biHeight = -gapi->h; | ||
1254 | pHeader->biPlanes = 1; | ||
1255 | pHeader->biBitCount = bpp; | ||
1256 | pHeader->biCompression = BI_RGB; | ||
1257 | pHeader->biSizeImage = (gapi->w * gapi->h * bpp) / 8; | ||
1258 | |||
1259 | // Color masks | ||
1260 | if( bpp == 16 ) | ||
1261 | { | ||
1262 | pColors[0] = REDMASK; | ||
1263 | pColors[1] = GREENMASK; | ||
1264 | pColors[2] = BLUEMASK; | ||
1265 | pHeader->biCompression = BI_BITFIELDS; | ||
1266 | } | ||
1267 | // Create the DIB | ||
1268 | hb = CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 ); | ||
1269 | |||
1270 | // copy data | ||
1271 | // FIXME: prevent misalignment, but I've never seen non aligned width of screen | ||
1272 | memcpy(bitmapData, gapi->buffer, pHeader->biSizeImage); | ||
1273 | srcDC = CreateCompatibleDC(hdc); | ||
1274 | prevObject = SelectObject(srcDC, hb); | ||
1275 | |||
1276 | BitBlt(hdc, 0, 0, gapi->w, gapi->h, srcDC, 0, 0, SRCCOPY); | ||
1277 | |||
1278 | SelectObject(srcDC, prevObject); | ||
1279 | DeleteObject(hb); | ||
1280 | DeleteDC(srcDC); | ||
1281 | } | ||
1282 | |||
1283 | int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | ||
1284 | { | ||
1285 | GAPI_CreatePalette(ncolors, colors); | ||
1286 | return 1; | ||
1287 | } | ||
diff --git a/apps/plugins/sdl/src/video/gapi/SDL_gapivideo.h b/apps/plugins/sdl/src/video/gapi/SDL_gapivideo.h deleted file mode 100644 index 842d098c22..0000000000 --- a/apps/plugins/sdl/src/video/gapi/SDL_gapivideo.h +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifndef _SDL_gapivideo_h | ||
25 | #define _SDL_gapivideo_h | ||
26 | |||
27 | #include "SDL_mouse.h" | ||
28 | #include "SDL_mutex.h" | ||
29 | #include "../SDL_sysvideo.h" | ||
30 | #include "../windib/SDL_gapidibvideo.h" | ||
31 | |||
32 | /* From gx.h, since it's not really C compliant */ | ||
33 | |||
34 | struct GXDisplayProperties { | ||
35 | DWORD cxWidth; | ||
36 | DWORD cyHeight; // notice lack of 'th' in the word height. | ||
37 | long cbxPitch; // number of bytes to move right one x pixel - can be negative. | ||
38 | long cbyPitch; // number of bytes to move down one y pixel - can be negative. | ||
39 | long cBPP; // # of bits in each pixel | ||
40 | DWORD ffFormat; // format flags. | ||
41 | }; | ||
42 | |||
43 | struct GXKeyList { | ||
44 | short vkUp; // key for up | ||
45 | POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates. | ||
46 | short vkDown; | ||
47 | POINT ptDown; | ||
48 | short vkLeft; | ||
49 | POINT ptLeft; | ||
50 | short vkRight; | ||
51 | POINT ptRight; | ||
52 | short vkA; | ||
53 | POINT ptA; | ||
54 | short vkB; | ||
55 | POINT ptB; | ||
56 | short vkC; | ||
57 | POINT ptC; | ||
58 | short vkStart; | ||
59 | POINT ptStart; | ||
60 | }; | ||
61 | |||
62 | typedef int (*PFNGXOpenDisplay)(HWND hWnd, DWORD dwFlags); | ||
63 | typedef int (*PFNGXCloseDisplay)(); | ||
64 | typedef void* (*PFNGXBeginDraw)(); | ||
65 | typedef int (*PFNGXEndDraw)(); | ||
66 | typedef int (*PFNGXOpenInput)(); | ||
67 | typedef int (*PFNGXCloseInput)(); | ||
68 | typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties)(); | ||
69 | typedef struct GXKeyList (*PFNGXGetDefaultKeys)(int iOptions); | ||
70 | typedef int (*PFNGXSuspend)(); | ||
71 | typedef int (*PFNGXResume)(); | ||
72 | typedef int (*PFNGXSetViewport)( DWORD dwTop, DWORD dwHeight, DWORD dwReserved1, DWORD dwReserved2 ); | ||
73 | typedef BOOL (*PFNGXIsDisplayDRAMBuffer)(); | ||
74 | |||
75 | struct GapiFunc | ||
76 | { | ||
77 | PFNGXOpenDisplay GXOpenDisplay; | ||
78 | PFNGXCloseDisplay GXCloseDisplay; | ||
79 | PFNGXBeginDraw GXBeginDraw; | ||
80 | PFNGXEndDraw GXEndDraw; | ||
81 | PFNGXOpenInput GXOpenInput; | ||
82 | PFNGXCloseInput GXCloseInput; | ||
83 | PFNGXGetDisplayProperties GXGetDisplayProperties; | ||
84 | PFNGXGetDefaultKeys GXGetDefaultKeys; | ||
85 | PFNGXSuspend GXSuspend; | ||
86 | PFNGXResume GXResume; | ||
87 | PFNGXSetViewport GXSetViewport; | ||
88 | PFNGXIsDisplayDRAMBuffer GXIsDisplayDRAMBuffer; | ||
89 | }; | ||
90 | |||
91 | #define kfLandscape 0x8 // Screen is rotated 270 degrees | ||
92 | #define kfPalette 0x10 // Pixel values are indexes into a palette | ||
93 | #define kfDirect 0x20 // Pixel values contain actual level information | ||
94 | #define kfDirect555 0x40 // 5 bits each for red, green and blue values in a pixel. | ||
95 | #define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel | ||
96 | #define kfDirect888 0x100 // 8 bits each for red, green and blue values in a pixel. | ||
97 | #define kfDirect444 0x200 // 4 red, 4 green, 4 blue | ||
98 | #define kfDirectInverted 0x400 | ||
99 | |||
100 | #define GX_FULLSCREEN 0x01 // for OpenDisplay() | ||
101 | #define GX_NORMALKEYS 0x02 | ||
102 | #define GX_LANDSCAPEKEYS 0x03 | ||
103 | |||
104 | |||
105 | /* GAPI video mode */ | ||
106 | typedef enum { | ||
107 | GAPI_NONE = 0, | ||
108 | GAPI_DIRECT_565, | ||
109 | GAPI_DIRECT_555, | ||
110 | GAPI_MONO, | ||
111 | GAPI_PALETTE | ||
112 | } GAPIVideoMode; | ||
113 | |||
114 | typedef unsigned short PIXEL; | ||
115 | |||
116 | /* Private display data | ||
117 | begin with DIB private structure to allow DIB events code sharing | ||
118 | */ | ||
119 | struct GapiInfo { | ||
120 | /* Rotation which has to be applied to the key (arrow keys) and mouse events measured in quarters of a circle | ||
121 | * counter clockwise */ | ||
122 | int coordinateTransform; | ||
123 | char hiresFix; /* using hires mode without defining hires resource */ | ||
124 | int invert; //TODO this is only written but never read, so it should be removed | ||
125 | |||
126 | #define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ | ||
127 | int SDL_nummodes[NUM_MODELISTS]; | ||
128 | SDL_Rect **SDL_modelist[NUM_MODELISTS]; | ||
129 | |||
130 | |||
131 | // The orientation of the video mode user wants to get | ||
132 | // Probably restricted to UP and RIGHT | ||
133 | SDL_ScreenOrientation userOrientation; | ||
134 | SDL_ScreenOrientation systemOrientation; | ||
135 | // -------------- | ||
136 | int useGXOpenDisplay; /* use GXOpenDispplay */ | ||
137 | int alreadyGXOpened; | ||
138 | int w, h; | ||
139 | // The orientation of GAPI framebuffer. | ||
140 | // Never changes on the same device. | ||
141 | SDL_ScreenOrientation gapiOrientation; | ||
142 | |||
143 | void *buffer; // may be 8, 16, 24, 32 bpp | ||
144 | PIXEL *videoMem; | ||
145 | BOOL needUpdate; | ||
146 | struct GXKeyList keyList; | ||
147 | struct GapiFunc gxFunc; | ||
148 | struct GXDisplayProperties gxProperties; | ||
149 | GAPIVideoMode videoMode; | ||
150 | int colorscale; | ||
151 | int dstLineStep; // in bytes | ||
152 | int dstPixelStep; // in bytes | ||
153 | int startOffset; // in bytes | ||
154 | int useVga; | ||
155 | int suspended; // do not pu anything into video memory | ||
156 | }; | ||
157 | |||
158 | |||
159 | |||
160 | #endif /* _SDL_gapivideo_h */ | ||