2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
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.
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.
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
22 #include "SDL_config.h"
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
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
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
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"
55 #include "../windib/SDL_gapidibvideo.h"
56 #include "SDL_gapivideo.h"
58 #define gapi this->hidden->gapiInfo
60 #define GAPIVID_DRIVER_NAME "gapi"
62 #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG)
63 #define REPORT_VIDEO_INFO 1
65 #define REPORT_VIDEO_INFO 0
68 // for testing with GapiEmu
69 #define USE_GAPI_EMU 0
70 #define EMULATE_AXIM_X30 0
71 #define WITHOUT_GAPI 0
73 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO
74 #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.")
85 // defined and used in SDL_sysevents.c
86 extern HINSTANCE aygshell;
87 extern void SDL_UnregisterApp();
88 extern int DIB_AddMode(_THIS, int bpp, int w, int h);
90 /* Initialization/Query functions */
91 static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat);
92 static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
93 static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
94 static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
95 static void GAPI_VideoQuit(_THIS);
97 /* Hardware surface functions */
98 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface);
99 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface);
100 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface);
101 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface);
103 /* Windows message handling functions, will not be processed */
104 static void GAPI_Activate(_THIS, BOOL active, BOOL minimized);
105 static void GAPI_RealizePalette(_THIS);
106 static void GAPI_PaletteChanged(_THIS, HWND window);
107 static void GAPI_WinPAINT(_THIS, HDC hdc);
110 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
112 static HMODULE g_hGapiLib = 0;
113 #define LINK(type,name,import) \
115 name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) );
117 static char g_bRawBufferAvailable = 0;
119 /* GAPI driver bootstrap functions */
121 /* hi res definitions */
122 typedef struct _RawFrameBufferInfo
131 } RawFrameBufferInfo;
133 static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0};
135 #define GETRAWFRAMEBUFFER 0x00020001
139 #define FORMAT_OTHER 3
141 /* Dell Axim x30 hangs when we use GAPI from landscape,
142 so lets avoid using GxOpenDisplay there via GETGXINFO trick
143 It seems that GAPI subsystem use the same ExtEscape code.
145 #define GETGXINFO 0x00020000
147 typedef struct GXDeviceInfo
149 long Version; //00 (should filled with 100 before calling ExtEscape)
150 void * pvFrameBuffer; //04
151 unsigned long cbStride; //08
152 unsigned long cxWidth; //0c
153 unsigned long cyHeight; //10
154 unsigned long cBPP; //14
155 unsigned long ffFormat; //18
156 char Unused[0x84-7*4];
159 static int GAPI_Available(void)
161 // try to use VGA display, even on emulator
162 HDC hdc = GetDC(NULL);
163 int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo);
164 ReleaseDC(NULL, hdc);
165 g_bRawBufferAvailable = result > 0;
167 //My Asus MyPAL 696 reports the RAWFRAMEBUFFER as available, but with a size of 0 x 0
168 if(g_RawFrameBufferInfo.cxPixels <= 0 || g_RawFrameBufferInfo.cyPixels <= 0){
169 g_bRawBufferAvailable = 0;
173 return g_bRawBufferAvailable;
177 g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll"));
180 SDL_SetError("Gapi Emu not found!");
182 return g_hGapiLib != 0;
185 // try to find gx.dll
186 g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll"));
189 g_hGapiLib = LoadLibrary(_T("gx.dll"));
190 if( !g_hGapiLib ) return g_bRawBufferAvailable;
196 static int cmpmodes(const void *va, const void *vb)
198 SDL_Rect *a = *(SDL_Rect **)va;
199 SDL_Rect *b = *(SDL_Rect **)vb;
206 static int GAPI_AddMode(_THIS, int bpp, int w, int h)
212 /* Check to see if we already have this mode */
213 if ( bpp < 8 ) { /* Not supported */
216 index = ((bpp+7)/8)-1;
217 for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) {
218 mode = gapi->SDL_modelist[index][i];
219 if ( (mode->w == w) && (mode->h == h) ) {
224 /* Set up the new video mode rectangle */
225 mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
226 if ( mode == NULL ) {
235 /* Allocate the new list of modes, and fill in the new mode */
236 next_mode = gapi->SDL_nummodes[index];
237 gapi->SDL_modelist[index] = (SDL_Rect **)
238 SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
239 if ( gapi->SDL_modelist[index] == NULL ) {
241 gapi->SDL_nummodes[index] = 0;
245 gapi->SDL_modelist[index][next_mode] = mode;
246 gapi->SDL_modelist[index][next_mode+1] = NULL;
247 gapi->SDL_nummodes[index]++;
252 static void GAPI_DeleteDevice(SDL_VideoDevice *device)
256 FreeLibrary(g_hGapiLib);
259 SDL_free(device->hidden->gapiInfo);
260 SDL_free(device->hidden);
264 static SDL_VideoDevice *GAPI_CreateDevice(int devindex)
266 SDL_VideoDevice *device;
268 if( !g_hGapiLib && !g_bRawBufferAvailable)
270 if( !GAPI_Available() )
272 SDL_SetError("GAPI dll is not found and VGA mode is not available!");
277 /* Initialize all variables that we clean on shutdown */
278 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
280 SDL_memset(device, 0, (sizeof *device));
281 device->hidden = (struct SDL_PrivateVideoData *)
282 SDL_malloc((sizeof *device->hidden));
284 SDL_memset(device->hidden, 0, (sizeof *device->hidden));
285 device->hidden->gapiInfo = (GapiInfo *)SDL_malloc((sizeof(GapiInfo)));
286 if(device->hidden->gapiInfo == NULL)
288 SDL_free(device->hidden);
289 device->hidden = NULL;
293 if ( (device == NULL) || (device->hidden == NULL) ) {
300 SDL_memset(device->hidden->gapiInfo, 0, (sizeof *device->hidden->gapiInfo));
302 /* Set the function pointers */
303 device->VideoInit = GAPI_VideoInit;
304 device->ListModes = GAPI_ListModes;
305 device->SetVideoMode = GAPI_SetVideoMode;
306 device->UpdateMouse = WIN_UpdateMouse;
307 device->CreateYUVOverlay = NULL;
308 device->SetColors = GAPI_SetColors;
309 device->UpdateRects = GAPI_UpdateRects;
310 device->VideoQuit = GAPI_VideoQuit;
311 device->AllocHWSurface = GAPI_AllocHWSurface;
312 device->CheckHWBlit = NULL;
313 device->FillHWRect = NULL;
314 device->SetHWColorKey = NULL;
315 device->SetHWAlpha = NULL;
316 device->LockHWSurface = GAPI_LockHWSurface;
317 device->UnlockHWSurface = GAPI_UnlockHWSurface;
318 device->FlipHWSurface = NULL;
319 device->FreeHWSurface = GAPI_FreeHWSurface;
320 device->SetCaption = WIN_SetWMCaption;
321 device->SetIcon = WIN_SetWMIcon;
322 device->IconifyWindow = WIN_IconifyWindow;
323 device->GrabInput = WIN_GrabInput;
324 device->GetWMInfo = WIN_GetWMInfo;
325 device->FreeWMCursor = WIN_FreeWMCursor;
326 device->CreateWMCursor = WIN_CreateWMCursor;
327 device->ShowWMCursor = WIN_ShowWMCursor;
328 device->WarpWMCursor = WIN_WarpWMCursor;
329 device->CheckMouseMode = WIN_CheckMouseMode;
330 device->InitOSKeymap = DIB_InitOSKeymap;
331 device->PumpEvents = DIB_PumpEvents;
333 /* Set up the windows message handling functions */
334 WIN_Activate = GAPI_Activate;
335 WIN_RealizePalette = GAPI_RealizePalette;
336 WIN_PaletteChanged = GAPI_PaletteChanged;
337 WIN_WinPAINT = GAPI_WinPAINT;
338 HandleMessage = DIB_HandleMessage;
340 device->free = GAPI_DeleteDevice;
342 /* Load gapi library */
343 #define gx device->hidden->gapiInfo->gxFunc
345 LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" )
346 LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" )
347 LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" )
348 LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" )
349 LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" )
350 LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" )
351 LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" )
352 LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" )
353 LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" )
354 LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" )
355 LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" )
356 LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" )
359 if( !gx.GXOpenDisplay )
363 FreeLibrary(g_hGapiLib);
368 if( !gx.GXOpenDisplay && !g_bRawBufferAvailable)
370 SDL_SetError("Error: damaged or unknown gapi.dll!\n");
371 GAPI_DeleteDevice(device);
378 VideoBootStrap GAPI_bootstrap = {
379 GAPIVID_DRIVER_NAME, "WinCE GAPI video driver",
380 GAPI_Available, GAPI_CreateDevice
383 static void FillStructs(_THIS, BOOL useVga)
388 /* fill a device properties */
392 gapi->gxProperties = gapi->gxFunc.GXGetDisplayProperties();
393 gapi->needUpdate = 1;
396 gapi->useGXOpenDisplay = 1;
399 /* check some devices and extract addition info */
400 SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 );
403 if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (gapi->gxProperties.cbxPitch > 0))
405 gapi->videoMem = (PIXEL*)0xac0755a0;
406 gapi->gxProperties.cbxPitch = -640;
407 gapi->gxProperties.cbyPitch = 2;
408 gapi->needUpdate = 0;
410 #if (EMULATE_AXIM_X30 == 0)
411 // buggy Dell Axim X30
412 if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 )
415 GXDeviceInfo gxInfo = {0};
416 HDC hdc = GetDC(NULL);
419 gxInfo.Version = 100;
420 result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo);
423 gapi->useGXOpenDisplay = 0;
424 gapi->videoMem = gxInfo.pvFrameBuffer;
425 gapi->needUpdate = 0;
426 gapi->gxProperties.cbxPitch = 2;
427 gapi->gxProperties.cbyPitch = 480;
428 gapi->gxProperties.cxWidth = gxInfo.cxWidth;
429 gapi->gxProperties.cyHeight = gxInfo.cyHeight;
430 gapi->gxProperties.ffFormat = gxInfo.ffFormat;
436 gapi->needUpdate = 0;
438 gapi->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP;
439 gapi->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride;
440 gapi->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride;
441 gapi->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels;
442 gapi->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels;
443 gapi->videoMem = g_RawFrameBufferInfo.pFramePointer;
446 switch( g_RawFrameBufferInfo.wFormat )
449 gapi->gxProperties.ffFormat = kfDirect565;
452 gapi->gxProperties.ffFormat = kfDirect555;
455 /* unknown pixel format, try define by BPP! */
456 switch( g_RawFrameBufferInfo.wBPP )
460 gapi->gxProperties.ffFormat = kfDirect;
462 gapi->gxProperties.ffFormat = kfDirect565;
464 gapi->gxProperties.ffFormat = kfDirect;
470 if( gapi->gxProperties.cBPP != 16 )
472 gapi->gapiOrientation = SDL_ORIENTATION_UP;
474 if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch > 0 ))
476 gapi->gapiOrientation = SDL_ORIENTATION_UP;
478 if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch < 0 ))
480 gapi->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660
482 if( (gapi->gxProperties.cbxPitch < 0) && (gapi->gxProperties.cbyPitch > 0 ))
484 gapi->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800
488 static void GAPI_CreatePalette(int ncolors, SDL_Color *colors)
490 // Setup a custom color palette
491 BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ];
493 LOGPALETTE* pLogical = (LOGPALETTE*)buffer;
494 PALETTEENTRY* entries = pLogical->palPalEntry;
498 for (i = 0; i < ncolors; ++i)
500 // Find intensity by replicating the bit patterns over a byte
501 entries[i].peRed = colors[i].r;
502 entries[i].peGreen = colors[i].g;
503 entries[i].peBlue = colors[i].b;
504 entries[i].peFlags = 0;
507 // Create the GDI palette object
508 pLogical->palVersion = 0x0300;
509 pLogical->palNumEntries = ncolors;
511 hPalette = CreatePalette( pLogical );
515 // Realize the palette
518 SelectPalette( hdc, hPalette, FALSE );
519 RealizePalette( hdc );
522 DeleteObject( hPalette );
525 int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat)
529 /* Create the window */
530 if ( DIB_CreateWindow(this) < 0 ) {
536 FillStructs(this, 0);
538 // SDL does not supports 2/4bpp mode, so use 16 bpp
539 bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
541 /* set up normal and landscape mode */
542 GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
543 GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
546 /* add hi-res mode */
547 if( g_bRawBufferAvailable &&
548 !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels)))
550 FillStructs(this, 1);
552 // SDL does not supports 2/4bpp mode, so use 16 bpp
553 bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
555 /* set up normal and landscape mode */
556 GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
557 GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
560 /* Determine the current screen size.
561 * This is NOT necessarily the size of the Framebuffer or GAPI, as they return
562 * the displaysize in ORIENTATION_UP */
563 this->info.current_w = GetSystemMetrics(SM_CXSCREEN);
564 this->info.current_h = GetSystemMetrics(SM_CYSCREEN);
566 /* Sort the mode lists */
567 for ( i=0; i<NUM_MODELISTS; ++i ) {
568 if ( gapi->SDL_nummodes[i] > 0 ) {
569 SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes);
573 vformat->BitsPerPixel = gapi->gxProperties.cBPP < 8 ? 16 : (unsigned char)gapi->gxProperties.cBPP;
576 if (gapi->gxProperties.ffFormat & kfDirect565) {
577 vformat->BitsPerPixel = 16;
578 vformat->Rmask = 0x0000f800;
579 vformat->Gmask = 0x000007e0;
580 vformat->Bmask = 0x0000001f;
581 gapi->videoMode = GAPI_DIRECT_565;
584 if (gapi->gxProperties.ffFormat & kfDirect555) {
585 vformat->BitsPerPixel = 16;
586 vformat->Rmask = 0x00007c00;
587 vformat->Gmask = 0x000003e0;
588 vformat->Bmask = 0x0000001f;
589 gapi->videoMode = GAPI_DIRECT_555;
592 if ((gapi->gxProperties.ffFormat & kfDirect) && (gapi->gxProperties.cBPP < 8)) {
593 // We'll perform the conversion
594 vformat->BitsPerPixel = 16;
595 vformat->Rmask = 0x0000f800; // 16 bit 565
596 vformat->Gmask = 0x000007e0;
597 vformat->Bmask = 0x0000001f;
598 if (gapi->gxProperties.ffFormat & kfDirectInverted)
599 gapi->invert = (1 << gapi->gxProperties.cBPP) - 1;
600 gapi->colorscale = gapi->gxProperties.cBPP < 8 ? 8 - gapi->gxProperties.cBPP : 0;
601 gapi->videoMode = GAPI_MONO;
604 if (gapi->gxProperties.ffFormat & kfPalette) {
605 gapi->videoMode = GAPI_PALETTE;
612 SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
614 return(gapi->SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
615 // return (SDL_Rect **) -1;
618 SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
619 int width, int height, int bpp, Uint32 flags)
622 Uint32 Rmask, Gmask, Bmask;
628 SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
632 /* Recalculate bitmasks if necessary */
633 if (bpp == current->format->BitsPerPixel) {
645 /* Default is 565 unless the display is specifically 555 */
646 if (gapi->gxProperties.ffFormat & kfDirect555) {
664 SDL_SetError("Unsupported Bits Per Pixel format requested");
667 video = SDL_CreateRGBSurface(SDL_SWSURFACE,
668 0, 0, bpp, Rmask, Gmask, Bmask, 0);
669 if ( video == NULL ) {
675 gapi->userOrientation = SDL_ORIENTATION_UP;
676 gapi->systemOrientation = SDL_ORIENTATION_UP;
677 video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */
682 FillStructs(this, 0);
683 if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight))
684 && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth)))
685 FillStructs(this, 1); // gapi is found but we use VGA resolution
687 FillStructs(this, 1);
689 if ( !gapi->needUpdate && !gapi->videoMem) {
690 SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug");
694 /* detect user landscape mode */
695 if( (width > height) && (gapi->gxProperties.cxWidth < gapi->gxProperties.cyHeight))
696 gapi->userOrientation = SDL_ORIENTATION_RIGHT;
698 if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN))
699 gapi->systemOrientation = SDL_ORIENTATION_RIGHT;
704 if(GetSystemMetrics(SM_CXSCREEN) < width && GetSystemMetrics(SM_CYSCREEN) < height)
709 switch( gapi->userOrientation )
711 case SDL_ORIENTATION_UP:
712 gapi->startOffset = 0;
713 gapi->dstLineStep = gapi->gxProperties.cbyPitch;
714 gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
716 case SDL_ORIENTATION_RIGHT:
717 switch( gapi->gapiOrientation )
719 case SDL_ORIENTATION_UP:
720 case SDL_ORIENTATION_RIGHT:
721 case SDL_ORIENTATION_LEFT:
722 if( (gapi->videoMode == GAPI_MONO) )
723 gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode
725 gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1);
727 gapi->dstLineStep = gapi->gxProperties.cbxPitch;
728 gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
733 video->w = gapi->w = width;
734 video->h = gapi->h = height;
735 video->pitch = SDL_CalculatePitch(video);
737 /* Small fix for WinCE/Win32 - when activating window
738 SDL_VideoSurface is equal to zero, so activating code
739 is not called properly for fullscreen windows because
740 macros WINDIB_FULLSCREEN uses SDL_VideoSurface
742 SDL_VideoSurface = video;
744 /* GAPI is always fullscreen, title bar is useless */
748 SetWindowLong(SDL_Window, GWL_STYLE, style);
750 /* Allocate bitmap */
753 SDL_free( gapi->buffer );
756 gapi->buffer = SDL_malloc(video->h * video->pitch);
757 video->pixels = gapi->buffer;
759 if ( ! gapi->buffer ) {
760 SDL_SetError("Couldn't allocate buffer for requested mode");
764 SDL_memset(gapi->buffer, 255, video->h * video->pitch);
765 MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
766 ShowWindow(SDL_Window, SW_SHOW);
767 SetForegroundWindow(SDL_Window);
770 Flush the message loop or this can cause big problems later
771 Especially if the user decides to use dialog boxes or assert()!
773 WIN_FlushMessageQueue();
775 /* Open GAPI display */
776 if( !gapi->useVga && gapi->useGXOpenDisplay && !gapi->alreadyGXOpened )
778 #if REPORT_VIDEO_INFO
779 printf("system display width (orig): %d\n", GetSystemMetrics(SM_CXSCREEN));
780 printf("system display height (orig): %d\n", GetSystemMetrics(SM_CYSCREEN));
782 gapi->alreadyGXOpened = 1;
783 if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
785 SDL_SetError("Couldn't initialize GAPI");
791 gapi->coordinateTransform = (4 - gapi->systemOrientation + gapi->userOrientation) % 4;
793 gapi->coordinateTransform = gapi->userOrientation;
795 #if REPORT_VIDEO_INFO
796 printf("Video properties:\n");
797 printf("display bpp: %d\n", gapi->gxProperties.cBPP);
798 printf("display width: %d\n", gapi->gxProperties.cxWidth);
799 printf("display height: %d\n", gapi->gxProperties.cyHeight);
800 printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN));
801 printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN));
802 printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
803 printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
804 printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
805 printf("user orientation: %d\n", gapi->userOrientation);
806 printf("system orientation: %d\n", gapi->systemOrientation);
807 printf("gapi orientation: %d\n", gapi->gapiOrientation);
810 if( !gapi->useVga && gapi->useGXOpenDisplay && gapi->needUpdate)
812 gapi->videoMem = gapi->gxFunc.GXBeginDraw();
813 gapi->gxFunc.GXEndDraw();
816 printf("video memory: 0x%x\n", gapi->videoMem);
817 printf("need update: %d\n", gapi->needUpdate);
818 printf("hi-res fix: %d\n", gapi->hiresFix);
819 printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
820 printf("use raw framebuffer: %d\n", gapi->useVga);
821 printf("video surface bpp: %d\n", video->format->BitsPerPixel);
822 printf("video surface width: %d\n", video->w);
823 printf("video surface height: %d\n", video->h);
824 printf("mouse/arrows transformation angle: %d\n", gapi->coordinateTransform);
829 allScreen.x = allScreen.y = 0;
830 allScreen.w = video->w - 1;
831 allScreen.h = video->h - 1;
832 GAPI_UpdateRects(this, 1, &allScreen);
838 /* We don't actually allow hardware surfaces other than the main one */
839 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
843 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface)
848 /* We need to wait for vertical retrace on page flipped displays */
849 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
854 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
859 static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines)
861 if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */
863 SDL_memcpy(destPointer, srcPointer, width);
867 // TODO: read 4 pixels, write DWORD
868 int step = gapi->dstPixelStep;
871 *destPointer = *srcPointer++;
878 /* Video memory is very slow so lets optimize as much as possible */
879 static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines)
881 PIXEL *line1, *line2;
882 int step = gapi->dstPixelStep / 2;
884 if( step == 1 ) /* optimized blitting on most devices */
886 SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
891 if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) &&
892 (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up
894 // to prevent data misalignment copy only one line
895 if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT))
896 || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
901 *destPointer = *srcPointer++;
907 /* read two lines at the same time, write DWORD */
909 line2 = srcPointer + SDL_VideoSurface->pitch / 2;
911 if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
912 while(width--) // iPaq 3800
914 *(DWORD*)destPointer =(*line2++ << 16) | *line1++;
919 destPointer += gapi->gxProperties.cbyPitch / 2;
921 while(width--) // iPaq 3660
923 *(DWORD*)destPointer =(*line1++ << 16) | *line2++;
930 // iPaq 3800 and user orientation landscape
931 if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
935 // to prevent data misalignment copy only one pixel
936 if( (((unsigned)destPointer & 3) == 0) && (width > 0))
938 *destPointer-- = *srcPointer++;
948 DWORD p = *(DWORD*)srcPointer;
949 *((DWORD*)destPointer) = (p << 16) | (p >> 16);
954 if( width & 1 ) // copy the last pixel
957 *destPointer = *srcPointer;
963 // modern iPaqs and user orientation landscape
964 // read two pixels, write DWORD
967 line2 = srcPointer + SDL_VideoSurface->pitch / 2;
969 if( (((unsigned)destPointer & 3) != 0) || (lines == 1) )
973 *destPointer = *srcPointer++;
981 *(DWORD*)destPointer =(*line2++ << 16) | *line1++;
982 destPointer -= gapi->gxProperties.cbyPitch / 2;
989 // Color component masks for 565
990 #define REDMASK (31<<11)
991 #define GREENMASK (63<<5)
992 #define BLUEMASK (31)
995 static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble)
997 PIXEL *line1, *line2;
998 int step = gapi->dstPixelStep;
1000 if( gapi->userOrientation == SDL_ORIENTATION_UP )
1002 if( yNibble ) // copy bottom half of a line
1006 PIXEL c1 = *srcPointer++;
1007 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1008 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
1009 destPointer += step;
1014 // either 1 pixel picture or tail, anyway this is the last line
1019 PIXEL c1 = *srcPointer++;
1020 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1021 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
1022 destPointer += step;
1028 line2 = srcPointer + SDL_VideoSurface->pitch / 2;
1032 PIXEL c1 = *line1++;
1033 PIXEL c2 = *line2++;
1034 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1035 c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
1036 *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
1037 destPointer += step;
1048 PIXEL c1 = *srcPointer++;
1049 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1050 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
1056 PIXEL c1 = *srcPointer;
1057 PIXEL c2 = *(srcPointer + 1);
1058 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1059 c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
1060 *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
1065 if( (width & 1) && !xNibble )
1067 PIXEL c1 = *srcPointer;
1068 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
1069 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
1076 static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects)
1080 int xNibble, yNibble;
1082 for (i=0; i<numrects; i++)
1084 unsigned char *destPointer;
1085 unsigned char *srcPointer;
1087 if( gapi->userOrientation == SDL_ORIENTATION_UP )
1088 destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep;
1090 destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep;
1092 srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
1093 yNibble = rects[i].y & 1; // TODO: only for 4 bpp
1094 xNibble = rects[i].x & 1;
1095 height = rects[i].h;
1098 switch(gapi->gxProperties.cBPP)
1102 linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble);
1105 height -= linesProcessed;
1106 if( gapi->userOrientation == SDL_ORIENTATION_UP )
1107 destPointer--; // always fill 1 byte
1108 else destPointer += gapi->dstLineStep;
1109 srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
1114 static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects)
1117 int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
1119 for (i=0; i<numrects; i++) {
1120 unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
1121 unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
1122 height = rects[i].h;
1124 // fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h);
1126 linesProcessed = height;
1128 while (height > 0) {
1129 switch(bytesPerPixel)
1132 linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height);
1135 #pragma warning(disable: 4133)
1136 linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height);
1139 height -= linesProcessed;
1140 destPointer += gapi->dstLineStep * linesProcessed;
1141 srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
1143 // fprintf(stderr, "End of rect\n");
1149 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
1151 // we do not want to corrupt video memory
1152 if( gapi->suspended ) return;
1154 if( gapi->needUpdate )
1155 gapi->videoMem = gapi->gxFunc.GXBeginDraw();
1157 if( gapi->gxProperties.cBPP < 8 )
1158 GAPI_UpdateRectsMono(this, numrects, rects);
1160 GAPI_UpdateRectsColor(this, numrects, rects);
1162 if( gapi->needUpdate )
1163 gapi->gxFunc.GXEndDraw();
1166 /* Note: If we are terminated, this could be called in the middle of
1167 another SDL video routine -- notably UpdateRects.
1169 void GAPI_VideoQuit(_THIS)
1172 /* Destroy the window and everything associated with it */
1175 if ((g_hGapiLib != 0) && this && gapi && gapi->gxFunc.GXCloseDisplay && !gapi->useVga)
1176 gapi->gxFunc.GXCloseDisplay();
1178 if (this->screen->pixels != NULL)
1180 SDL_free(this->screen->pixels);
1181 this->screen->pixels = NULL;
1184 DestroyIcon(screen_icn);
1188 DIB_DestroyWindow(this);
1189 SDL_UnregisterApp();
1192 #if defined(_WIN32_WCE)
1194 // Unload wince aygshell library to prevent leak
1197 FreeLibrary(aygshell);
1202 /* Free video mode lists */
1203 for ( i=0; i<NUM_MODELISTS; ++i ) {
1204 if ( gapi->SDL_modelist[i] != NULL ) {
1205 for ( j=0; gapi->SDL_modelist[i][j]; ++j )
1206 SDL_free(gapi->SDL_modelist[i][j]);
1207 SDL_free(gapi->SDL_modelist[i]);
1208 gapi->SDL_modelist[i] = NULL;
1216 static void GAPI_Activate(_THIS, BOOL active, BOOL minimized)
1218 //Nothing to do here (as far as I know)
1221 static void GAPI_RealizePalette(_THIS)
1223 OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
1226 static void GAPI_PaletteChanged(_THIS, HWND window)
1228 OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
1231 static void GAPI_WinPAINT(_THIS, HDC hdc)
1233 // draw current offscreen buffer on hdc
1235 int bpp = 16; // we always use either 8 or 16 bpp internally
1237 unsigned short *bitmapData;
1242 BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0};
1243 BITMAPINFO* pBMI = (BITMAPINFO*)buffer;
1244 BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader;
1245 DWORD* pColors = (DWORD*)&pBMI->bmiColors;
1247 // CreateDIBSection does not support 332 pixel format on wce
1248 if( gapi->gxProperties.cBPP == 8 ) return;
1251 pHeader->biSize = sizeof(BITMAPINFOHEADER);
1252 pHeader->biWidth = gapi->w;
1253 pHeader->biHeight = -gapi->h;
1254 pHeader->biPlanes = 1;
1255 pHeader->biBitCount = bpp;
1256 pHeader->biCompression = BI_RGB;
1257 pHeader->biSizeImage = (gapi->w * gapi->h * bpp) / 8;
1262 pColors[0] = REDMASK;
1263 pColors[1] = GREENMASK;
1264 pColors[2] = BLUEMASK;
1265 pHeader->biCompression = BI_BITFIELDS;
1268 hb = CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 );
1271 // FIXME: prevent misalignment, but I've never seen non aligned width of screen
1272 memcpy(bitmapData, gapi->buffer, pHeader->biSizeImage);
1273 srcDC = CreateCompatibleDC(hdc);
1274 prevObject = SelectObject(srcDC, hb);
1276 BitBlt(hdc, 0, 0, gapi->w, gapi->h, srcDC, 0, 0, SRCCOPY);
1278 SelectObject(srcDC, prevObject);
1283 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1285 GAPI_CreatePalette(ncolors, colors);