• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GAPI_Available(void)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 
cmpmodes(const void * va,const void * vb)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 
GAPI_AddMode(_THIS,int bpp,int w,int h)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 
GAPI_DeleteDevice(SDL_VideoDevice * device)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 
GAPI_CreateDevice(int devindex)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 
FillStructs(_THIS,BOOL useVga)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 
GAPI_CreatePalette(int ncolors,SDL_Color * colors)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 
GAPI_VideoInit(_THIS,SDL_PixelFormat * vformat)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 	/* Determine the current screen size */
533 	this->info.current_w = gapi->gxProperties.cxWidth;
534 	this->info.current_h = gapi->gxProperties.cyHeight;
535 
536 	/* Sort the mode lists */
537 	for ( i=0; i<NUM_MODELISTS; ++i ) {
538 		if ( gapi->SDL_nummodes[i] > 0 ) {
539 			SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes);
540 		}
541 	}
542 
543 	vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP;
544 
545 	// Get color mask
546 	if (this->hidden->gxProperties.ffFormat & kfDirect565) {
547 		vformat->BitsPerPixel = 16;
548 		vformat->Rmask = 0x0000f800;
549 		vformat->Gmask = 0x000007e0;
550 		vformat->Bmask = 0x0000001f;
551 		this->hidden->videoMode = GAPI_DIRECT_565;
552 	}
553 	else
554 	if (this->hidden->gxProperties.ffFormat & kfDirect555) {
555 		vformat->BitsPerPixel = 16;
556 		vformat->Rmask = 0x00007c00;
557 		vformat->Gmask = 0x000003e0;
558 		vformat->Bmask = 0x0000001f;
559 		this->hidden->videoMode = GAPI_DIRECT_555;
560 	}
561 	else
562 	if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) {
563 		// We'll perform the conversion
564 		vformat->BitsPerPixel = 16;
565 		vformat->Rmask = 0x0000f800; // 16 bit 565
566 		vformat->Gmask = 0x000007e0;
567 		vformat->Bmask = 0x0000001f;
568 		if (this->hidden->gxProperties.ffFormat & kfDirectInverted)
569 			this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1;
570 		this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0;
571 		this->hidden->videoMode = GAPI_MONO;
572 	}
573 	else
574 	if (this->hidden->gxProperties.ffFormat & kfPalette) {
575 		this->hidden->videoMode = GAPI_PALETTE;
576 	}
577 
578 	/* We're done! */
579 	return(0);
580 }
581 
GAPI_ListModes(_THIS,SDL_PixelFormat * format,Uint32 flags)582 SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
583 {
584 	return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
585 //  	 return (SDL_Rect **) -1;
586 }
587 
GAPI_SetVideoMode(_THIS,SDL_Surface * current,int width,int height,int bpp,Uint32 flags)588 SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
589 				int width, int height, int bpp, Uint32 flags)
590 {
591 	SDL_Surface *video;
592 	Uint32 Rmask, Gmask, Bmask;
593 	DWORD style;
594 	SDL_Rect allScreen;
595 
596 	if( bpp < 4 )
597 	{
598 		SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
599 		return 0;
600 	}
601 
602 	/* Recalculate bitmasks if necessary */
603 	if (bpp == current->format->BitsPerPixel) {
604 		video = current;
605 	}
606 	else {
607 		switch(bpp) {
608 			case 8:
609 				Rmask = 0;
610 				Gmask = 0;
611 				Bmask = 0;
612 				break;
613 			case 15:
614 			case 16:
615 				/* Default is 565 unless the display is specifically 555 */
616 				if (this->hidden->gxProperties.ffFormat & kfDirect555) {
617 					Rmask = 0x00007c00;
618 					Gmask = 0x000003e0;
619 					Bmask = 0x0000001f;
620 				}
621 				else {
622 					Rmask = 0x0000f800;
623 					Gmask = 0x000007e0;
624 					Bmask = 0x0000001f;
625 				}
626 				break;
627 			case 24:
628 			case 32:
629 				Rmask = 0x00ff0000;
630 				Gmask = 0x0000ff00;
631 				Bmask = 0x000000ff;
632 				break;
633 			default:
634 				SDL_SetError("Unsupported Bits Per Pixel format requested");
635 				return NULL;
636 		}
637 		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
638 					0, 0, bpp, Rmask, Gmask, Bmask, 0);
639 		if ( video == NULL ) {
640 			SDL_OutOfMemory();
641 			return(NULL);
642 		}
643 	}
644 
645 	gapi->userOrientation = SDL_ORIENTATION_UP;
646 	video->flags = SDL_FULLSCREEN;	/* Clear flags, GAPI supports fullscreen only */
647 
648 	/* GAPI or VGA? */
649 	if( g_hGapiLib )
650 	{
651 		FillStructs(this, 0);
652 		if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight))
653 			&& (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth)))
654 			FillStructs(this, 1); // gapi is found but we use VGA resolution
655 	} else
656 		FillStructs(this, 1);
657 
658 	if ( !this->hidden->needUpdate && !this->hidden->videoMem) {
659 		SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug");
660 		return(NULL);
661 	}
662 
663 	/* detect user landscape mode */
664 	if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN)))
665 		gapi->userOrientation = SDL_ORIENTATION_RIGHT;
666 
667 	/* shall we apply hires fix? for example when we do not use hires resource */
668 	gapi->hiresFix = 0;
669 	if( gapi->userOrientation == SDL_ORIENTATION_RIGHT )
670 	{
671 		if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN)))
672 			gapi->hiresFix = 1;
673 	} else
674 		if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN)))
675 			if( !((width == GetSystemMetrics(SM_CYSCREEN)) && (height == GetSystemMetrics(SM_CXSCREEN)))) // user portrait, device landscape
676 				gapi->hiresFix = 1;
677 
678 	switch( gapi->userOrientation )
679 	{
680 	case SDL_ORIENTATION_UP:
681 		gapi->startOffset = 0;
682 		gapi->dstLineStep = gapi->gxProperties.cbyPitch;
683 		gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
684 		break;
685 	case SDL_ORIENTATION_RIGHT:
686 		switch( gapi->gapiOrientation )
687 		{
688 		case SDL_ORIENTATION_UP:
689 		case SDL_ORIENTATION_RIGHT:
690 		case SDL_ORIENTATION_LEFT:
691 			if( (this->hidden->videoMode == GAPI_MONO) )
692 				gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode
693 			else
694 				gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1);
695 
696 			gapi->dstLineStep = gapi->gxProperties.cbxPitch;
697 			gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
698 			break;
699 		}
700 	}
701 
702 	video->w = this->hidden->w = width;
703 	video->h = this->hidden->h = height;
704 	video->pitch = SDL_CalculatePitch(video);
705 
706 	/* Small fix for WinCE/Win32 - when activating window
707 	   SDL_VideoSurface is equal to zero, so activating code
708 	   is not called properly for fullscreen windows because
709 	   macros WINDIB_FULLSCREEN uses SDL_VideoSurface
710 	*/
711 	SDL_VideoSurface = video;
712 
713 	/* GAPI is always fullscreen, title bar is useless */
714 	style = 0;
715 
716 	if (!SDL_windowid)
717 		SetWindowLong(SDL_Window, GWL_STYLE, style);
718 
719 	/* Allocate bitmap */
720 	if(gapiBuffer)
721 	{
722 		SDL_free(gapiBuffer);
723 		gapiBuffer = NULL;
724 	}
725 	gapiBuffer = SDL_malloc(video->h * video->pitch);
726 	video->pixels = gapiBuffer;
727 
728 	if ( ! this->hidden->buffer ) {
729 		SDL_SetError("Couldn't allocate buffer for requested mode");
730 		return(NULL);
731 	}
732 
733 	SDL_memset(gapiBuffer, 255, video->h * video->pitch);
734 	MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
735 	ShowWindow(SDL_Window, SW_SHOW);
736 	SetForegroundWindow(SDL_Window);
737 
738 	/* JC 14 Mar 2006
739 		Flush the message loop or this can cause big problems later
740 		Especially if the user decides to use dialog boxes or assert()!
741 	*/
742 	WIN_FlushMessageQueue();
743 
744 	/* Open GAPI display */
745 	if( !gapi->useVga && this->hidden->useGXOpenDisplay )
746 		if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
747 		{
748 			SDL_SetError("Couldn't initialize GAPI");
749 			return(NULL);
750 		}
751 
752 #if REPORT_VIDEO_INFO
753 	printf("Video properties:\n");
754 	printf("display bpp: %d\n", gapi->gxProperties.cBPP);
755 	printf("display width: %d\n", gapi->gxProperties.cxWidth);
756 	printf("display height: %d\n", gapi->gxProperties.cyHeight);
757 	printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
758 	printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
759 	printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
760 
761 	if( !gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate)
762 	{
763 		gapi->videoMem = gapi->gxFunc.GXBeginDraw();
764 		gapi->gxFunc.GXEndDraw();
765 	}
766 
767 	printf("video memory: 0x%x\n", gapi->videoMem);
768 	printf("need update: %d\n", gapi->needUpdate);
769 	printf("hi-res fix: %d\n", gapi->hiresFix);
770 	printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
771 	printf("use raw framebuffer: %d\n", gapi->useVga);
772 	printf("video surface bpp: %d\n", video->format->BitsPerPixel);
773 	printf("video surface width: %d\n", video->w);
774 	printf("video surface height: %d\n", video->h);
775 #endif
776 
777 
778 	/* Blank screen */
779 	allScreen.x = allScreen.y = 0;
780 	allScreen.w = video->w - 1;
781 	allScreen.h = video->h - 1;
782 	GAPI_UpdateRects(this, 1, &allScreen);
783 
784 	/* We're done */
785 	return(video);
786 }
787 
788 /* We don't actually allow hardware surfaces other than the main one */
GAPI_AllocHWSurface(_THIS,SDL_Surface * surface)789 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
790 {
791 	return(-1);
792 }
GAPI_FreeHWSurface(_THIS,SDL_Surface * surface)793 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface)
794 {
795 	return;
796 }
797 
798 /* We need to wait for vertical retrace on page flipped displays */
GAPI_LockHWSurface(_THIS,SDL_Surface * surface)799 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
800 {
801 	return(0);
802 }
803 
GAPI_UnlockHWSurface(_THIS,SDL_Surface * surface)804 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
805 {
806 	return;
807 }
808 
updateLine8to8(_THIS,unsigned char * srcPointer,unsigned char * destPointer,int width,int height,int lines)809 static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines)
810 {
811 	if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */
812 	{
813 		SDL_memcpy(destPointer, srcPointer, width);
814 		return 1;
815 	} else
816 	{
817 		// TODO: read 4 pixels, write DWORD
818 		int step = gapi->dstPixelStep;
819 		while(width--)
820 		{
821 			*destPointer = *srcPointer++;
822 			destPointer += step;
823 		}
824 	}
825 	return 1;
826 }
827 
828 /* Video memory is very slow so lets optimize as much as possible */
updateLine16to16(_THIS,PIXEL * srcPointer,PIXEL * destPointer,int width,int height,int lines)829 static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines)
830 {
831 	PIXEL *line1, *line2;
832 	int step = gapi->dstPixelStep / 2;
833 
834 	if( step == 1 ) /* optimized blitting on most devices */
835 	{
836 		SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
837 		return 1;
838 	}
839 	else
840 	{
841 		if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) &&
842 			(gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up
843 		{
844 			// to prevent data misalignment copy only one line
845 			if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT))
846 				|| ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
847 				|| (lines == 1) )
848 			{
849 				while(width--)
850 				{
851 					*destPointer = *srcPointer++;
852 					destPointer += step;
853 				}
854 				return 1;
855 			}
856 
857 			/* read two lines at the same time, write DWORD */
858 			line1 = srcPointer;
859 			line2 = srcPointer + SDL_VideoSurface->pitch / 2;
860 
861 			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
862 				while(width--) // iPaq 3800
863 				{
864 					*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
865 					destPointer += step;
866 				}
867 			else
868 			{
869 				destPointer += gapi->gxProperties.cbyPitch / 2;
870 
871 				while(width--) // iPaq 3660
872 				{
873 					*(DWORD*)destPointer =(*line1++ << 16) | *line2++;
874 					destPointer += step;
875 				}
876 			}
877 			return 2;
878 		} else
879 		{
880 			// iPaq 3800 and user orientation landscape
881 			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
882 			{
883 				int w1;
884 
885 				// to prevent data misalignment copy only one pixel
886 				if( (((unsigned)destPointer & 3) == 0) && (width > 0))
887 				{
888 					*destPointer-- = *srcPointer++;
889 					width--;
890 				}
891 
892 				destPointer--;
893 
894 				w1 = width / 2;
895 
896 				while(w1--)
897 				{
898 					DWORD p = *(DWORD*)srcPointer;
899 					*((DWORD*)destPointer) = (p << 16) | (p >> 16);
900 					destPointer -= 2;
901 					srcPointer += 2;
902 				}
903 
904 				if( width & 1 ) // copy the last pixel
905 				{
906 					destPointer++;
907 					*destPointer = *srcPointer;
908 				}
909 
910 				return 1;
911 			}
912 
913 			// modern iPaqs and user orientation landscape
914 			// read two pixels, write DWORD
915 
916 			line1 = srcPointer;
917 			line2 = srcPointer + SDL_VideoSurface->pitch / 2;
918 
919 			if( (((unsigned)destPointer & 3) != 0) || (lines == 1) )
920 			{
921 				while(width--)
922 				{
923 					*destPointer = *srcPointer++;
924 					destPointer += step;
925 				}
926 				return 1;
927 			}
928 
929 			while(width--)
930 			{
931 				*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
932 				destPointer -= gapi->gxProperties.cbyPitch / 2;
933 			}
934 			return 2;
935 		}
936 	}
937 }
938 
939 // Color component masks for 565
940 #define REDMASK (31<<11)
941 #define GREENMASK (63<<5)
942 #define BLUEMASK (31)
943 
944 
updateLine16to4(_THIS,PIXEL * srcPointer,unsigned char * destPointer,int width,int height,int lines,int yNibble,int xNibble)945 static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble)
946 {
947 	PIXEL *line1, *line2;
948 	int step = gapi->dstPixelStep;
949 
950 	if( gapi->userOrientation == SDL_ORIENTATION_UP )
951 	{
952 		if( yNibble ) // copy bottom half of a line
953 		{
954 			while(width--)
955 			{
956 				PIXEL c1 = *srcPointer++;
957 				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
958 				*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
959 				destPointer += step;
960 			}
961 			return 1;
962 		}
963 
964 		// either 1 pixel picture or tail, anyway this is the last line
965 		if( lines == 1 )
966 		{
967 			while(width--)
968 			{
969 				PIXEL c1 = *srcPointer++;
970 				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
971 				*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
972 				destPointer += step;
973 			}
974 			return 1;
975 		}
976 
977 		line1 = srcPointer;
978 		line2 = srcPointer + SDL_VideoSurface->pitch / 2;
979 
980 		while(width--)
981 		{
982 			PIXEL c1 = *line1++;
983 			PIXEL c2 = *line2++;
984 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
985 			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
986 			*destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
987 			destPointer += step;
988 		}
989 		return 2;
990 	} else
991 	{
992 		int w1;
993 		w1 = width / 2;
994 
995 		if( xNibble )
996 		{
997 			// copy one pixel
998 			PIXEL c1 = *srcPointer++;
999 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1000 			*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
1001 			destPointer++;
1002 		}
1003 
1004 		while(w1--)
1005 		{
1006 			PIXEL c1 = *srcPointer;
1007 			PIXEL c2 = *(srcPointer + 1);
1008 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1009 			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
1010 			*destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
1011 			srcPointer += 2;
1012 		}
1013 
1014 		// copy tail
1015 		if( (width & 1) && !xNibble )
1016 		{
1017 			PIXEL c1 = *srcPointer;
1018 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1019 			*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
1020 		}
1021 
1022 		return 1;
1023 	}
1024 }
1025 
GAPI_UpdateRectsMono(_THIS,int numrects,SDL_Rect * rects)1026 static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects)
1027 {
1028 	int i, height;
1029 	int linesProcessed;
1030 	int xNibble, yNibble;
1031 
1032 	for (i=0; i<numrects; i++)
1033 	{
1034 		unsigned char *destPointer;
1035 		unsigned char *srcPointer;
1036 
1037 		if( gapi->userOrientation == SDL_ORIENTATION_UP )
1038 			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep;
1039 		else
1040 			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep;
1041 
1042 		srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
1043 		yNibble = rects[i].y & 1; // TODO: only for 4 bpp
1044 		xNibble = rects[i].x & 1;
1045 		height = rects[i].h;
1046 		while (height > 0)
1047 		{
1048 			switch(gapi->gxProperties.cBPP)
1049 			{
1050 			case 2: // TODO
1051 			case 4:
1052 					linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble);
1053 					yNibble = 0;
1054 			}
1055 			height -= linesProcessed;
1056 			if( gapi->userOrientation == SDL_ORIENTATION_UP )
1057 				destPointer--; // always fill 1 byte
1058 			else destPointer += gapi->dstLineStep;
1059 			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
1060 		}
1061 	}
1062 }
1063 
GAPI_UpdateRectsColor(_THIS,int numrects,SDL_Rect * rects)1064 static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects)
1065 {
1066 	int i, height;
1067 	int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
1068 	int linesProcessed;
1069 	for (i=0; i<numrects; i++) {
1070 		unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
1071 		unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
1072 		height = rects[i].h;
1073 
1074 //		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);
1075 //		fflush(stderr);
1076 		linesProcessed = height;
1077 
1078 		while (height > 0) {
1079 			switch(bytesPerPixel)
1080 			{
1081 			case 1:
1082 				linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height);
1083 				break;
1084 			case 2:
1085 #pragma warning(disable: 4133)
1086 				linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height);
1087 				break;
1088 			}
1089 			height -= linesProcessed;
1090 			destPointer += gapi->dstLineStep * linesProcessed;
1091 			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
1092 		}
1093 //		fprintf(stderr, "End of rect\n");
1094 //		fflush(stderr);
1095 	}
1096 }
1097 
1098 
GAPI_UpdateRects(_THIS,int numrects,SDL_Rect * rects)1099 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
1100 {
1101 	// we do not want to corrupt video memory
1102 	if( gapi->suspended ) return;
1103 
1104 	if( gapi->needUpdate )
1105 		gapi->videoMem = gapi->gxFunc.GXBeginDraw();
1106 
1107 	if( gapi->gxProperties.cBPP < 8 )
1108 		GAPI_UpdateRectsMono(this, numrects, rects);
1109 	else
1110 		GAPI_UpdateRectsColor(this, numrects, rects);
1111 
1112 	if( gapi->needUpdate )
1113 		gapi->gxFunc.GXEndDraw();
1114 }
1115 
1116 /* Note:  If we are terminated, this could be called in the middle of
1117    another SDL video routine -- notably UpdateRects.
1118 */
GAPI_VideoQuit(_THIS)1119 void GAPI_VideoQuit(_THIS)
1120 {
1121 	int i, j;
1122 	/* Destroy the window and everything associated with it */
1123 	if ( SDL_Window )
1124 	{
1125 	    if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga)
1126 			this->hidden->gxFunc.GXCloseDisplay();
1127 
1128 		if (this->screen->pixels != NULL)
1129 		{
1130 			SDL_free(this->screen->pixels);
1131 			this->screen->pixels = NULL;
1132 		}
1133 		if ( screen_icn ) {
1134 			DestroyIcon(screen_icn);
1135 			screen_icn = NULL;
1136 		}
1137 
1138 		DIB_DestroyWindow(this);
1139 		SDL_UnregisterApp();
1140 
1141 		SDL_Window = NULL;
1142 #if defined(_WIN32_WCE)
1143 
1144 // Unload wince aygshell library to prevent leak
1145 		if( aygshell )
1146 		{
1147 			FreeLibrary(aygshell);
1148 			aygshell = NULL;
1149 		}
1150 #endif
1151 
1152 	/* Free video mode lists */
1153 	for ( i=0; i<NUM_MODELISTS; ++i ) {
1154 		if ( gapi->SDL_modelist[i] != NULL ) {
1155 			for ( j=0; gapi->SDL_modelist[i][j]; ++j )
1156 				SDL_free(gapi->SDL_modelist[i][j]);
1157 			SDL_free(gapi->SDL_modelist[i]);
1158 			gapi->SDL_modelist[i] = NULL;
1159 		}
1160 	}
1161 
1162 	}
1163 
1164 }
1165 
GAPI_RealizePalette(_THIS)1166 static void GAPI_RealizePalette(_THIS)
1167 {
1168 	OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
1169 }
1170 
GAPI_PaletteChanged(_THIS,HWND window)1171 static void GAPI_PaletteChanged(_THIS, HWND window)
1172 {
1173 	OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
1174 }
1175 
GAPI_WinPAINT(_THIS,HDC hdc)1176 static void GAPI_WinPAINT(_THIS, HDC hdc)
1177 {
1178 	// draw current offscreen buffer on hdc
1179 
1180 	int bpp = 16; // we always use either 8 or 16 bpp internally
1181 	HGDIOBJ prevObject;
1182 	unsigned short *bitmapData;
1183 	HBITMAP hb;
1184 	HDC srcDC;
1185 
1186     // Create a DIB
1187     BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0};
1188     BITMAPINFO*       pBMI    = (BITMAPINFO*)buffer;
1189     BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader;
1190     DWORD*            pColors = (DWORD*)&pBMI->bmiColors;
1191 
1192 	// CreateDIBSection does not support 332 pixel format on wce
1193 	if( gapi->gxProperties.cBPP == 8 ) return;
1194 
1195     // DIB Header
1196     pHeader->biSize            = sizeof(BITMAPINFOHEADER);
1197     pHeader->biWidth           = this->hidden->w;
1198     pHeader->biHeight          = -this->hidden->h;
1199     pHeader->biPlanes          = 1;
1200     pHeader->biBitCount        = bpp;
1201     pHeader->biCompression     = BI_RGB;
1202     pHeader->biSizeImage       = (this->hidden->w * this->hidden->h * bpp) / 8;
1203 
1204     // Color masks
1205 	if( bpp == 16 )
1206 	{
1207 		pColors[0] = REDMASK;
1208 		pColors[1] = GREENMASK;
1209 		pColors[2] = BLUEMASK;
1210 		pHeader->biCompression = BI_BITFIELDS;
1211 	}
1212     // Create the DIB
1213     hb =  CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 );
1214 
1215 	// copy data
1216 	// FIXME: prevent misalignment, but I've never seen non aligned width of screen
1217 	memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage);
1218 	srcDC = CreateCompatibleDC(hdc);
1219 	prevObject = SelectObject(srcDC, hb);
1220 
1221 	BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY);
1222 
1223 	SelectObject(srcDC, prevObject);
1224 	DeleteObject(hb);
1225 	DeleteDC(srcDC);
1226 }
1227 
GAPI_SetColors(_THIS,int firstcolor,int ncolors,SDL_Color * colors)1228 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1229 {
1230 	GAPI_CreatePalette(ncolors, colors);
1231 	return 1;
1232 }
1233