SDL-1.2.14
[sdl_omap.git] / src / video / gapi / SDL_gapivideo.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #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 }