Mercurial > sdl-ios-xcode
comparison src/video/gapi/SDL_gapivideo.c @ 1251:86d0d01290ea
Updated Windows CE/PocketPC support...adds GAPI driver, landscape mode,
updated project files, VS2005 support, VGA mode, more device support, etc,
etc, etc.
Fixes Bugzilla #47 and #28.
--ryan.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Thu, 19 Jan 2006 08:43:00 +0000 |
parents | |
children | c9b51268668f |
comparison
equal
deleted
inserted
replaced
1250:a4d515d0fc3a | 1251:86d0d01290ea |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2004 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Pocket PC GAPI SDL video driver implementation; | |
29 Implemented by Dmitry Yakimov - support@activekitten.com | |
30 Inspired by http://arisme.free.fr/ports/SDL.php | |
31 */ | |
32 | |
33 // TODO: copy surface on window when lost focus | |
34 // TODO: test buttons rotation | |
35 // TODO: test on be300 and HPC ( check WinDib fullscreen keys catching ) | |
36 // TODO: test on smartphones | |
37 // TODO: windib on SH3 PPC2000 landscape test | |
38 // TODO: optimize 8bpp landscape mode | |
39 | |
40 #include <stdio.h> | |
41 #include <stdlib.h> | |
42 #include <string.h> | |
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 "SDL_events_c.h" | |
51 | |
52 #include "SDL_syswm_c.h" | |
53 #include "SDL_sysmouse_c.h" | |
54 #include "SDL_dibevents_c.h" | |
55 | |
56 #include "SDL_gapivideo.h" | |
57 | |
58 #define GAPIVID_DRIVER_NAME "gapi" | |
59 | |
60 #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG) | |
61 #define REPORT_VIDEO_INFO 1 | |
62 #else | |
63 #define REPORT_VIDEO_INFO 0 | |
64 #endif | |
65 | |
66 // for testing with GapiEmu | |
67 #define USE_GAPI_EMU 0 | |
68 | |
69 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO | |
70 #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") | |
71 #endif | |
72 | |
73 // defined and used in SDL_sysevents.c | |
74 extern HINSTANCE aygshell; | |
75 extern void SDL_UnregisterApp(); | |
76 extern int DIB_AddMode(_THIS, int bpp, int w, int h); | |
77 | |
78 /* Initialization/Query functions */ | |
79 static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
80 static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
81 static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
82 static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
83 static void GAPI_VideoQuit(_THIS); | |
84 | |
85 /* Hardware surface functions */ | |
86 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); | |
87 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); | |
88 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
89 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); | |
90 | |
91 /* Windows message handling functions, will not be processed */ | |
92 static void GAPI_RealizePalette(_THIS); | |
93 static void GAPI_PaletteChanged(_THIS, HWND window); | |
94 static void GAPI_WinPAINT(_THIS, HDC hdc); | |
95 | |
96 /* etc. */ | |
97 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); | |
98 | |
99 static HMODULE g_hGapiLib = 0; | |
100 #define LINK(type,name,import) \ | |
101 if( g_hGapiLib ) \ | |
102 name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); | |
103 | |
104 static char g_bRawBufferAvailable = 0; | |
105 | |
106 /* GAPI driver bootstrap functions */ | |
107 | |
108 /* hi res definitions */ | |
109 typedef struct _RawFrameBufferInfo | |
110 { | |
111 WORD wFormat; | |
112 WORD wBPP; | |
113 VOID *pFramePointer; | |
114 int cxStride; | |
115 int cyStride; | |
116 int cxPixels; | |
117 int cyPixels; | |
118 } RawFrameBufferInfo; | |
119 | |
120 static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0}; | |
121 | |
122 #define GETRAWFRAMEBUFFER 0x00020001 | |
123 | |
124 #define FORMAT_565 1 | |
125 #define FORMAT_555 2 | |
126 #define FORMAT_OTHER 3 | |
127 | |
128 static int GAPI_Available(void) | |
129 { | |
130 // try to use VGA display, even on emulator | |
131 HDC hdc = GetDC(NULL); | |
132 int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo); | |
133 ReleaseDC(NULL, hdc); | |
134 g_bRawBufferAvailable = result > 0; | |
135 | |
136 #if USE_GAPI_EMU | |
137 g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll")); | |
138 if( !g_hGapiLib ) | |
139 { | |
140 SDL_SetError("Gapi Emu not found!"); | |
141 } | |
142 return g_hGapiLib != 0; | |
143 #endif | |
144 | |
145 // try to find gx.dll | |
146 g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll")); | |
147 if( !g_hGapiLib ) | |
148 { | |
149 g_hGapiLib = LoadLibrary(_T("gx.dll")); | |
150 if( !g_hGapiLib ) return g_bRawBufferAvailable; | |
151 } | |
152 | |
153 return(1); | |
154 } | |
155 | |
156 static int cmpmodes(const void *va, const void *vb) | |
157 { | |
158 SDL_Rect *a = *(SDL_Rect **)va; | |
159 SDL_Rect *b = *(SDL_Rect **)vb; | |
160 if ( a->w == b->w ) | |
161 return b->h - a->h; | |
162 else | |
163 return b->w - a->w; | |
164 } | |
165 | |
166 static int GAPI_AddMode(_THIS, int bpp, int w, int h) | |
167 { | |
168 SDL_Rect *mode; | |
169 int i, index; | |
170 int next_mode; | |
171 | |
172 /* Check to see if we already have this mode */ | |
173 if ( bpp < 8 ) { /* Not supported */ | |
174 return(0); | |
175 } | |
176 index = ((bpp+7)/8)-1; | |
177 for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) { | |
178 mode = gapi->SDL_modelist[index][i]; | |
179 if ( (mode->w == w) && (mode->h == h) ) { | |
180 return(0); | |
181 } | |
182 } | |
183 | |
184 /* Set up the new video mode rectangle */ | |
185 mode = (SDL_Rect *)malloc(sizeof *mode); | |
186 if ( mode == NULL ) { | |
187 SDL_OutOfMemory(); | |
188 return(-1); | |
189 } | |
190 mode->x = 0; | |
191 mode->y = 0; | |
192 mode->w = w; | |
193 mode->h = h; | |
194 | |
195 /* Allocate the new list of modes, and fill in the new mode */ | |
196 next_mode = gapi->SDL_nummodes[index]; | |
197 gapi->SDL_modelist[index] = (SDL_Rect **) | |
198 realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); | |
199 if ( gapi->SDL_modelist[index] == NULL ) { | |
200 SDL_OutOfMemory(); | |
201 gapi->SDL_nummodes[index] = 0; | |
202 free(mode); | |
203 return(-1); | |
204 } | |
205 gapi->SDL_modelist[index][next_mode] = mode; | |
206 gapi->SDL_modelist[index][next_mode+1] = NULL; | |
207 gapi->SDL_nummodes[index]++; | |
208 | |
209 return(0); | |
210 } | |
211 | |
212 static void GAPI_DeleteDevice(SDL_VideoDevice *device) | |
213 { | |
214 if( g_hGapiLib ) | |
215 { | |
216 FreeLibrary(g_hGapiLib); | |
217 g_hGapiLib = 0; | |
218 } | |
219 free(device->hidden); | |
220 free(device); | |
221 } | |
222 | |
223 static SDL_VideoDevice *GAPI_CreateDevice(int devindex) | |
224 { | |
225 SDL_VideoDevice *device; | |
226 | |
227 if( !g_hGapiLib && !g_bRawBufferAvailable) | |
228 { | |
229 if( !GAPI_Available() ) | |
230 { | |
231 SDL_SetError("GAPI dll is not found and VGA mode is not available!"); | |
232 return 0; | |
233 } | |
234 } | |
235 | |
236 /* Initialize all variables that we clean on shutdown */ | |
237 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
238 if ( device ) { | |
239 memset(device, 0, (sizeof *device)); | |
240 device->hidden = (struct SDL_PrivateVideoData *) | |
241 malloc((sizeof *device->hidden)); | |
242 } | |
243 if ( (device == NULL) || (device->hidden == NULL) ) { | |
244 SDL_OutOfMemory(); | |
245 if ( device ) { | |
246 free(device); | |
247 } | |
248 return(0); | |
249 } | |
250 memset(device->hidden, 0, (sizeof *device->hidden)); | |
251 | |
252 /* Set the function pointers */ | |
253 device->VideoInit = GAPI_VideoInit; | |
254 device->ListModes = GAPI_ListModes; | |
255 device->SetVideoMode = GAPI_SetVideoMode; | |
256 device->UpdateMouse = WIN_UpdateMouse; | |
257 device->CreateYUVOverlay = NULL; | |
258 device->SetColors = GAPI_SetColors; | |
259 device->UpdateRects = GAPI_UpdateRects; | |
260 device->VideoQuit = GAPI_VideoQuit; | |
261 device->AllocHWSurface = GAPI_AllocHWSurface; | |
262 device->CheckHWBlit = NULL; | |
263 device->FillHWRect = NULL; | |
264 device->SetHWColorKey = NULL; | |
265 device->SetHWAlpha = NULL; | |
266 device->LockHWSurface = GAPI_LockHWSurface; | |
267 device->UnlockHWSurface = GAPI_UnlockHWSurface; | |
268 device->FlipHWSurface = NULL; | |
269 device->FreeHWSurface = GAPI_FreeHWSurface; | |
270 device->SetCaption = WIN_SetWMCaption; | |
271 device->SetIcon = WIN_SetWMIcon; | |
272 device->IconifyWindow = WIN_IconifyWindow; | |
273 device->GrabInput = WIN_GrabInput; | |
274 device->GetWMInfo = WIN_GetWMInfo; | |
275 device->FreeWMCursor = WIN_FreeWMCursor; | |
276 device->CreateWMCursor = WIN_CreateWMCursor; | |
277 device->ShowWMCursor = WIN_ShowWMCursor; | |
278 device->WarpWMCursor = WIN_WarpWMCursor; | |
279 device->CheckMouseMode = WIN_CheckMouseMode; | |
280 device->InitOSKeymap = DIB_InitOSKeymap; | |
281 device->PumpEvents = DIB_PumpEvents; | |
282 | |
283 /* Set up the windows message handling functions */ | |
284 WIN_RealizePalette = GAPI_RealizePalette; | |
285 WIN_PaletteChanged = GAPI_PaletteChanged; | |
286 WIN_WinPAINT = GAPI_WinPAINT; | |
287 HandleMessage = DIB_HandleMessage; | |
288 | |
289 device->free = GAPI_DeleteDevice; | |
290 | |
291 /* Load gapi library */ | |
292 #define gx device->hidden->gxFunc | |
293 | |
294 LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" ) | |
295 LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" ) | |
296 LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" ) | |
297 LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" ) | |
298 LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" ) | |
299 LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" ) | |
300 LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" ) | |
301 LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" ) | |
302 LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" ) | |
303 LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" ) | |
304 LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" ) | |
305 LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" ) | |
306 | |
307 /* wrong gapi.dll */ | |
308 if( !gx.GXOpenDisplay ) | |
309 { | |
310 if( g_hGapiLib ) | |
311 { | |
312 FreeLibrary(g_hGapiLib); | |
313 g_hGapiLib = 0; | |
314 } | |
315 } | |
316 | |
317 if( !gx.GXOpenDisplay && !g_bRawBufferAvailable) | |
318 { | |
319 SDL_SetError("Error: damaged or unknown gapi.dll!\n"); | |
320 GAPI_DeleteDevice(device); | |
321 return 0; | |
322 } | |
323 | |
324 return device; | |
325 } | |
326 | |
327 VideoBootStrap GAPI_bootstrap = { | |
328 GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", | |
329 GAPI_Available, GAPI_CreateDevice | |
330 }; | |
331 | |
332 static void FillStructs(_THIS, BOOL useVga) | |
333 { | |
334 #ifdef _ARM_ | |
335 WCHAR oemstr[100]; | |
336 #endif | |
337 /* fill a device properties */ | |
338 | |
339 if( !useVga ) | |
340 { | |
341 this->hidden->gxProperties = this->hidden->gxFunc.GXGetDisplayProperties(); | |
342 this->hidden->needUpdate = 1; | |
343 this->hidden->hiresFix = 0; | |
344 this->hidden->useVga = 0; | |
345 #ifdef _ARM_ | |
346 /* check some devices and extract addition info */ | |
347 SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 ); | |
348 | |
349 // buggy iPaq38xx | |
350 if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (this->hidden->gxProperties.cbxPitch > 0)) | |
351 { | |
352 this->hidden->videoMem = (PIXEL*)0xac0755a0; | |
353 this->hidden->gxProperties.cbxPitch = -640; | |
354 this->hidden->gxProperties.cbyPitch = 2; | |
355 this->hidden->needUpdate = 0; | |
356 } | |
357 #endif | |
358 } else | |
359 { | |
360 this->hidden->needUpdate = 0; | |
361 this->hidden->hiresFix = 0; | |
362 this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP; | |
363 this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride; | |
364 this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride; | |
365 this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels; | |
366 this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels; | |
367 this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer; | |
368 this->hidden->useVga = 1; | |
369 | |
370 switch( g_RawFrameBufferInfo.wFormat ) | |
371 { | |
372 case FORMAT_565: | |
373 this->hidden->gxProperties.ffFormat = kfDirect565; | |
374 break; | |
375 case FORMAT_555: | |
376 this->hidden->gxProperties.ffFormat = kfDirect555; | |
377 break; | |
378 default: | |
379 /* unknown pixel format, try define by BPP! */ | |
380 switch( g_RawFrameBufferInfo.wBPP ) | |
381 { | |
382 case 4: | |
383 case 8: | |
384 this->hidden->gxProperties.ffFormat = kfDirect; | |
385 case 16: | |
386 this->hidden->gxProperties.ffFormat = kfDirect565; | |
387 default: | |
388 this->hidden->gxProperties.ffFormat = kfDirect; | |
389 break; | |
390 } | |
391 } | |
392 } | |
393 | |
394 if( this->hidden->gxProperties.cBPP != 16 ) | |
395 { | |
396 this->hidden->gapiOrientation = SDL_ORIENTATION_UP; | |
397 } else | |
398 if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch > 0 )) | |
399 { | |
400 this->hidden->gapiOrientation = SDL_ORIENTATION_UP; | |
401 } else | |
402 if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch < 0 )) | |
403 { | |
404 this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660 | |
405 } else | |
406 if( (this->hidden->gxProperties.cbxPitch < 0) && (this->hidden->gxProperties.cbyPitch > 0 )) | |
407 { | |
408 this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800 | |
409 } | |
410 } | |
411 | |
412 static void GAPI_CreatePalette(int ncolors, SDL_Color *colors) | |
413 { | |
414 // Setup a custom color palette | |
415 BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ]; | |
416 int i; | |
417 LOGPALETTE* pLogical = (LOGPALETTE*)buffer; | |
418 PALETTEENTRY* entries = pLogical->palPalEntry; | |
419 HPALETTE hPalette; | |
420 HDC hdc; | |
421 | |
422 for (i = 0; i < ncolors; ++i) | |
423 { | |
424 // Find intensity by replicating the bit patterns over a byte | |
425 entries[i].peRed = colors[i].r; | |
426 entries[i].peGreen = colors[i].g; | |
427 entries[i].peBlue = colors[i].b; | |
428 entries[i].peFlags = 0; | |
429 } | |
430 | |
431 // Create the GDI palette object | |
432 pLogical->palVersion = 0x0300; | |
433 pLogical->palNumEntries = ncolors; | |
434 | |
435 hPalette = CreatePalette( pLogical ); | |
436 ASSERT(hPalette); | |
437 | |
438 | |
439 // Realize the palette | |
440 hdc = GetDC(0); | |
441 | |
442 SelectPalette( hdc, hPalette, FALSE ); | |
443 RealizePalette( hdc ); | |
444 | |
445 ReleaseDC( 0, hdc ); | |
446 DeleteObject( hPalette ); | |
447 } | |
448 | |
449 int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
450 { | |
451 int i,bpp; | |
452 | |
453 /* Create the window */ | |
454 if ( DIB_CreateWindow(this) < 0 ) { | |
455 return(-1); | |
456 } | |
457 | |
458 if( g_hGapiLib ) | |
459 { | |
460 FillStructs(this, 0); | |
461 | |
462 // SDL does not supports 2/4bpp mode, so use 16 bpp | |
463 bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; | |
464 | |
465 /* set up normal and landscape mode */ | |
466 GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); | |
467 GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); | |
468 } | |
469 | |
470 /* add hi-res mode */ | |
471 if( g_bRawBufferAvailable && | |
472 !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels))) | |
473 { | |
474 FillStructs(this, 1); | |
475 | |
476 // SDL does not supports 2/4bpp mode, so use 16 bpp | |
477 bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; | |
478 | |
479 /* set up normal and landscape mode */ | |
480 GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); | |
481 GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); | |
482 } | |
483 | |
484 /* Sort the mode lists */ | |
485 for ( i=0; i<NUM_MODELISTS; ++i ) { | |
486 if ( gapi->SDL_nummodes[i] > 0 ) { | |
487 qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes); | |
488 } | |
489 } | |
490 | |
491 vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP; | |
492 | |
493 // Get color mask | |
494 if (this->hidden->gxProperties.ffFormat & kfDirect565) { | |
495 vformat->BitsPerPixel = 16; | |
496 vformat->Rmask = 0x0000f800; | |
497 vformat->Gmask = 0x000007e0; | |
498 vformat->Bmask = 0x0000001f; | |
499 this->hidden->videoMode = GAPI_DIRECT_565; | |
500 } | |
501 else | |
502 if (this->hidden->gxProperties.ffFormat & kfDirect555) { | |
503 vformat->BitsPerPixel = 16; | |
504 vformat->Rmask = 0x00007c00; | |
505 vformat->Gmask = 0x000003e0; | |
506 vformat->Bmask = 0x0000001f; | |
507 this->hidden->videoMode = GAPI_DIRECT_555; | |
508 } | |
509 else | |
510 if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) { | |
511 // We'll perform the conversion | |
512 vformat->BitsPerPixel = 16; | |
513 vformat->Rmask = 0x0000f800; // 16 bit 565 | |
514 vformat->Gmask = 0x000007e0; | |
515 vformat->Bmask = 0x0000001f; | |
516 if (this->hidden->gxProperties.ffFormat & kfDirectInverted) | |
517 this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1; | |
518 this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0; | |
519 this->hidden->videoMode = GAPI_MONO; | |
520 } | |
521 else | |
522 if (this->hidden->gxProperties.ffFormat & kfPalette) { | |
523 this->hidden->videoMode = GAPI_PALETTE; | |
524 } | |
525 | |
526 /* We're done! */ | |
527 return(0); | |
528 } | |
529 | |
530 SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
531 { | |
532 return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]); | |
533 // return (SDL_Rect **) -1; | |
534 } | |
535 | |
536 SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, | |
537 int width, int height, int bpp, Uint32 flags) | |
538 { | |
539 SDL_Surface *video; | |
540 Uint32 Rmask, Gmask, Bmask; | |
541 DWORD style; | |
542 SDL_Rect allScreen; | |
543 | |
544 if( bpp < 4 ) | |
545 { | |
546 SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!"); | |
547 return 0; | |
548 } | |
549 | |
550 /* Recalculate bitmasks if necessary */ | |
551 if (bpp == current->format->BitsPerPixel) { | |
552 video = current; | |
553 } | |
554 else { | |
555 switch(bpp) { | |
556 case 8: | |
557 Rmask = 0; | |
558 Gmask = 0; | |
559 Bmask = 0; | |
560 break; | |
561 case 15: | |
562 case 16: | |
563 /* Default is 565 unless the display is specifically 555 */ | |
564 if (this->hidden->gxProperties.ffFormat & kfDirect555) { | |
565 Rmask = 0x00007c00; | |
566 Gmask = 0x000003e0; | |
567 Bmask = 0x0000001f; | |
568 } | |
569 else { | |
570 Rmask = 0x0000f800; | |
571 Gmask = 0x000007e0; | |
572 Bmask = 0x0000001f; | |
573 } | |
574 break; | |
575 case 24: | |
576 case 32: | |
577 Rmask = 0x00ff0000; | |
578 Gmask = 0x0000ff00; | |
579 Bmask = 0x000000ff; | |
580 break; | |
581 default: | |
582 SDL_SetError("Unsupported Bits Per Pixel format requested"); | |
583 return NULL; | |
584 } | |
585 video = SDL_CreateRGBSurface(SDL_SWSURFACE, | |
586 0, 0, bpp, Rmask, Gmask, Bmask, 0); | |
587 if ( video == NULL ) { | |
588 SDL_OutOfMemory(); | |
589 return(NULL); | |
590 } | |
591 } | |
592 | |
593 gapi->userOrientation = SDL_ORIENTATION_UP; | |
594 video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */ | |
595 | |
596 /* GAPI or VGA? */ | |
597 if( g_hGapiLib ) | |
598 { | |
599 FillStructs(this, 0); | |
600 if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight)) | |
601 && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth))) | |
602 FillStructs(this, 1); // gapi is found but we use VGA resolution | |
603 } else | |
604 FillStructs(this, 1); | |
605 | |
606 if ( !this->hidden->needUpdate && !this->hidden->videoMem) { | |
607 SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug"); | |
608 return(NULL); | |
609 } | |
610 | |
611 /* detect landscape mode */ | |
612 if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN))) | |
613 gapi->userOrientation = SDL_ORIENTATION_RIGHT; | |
614 | |
615 /* shall we apply hires fix? for example when we do not use hires resource */ | |
616 gapi->hiresFix = 0; | |
617 if( gapi->userOrientation == SDL_ORIENTATION_RIGHT ) | |
618 { | |
619 if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN))) | |
620 gapi->hiresFix = 1; | |
621 } else | |
622 if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN))) | |
623 gapi->hiresFix = 1; | |
624 | |
625 switch( gapi->userOrientation ) | |
626 { | |
627 case SDL_ORIENTATION_UP: | |
628 gapi->startOffset = 0; | |
629 gapi->dstLineStep = gapi->gxProperties.cbyPitch; | |
630 gapi->dstPixelStep = gapi->gxProperties.cbxPitch; | |
631 break; | |
632 case SDL_ORIENTATION_RIGHT: | |
633 switch( gapi->gapiOrientation ) | |
634 { | |
635 case SDL_ORIENTATION_UP: | |
636 case SDL_ORIENTATION_RIGHT: | |
637 case SDL_ORIENTATION_LEFT: | |
638 if( (this->hidden->videoMode == GAPI_MONO) ) | |
639 gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode | |
640 else | |
641 gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1); | |
642 | |
643 gapi->dstLineStep = gapi->gxProperties.cbxPitch; | |
644 gapi->dstPixelStep = -gapi->gxProperties.cbyPitch; | |
645 break; | |
646 } | |
647 } | |
648 | |
649 video->w = this->hidden->w = width; | |
650 video->h = this->hidden->h = height; | |
651 video->pitch = SDL_CalculatePitch(video); | |
652 | |
653 /* Small fix for WinCE/Win32 - when activating window | |
654 SDL_VideoSurface is equal to zero, so activating code | |
655 is not called properly for fullscreen windows because | |
656 macros WINDIB_FULLSCREEN uses SDL_VideoSurface | |
657 */ | |
658 SDL_VideoSurface = video; | |
659 | |
660 /* GAPI is always fullscreen, title bar is useless */ | |
661 style = 0; | |
662 | |
663 if (!SDL_windowid) | |
664 SetWindowLong(SDL_Window, GWL_STYLE, style); | |
665 | |
666 /* Allocate bitmap */ | |
667 if(gapiBuffer) | |
668 { | |
669 free(gapiBuffer); | |
670 gapiBuffer = NULL; | |
671 } | |
672 gapiBuffer = malloc(video->h * video->pitch); | |
673 video->pixels = gapiBuffer; | |
674 | |
675 if ( ! this->hidden->buffer ) { | |
676 SDL_SetError("Couldn't allocate buffer for requested mode"); | |
677 return(NULL); | |
678 } | |
679 | |
680 memset(gapiBuffer, 255, video->h * video->pitch); | |
681 MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE); | |
682 ShowWindow(SDL_Window, SW_SHOW); | |
683 SetForegroundWindow(SDL_Window); | |
684 | |
685 #if REPORT_VIDEO_INFO | |
686 printf("Video properties:\n"); | |
687 printf("display bpp: %d\n", gapi->gxProperties.cBPP); | |
688 printf("display width: %d\n", gapi->gxProperties.cxWidth); | |
689 printf("display height: %d\n", gapi->gxProperties.cyHeight); | |
690 printf("x pitch: %d\n", gapi->gxProperties.cbxPitch); | |
691 printf("y pitch: %d\n", gapi->gxProperties.cbyPitch); | |
692 printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat); | |
693 printf("video memory: 0x%x\n", gapi->videoMem); | |
694 printf("need update: %d\n", gapi->needUpdate); | |
695 printf("hi-res fix: %d\n", gapi->hiresFix); | |
696 printf("VGA is available on the device: %d\n", g_bRawBufferAvailable); | |
697 printf("use VGA resolution: %d\n", gapi->useVga); | |
698 printf("video surface bpp: %d\n", video->format->BitsPerPixel); | |
699 printf("video surface width: %d\n", video->w); | |
700 printf("video surface height: %d\n", video->h); | |
701 #endif | |
702 | |
703 /* Open GAPI display */ | |
704 if( !gapi->useVga ) | |
705 if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) ) | |
706 { | |
707 SDL_SetError("Couldn't initialize GAPI"); | |
708 return(NULL); | |
709 } | |
710 | |
711 /* Blank screen */ | |
712 allScreen.x = allScreen.y = 0; | |
713 allScreen.w = video->w - 1; | |
714 allScreen.h = video->h - 1; | |
715 GAPI_UpdateRects(this, 1, &allScreen); | |
716 | |
717 /* We're done */ | |
718 return(video); | |
719 } | |
720 | |
721 /* We don't actually allow hardware surfaces other than the main one */ | |
722 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) | |
723 { | |
724 return(-1); | |
725 } | |
726 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) | |
727 { | |
728 return; | |
729 } | |
730 | |
731 /* We need to wait for vertical retrace on page flipped displays */ | |
732 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) | |
733 { | |
734 return(0); | |
735 } | |
736 | |
737 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
738 { | |
739 return; | |
740 } | |
741 | |
742 static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines) | |
743 { | |
744 if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */ | |
745 { | |
746 memcpy(destPointer, srcPointer, width); | |
747 return 1; | |
748 } else | |
749 { | |
750 // TODO: read 4 pixels, write DWORD | |
751 int step = gapi->dstPixelStep; | |
752 while(width--) | |
753 { | |
754 *destPointer = *srcPointer++; | |
755 destPointer += step; | |
756 } | |
757 } | |
758 return 1; | |
759 } | |
760 | |
761 /* Video memory is very slow so lets optimize as much as possible */ | |
762 static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines) | |
763 { | |
764 PIXEL *line1, *line2; | |
765 int step = gapi->dstPixelStep / 2; | |
766 | |
767 if( step == 1 ) /* optimized blitting on most devices */ | |
768 { | |
769 memcpy(destPointer, srcPointer, width * sizeof(PIXEL)); | |
770 return 1; | |
771 } | |
772 else | |
773 { | |
774 if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) && | |
775 (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up | |
776 { | |
777 // to prevent data misalignment copy only one line | |
778 if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) | |
779 || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT)) | |
780 || (lines == 1) ) | |
781 { | |
782 while(width--) | |
783 { | |
784 *destPointer = *srcPointer++; | |
785 destPointer += step; | |
786 } | |
787 return 1; | |
788 } | |
789 | |
790 /* read two lines at the same time, write DWORD */ | |
791 line1 = srcPointer; | |
792 line2 = srcPointer + SDL_VideoSurface->pitch / 2; | |
793 | |
794 if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) | |
795 while(width--) // iPaq 3800 | |
796 { | |
797 *(DWORD*)destPointer =(*line2++ << 16) | *line1++; | |
798 destPointer += step; | |
799 } | |
800 else | |
801 { | |
802 destPointer += gapi->gxProperties.cbyPitch / 2; | |
803 while(width--) // iPaq 3660 | |
804 { | |
805 *(DWORD*)destPointer =(*line1++ << 16) | *line2++; | |
806 destPointer += step; | |
807 } | |
808 } | |
809 return 2; | |
810 } else | |
811 { | |
812 // iPaq 3800 and user orientation landscape | |
813 if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) | |
814 { | |
815 int w1; | |
816 | |
817 // to prevent data misalignment copy only one pixel | |
818 if( (((unsigned)destPointer & 3) == 0) && (width > 0)) | |
819 { | |
820 *destPointer-- = *srcPointer++; | |
821 width--; | |
822 } | |
823 | |
824 destPointer--; | |
825 | |
826 w1 = width / 2; | |
827 | |
828 while(w1--) | |
829 { | |
830 DWORD p = *(DWORD*)srcPointer; | |
831 *((DWORD*)destPointer) = (p << 16) | (p >> 16); | |
832 destPointer -= 2; | |
833 srcPointer += 2; | |
834 } | |
835 | |
836 if( width & 1 ) // copy the last pixel | |
837 { | |
838 destPointer++; | |
839 *destPointer = *srcPointer; | |
840 } | |
841 | |
842 return 1; | |
843 } | |
844 | |
845 // modern iPaqs and user orientation landscape | |
846 // read two pixels, write DWORD | |
847 | |
848 line1 = srcPointer; | |
849 line2 = srcPointer + SDL_VideoSurface->pitch / 2; | |
850 | |
851 if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) | |
852 { | |
853 while(width--) | |
854 { | |
855 *destPointer = *srcPointer++; | |
856 destPointer += step; | |
857 } | |
858 return 1; | |
859 } | |
860 | |
861 while(width--) | |
862 { | |
863 *(DWORD*)destPointer =(*line2++ << 16) | *line1++; | |
864 destPointer -= gapi->gxProperties.cbyPitch / 2; | |
865 } | |
866 return 2; | |
867 } | |
868 } | |
869 } | |
870 | |
871 // Color component masks for 565 | |
872 #define REDMASK (31<<11) | |
873 #define GREENMASK (63<<5) | |
874 #define BLUEMASK (31) | |
875 | |
876 | |
877 static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble) | |
878 { | |
879 PIXEL *line1, *line2; | |
880 int step = gapi->dstPixelStep; | |
881 | |
882 if( gapi->userOrientation == SDL_ORIENTATION_UP ) | |
883 { | |
884 if( yNibble ) // copy bottom half of a line | |
885 { | |
886 while(width--) | |
887 { | |
888 PIXEL c1 = *srcPointer++; | |
889 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | |
890 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); | |
891 destPointer += step; | |
892 } | |
893 return 1; | |
894 } | |
895 | |
896 // either 1 pixel picture or tail, anyway this is the last line | |
897 if( lines == 1 ) | |
898 { | |
899 while(width--) | |
900 { | |
901 PIXEL c1 = *srcPointer++; | |
902 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | |
903 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); | |
904 destPointer += step; | |
905 } | |
906 return 1; | |
907 } | |
908 | |
909 line1 = srcPointer; | |
910 line2 = srcPointer + SDL_VideoSurface->pitch / 2; | |
911 | |
912 while(width--) | |
913 { | |
914 PIXEL c1 = *line1++; | |
915 PIXEL c2 = *line2++; | |
916 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | |
917 c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); | |
918 *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4)); | |
919 destPointer += step; | |
920 } | |
921 return 2; | |
922 } else | |
923 { | |
924 int w1; | |
925 w1 = width / 2; | |
926 | |
927 if( xNibble ) | |
928 { | |
929 // copy one pixel | |
930 PIXEL c1 = *srcPointer++; | |
931 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | |
932 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); | |
933 destPointer++; | |
934 } | |
935 | |
936 while(w1--) | |
937 { | |
938 PIXEL c1 = *srcPointer; | |
939 PIXEL c2 = *(srcPointer + 1); | |
940 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | |
941 c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); | |
942 *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4)); | |
943 srcPointer += 2; | |
944 } | |
945 | |
946 // copy tail | |
947 if( (width & 1) && !xNibble ) | |
948 { | |
949 PIXEL c1 = *srcPointer; | |
950 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); | |
951 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); | |
952 } | |
953 | |
954 return 1; | |
955 } | |
956 } | |
957 | |
958 static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects) | |
959 { | |
960 int i, height; | |
961 int linesProcessed; | |
962 int xNibble, yNibble; | |
963 | |
964 for (i=0; i<numrects; i++) | |
965 { | |
966 unsigned char *destPointer; | |
967 unsigned char *srcPointer; | |
968 | |
969 if( gapi->userOrientation == SDL_ORIENTATION_UP ) | |
970 destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep; | |
971 else | |
972 destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep; | |
973 | |
974 srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2; | |
975 yNibble = rects[i].y & 1; // TODO: only for 4 bpp | |
976 xNibble = rects[i].x & 1; | |
977 height = rects[i].h; | |
978 while (height > 0) | |
979 { | |
980 switch(gapi->gxProperties.cBPP) | |
981 { | |
982 case 2: // TODO | |
983 case 4: | |
984 linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble); | |
985 yNibble = 0; | |
986 } | |
987 height -= linesProcessed; | |
988 if( gapi->userOrientation == SDL_ORIENTATION_UP ) | |
989 destPointer--; // always fill 1 byte | |
990 else destPointer += gapi->dstLineStep; | |
991 srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes | |
992 } | |
993 } | |
994 } | |
995 | |
996 static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects) | |
997 { | |
998 int i, height; | |
999 int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8; | |
1000 int linesProcessed; | |
1001 for (i=0; i<numrects; i++) { | |
1002 unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep; | |
1003 unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel; | |
1004 height = rects[i].h; | |
1005 | |
1006 // 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); | |
1007 // fflush(stderr); | |
1008 linesProcessed = height; | |
1009 | |
1010 while (height > 0) { | |
1011 switch(bytesPerPixel) | |
1012 { | |
1013 case 1: | |
1014 linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height); | |
1015 break; | |
1016 case 2: | |
1017 #pragma warning(disable: 4133) | |
1018 linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height); | |
1019 break; | |
1020 } | |
1021 height -= linesProcessed; | |
1022 destPointer += gapi->dstLineStep * linesProcessed; | |
1023 srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes | |
1024 } | |
1025 // fprintf(stderr, "End of rect\n"); | |
1026 // fflush(stderr); | |
1027 } | |
1028 } | |
1029 | |
1030 | |
1031 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects) | |
1032 { | |
1033 if( gapi->needUpdate ) | |
1034 gapi->videoMem = gapi->gxFunc.GXBeginDraw(); | |
1035 | |
1036 if( gapi->gxProperties.cBPP < 8 ) | |
1037 GAPI_UpdateRectsMono(this, numrects, rects); | |
1038 else | |
1039 GAPI_UpdateRectsColor(this, numrects, rects); | |
1040 | |
1041 if( gapi->needUpdate ) | |
1042 gapi->gxFunc.GXEndDraw(); | |
1043 } | |
1044 | |
1045 static void FlushMessageQueue() | |
1046 { | |
1047 MSG msg; | |
1048 while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { | |
1049 if ( msg.message == WM_QUIT ) break; | |
1050 TranslateMessage( &msg ); | |
1051 DispatchMessage( &msg ); | |
1052 } | |
1053 } | |
1054 | |
1055 | |
1056 /* Note: If we are terminated, this could be called in the middle of | |
1057 another SDL video routine -- notably UpdateRects. | |
1058 */ | |
1059 void GAPI_VideoQuit(_THIS) | |
1060 { | |
1061 int i, j; | |
1062 /* Destroy the window and everything associated with it */ | |
1063 if ( SDL_Window ) | |
1064 { | |
1065 if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga) | |
1066 this->hidden->gxFunc.GXCloseDisplay(); | |
1067 | |
1068 if (this->screen->pixels != NULL) | |
1069 { | |
1070 free(this->screen->pixels); | |
1071 this->screen->pixels = NULL; | |
1072 } | |
1073 if ( screen_icn ) { | |
1074 DestroyIcon(screen_icn); | |
1075 screen_icn = NULL; | |
1076 } | |
1077 | |
1078 DIB_DestroyWindow(this); | |
1079 SDL_UnregisterApp(); | |
1080 FlushMessageQueue(); | |
1081 | |
1082 SDL_Window = NULL; | |
1083 #if defined(_WIN32_WCE) | |
1084 | |
1085 // Unload wince aygshell library to prevent leak | |
1086 if( aygshell ) | |
1087 { | |
1088 FreeLibrary(aygshell); | |
1089 aygshell = NULL; | |
1090 } | |
1091 #endif | |
1092 | |
1093 /* Free video mode lists */ | |
1094 for ( i=0; i<NUM_MODELISTS; ++i ) { | |
1095 if ( gapi->SDL_modelist[i] != NULL ) { | |
1096 for ( j=0; gapi->SDL_modelist[i][j]; ++j ) | |
1097 free(gapi->SDL_modelist[i][j]); | |
1098 free(gapi->SDL_modelist[i]); | |
1099 gapi->SDL_modelist[i] = NULL; | |
1100 } | |
1101 } | |
1102 | |
1103 } | |
1104 | |
1105 } | |
1106 | |
1107 static void GAPI_RealizePalette(_THIS) | |
1108 { | |
1109 OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); | |
1110 } | |
1111 | |
1112 static void GAPI_PaletteChanged(_THIS, HWND window) | |
1113 { | |
1114 OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); | |
1115 } | |
1116 | |
1117 /* Exported for the windows message loop only */ | |
1118 static void GAPI_WinPAINT(_THIS, HDC hdc) | |
1119 { | |
1120 OutputDebugString(TEXT("GAPI_WinPAINT NOT IMPLEMENTED !\r\n")); | |
1121 } | |
1122 | |
1123 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
1124 { | |
1125 GAPI_CreatePalette(ncolors, colors); | |
1126 return 1; | |
1127 } |