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