comparison src/video/gapi/SDL_gapivideo.c @ 1251:86d0d01290ea

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