Mercurial > sdl-ios-xcode
view src/video/gapi/SDL_gapivideo.c @ 4157:baf615f9f2a0 SDL-1.2
Date: Thu, 16 Oct 2008 20:27:34 +0400
From: "Ilya Kasnacheev" <ilya.kasnacheev@gmail.com>
To: sdl@lists.libsdl.org
Subject: [SDL] SDL for Windows CE: a few GAPI patches
Hi *!
I've just ported a POWDER roguelike ( http://www.zincland.com/powder/ ) to
Windows CE (PDAs, Windows Mobile/Pocket PC). To do that, I had to get libsdl
working. Thanks for the awesome project files, it built without a hitch.
Nevertheless, I've found quite a few bugs in Windows CE (GAPI) SDL
implementation, which I've solved and now present as a serie of patches.
I'll try carefully annotate them. Please annotate them so I can work
toward accepting
them into the main source tree since without them SDL isn't really working on
Windows CE (I wonder why nobody fixed them before, btw: why isn't SDL popular as
a way to develop Windows CE games? Where are no ports?)
These changes can't be considered flawless, but they can be considered working
because I've yet to hear complains about things I fixed and POWDER build for
Windows CE is now considered stable.
Note: my comments start with !!, delete them before applying.
diff -bru SDL-1.2.13/src/video/gapi/SDL_gapivideo.c
SDL-1.2.13-new/src/video/gapi/SDL_gapivideo.c
--- SDL-1.2.13/src/video/gapi/SDL_gapivideo.c 2007-12-31
07:48:00.000000000 +0300
+++ SDL-1.2.13-new/src/video/gapi/SDL_gapivideo.c 2008-10-16
20:02:11.000000000 +0400
@@ -643,6 +643,7 @@
}
gapi->userOrientation = SDL_ORIENTATION_UP;
+ gapi->systemOrientation = SDL_ORIENTATION_UP;
video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports
fullscreen only */
/* GAPI or VGA? */
@@ -661,18 +662,21 @@
}
/* detect user landscape mode */
- if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) <
GetSystemMetrics(SM_CYSCREEN)))
+ if( (width > height) && (gapi->gxProperties.cxWidth <
gapi->gxProperties.cyHeight))
gapi->userOrientation = SDL_ORIENTATION_RIGHT;
+ if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN))
+ gapi->systemOrientation = SDL_ORIENTATION_RIGHT;
+
/* shall we apply hires fix? for example when we do not use
hires resource */
gapi->hiresFix = 0;
- if( gapi->userOrientation == SDL_ORIENTATION_RIGHT )
+ if( gapi->systemOrientation == gapi->userOrientation )
{
- if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height
> GetSystemMetrics(SM_CXSCREEN)))
+ if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height
> GetSystemMetrics(SM_CYSCREEN)))
gapi->hiresFix = 1;
} else
- if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height
> GetSystemMetrics(SM_CYSCREEN)))
- if( !((width == GetSystemMetrics(SM_CYSCREEN))
&& (height == GetSystemMetrics(SM_CXSCREEN)))) // user portrait,
device landscape
+ if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height
> GetSystemMetrics(SM_CXSCREEN)))
+// if( !((width == gapi->gxProperties.cyHeight)
&& (height == gapi->gxProperties.cxWidth))) // user portrait, device
landscape
gapi->hiresFix = 1;
switch( gapi->userOrientation )
!! It used to query system metrics which return dimensions according to screen
!! orientation, which can really be portrait, left landscape or right landscape.
!! This is presumably incorrect because we couldn't care less about user mode
!! dimensions - all we want are the GAPI framebuffer dimensions, which
only match
!! user dimensions in one of possible orientations.
!! There's a fair dose of cargo cult programming involved in this fix, but it
!! used to work only in one orientation (portrait for PDAs, where frame-buffer
!! have same orientation as user screen), and now it works on all orientations.
@@ -742,21 +746,30 @@
WIN_FlushMessageQueue();
/* Open GAPI display */
- if( !gapi->useVga && this->hidden->useGXOpenDisplay )
+ if( !gapi->useVga && this->hidden->useGXOpenDisplay &&
!this->hidden->alreadyGXOpened )
+ {
+ this->hidden->alreadyGXOpened = 1;
if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
{
SDL_SetError("Couldn't initialize GAPI");
return(NULL);
}
+ }
#if REPORT_VIDEO_INFO
printf("Video properties:\n");
printf("display bpp: %d\n", gapi->gxProperties.cBPP);
printf("display width: %d\n", gapi->gxProperties.cxWidth);
printf("display height: %d\n", gapi->gxProperties.cyHeight);
+ printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN));
+ printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN));
printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
+ printf("user orientation: %d\n", gapi->userOrientation);
+ printf("system orientation: %d\n", gapi->userOrientation);
+ printf("gapi orientation: %d\n", gapi->gapiOrientation);
+
if( !gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate)
{
!! Previous version used to call gapi->gxFunc.GXOpenDisplay each time the video
!! mode would be changed. You shouldn't, because this call has a
meaning "Lock the
!! GAPI framebuffer, designate it as busy", so the second call will fail (it is
!! already locked/busy).
!! Testing might not find that because most programs set up the video mode only
!! once, but POWDER does this once in a while, so it crashed when in
320x240 mode
!! (640x480 mode doesn't use that code, it worked fine).
diff -bru SDL-1.2.13/src/video/gapi/SDL_gapivideo.h
SDL-1.2.13-new/src/video/gapi/SDL_gapivideo.h
--- SDL-1.2.13/src/video/gapi/SDL_gapivideo.h 2007-12-31
07:48:00.000000000 +0300
+++ SDL-1.2.13-new/src/video/gapi/SDL_gapivideo.h 2008-10-16
20:02:11.000000000 +0400
@@ -132,12 +132,17 @@
#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
+ // The orientation of the video mode user wants to get
+ // Probably restricted to UP and RIGHT
enum SDL_ScreenOrientation userOrientation;
int invert;
char hiresFix; // using hires mode without defining hires resource
// --------------
int useGXOpenDisplay; /* use GXOpenDispplay */
+ int alreadyGXOpened;
int w, h;
+ // The orientation of GAPI framebuffer.
+ // Never changes on the same device.
enum SDL_ScreenOrientation gapiOrientation;
void *buffer; // may be 8, 16, 24, 32 bpp
@@ -153,6 +158,10 @@
int startOffset; // in bytes
int useVga;
int suspended; // do not pu anything into video memory
+ // The orientation of the system, as defined by SM_CXSCREEN
and SM_CYSCREEN
+ // User can change it by using 'screen layout' in system options
+ // Restricted to UP or RIGHT
+ enum SDL_ScreenOrientation systemOrientation;
};
!! This is a flag variable, see the previous comment
!! And yet another orientation: now we have to keep three of them in mind.
diff -bru SDL-1.2.13/src/video/wincommon/SDL_sysevents.c
SDL-1.2.13-new/src/video/wincommon/SDL_sysevents.c
--- SDL-1.2.13/src/video/wincommon/SDL_sysevents.c 2007-12-31
07:48:02.000000000 +0300
+++ SDL-1.2.13-new/src/video/wincommon/SDL_sysevents.c 2008-10-16
20:02:12.000000000 +0400
@@ -160,10 +160,22 @@
#endif */
}
break;
+ // FIXME: Older version used just SDL_VideoSurface->(w, h)
+ // w and h are "clipped" while x and y are "raw", which caused
+ // x in former and y in latter case to be clipped in a
wrong direction,
+ // thus offsetting the coordinate on 2 x clip pixels
+ // (like, 128 for 640 -> 512 clipping).
+ // We will now try to extract and use raw values.
+ // The way to do that RIGHT is do
(orientation-dependent) clipping before
+ // doing this transform, but it's hardly possible.
+
+ // SEE SDL_mouse.c /ClipOffset to understand these calculations.
case SDL_ORIENTATION_RIGHT:
if (!SDL_VideoSurface)
break;
- rotatedX = SDL_VideoSurface->w - *y;
+ rotatedX = (2 *
((SDL_VideoSurface->offset%SDL_VideoSurface->pitch)/
+ SDL_VideoSurface->format->BytesPerPixel))
+ + SDL_VideoSurface->w - *y;
rotatedY = *x;
*x = rotatedX;
*y = rotatedY;
@@ -172,7 +184,8 @@
if (!SDL_VideoSurface)
break;
rotatedX = *y;
- rotatedY = SDL_VideoSurface->h - *x;
+ rotatedY = (2 *
(SDL_VideoSurface->offset/SDL_VideoSurface->pitch))
+ + SDL_VideoSurface->h - *x;
*x = rotatedX;
*y = rotatedY;
break;
!! That's the trickest part, hence the long comment.
!! GAPI would really support only 320x240 or 640x480 mode, if application
!! requested the different screen size (as POWDER did, wishing
256x192), then SDL
!! is going to grab the first mode that fits the requested, and pad the screen
!! with black bars (as they do with wide-screen films).
!! It would also get, say, 240x320 mode, and to turn it into 256x192 it would
!! need to rotate mouse clicks.
!! It worked, but one bug slipped through: it would receive mouse clicks
!! unpadded, then rotate them, and then pad the black bars. The
problem is: rotate
!! is done by GAPI driver while padding is done by SDL core. SDL core
doesn't know
!! anything about rotating, so it would pad one of dimensions incorrectly.
I understand that some of my claims (or code) might seem unbacked, but you can
always grab the POWDER binary, compile your own libsdl with one or more of
those fixes turned off, and see how weird it would misbehave. I can even supply
you with those custom builds of libsdl if you don't want to set up the build
environment for windows ce, you'll just need a PDA or a smartphone with it.
I plan to take care of SDL on Windows CE as long as I maintain the POWDER port.
POWDER is good for that because it:
Employs both padded (with centered image, black bars) and unpadded
(image occupies full screen) graphics; initializes video more than
once; uses both 320x240 and 640x480 video; uses both stylus and
buttons.
There's still a list of unresolved issues which I'm planning to fix:
1) Arrow buttons on PDA return weird scancodes compared to PC, this
caused the game to misbehave before I've fixed that. You can see it on
those diagrams:
http://wrar.name/upload/powder-htc.png
http://wrar.name/upload/powder-pda.png
2) SDL (or underlying windows) doesn't care to rotate arrow presses
when we're in a low-res GAPI mode, but it will rotate them in VGA mode
(because of different screen orientations, the same arrow buttons can
suddently mean different directions). Solution: we should stick to
GAPI user orientation (the orientation the program supposedly wants)
and rotate the keys on our own.
_______________________________________________
SDL mailing list
SDL@lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 07 Nov 2008 04:15:36 +0000 |
parents | 31c7c57af8a4 |
children | a1b03ba2fcd0 |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" /* Pocket PC GAPI SDL video driver implementation; Implemented by Dmitry Yakimov - support@activekitten.com Inspired by http://arisme.free.fr/ports/SDL.php */ // TODO: copy surface on window when lost focus // TODO: test buttons rotation // TODO: test on be300 and HPC ( check WinDib fullscreen keys catching ) // TODO: test on smartphones // TODO: windib on SH3 PPC2000 landscape test // TODO: optimize 8bpp landscape mode // there is some problems in runnings apps from a device landscape mode // due to WinCE bugs. Some works and some - does not. // TODO: finish Axim Dell X30 and user landscape mode, device landscape mode // TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion // TODO: fix running GAPI apps from landscape mode - // wince goes to portrait mode, but does not update video memory #include "SDL.h" #include "SDL_error.h" #include "SDL_video.h" #include "SDL_mouse.h" #include "../SDL_sysvideo.h" #include "../SDL_pixels_c.h" #include "../../events/SDL_events_c.h" #include "../wincommon/SDL_syswm_c.h" #include "../wincommon/SDL_sysmouse_c.h" #include "../windib/SDL_dibevents_c.h" #include "SDL_gapivideo.h" #define GAPIVID_DRIVER_NAME "gapi" #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG) #define REPORT_VIDEO_INFO 1 #else #define REPORT_VIDEO_INFO 0 #endif // for testing with GapiEmu #define USE_GAPI_EMU 0 #define EMULATE_AXIM_X30 0 #define WITHOUT_GAPI 0 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") #endif #ifndef _T #define _T(x) L##x #endif #ifndef ASSERT #define ASSERT(x) #endif // defined and used in SDL_sysevents.c extern HINSTANCE aygshell; extern void SDL_UnregisterApp(); extern int DIB_AddMode(_THIS, int bpp, int w, int h); /* Initialization/Query functions */ static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); static void GAPI_VideoQuit(_THIS); /* Hardware surface functions */ static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); /* Windows message handling functions, will not be processed */ static void GAPI_RealizePalette(_THIS); static void GAPI_PaletteChanged(_THIS, HWND window); static void GAPI_WinPAINT(_THIS, HDC hdc); /* etc. */ static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); static HMODULE g_hGapiLib = 0; #define LINK(type,name,import) \ if( g_hGapiLib ) \ name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); static char g_bRawBufferAvailable = 0; /* GAPI driver bootstrap functions */ /* hi res definitions */ typedef struct _RawFrameBufferInfo { WORD wFormat; WORD wBPP; VOID *pFramePointer; int cxStride; int cyStride; int cxPixels; int cyPixels; } RawFrameBufferInfo; static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0}; #define GETRAWFRAMEBUFFER 0x00020001 #define FORMAT_565 1 #define FORMAT_555 2 #define FORMAT_OTHER 3 /* Dell Axim x30 hangs when we use GAPI from landscape, so lets avoid using GxOpenDisplay there via GETGXINFO trick It seems that GAPI subsystem use the same ExtEscape code. */ #define GETGXINFO 0x00020000 typedef struct GXDeviceInfo { long Version; //00 (should filled with 100 before calling ExtEscape) void * pvFrameBuffer; //04 unsigned long cbStride; //08 unsigned long cxWidth; //0c unsigned long cyHeight; //10 unsigned long cBPP; //14 unsigned long ffFormat; //18 char Unused[0x84-7*4]; } GXDeviceInfo; static int GAPI_Available(void) { // try to use VGA display, even on emulator HDC hdc = GetDC(NULL); int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo); ReleaseDC(NULL, hdc); g_bRawBufferAvailable = result > 0; #if WITHOUT_GAPI return g_bRawBufferAvailable; #endif #if USE_GAPI_EMU g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll")); if( !g_hGapiLib ) { SDL_SetError("Gapi Emu not found!"); } return g_hGapiLib != 0; #endif // try to find gx.dll g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll")); if( !g_hGapiLib ) { g_hGapiLib = LoadLibrary(_T("gx.dll")); if( !g_hGapiLib ) return g_bRawBufferAvailable; } return(1); } static int cmpmodes(const void *va, const void *vb) { SDL_Rect *a = *(SDL_Rect **)va; SDL_Rect *b = *(SDL_Rect **)vb; if ( a->w == b->w ) return b->h - a->h; else return b->w - a->w; } static int GAPI_AddMode(_THIS, int bpp, int w, int h) { SDL_Rect *mode; int i, index; int next_mode; /* Check to see if we already have this mode */ if ( bpp < 8 ) { /* Not supported */ return(0); } index = ((bpp+7)/8)-1; for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) { mode = gapi->SDL_modelist[index][i]; if ( (mode->w == w) && (mode->h == h) ) { return(0); } } /* Set up the new video mode rectangle */ mode = (SDL_Rect *)SDL_malloc(sizeof *mode); if ( mode == NULL ) { SDL_OutOfMemory(); return(-1); } mode->x = 0; mode->y = 0; mode->w = w; mode->h = h; /* Allocate the new list of modes, and fill in the new mode */ next_mode = gapi->SDL_nummodes[index]; gapi->SDL_modelist[index] = (SDL_Rect **) SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); if ( gapi->SDL_modelist[index] == NULL ) { SDL_OutOfMemory(); gapi->SDL_nummodes[index] = 0; SDL_free(mode); return(-1); } gapi->SDL_modelist[index][next_mode] = mode; gapi->SDL_modelist[index][next_mode+1] = NULL; gapi->SDL_nummodes[index]++; return(0); } static void GAPI_DeleteDevice(SDL_VideoDevice *device) { if( g_hGapiLib ) { FreeLibrary(g_hGapiLib); g_hGapiLib = 0; } SDL_free(device->hidden); SDL_free(device); } static SDL_VideoDevice *GAPI_CreateDevice(int devindex) { SDL_VideoDevice *device; if( !g_hGapiLib && !g_bRawBufferAvailable) { if( !GAPI_Available() ) { SDL_SetError("GAPI dll is not found and VGA mode is not available!"); return 0; } } /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); if ( device ) { SDL_memset(device, 0, (sizeof *device)); device->hidden = (struct SDL_PrivateVideoData *) SDL_malloc((sizeof *device->hidden)); } if ( (device == NULL) || (device->hidden == NULL) ) { SDL_OutOfMemory(); if ( device ) { SDL_free(device); } return(0); } SDL_memset(device->hidden, 0, (sizeof *device->hidden)); /* Set the function pointers */ device->VideoInit = GAPI_VideoInit; device->ListModes = GAPI_ListModes; device->SetVideoMode = GAPI_SetVideoMode; device->UpdateMouse = WIN_UpdateMouse; device->CreateYUVOverlay = NULL; device->SetColors = GAPI_SetColors; device->UpdateRects = GAPI_UpdateRects; device->VideoQuit = GAPI_VideoQuit; device->AllocHWSurface = GAPI_AllocHWSurface; device->CheckHWBlit = NULL; device->FillHWRect = NULL; device->SetHWColorKey = NULL; device->SetHWAlpha = NULL; device->LockHWSurface = GAPI_LockHWSurface; device->UnlockHWSurface = GAPI_UnlockHWSurface; device->FlipHWSurface = NULL; device->FreeHWSurface = GAPI_FreeHWSurface; device->SetCaption = WIN_SetWMCaption; device->SetIcon = WIN_SetWMIcon; device->IconifyWindow = WIN_IconifyWindow; device->GrabInput = WIN_GrabInput; device->GetWMInfo = WIN_GetWMInfo; device->FreeWMCursor = WIN_FreeWMCursor; device->CreateWMCursor = WIN_CreateWMCursor; device->ShowWMCursor = WIN_ShowWMCursor; device->WarpWMCursor = WIN_WarpWMCursor; device->CheckMouseMode = WIN_CheckMouseMode; device->InitOSKeymap = DIB_InitOSKeymap; device->PumpEvents = DIB_PumpEvents; /* Set up the windows message handling functions */ WIN_RealizePalette = GAPI_RealizePalette; WIN_PaletteChanged = GAPI_PaletteChanged; WIN_WinPAINT = GAPI_WinPAINT; HandleMessage = DIB_HandleMessage; device->free = GAPI_DeleteDevice; /* Load gapi library */ #define gx device->hidden->gxFunc LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" ) LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" ) LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" ) LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" ) LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" ) LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" ) LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" ) LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" ) LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" ) LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" ) LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" ) LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" ) /* wrong gapi.dll */ if( !gx.GXOpenDisplay ) { if( g_hGapiLib ) { FreeLibrary(g_hGapiLib); g_hGapiLib = 0; } } if( !gx.GXOpenDisplay && !g_bRawBufferAvailable) { SDL_SetError("Error: damaged or unknown gapi.dll!\n"); GAPI_DeleteDevice(device); return 0; } return device; } VideoBootStrap GAPI_bootstrap = { GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", GAPI_Available, GAPI_CreateDevice }; static void FillStructs(_THIS, BOOL useVga) { #ifdef _ARM_ WCHAR oemstr[100]; #endif /* fill a device properties */ if( !useVga ) { this->hidden->gxProperties = this->hidden->gxFunc.GXGetDisplayProperties(); this->hidden->needUpdate = 1; this->hidden->hiresFix = 0; this->hidden->useVga = 0; this->hidden->useGXOpenDisplay = 1; #ifdef _ARM_ /* check some devices and extract addition info */ SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 ); // buggy iPaq38xx if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (this->hidden->gxProperties.cbxPitch > 0)) { this->hidden->videoMem = (PIXEL*)0xac0755a0; this->hidden->gxProperties.cbxPitch = -640; this->hidden->gxProperties.cbyPitch = 2; this->hidden->needUpdate = 0; } #if (EMULATE_AXIM_X30 == 0) // buggy Dell Axim X30 if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 ) #endif { GXDeviceInfo gxInfo = {0}; HDC hdc = GetDC(NULL); int result; gxInfo.Version = 100; result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo); if( result > 0 ) { this->hidden->useGXOpenDisplay = 0; this->hidden->videoMem = gxInfo.pvFrameBuffer; this->hidden->needUpdate = 0; this->hidden->gxProperties.cbxPitch = 2; this->hidden->gxProperties.cbyPitch = 480; this->hidden->gxProperties.cxWidth = gxInfo.cxWidth; this->hidden->gxProperties.cyHeight = gxInfo.cyHeight; this->hidden->gxProperties.ffFormat = gxInfo.ffFormat; } } #endif } else { this->hidden->needUpdate = 0; this->hidden->hiresFix = 0; this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP; this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride; this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride; this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels; this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels; this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer; this->hidden->useVga = 1; switch( g_RawFrameBufferInfo.wFormat ) { case FORMAT_565: this->hidden->gxProperties.ffFormat = kfDirect565; break; case FORMAT_555: this->hidden->gxProperties.ffFormat = kfDirect555; break; default: /* unknown pixel format, try define by BPP! */ switch( g_RawFrameBufferInfo.wBPP ) { case 4: case 8: this->hidden->gxProperties.ffFormat = kfDirect; case 16: this->hidden->gxProperties.ffFormat = kfDirect565; default: this->hidden->gxProperties.ffFormat = kfDirect; break; } } } if( this->hidden->gxProperties.cBPP != 16 ) { this->hidden->gapiOrientation = SDL_ORIENTATION_UP; } else if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch > 0 )) { this->hidden->gapiOrientation = SDL_ORIENTATION_UP; } else if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch < 0 )) { this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660 } else if( (this->hidden->gxProperties.cbxPitch < 0) && (this->hidden->gxProperties.cbyPitch > 0 )) { this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800 } } static void GAPI_CreatePalette(int ncolors, SDL_Color *colors) { // Setup a custom color palette BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ]; int i; LOGPALETTE* pLogical = (LOGPALETTE*)buffer; PALETTEENTRY* entries = pLogical->palPalEntry; HPALETTE hPalette; HDC hdc; for (i = 0; i < ncolors; ++i) { // Find intensity by replicating the bit patterns over a byte entries[i].peRed = colors[i].r; entries[i].peGreen = colors[i].g; entries[i].peBlue = colors[i].b; entries[i].peFlags = 0; } // Create the GDI palette object pLogical->palVersion = 0x0300; pLogical->palNumEntries = ncolors; hPalette = CreatePalette( pLogical ); ASSERT(hPalette); // Realize the palette hdc = GetDC(0); SelectPalette( hdc, hPalette, FALSE ); RealizePalette( hdc ); ReleaseDC( 0, hdc ); DeleteObject( hPalette ); } int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat) { int i,bpp; /* Create the window */ if ( DIB_CreateWindow(this) < 0 ) { return(-1); } if( g_hGapiLib ) { FillStructs(this, 0); // SDL does not supports 2/4bpp mode, so use 16 bpp bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; /* set up normal and landscape mode */ GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); } /* add hi-res mode */ if( g_bRawBufferAvailable && !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels))) { FillStructs(this, 1); // SDL does not supports 2/4bpp mode, so use 16 bpp bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; /* set up normal and landscape mode */ GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); } /* Determine the current screen size */ this->info.current_w = gapi->gxProperties.cxWidth; this->info.current_h = gapi->gxProperties.cyHeight; /* Sort the mode lists */ for ( i=0; i<NUM_MODELISTS; ++i ) { if ( gapi->SDL_nummodes[i] > 0 ) { SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes); } } vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP; // Get color mask if (this->hidden->gxProperties.ffFormat & kfDirect565) { vformat->BitsPerPixel = 16; vformat->Rmask = 0x0000f800; vformat->Gmask = 0x000007e0; vformat->Bmask = 0x0000001f; this->hidden->videoMode = GAPI_DIRECT_565; } else if (this->hidden->gxProperties.ffFormat & kfDirect555) { vformat->BitsPerPixel = 16; vformat->Rmask = 0x00007c00; vformat->Gmask = 0x000003e0; vformat->Bmask = 0x0000001f; this->hidden->videoMode = GAPI_DIRECT_555; } else if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) { // We'll perform the conversion vformat->BitsPerPixel = 16; vformat->Rmask = 0x0000f800; // 16 bit 565 vformat->Gmask = 0x000007e0; vformat->Bmask = 0x0000001f; if (this->hidden->gxProperties.ffFormat & kfDirectInverted) this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1; this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0; this->hidden->videoMode = GAPI_MONO; } else if (this->hidden->gxProperties.ffFormat & kfPalette) { this->hidden->videoMode = GAPI_PALETTE; } /* We're done! */ return(0); } SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) { return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]); // return (SDL_Rect **) -1; } SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { SDL_Surface *video; Uint32 Rmask, Gmask, Bmask; DWORD style; SDL_Rect allScreen; if( bpp < 4 ) { SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!"); return 0; } /* Recalculate bitmasks if necessary */ if (bpp == current->format->BitsPerPixel) { video = current; } else { switch(bpp) { case 8: Rmask = 0; Gmask = 0; Bmask = 0; break; case 15: case 16: /* Default is 565 unless the display is specifically 555 */ if (this->hidden->gxProperties.ffFormat & kfDirect555) { Rmask = 0x00007c00; Gmask = 0x000003e0; Bmask = 0x0000001f; } else { Rmask = 0x0000f800; Gmask = 0x000007e0; Bmask = 0x0000001f; } break; case 24: case 32: Rmask = 0x00ff0000; Gmask = 0x0000ff00; Bmask = 0x000000ff; break; default: SDL_SetError("Unsupported Bits Per Pixel format requested"); return NULL; } video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp, Rmask, Gmask, Bmask, 0); if ( video == NULL ) { SDL_OutOfMemory(); return(NULL); } } gapi->userOrientation = SDL_ORIENTATION_UP; gapi->systemOrientation = SDL_ORIENTATION_UP; video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */ /* GAPI or VGA? */ if( g_hGapiLib ) { FillStructs(this, 0); if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight)) && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth))) FillStructs(this, 1); // gapi is found but we use VGA resolution } else FillStructs(this, 1); if ( !this->hidden->needUpdate && !this->hidden->videoMem) { SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug"); return(NULL); } /* detect user landscape mode */ if( (width > height) && (gapi->gxProperties.cxWidth < gapi->gxProperties.cyHeight)) gapi->userOrientation = SDL_ORIENTATION_RIGHT; if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN)) gapi->systemOrientation = SDL_ORIENTATION_RIGHT; /* shall we apply hires fix? for example when we do not use hires resource */ gapi->hiresFix = 0; if( gapi->systemOrientation == gapi->userOrientation ) { if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN))) gapi->hiresFix = 1; } else if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN))) // if( !((width == gapi->gxProperties.cyHeight) && (height == gapi->gxProperties.cxWidth))) // user portrait, device landscape gapi->hiresFix = 1; switch( gapi->userOrientation ) { case SDL_ORIENTATION_UP: gapi->startOffset = 0; gapi->dstLineStep = gapi->gxProperties.cbyPitch; gapi->dstPixelStep = gapi->gxProperties.cbxPitch; break; case SDL_ORIENTATION_RIGHT: switch( gapi->gapiOrientation ) { case SDL_ORIENTATION_UP: case SDL_ORIENTATION_RIGHT: case SDL_ORIENTATION_LEFT: if( (this->hidden->videoMode == GAPI_MONO) ) gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode else gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1); gapi->dstLineStep = gapi->gxProperties.cbxPitch; gapi->dstPixelStep = -gapi->gxProperties.cbyPitch; break; } } video->w = this->hidden->w = width; video->h = this->hidden->h = height; video->pitch = SDL_CalculatePitch(video); /* Small fix for WinCE/Win32 - when activating window SDL_VideoSurface is equal to zero, so activating code is not called properly for fullscreen windows because macros WINDIB_FULLSCREEN uses SDL_VideoSurface */ SDL_VideoSurface = video; /* GAPI is always fullscreen, title bar is useless */ style = 0; if (!SDL_windowid) SetWindowLong(SDL_Window, GWL_STYLE, style); /* Allocate bitmap */ if(gapiBuffer) { SDL_free(gapiBuffer); gapiBuffer = NULL; } gapiBuffer = SDL_malloc(video->h * video->pitch); video->pixels = gapiBuffer; if ( ! this->hidden->buffer ) { SDL_SetError("Couldn't allocate buffer for requested mode"); return(NULL); } SDL_memset(gapiBuffer, 255, video->h * video->pitch); MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE); ShowWindow(SDL_Window, SW_SHOW); SetForegroundWindow(SDL_Window); /* JC 14 Mar 2006 Flush the message loop or this can cause big problems later Especially if the user decides to use dialog boxes or assert()! */ WIN_FlushMessageQueue(); /* Open GAPI display */ if( !gapi->useVga && this->hidden->useGXOpenDisplay && !this->hidden->alreadyGXOpened ) { this->hidden->alreadyGXOpened = 1; if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) ) { SDL_SetError("Couldn't initialize GAPI"); return(NULL); } } #if REPORT_VIDEO_INFO printf("Video properties:\n"); printf("display bpp: %d\n", gapi->gxProperties.cBPP); printf("display width: %d\n", gapi->gxProperties.cxWidth); printf("display height: %d\n", gapi->gxProperties.cyHeight); printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN)); printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN)); printf("x pitch: %d\n", gapi->gxProperties.cbxPitch); printf("y pitch: %d\n", gapi->gxProperties.cbyPitch); printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat); printf("user orientation: %d\n", gapi->userOrientation); printf("system orientation: %d\n", gapi->userOrientation); printf("gapi orientation: %d\n", gapi->gapiOrientation); if( !gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate) { gapi->videoMem = gapi->gxFunc.GXBeginDraw(); gapi->gxFunc.GXEndDraw(); } printf("video memory: 0x%x\n", gapi->videoMem); printf("need update: %d\n", gapi->needUpdate); printf("hi-res fix: %d\n", gapi->hiresFix); printf("VGA is available on the device: %d\n", g_bRawBufferAvailable); printf("use raw framebuffer: %d\n", gapi->useVga); printf("video surface bpp: %d\n", video->format->BitsPerPixel); printf("video surface width: %d\n", video->w); printf("video surface height: %d\n", video->h); #endif /* Blank screen */ allScreen.x = allScreen.y = 0; allScreen.w = video->w - 1; allScreen.h = video->h - 1; GAPI_UpdateRects(this, 1, &allScreen); /* We're done */ return(video); } /* We don't actually allow hardware surfaces other than the main one */ static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) { return(-1); } static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) { return; } /* We need to wait for vertical retrace on page flipped displays */ static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) { return(0); } static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) { return; } static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines) { if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */ { SDL_memcpy(destPointer, srcPointer, width); return 1; } else { // TODO: read 4 pixels, write DWORD int step = gapi->dstPixelStep; while(width--) { *destPointer = *srcPointer++; destPointer += step; } } return 1; } /* Video memory is very slow so lets optimize as much as possible */ static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines) { PIXEL *line1, *line2; int step = gapi->dstPixelStep / 2; if( step == 1 ) /* optimized blitting on most devices */ { SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL)); return 1; } else { if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) && (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up { // to prevent data misalignment copy only one line if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT)) || (lines == 1) ) { while(width--) { *destPointer = *srcPointer++; destPointer += step; } return 1; } /* read two lines at the same time, write DWORD */ line1 = srcPointer; line2 = srcPointer + SDL_VideoSurface->pitch / 2; if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) while(width--) // iPaq 3800 { *(DWORD*)destPointer =(*line2++ << 16) | *line1++; destPointer += step; } else { destPointer += gapi->gxProperties.cbyPitch / 2; while(width--) // iPaq 3660 { *(DWORD*)destPointer =(*line1++ << 16) | *line2++; destPointer += step; } } return 2; } else { // iPaq 3800 and user orientation landscape if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) { int w1; // to prevent data misalignment copy only one pixel if( (((unsigned)destPointer & 3) == 0) && (width > 0)) { *destPointer-- = *srcPointer++; width--; } destPointer--; w1 = width / 2; while(w1--) { DWORD p = *(DWORD*)srcPointer; *((DWORD*)destPointer) = (p << 16) | (p >> 16); destPointer -= 2; srcPointer += 2; } if( width & 1 ) // copy the last pixel { destPointer++; *destPointer = *srcPointer; } return 1; } // modern iPaqs and user orientation landscape // read two pixels, write DWORD line1 = srcPointer; line2 = srcPointer + SDL_VideoSurface->pitch / 2; if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) { while(width--) { *destPointer = *srcPointer++; destPointer += step; } return 1; } while(width--) { *(DWORD*)destPointer =(*line2++ << 16) | *line1++; destPointer -= gapi->gxProperties.cbyPitch / 2; } return 2; } } } // Color component masks for 565 #define REDMASK (31<<11) #define GREENMASK (63<<5) #define BLUEMASK (31) static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble) { PIXEL *line1, *line2; int step = gapi->dstPixelStep; if( gapi->userOrientation == SDL_ORIENTATION_UP ) { if( yNibble ) // copy bottom half of a line { while(width--) { PIXEL c1 = *srcPointer++; c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); destPointer += step; } return 1; } // either 1 pixel picture or tail, anyway this is the last line if( lines == 1 ) { while(width--) { PIXEL c1 = *srcPointer++; c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); destPointer += step; } return 1; } line1 = srcPointer; line2 = srcPointer + SDL_VideoSurface->pitch / 2; while(width--) { PIXEL c1 = *line1++; PIXEL c2 = *line2++; c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4)); destPointer += step; } return 2; } else { int w1; w1 = width / 2; if( xNibble ) { // copy one pixel PIXEL c1 = *srcPointer++; c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); destPointer++; } while(w1--) { PIXEL c1 = *srcPointer; PIXEL c2 = *(srcPointer + 1); c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4)); srcPointer += 2; } // copy tail if( (width & 1) && !xNibble ) { PIXEL c1 = *srcPointer; c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); } return 1; } } static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects) { int i, height; int linesProcessed; int xNibble, yNibble; for (i=0; i<numrects; i++) { unsigned char *destPointer; unsigned char *srcPointer; if( gapi->userOrientation == SDL_ORIENTATION_UP ) destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep; else destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep; srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2; yNibble = rects[i].y & 1; // TODO: only for 4 bpp xNibble = rects[i].x & 1; height = rects[i].h; while (height > 0) { switch(gapi->gxProperties.cBPP) { case 2: // TODO case 4: linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble); yNibble = 0; } height -= linesProcessed; if( gapi->userOrientation == SDL_ORIENTATION_UP ) destPointer--; // always fill 1 byte else destPointer += gapi->dstLineStep; srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes } } } static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects) { int i, height; int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8; int linesProcessed; for (i=0; i<numrects; i++) { unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep; unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel; height = rects[i].h; // 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); // fflush(stderr); linesProcessed = height; while (height > 0) { switch(bytesPerPixel) { case 1: linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height); break; case 2: #pragma warning(disable: 4133) linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height); break; } height -= linesProcessed; destPointer += gapi->dstLineStep * linesProcessed; srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes } // fprintf(stderr, "End of rect\n"); // fflush(stderr); } } static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects) { // we do not want to corrupt video memory if( gapi->suspended ) return; if( gapi->needUpdate ) gapi->videoMem = gapi->gxFunc.GXBeginDraw(); if( gapi->gxProperties.cBPP < 8 ) GAPI_UpdateRectsMono(this, numrects, rects); else GAPI_UpdateRectsColor(this, numrects, rects); if( gapi->needUpdate ) gapi->gxFunc.GXEndDraw(); } /* Note: If we are terminated, this could be called in the middle of another SDL video routine -- notably UpdateRects. */ void GAPI_VideoQuit(_THIS) { int i, j; /* Destroy the window and everything associated with it */ if ( SDL_Window ) { if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga) this->hidden->gxFunc.GXCloseDisplay(); if (this->screen->pixels != NULL) { SDL_free(this->screen->pixels); this->screen->pixels = NULL; } if ( screen_icn ) { DestroyIcon(screen_icn); screen_icn = NULL; } DIB_DestroyWindow(this); SDL_UnregisterApp(); SDL_Window = NULL; #if defined(_WIN32_WCE) // Unload wince aygshell library to prevent leak if( aygshell ) { FreeLibrary(aygshell); aygshell = NULL; } #endif /* Free video mode lists */ for ( i=0; i<NUM_MODELISTS; ++i ) { if ( gapi->SDL_modelist[i] != NULL ) { for ( j=0; gapi->SDL_modelist[i][j]; ++j ) SDL_free(gapi->SDL_modelist[i][j]); SDL_free(gapi->SDL_modelist[i]); gapi->SDL_modelist[i] = NULL; } } } } static void GAPI_RealizePalette(_THIS) { OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); } static void GAPI_PaletteChanged(_THIS, HWND window) { OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); } static void GAPI_WinPAINT(_THIS, HDC hdc) { // draw current offscreen buffer on hdc int bpp = 16; // we always use either 8 or 16 bpp internally HGDIOBJ prevObject; unsigned short *bitmapData; HBITMAP hb; HDC srcDC; // Create a DIB BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0}; BITMAPINFO* pBMI = (BITMAPINFO*)buffer; BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader; DWORD* pColors = (DWORD*)&pBMI->bmiColors; // CreateDIBSection does not support 332 pixel format on wce if( gapi->gxProperties.cBPP == 8 ) return; // DIB Header pHeader->biSize = sizeof(BITMAPINFOHEADER); pHeader->biWidth = this->hidden->w; pHeader->biHeight = -this->hidden->h; pHeader->biPlanes = 1; pHeader->biBitCount = bpp; pHeader->biCompression = BI_RGB; pHeader->biSizeImage = (this->hidden->w * this->hidden->h * bpp) / 8; // Color masks if( bpp == 16 ) { pColors[0] = REDMASK; pColors[1] = GREENMASK; pColors[2] = BLUEMASK; pHeader->biCompression = BI_BITFIELDS; } // Create the DIB hb = CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 ); // copy data // FIXME: prevent misalignment, but I've never seen non aligned width of screen memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage); srcDC = CreateCompatibleDC(hdc); prevObject = SelectObject(srcDC, hb); BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY); SelectObject(srcDC, prevObject); DeleteObject(hb); DeleteDC(srcDC); } int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) { GAPI_CreatePalette(ncolors, colors); return 1; }