📄 sdl_gapivideo.c
字号:
/* 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.comInspired 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// defined and used in SDL_sysevents.cextern 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 0x00020000typedef struct GXDeviceInfo{long Version; //00 (should filled with 100 before calling ExtEscape)void * pvFrameBuffer; //04unsigned long cbStride; //08unsigned long cxWidth; //0cunsigned long cyHeight; //10unsigned long cBPP; //14unsigned long ffFormat; //18char 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -