From 595584c457def09450869c43185aa42ecabad25a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 27 Jul 2010 21:31:28 -0700 Subject: [PATCH] Andrey A. I made a video driver GAPI/RAW for WinCE (SDL-1.3). RAW mode has a priority, and also, GAPI mode works with environment "SDL_VIDEO_RENDERER=gapi" and for RAW mode "SDL_VIDEO_RENDERER=raw". I checked the work on the screens of VGA, WVGA, QVGA, WQVGA, HVGA, + tested all modes with WindowsMobile Emulator. Also, correctly draws the pointer position and the scale of the pointer for VGA/WVGA modes, correctly draws top left position for DM orientation screen, and portrait/landscape/square geometry the screen also correct. Also, I added a small fix for GDI fullscreen mode. Patch for latest revision SDL-1.3 in an attachment. Also added small path for mingw32ce build. --- configure.in | 22 +- src/video/SDL_sysvideo.h | 3 - src/video/SDL_video.c | 3 - src/video/win32/SDL_ceddrawrender.c | 2 + src/video/win32/SDL_d3drender.c | 2 + src/video/win32/SDL_gapirender.c | 1631 ++++++++++++++++++-------- src/video/win32/SDL_gapirender.h | 6 +- src/video/win32/SDL_gapirender_c.h | 97 -- src/video/win32/SDL_gdirender.c | 31 + src/video/win32/SDL_win32clipboard.c | 8 + src/video/win32/SDL_win32events.c | 16 + src/video/win32/SDL_win32modes.c | 8 + src/video/win32/SDL_win32video.c | 23 +- src/video/win32/SDL_win32video.h | 14 + src/video/win32/SDL_win32window.c | 89 +- src/video/win32/SDL_win32window.h | 9 + 16 files changed, 1275 insertions(+), 689 deletions(-) diff --git a/configure.in b/configure.in index 59df10bca..dd4778992 100644 --- a/configure.in +++ b/configure.in @@ -1917,7 +1917,7 @@ CheckWIN32() AC_MSG_CHECKING(Windows CE) have_wince=no AC_TRY_COMPILE([ -#ifndef _WIN32_WCE +#if !defined(_WIN32_WCE) && !defined(__MINGW32CE__) #error This is not Windows CE #endif ],[ @@ -2388,6 +2388,12 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau SOURCES="$SOURCES $srcdir/src/atomic/win32/*.c" have_atomic=yes fi + # Set up dummy files for the joystick for now + if test x$enable_joystick = xyes; then + AC_DEFINE(SDL_JOYSTICK_DUMMY) + SOURCES="$SOURCES $srcdir/src/joystick/dummy/*.c" + have_joystick=yes + fi # Set up files for the thread library if test x$enable_threads = xyes; then AC_DEFINE(SDL_THREAD_WIN32) @@ -2411,10 +2417,20 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau fi # Set up the system libraries we need EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lcoredll -lcommctrl -lmmtimer" + + # mingw32ce library + case "$host" in + *-mingw32ce) + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmingwex" + ;; + *) + ;; + esac + # The Win32 platform requires special setup SDLMAIN_SOURCES="$srcdir/src/main/win32/*.c" - SDL_CFLAGS="$SDL_CFLAGS -Dmain=SDL_main -D_WIN32_WCE=0x420" - SDL_LIBS="-lSDLmain $SDL_LIBS" + EXTRA_CFLAGS="$EXTRA_CFLAGS -Dmain=SDL_main -D_WIN32_WCE=0x420" + EXTRA_LDFLAGS="-lSDLmain $EXTRA_LDFLAGS" ;; *-*-cygwin* | *-*-mingw32*) ARCH=win32 diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 91b2177cb..6f9ef8355 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -387,9 +387,6 @@ extern VideoBootStrap PS3_bootstrap; #if SDL_VIDEO_DRIVER_SVGALIB extern VideoBootStrap SVGALIB_bootstrap; #endif -#if SDL_VIDEO_DRIVER_GAPI -extern VideoBootStrap GAPI_bootstrap; -#endif #if SDL_VIDEO_DRIVER_WIN32 extern VideoBootStrap WIN32_bootstrap; #endif diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 1673d0e0a..2ac28dbc2 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -67,9 +67,6 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_SVGALIB &SVGALIB_bootstrap, #endif -#if SDL_VIDEO_DRIVER_GAPI - &GAPI_bootstrap, -#endif #if SDL_VIDEO_DRIVER_WIN32 &WIN32_bootstrap, #endif diff --git a/src/video/win32/SDL_ceddrawrender.c b/src/video/win32/SDL_ceddrawrender.c index ea2d287dd..43ebe4eba 100644 --- a/src/video/win32/SDL_ceddrawrender.c +++ b/src/video/win32/SDL_ceddrawrender.c @@ -459,6 +459,8 @@ DDRAW_CreateRenderer(SDL_Window * window, Uint32 flags) } data->ddraw = videodata->ddraw; + videodata->render = RENDER_DDRAW; + renderer->DisplayModeChanged = DDRAW_DisplayModeChanged; renderer->CreateTexture = DDRAW_CreateTexture; renderer->QueryTexturePixels = DDRAW_QueryTexturePixels; diff --git a/src/video/win32/SDL_d3drender.c b/src/video/win32/SDL_d3drender.c index 1bb92ee72..661446a7f 100644 --- a/src/video/win32/SDL_d3drender.c +++ b/src/video/win32/SDL_d3drender.c @@ -451,6 +451,8 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) } data->d3d = videodata->d3d; + videodata->render = RENDER_D3D; + renderer->DisplayModeChanged = D3D_DisplayModeChanged; renderer->CreateTexture = D3D_CreateTexture; renderer->QueryTexturePixels = D3D_QueryTexturePixels; diff --git a/src/video/win32/SDL_gapirender.c b/src/video/win32/SDL_gapirender.c index 3eedeaad5..b54c42705 100644 --- a/src/video/win32/SDL_gapirender.c +++ b/src/video/win32/SDL_gapirender.c @@ -1,670 +1,1281 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2010 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 - - Stefan Klug - klug.stefan@gmx.de -*/ +/*************************************************************************** + * Copyright (C) 2010 by Andrey Afletdinov * + * * + * WinCE RAW/GAPI video driver * + * * + * Part of the SDL - (Simple DirectMedia Layer) * + * http://www.libsdl.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + #include "SDL_config.h" #if SDL_VIDEO_RENDER_GAPI #include "SDL_win32video.h" -//#include "../SDL_sysvideo.h" +#include "SDL_win32window.h" #include "../SDL_yuv_sw_c.h" -#include "../SDL_renderer_sw.h" - -#include "SDL_gapirender_c.h" - -#define GAPI_RENDERER_DEBUG 1 -/* GAPI renderer implementation */ +// RawFrameBufferInfo +typedef struct +{ + WORD wFormat; + WORD wBPP; + VOID *pFramePointer; + int cxStride; + int cyStride; + int cxPixels; + int cyPixels; +} RawFrameBufferInfo; + +// GXDeviceInfo +typedef struct +{ + long Version; + void* pvFrameBuffer; + unsigned long cbStride; + unsigned long cxWidth; + unsigned long cyHeight; + unsigned long cBPP; + unsigned long ffFormat; + char unknown[0x84 - 7 * 4]; +} GXDeviceInfo; + +// wince: GXDisplayProperties +struct GXDisplayProperties +{ + DWORD cxWidth; + DWORD cyHeight; + long cbxPitch; + long cbyPitch; + long cBPP; + DWORD ffFormat; +}; -static SDL_Renderer *GAPI_CreateRenderer(SDL_Window * window, Uint32 flags); -static int GAPI_RenderDrawPoints(SDL_Renderer * renderer, - const SDL_Point * points, int count); -static int GAPI_RenderDrawLines(SDL_Renderer * renderer, - const SDL_Point * points, int count); -static int GAPI_RenderDrawRects(SDL_Renderer * renderer, - const SDL_Rect ** rects, int count); -static int GAPI_RenderFillRects(SDL_Renderer * renderer, - const SDL_Rect ** rects, int count); -static int GAPI_RenderCopy(SDL_Renderer * renderer, - SDL_Texture * texture, - const SDL_Rect * srcrect, - const SDL_Rect * dstrect); -static void GAPI_RenderPresent(SDL_Renderer * renderer); -static void GAPI_DestroyRenderer(SDL_Renderer * renderer); +// gx.dll +typedef int (*PFNGXOpenDisplay)(HWND hWnd, DWORD dwFlags); +typedef int (*PFNGXCloseDisplay)(); +typedef void* (*PFNGXBeginDraw)(); +typedef int (*PFNGXEndDraw)(); +typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties)(); +typedef int (*PFNGXSuspend)(); +typedef int (*PFNGXResume)(); +typedef struct +{ + // gx.dll + HMODULE hGapiLib; + PFNGXOpenDisplay GXOpenDisplay; + PFNGXCloseDisplay GXCloseDisplay; + PFNGXBeginDraw GXBeginDraw; + PFNGXEndDraw GXEndDraw; + PFNGXGetDisplayProperties GXGetDisplayProperties; + PFNGXSuspend GXSuspend; + PFNGXResume GXResume; +} GapiInfo; + +//#ifndef DM_DISPLAYORIENTATION +//#define DM_DISPLAYORIENTATION 0x00800000L +//#endif + +#define FORMAT_565 1 +#define FORMAT_555 2 +#define FORMAT_OTHER 3 + +#define GETRAWFRAMEBUFFER 0x00020001 +#define GETGXINFO 0x00020000 + +#define kfPalette 0x10 +#define kfDirect 0x20 +#define kfDirect555 0x40 +#define kfDirect565 0x80 + +#define GX_FULLSCREEN 0x01 + +enum ScreenOrientation { ORIENTATION_UNKNOWN = -1, ORIENTATION_UP = DMDO_0, ORIENTATION_DOWN = DMDO_180, ORIENTATION_LEFT = DMDO_270, ORIENTATION_RIGHT = DMDO_90 }; +enum ScreenGeometry { GEOMETRY_UNKNOWN, GEOMETRY_PORTRAIT, GEOMETRY_LANDSCAPE, GEOMETRY_SQUARE }; +enum FrameBufferFlags { FB_SKIP_OFFSET = 0x0001, FB_RAW_MODE = 0x0002, FB_SUSPENDED = 0x0004 }; + +// private framebuffer info +typedef struct +{ + int width; + int height; + int xpitch; + int ypitch; + int offset; +} FrameBufferInfo; + +// private display data +typedef struct +{ + unsigned char* pixels; // video memory + int format; // video format + FrameBufferInfo fb; // framebuffer geometry + GapiInfo* gapi; // GAPI module + int userOrientation; + int systemOrientation; + int hardwareGeometry; + int flags; // fb flags + float scale; // scale pointer position + int debug; + +} WINCE_RenderData; +typedef struct +{ + SDL_SW_YUVTexture *yuv; + Uint32 format; + void *pixels; + int pitch; + +} WINCE_TextureData; + + +// system func +SDL_Renderer* WINCE_CreateRenderer(SDL_Window* window, Uint32 flags); +void WINCE_DestroyRenderer(SDL_Renderer* renderer); + +int WINCE_CreateTexture(SDL_Renderer* renderer, SDL_Texture* texture); +void WINCE_DestroyTexture(SDL_Renderer* renderer, SDL_Texture* texture); +int WINCE_QueryTexturePixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch); +int WINCE_UpdateTexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, const void* pixels, int pitch); +int WINCE_LockTexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, int dirty, void** pixels, int* pitch); +void WINCE_UnlockTexture(SDL_Renderer* renderer, SDL_Texture* texture); + +int WINCE_Available(void); +void WINCE_SetupOrientation(WINCE_RenderData* data, int width, int height); + +int WINCE_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srect, const SDL_Rect* drect); +void WINCE_ShowWindow(_THIS, SDL_Window* window, int visible); + +void WINCE_RenderPresent(SDL_Renderer* renderer); +int WINCE_RenderDrawPoints(SDL_Renderer* renderer, const SDL_Point* points, int count); +int WINCE_RenderDrawLines(SDL_Renderer* renderer, const SDL_Point* points, int count); +int WINCE_RenderDrawRects(SDL_Renderer* renderer, const SDL_Rect ** rects, int count); +int WINCE_RenderFillRects(SDL_Renderer* renderer, const SDL_Rect** rects, int count); + +void WINCE_PointerCoordinateTransform(SDL_Window* window, POINT* pt); +void WINCE_DumpVideoInfo(WINCE_RenderData* data); +void WINCE_PortraitTransform(WINCE_RenderData* data, int width, int height); +void WINCE_LandscapeTransform(WINCE_RenderData* data, int width, int height); +void WINCE_SquareTransform(WINCE_RenderData* data, int width, int height); +int WINCE_FixedGeometry(FrameBufferInfo* fb, int bpp, int debug); +int WINCE_GetDMOrientation(void); +int WINCE_SetDMOrientation(int orientation); +void WINCE_UpdateYUVTextureData(SDL_Texture* texture); + +// gapi engine specific +int GAPI_Init(WINCE_RenderData* data, HWND hwnd); +void GAPI_Quit(WINCE_RenderData* data); + +// raw engine specific +int RAW_Init(WINCE_RenderData* data); +void RAW_Quit(WINCE_RenderData* data); + +// tools +void FrameBufferRotate(FrameBufferInfo* src, int orientation); +int GetFrameBufferOrientation(const FrameBufferInfo* src); +void PointerRotate(POINT* pt, const FrameBufferInfo* fb, int orientation); +void FrameBufferInitialize(FrameBufferInfo* fb); +void FrameBufferDumpInfo(const FrameBufferInfo* fb, const char*); +const char* GetOrientationName(int orientation); +void UpdateLine16to16(const FrameBufferInfo* fb, const Uint16* src, Uint16* dst, Uint16 width); + +// stdlib +inline int __abs(int x){ return x < 0 ? -x : x; }; +inline void __swap(int* a, int* b){ int t = *a; *a = *b; *b = t; }; + +#define GAPI_RENDER_NAME "gapi" +#define RAW_RENDER_NAME "raw" +// SDL_RenderDriver GAPI_RenderDriver = { - GAPI_CreateRenderer, + WINCE_CreateRenderer, { - "gapi", - (SDL_RENDERER_SINGLEBUFFER), - } + GAPI_RENDER_NAME, + (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD), + (SDL_TEXTUREMODULATE_NONE), + (SDL_BLENDMODE_NONE), + (SDL_TEXTURESCALEMODE_NONE), + 7, + { + SDL_PIXELFORMAT_RGB555, + SDL_PIXELFORMAT_RGB565, + SDL_PIXELFORMAT_YV12, + SDL_PIXELFORMAT_IYUV, + SDL_PIXELFORMAT_YUY2, + SDL_PIXELFORMAT_UYVY, + SDL_PIXELFORMAT_YVYU + }, + 0, + 0 + } }; -static HMODULE g_hGapiLib = 0; - -// for testing with GapiEmu -#define USE_GAPI_EMU 0 -#define EMULATE_AXIM_X30 0 - -#if 0 -#define GAPI_LOG(...) printf(__VA_ARGS__) -#else -#define GAPI_LOG(...) -#endif - - -#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 - - -static void -GAPI_SetError(const char *prefix, HRESULT result) -{ - const char *error; - - switch (result) { - default: - error = "UNKNOWN"; - break; +SDL_RenderDriver RAW_RenderDriver = { + WINCE_CreateRenderer, + { + RAW_RENDER_NAME, + (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD), + (SDL_TEXTUREMODULATE_NONE), + (SDL_BLENDMODE_NONE), + (SDL_TEXTURESCALEMODE_NONE), + 7, + { + SDL_PIXELFORMAT_RGB555, + SDL_PIXELFORMAT_RGB565, + SDL_PIXELFORMAT_YV12, + SDL_PIXELFORMAT_IYUV, + SDL_PIXELFORMAT_YUY2, + SDL_PIXELFORMAT_UYVY, + SDL_PIXELFORMAT_YVYU + }, + 0, + 0 } - SDL_SetError("%s: %s", prefix, error); -} +}; -void -GAPI_AddRenderDriver(_THIS) +int WINCE_Available(void) { - int i; + const char* preferably = SDL_getenv("SDL_VIDEO_RENDERER"); - /* TODO: should we check for support of GetRawFramebuffer here? - */ -#if USE_GAPI_EMU - g_hGapiLib = LoadLibrary(L"GAPI_Emu.dll"); -#else - g_hGapiLib = LoadLibrary(L"\\Windows\\gx.dll"); -#endif + // raw check + RawFrameBufferInfo rfbi = { 0 }; + HDC hdc = GetDC(NULL); + int render_raw = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *) &rfbi); + ReleaseDC(NULL, hdc); - if (g_hGapiLib) { -#define LINK(name,import) gx.name = (PFN##name)GetProcAddress( g_hGapiLib, L##import ); - - LINK(GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z") - LINK(GXCloseDisplay, "?GXCloseDisplay@@YAHXZ") - LINK(GXBeginDraw, "?GXBeginDraw@@YAPAXXZ") - LINK(GXEndDraw, "?GXEndDraw@@YAHXZ") - LINK(GXOpenInput, "?GXOpenInput@@YAHXZ") - LINK(GXCloseInput, "?GXCloseInput@@YAHXZ") - LINK(GXGetDisplayProperties, - "?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") - LINK(GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z") - LINK(GXSuspend, "?GXSuspend@@YAHXZ") - LINK(GXResume, "?GXResume@@YAHXZ") - LINK(GXSetViewport, "?GXSetViewport@@YAHKKKK@Z") - LINK(GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ") - - /* wrong gapi.dll */ - if (!gx.GXOpenDisplay) { - FreeLibrary(g_hGapiLib); - g_hGapiLib = 0; - } -#undef LINK - } + if(render_raw != 0 && rfbi.cxPixels != 0 && rfbi.cyPixels != 0 && + rfbi.pFramePointer != 0 && rfbi.cxStride != 0 && rfbi.cyStride != 0) + render_raw = 1; - for (i = 0; i < _this->num_displays; ++i) { - SDL_AddRenderDriver(&_this->displays[i], &GAPI_RenderDriver); - } -} + if(preferably && 0 == SDL_strcasecmp(preferably, RAW_RENDER_NAME)) return 0 != render_raw; -typedef enum -{ - USAGE_GX_FUNCS = 0x0001, /* enable to use GXOpen/GXClose/GXBeginDraw... */ - USAGE_DATA_PTR_CONSTANT = 0x0002 /* the framebuffer is at a constant location, don't use values from GXBeginDraw() */ -} GAPI_UsageFlags; + // gapi check + HMODULE render_gapi = LoadLibrary(TEXT("\\Windows\\gx.dll")); + if(0 == render_gapi) + render_gapi = LoadLibrary(TEXT("gx.dll")); + FreeLibrary(render_gapi); + if(preferably && 0 == SDL_strcasecmp(preferably, GAPI_RENDER_NAME)) return 0 != render_gapi; + return 0 != render_raw || 0 != render_gapi; +} -typedef struct +void WINCE_AddRenderDriver(_THIS) { - int w; - int h; - int xPitch; /* bytes to move to go to the next pixel */ - int yPitch; /* bytes to move to go to the next line */ - int offset; /* data offset, to add to the data returned from GetFramebuffer, before processing */ + HDC hdc; + HMODULE render_gapi; + int render_raw, ii; + const char* preferably = SDL_getenv("SDL_VIDEO_RENDERER"); - void *data; - Uint32 usageFlags; /* these flags contain options to define screen handling and to reliably workarounds */ + // raw check + RawFrameBufferInfo rfbi = { 0 }; + hdc = GetDC(NULL); + render_raw = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *) &rfbi); + ReleaseDC(NULL, hdc); - Uint32 format; /* pixel format as defined in SDL_pixels.h */ + if(render_raw != 0 && rfbi.cxPixels != 0 && rfbi.cyPixels != 0 && + rfbi.pFramePointer != 0 && rfbi.cxStride != 0 && rfbi.cyStride != 0) + render_raw = 1; -} GAPI_RenderData; + // gapi check + render_gapi = LoadLibrary(TEXT("\\Windows\\gx.dll")); + if(0 == render_gapi) + render_gapi = LoadLibrary(TEXT("gx.dll")); + if(render_gapi) + FreeLibrary(render_gapi); -static Uint32 -GuessPixelFormatFromBpp(int bpp) -{ - switch (bpp) { - case 15: - return SDL_PIXELFORMAT_RGB555; - case 16: - return SDL_PIXELFORMAT_RGB565; - default: - return SDL_PIXELFORMAT_UNKNOWN; - break; + for(ii = 0; ii < _this->num_displays; ++ii) + { + if(preferably) + { + if(0 == SDL_strcasecmp(preferably, RAW_RENDER_NAME) && render_raw) + SDL_AddRenderDriver(&_this->displays[ii], &RAW_RenderDriver); + else + if(0 == SDL_strcasecmp(preferably, GAPI_RENDER_NAME) && render_gapi) + SDL_AddRenderDriver(&_this->displays[ii], &GAPI_RenderDriver); + } + else + { + if(render_raw) + SDL_AddRenderDriver(&_this->displays[ii], &RAW_RenderDriver); + if(render_gapi) + SDL_AddRenderDriver(&_this->displays[ii], &GAPI_RenderDriver); + } } } -static GAPI_RenderData * -FillRenderDataRawFramebuffer(SDL_Window * window) +SDL_Renderer* WINCE_CreateRenderer(SDL_Window* window, Uint32 flags) { - RawFrameBufferInfo rbi; - GAPI_RenderData *renderdata; - HDC hdc; + SDL_VideoDisplay* display = window->display; + SDL_DisplayMode* displayMode = &display->current_mode; + SDL_WindowData* windowdata = (SDL_WindowData *) window->driverdata; + SDL_Renderer* renderer; + WINCE_RenderData* data; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; - //TODO should we use the hdc of the window? - hdc = GetDC(NULL); - int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, - sizeof(RawFrameBufferInfo), - (char *) &rbi); - ReleaseDC(NULL, hdc); + if(!(window->flags & SDL_WINDOW_FULLSCREEN)) + window->flags |= SDL_WINDOW_FULLSCREEN; - if (!(result > 0)) { + if(!SDL_PixelFormatEnumToMasks(displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) + { + SDL_SetError("Unknown display format"); return NULL; } - /* Asus A696 returns wrong results so we do a sanity check - See: - http://groups.google.com/group/microsoft.public.smartphone.developer/browse_thread/thread/4fde5bddd477de81 - */ - if (rbi.cxPixels <= 0 || - rbi.cyPixels <= 0 || - rbi.cxStride == 0 || rbi.cyStride == 0 || rbi.pFramePointer == 0) { - return NULL; - } + switch(window->fullscreen_mode.format) + { + case SDL_PIXELFORMAT_RGB555: + case SDL_PIXELFORMAT_RGB565: + break; + default: + SDL_SetError("Support only 16 or 15 bpp"); + return NULL; + } - renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(*renderdata)); - if (!renderdata) { + renderer = (SDL_Renderer*) SDL_calloc(1, sizeof(SDL_Renderer)); + if(!renderer) + { SDL_OutOfMemory(); return NULL; } - //Try to match the window size - //TODO add rotation support - if (rbi.cxPixels != window->w || rbi.cyPixels != window->h) { - SDL_free(renderdata); + + data = (WINCE_RenderData*) SDL_calloc(1, sizeof(WINCE_RenderData)); + if(!data) + { + WINCE_DestroyRenderer(renderer); + SDL_OutOfMemory(); return NULL; } - //Check that the display uses a known display format - switch (rbi.wFormat) { - case FORMAT_565: - renderdata->format = SDL_PIXELFORMAT_RGB565; - break; - case FORMAT_555: - renderdata->format = SDL_PIXELFORMAT_RGB555; - break; - default: - //TODO we should add support for other formats - SDL_free(renderdata); + + // initialize internal engine + if(!RAW_Init(data) && !GAPI_Init(data, windowdata->hwnd)) + { + WINCE_DestroyRenderer(renderer); return NULL; } - renderdata->usageFlags = USAGE_DATA_PTR_CONSTANT; - renderdata->data = rbi.pFramePointer; - renderdata->w = rbi.cxPixels; - renderdata->h = rbi.cyPixels; - renderdata->xPitch = rbi.cxStride; - renderdata->yPitch = rbi.cyStride; - return renderdata; + // set debug + data->debug = SDL_getenv("DEBUG_VIDEO_GAPI") || SDL_getenv("GAPI_RENDERER_DEBUG") ? 1 : 0; +#if defined(DEBUG_VIDEO_GAPI) || defined(GAPI_RENDERER_DEBUG) + data->debug = 1; +#endif -} + windowdata->videodata->render = data->gapi ? RENDER_GAPI : RENDER_RAW; + windowdata->videodata->CoordTransform = WINCE_PointerCoordinateTransform; + + window->display->device->MaximizeWindow = NULL; + window->display->device->MinimizeWindow = NULL; + + WINCE_SetupOrientation(data, window->w, window->h); + renderer->CreateTexture = WINCE_CreateTexture; + renderer->DestroyTexture = WINCE_DestroyTexture; + renderer->QueryTexturePixels = WINCE_QueryTexturePixels; + renderer->UpdateTexture = WINCE_UpdateTexture; + renderer->LockTexture = WINCE_LockTexture; + renderer->UnlockTexture = WINCE_UnlockTexture; -static GAPI_RenderData * -FillRenderDataGAPI(SDL_Window * window) + renderer->RenderCopy = WINCE_RenderCopy; + renderer->DestroyRenderer = WINCE_DestroyRenderer; + + renderer->RenderPresent = WINCE_RenderPresent; + renderer->RenderDrawPoints = WINCE_RenderDrawPoints; + renderer->RenderDrawLines = WINCE_RenderDrawLines; + renderer->RenderDrawRects = WINCE_RenderDrawRects; + renderer->RenderFillRects = WINCE_RenderFillRects; + + renderer->info = data->gapi ? GAPI_RenderDriver.info : RAW_RenderDriver.info; + + renderer->window = window; + renderer->driverdata = data; + + return renderer; +} + +void WINCE_DestroyRenderer(SDL_Renderer* renderer) { - GAPI_RenderData *renderdata; - struct GXDisplayProperties gxdp; - int tmp; + WINCE_RenderData *renderdata = (WINCE_RenderData*) renderer->driverdata; -#ifdef _ARM_ - WCHAR oemstr[100]; -#endif + if(renderdata) + { + if(renderdata->gapi) + GAPI_Quit(renderdata); + else + RAW_Quit(renderdata); - if (!g_hGapiLib) { - return NULL; + SDL_free(renderdata); + } + + SDL_free(renderer); +} + +int WINCE_CreateTexture(SDL_Renderer* renderer, SDL_Texture* texture) +{ + WINCE_TextureData* texturedata = (WINCE_TextureData*) SDL_calloc(1, sizeof(WINCE_TextureData)); + if(NULL == texturedata) + { + SDL_OutOfMemory(); + return -1; } - renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(GAPI_RenderData)); - if (!renderdata) { + texturedata->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); + texturedata->pixels = SDL_malloc(texture->h * texturedata->pitch); + if(NULL == texturedata->pixels) + { SDL_OutOfMemory(); - return NULL; + return -1; } - gxdp = gx.GXGetDisplayProperties(); - renderdata->usageFlags = USAGE_GX_FUNCS; - renderdata->w = gxdp.cxWidth; - renderdata->h = gxdp.cyHeight; - renderdata->xPitch = gxdp.cbxPitch; - renderdata->yPitch = gxdp.cbyPitch; - - //Check that the display uses a known display format - if (gxdp.ffFormat & kfDirect565) { - renderdata->format = SDL_PIXELFORMAT_RGB565; - } else if (gxdp.ffFormat & kfDirect555) { - renderdata->format = SDL_PIXELFORMAT_RGB555; - } else { - renderdata->format = SDL_PIXELFORMAT_UNKNOWN; - } - - /* apply some device specific corrections */ -#ifdef _ARM_ - SystemParametersInfo(SPI_GETOEMINFO, sizeof(oemstr), oemstr, 0); - - // buggy iPaq38xx - if ((oemstr[12] == 'H') && (oemstr[13] == '3') - && (oemstr[14] == '8') - && (gxdp.cbxPitch > 0)) { - renderdata->data = (void *) 0xac0755a0; - renderdata->xPitch = -640; - renderdata->yPitch = 2; - } -#if (EMULATE_AXIM_X30 == 0) - // buggy Dell Axim X30 - if (_tcsncmp(oemstr, L"Dell Axim X30", 13) == 0) -#endif + if(SDL_ISPIXELFORMAT_FOURCC(texture->format)) { - 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) { - renderdata->usageFlags = USAGE_DATA_PTR_CONSTANT; /* no more GAPI usage from now */ - renderdata->data = gxInfo.pvFrameBuffer; - this->hidden->needUpdate = 0; - renderdata->xPitch = 2; - renderdata->yPitch = 480; - renderdata->w = gxInfo.cxWidth; - renderdata->h = gxInfo.cyHeight; - - //Check that the display uses a known display format - switch (rbi->wFormat) { - case FORMAT_565: - renderdata->format = SDL_PIXELFORMAT_RGB565; - break; - case FORMAT_555: - renderdata->format = SDL_PIXELFORMAT_RGB555; - break; - default: - //TODO we should add support for other formats - SDL_free(renderdata); - return NULL; - } + texturedata->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); + if(NULL == texturedata->yuv) + { + SDL_OutOfMemory(); + return -1; } + SDL_Window* window = renderer->window; + SDL_VideoDisplay* display = window->display; + texturedata->format = display->current_mode.format; + } + else + { + texturedata->yuv = NULL; + texturedata->format = texture->format; } -#endif + texture->driverdata = texturedata; - if (renderdata->format == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetError("Gapi Pixelformat is unknown"); - SDL_free(renderdata); - return NULL; + return 0; +} + +void WINCE_DestroyTexture(SDL_Renderer* renderer, SDL_Texture* texture) +{ + WINCE_TextureData *texturedata = (WINCE_TextureData*) texture->driverdata; + + if(texturedata) + { + if(texturedata->yuv) SDL_SW_DestroyYUVTexture(texturedata->yuv); + if(texturedata->pixels) SDL_free(texturedata->pixels); + SDL_free(texturedata); + texture->driverdata = NULL; } +} - /* Gapi always returns values in standard orientation, so we manually apply - the current orientation - */ +int WINCE_QueryTexturePixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch) +{ + WINCE_TextureData* texturedata = (WINCE_TextureData*) texture->driverdata; - DEVMODE settings; - SDL_memset(&settings, 0, sizeof(DEVMODE)); - settings.dmSize = sizeof(DEVMODE); + if(texturedata->yuv) + return SDL_SW_QueryYUVTexturePixels(texturedata->yuv, pixels, pitch); - settings.dmFields = DM_DISPLAYORIENTATION; - ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL); + *pixels = texturedata->pixels; + *pitch = texturedata->pitch; - if (settings.dmDisplayOrientation == DMDO_90) { + return 0; +} - tmp = renderdata->w; - renderdata->w = renderdata->h; - renderdata->h = tmp; +int WINCE_UpdateTexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, const void* pixels, int pitch) +{ + WINCE_TextureData* texturedata = (WINCE_TextureData*) texture->driverdata; - tmp = renderdata->xPitch; - renderdata->xPitch = -renderdata->yPitch; - renderdata->yPitch = tmp; + if(texturedata->yuv) + { + if(SDL_SW_UpdateYUVTexture(texturedata->yuv, rect, pixels, pitch) < 0) + return -1; + WINCE_UpdateYUVTextureData(texture); + return 0; + } - renderdata->offset = -renderdata->w * renderdata->xPitch; + if(0 < rect->w && 0 < rect->h) + { + const unsigned char *src = ((const unsigned char*) pixels); + unsigned char *dst = ((unsigned char*) texturedata->pixels) + + rect->y * texturedata->pitch + + rect->x * SDL_BYTESPERPIXEL(texture->format); + int length = rect->w * SDL_BYTESPERPIXEL(texture->format); + int height = rect->h; + + while(height--) + { + SDL_memcpy(dst, src, length); + dst += texturedata->pitch; + src += pitch; + } + } + + return 0; +} + +int WINCE_LockTexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, int dirty, void** pixels, int* pitch) +{ + WINCE_TextureData *texturedata = (WINCE_TextureData*) texture->driverdata; - } else if (settings.dmDisplayOrientation == DMDO_180) { + if(texturedata->yuv) + return SDL_SW_LockYUVTexture(texturedata->yuv, rect, dirty, pixels, pitch); - renderdata->xPitch = -renderdata->xPitch; - renderdata->yPitch = -renderdata->yPitch; + *pixels = (void *) ((unsigned char*) texturedata->pixels + + rect->y * texturedata->pitch + + rect->x * SDL_BYTESPERPIXEL(texture->format)); + *pitch = texturedata->pitch; +} - renderdata->offset = -renderdata->h * renderdata->yPitch - - renderdata->w * renderdata->xPitch; +void WINCE_UnlockTexture(SDL_Renderer* renderer, SDL_Texture* texture) +{ + WINCE_TextureData *texturedata = (WINCE_TextureData*) texture->driverdata; - } else if (settings.dmDisplayOrientation == DMDO_270) { + if(texturedata->yuv) + { + SDL_SW_UnlockYUVTexture(texturedata->yuv); + WINCE_UpdateYUVTextureData(texture); + } +} - tmp = renderdata->w; - renderdata->w = renderdata->h; - renderdata->h = tmp; +int WINCE_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srect, const SDL_Rect* drect) +{ + WINCE_RenderData* dstdata = (WINCE_RenderData*) renderer->driverdata; + WINCE_TextureData* srcdata = (WINCE_TextureData*) texture->driverdata; - tmp = renderdata->xPitch; - renderdata->xPitch = renderdata->yPitch; - renderdata->yPitch = -tmp; + if((dstdata->flags & FB_SUSPENDED) || + 0 >= srect->w || 0 >= srect->h) return; - renderdata->offset = -renderdata->h * renderdata->yPitch; + // lock gapi + if(dstdata->gapi) dstdata->gapi->GXBeginDraw(); + const unsigned char *src = ((const unsigned char*) srcdata->pixels); + unsigned char *dst = dstdata->pixels + (dstdata->flags & FB_SKIP_OFFSET ? 0 : dstdata->fb.offset) + + drect->y * dstdata->fb.ypitch + + drect->x * dstdata->fb.xpitch; + if(srcdata->yuv) + { + return SDL_SW_CopyYUVToRGB(srcdata->yuv, + srect, srcdata->format, + drect->w, drect->h, dst, + dstdata->fb.ypitch); } + else + { + int height = drect->h; + int length = drect->w * SDL_BYTESPERPIXEL(texture->format); // in bytes - if (renderdata->w != window->w || renderdata->h != window->h) { - GAPI_LOG("GAPI open failed, wrong size %i %i %i %i\n", renderdata->w, - renderdata->h, renderdata->xPitch, renderdata->yPitch); - SDL_free(renderdata); - return NULL; + while(height--) + { + switch(SDL_BYTESPERPIXEL(texture->format)) + { + case 2: UpdateLine16to16(&dstdata->fb, (Uint16*) src, (Uint16*) dst, length >> 1); break; + + default: break; + } + + dst += dstdata->fb.ypitch; + src += srcdata->pitch; + } } - return renderdata; + // unlock gapi + if(dstdata->gapi) dstdata->gapi->GXEndDraw(); + return 0; } - -/* This function does the whole encapsulation of Gapi/RAWFRAMEBUFFER - it should handle all the device dependent details and fill the device INDEPENDENT - RenderData structure. - */ -GAPI_RenderData * -FillRenderData(SDL_Window * window) +void WINCE_RenderPresent(SDL_Renderer* renderer) { - /* We try to match the requested window to the modes available by GAPI and RAWFRAMEBUFFER. - First RAWFRAMEBUFFER is tried, as it is the most reliable one - Look here for detailed discussions: - http://pdaphonehome.com/forums/samsung-i700/28087-just-saw.html - http://blogs.msdn.com/windowsmobile/archive/2007/08/13/have-you-migrated-to-directdraw-yet.aspx - */ - - GAPI_RenderData *res; +} - res = FillRenderDataRawFramebuffer(window); - GAPI_LOG("FillRenderDataRawFramebuffer: %p\n", res); - if (res) { - return res; - } - //Now we try gapi - res = FillRenderDataGAPI(window); - GAPI_LOG("FillRenderDataGAPI: %p\n", res); +int WINCE_RenderDrawPoints(SDL_Renderer* renderer, const SDL_Point* points, int count) +{ + SDL_Unsupported(); + return -1; +} - return res; +int WINCE_RenderDrawLines(SDL_Renderer* renderer, const SDL_Point* points, int count) +{ + SDL_Unsupported(); + return -1; } -void * -GetFramebuffer() +int WINCE_RenderDrawRects(SDL_Renderer* renderer, const SDL_Rect ** rects, int count) { + SDL_Unsupported(); + return -1; +} +int WINCE_RenderFillRects(SDL_Renderer* renderer, const SDL_Rect** rects, int count) +{ + SDL_Unsupported(); + return -1; } -SDL_Renderer * -GAPI_CreateRenderer(SDL_Window * window, Uint32 flags) + +void WINCE_SetupOrientation(WINCE_RenderData* data, int width, int height) { - SDL_VideoDisplay *display = window->display; - SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; - SDL_DisplayMode *displayMode = &display->current_mode; - SDL_Renderer *renderer; - GAPI_RenderData *data; - int i, n; - int bpp; - Uint32 Rmask, Gmask, Bmask, Amask; + const float maxW1 = GetSystemMetrics(SM_CXSCREEN) > GetSystemMetrics(SM_CYSCREEN) ? GetSystemMetrics(SM_CXSCREEN) : GetSystemMetrics(SM_CYSCREEN); + const float maxW2 = data->fb.width > data->fb.height ? data->fb.width : data->fb.height; - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - SDL_SetError("Gapi supports only fullscreen windows"); - return NULL; - } + // scale define + data->scale = maxW2 / maxW1; - if (!SDL_PixelFormatEnumToMasks - (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { - SDL_SetError("Unknown display format"); - return NULL; + // init fb values + FrameBufferInitialize(&data->fb); + + // orientation values + data->userOrientation = ORIENTATION_UP; + data->systemOrientation = WINCE_GetDMOrientation(); + data->hardwareGeometry = data->fb.width == data->fb.height ? GEOMETRY_SQUARE : + (data->fb.width < data->fb.height ? GEOMETRY_PORTRAIT : GEOMETRY_LANDSCAPE); + + if(data->debug) + WINCE_DumpVideoInfo(data); + + if(data->systemOrientation == ORIENTATION_UNKNOWN) + data->systemOrientation == ORIENTATION_UP; + + data->userOrientation = ORIENTATION_UP; + + switch(data->hardwareGeometry) + { + case GEOMETRY_PORTRAIT: WINCE_PortraitTransform(data, width, height); break; + case GEOMETRY_LANDSCAPE: WINCE_LandscapeTransform(data, width, height); break; + case GEOMETRY_SQUARE: WINCE_SquareTransform(data, width, height); break; + default: break; } - renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); - if (!renderer) { - SDL_OutOfMemory(); - return NULL; + // debug + if(data->debug) + { + printf("\n"); + printf("user video width: %d\n", width); + printf("user video height: %d\n", height); + FrameBufferDumpInfo(&data->fb, "user"); } +} - data = FillRenderData(window); - if (!data) { - GAPI_DestroyRenderer(renderer); - SDL_OutOfMemory(); - return NULL; +void WINCE_DumpVideoInfo(WINCE_RenderData* data) +{ + // get oem info + WCHAR oemInfo[48]; + SDL_memset(oemInfo, 0, sizeof(oemInfo)); + SystemParametersInfo(SPI_GETOEMINFO, sizeof(oemInfo) - sizeof(WCHAR), oemInfo, 0); + + printf("hardware oem: "); + wprintf(oemInfo); + printf("\n"); + + printf("video driver mode: %s\n", (data->flags & FB_RAW_MODE ? RAW_RENDER_NAME : GAPI_RENDER_NAME)); + printf("GetSystemMetrics(SM_CXSCREEN): %d\n", GetSystemMetrics(SM_CXSCREEN)); + printf("GetSystemMetrics(SM_CYSCREEN): %d\n", GetSystemMetrics(SM_CYSCREEN)); + printf("scale coord: %f\n", data->scale); + + FrameBufferDumpInfo(&data->fb, "hardware"); + + printf("display format: %p\n", data->format); + printf("display bits per pixel: %d\n", SDL_BITSPERPIXEL(data->format)); + printf("display bytes per pixel: %d\n", SDL_BYTESPERPIXEL(data->format)); + printf("display memory: %p\n", data->pixels); + printf("system orientation: %d, %s\n", data->systemOrientation, GetOrientationName(data->systemOrientation)); + printf("hardware geometry: %d\n", data->hardwareGeometry); +} + +void WINCE_ShowWindow(_THIS, SDL_Window* window, int visible) +{ + SDL_WindowData* windowdata = (SDL_WindowData*) window->driverdata; + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + SDL_Renderer* renderer = (SDL_Renderer*) window->renderer; + + if(visible) + { + if(window->flags & SDL_WINDOW_FULLSCREEN) + { + if(videodata->SHFullScreen) + videodata->SHFullScreen(windowdata->hwnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON); + ShowWindow(FindWindow(TEXT("HHTaskBar"), NULL), SW_HIDE); + } + + ShowWindow(windowdata->hwnd, SW_SHOW); + SetForegroundWindow(windowdata->hwnd); + + if(renderer && + (videodata->render == RENDER_GAPI || videodata->render == RENDER_RAW)) + { + WINCE_RenderData* renderdata = (WINCE_RenderData*) renderer->driverdata; + renderdata->flags &= ~FB_SUSPENDED; + if(renderdata->gapi) renderdata->gapi->GXResume(); + } } + else + { + if(renderer && + (videodata->render == RENDER_GAPI || videodata->render == RENDER_RAW)) + { + WINCE_RenderData* renderdata = (WINCE_RenderData*) renderer->driverdata; + if(renderdata->gapi) renderdata->gapi->GXSuspend(); + renderdata->flags |= FB_SUSPENDED; + } + + ShowWindow(windowdata->hwnd, SW_HIDE); + + if(window->flags & SDL_WINDOW_FULLSCREEN) + { + if(videodata->SHFullScreen) + videodata->SHFullScreen(windowdata->hwnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON | SHFS_SHOWSIPBUTTON); + ShowWindow(FindWindow(TEXT("HHTaskBar"), NULL), SW_SHOW); + } + } +} - renderer->RenderDrawPoints = GAPI_RenderDrawPoints; - renderer->RenderDrawLines = GAPI_RenderDrawLines; - renderer->RenderDrawRects = GAPI_RenderDrawRects; - renderer->RenderFillRects = GAPI_RenderFillRects; - renderer->RenderCopy = GAPI_RenderCopy; - renderer->RenderPresent = GAPI_RenderPresent; - renderer->DestroyRenderer = GAPI_DestroyRenderer; - renderer->info.name = GAPI_RenderDriver.info.name; - renderer->info.flags = 0; - renderer->window = window; - renderer->driverdata = data; - /* Gapi provides only a framebuffer so lets use software implementation */ - Setup_SoftwareRenderer(renderer); - -#ifdef GAPI_RENDERER_DEBUG - printf("Created gapi renderer\n"); - printf("use GX functions: %i\n", data->usageFlags & USAGE_GX_FUNCS); - printf("framebuffer is constant: %i\n", - data->usageFlags & USAGE_DATA_PTR_CONSTANT); - printf("w: %i h: %i\n", data->w, data->h); - printf("data ptr: %p\n", data->data); /* this can be 0 in case of GAPI usage */ - printf("xPitch: %i\n", data->xPitch); - printf("yPitch: %i\n", data->yPitch); - printf("offset: %i\n", data->offset); - printf("format: %x\n", data->format); -#endif +void WINCE_PointerCoordinateTransform(SDL_Window* window, POINT* pt) +{ + WINCE_RenderData* data = (WINCE_RenderData*) window->renderer->driverdata; - if (data->usageFlags & USAGE_GX_FUNCS) { - if (gx.GXOpenDisplay(windowdata->hwnd, GX_FULLSCREEN) == 0) { - GAPI_DestroyRenderer(renderer); - return NULL; - } + pt->x *= data->scale; + pt->y *= data->scale; + + PointerRotate(pt, &data->fb, data->userOrientation); +} + +void WINCE_PortraitTransform(WINCE_RenderData* data, int width, int height) +{ + if(data->systemOrientation != ORIENTATION_UP) + FrameBufferRotate(&data->fb, data->systemOrientation); + + if(data->fb.width != width || data->fb.height != height) + switch(data->systemOrientation) + { + case ORIENTATION_UP: + case ORIENTATION_LEFT: data->userOrientation = ORIENTATION_RIGHT; break; + case ORIENTATION_RIGHT: + case ORIENTATION_DOWN: data->userOrientation = ORIENTATION_LEFT; break; + default: break; } - return renderer; + if(data->userOrientation != ORIENTATION_UP) + FrameBufferRotate(&data->fb, data->userOrientation); } -static int -GAPI_RenderDrawPoints(SDL_Renderer * renderer, - const SDL_Point * points, int count) +void WINCE_LandscapeTransform(WINCE_RenderData* data, int width, int height) { - // TODO implement - SDL_Unsupported(); - return -1; + switch(data->systemOrientation) + { + case ORIENTATION_UP: FrameBufferRotate(&data->fb, ORIENTATION_LEFT); break; + case ORIENTATION_LEFT:FrameBufferRotate(&data->fb, ORIENTATION_DOWN); break; + case ORIENTATION_DOWN:FrameBufferRotate(&data->fb, ORIENTATION_RIGHT); break; + default: break; + } + + if(data->fb.width != width || data->fb.height != height) + switch(data->systemOrientation) + { + case ORIENTATION_UP: + case ORIENTATION_LEFT: data->userOrientation = ORIENTATION_RIGHT; break; + case ORIENTATION_RIGHT: + case ORIENTATION_DOWN: data->userOrientation = ORIENTATION_LEFT; break; + default: break; + } + + if(data->userOrientation != ORIENTATION_UP) + FrameBufferRotate(&data->fb, data->userOrientation); } -static int -GAPI_RenderDrawLines(SDL_Renderer * renderer, - const SDL_Point * points, int count) +void WINCE_SquareTransform(WINCE_RenderData* data, int width, int height) { - // TODO implement - SDL_Unsupported(); - return -1; + WINCE_PortraitTransform(data, width, height); } -static int -GAPI_RenderDrawRects(SDL_Renderer * renderer, - const SDL_Rect ** rects, int count) +int WINCE_FixedGeometry(FrameBufferInfo* fb, int bpp, int debug) { - // TODO implement - SDL_Unsupported(); - return -1; + // check square + if(GetSystemMetrics(SM_CXSCREEN) == GetSystemMetrics(SM_CYSCREEN) && + fb->width != fb->height) + { + if(fb->width < fb->height) + fb->height = fb->width; + else + if(fb->height < fb->width) + fb->width = fb->height; + } + + // check width + if(__abs(fb->xpitch) == bpp && + fb->width != __abs(fb->ypitch) / bpp) + { + if(fb->height == __abs(fb->ypitch) / bpp) + { + __swap(&fb->width, &fb->height); + + if(debug) + printf("WINCE_FixedGeometry: width: %d, height: %d\n", fb->width, fb->height); + } + else + return -1; + } + else + // check height + if(__abs(fb->ypitch) == bpp && + fb->height != __abs(fb->xpitch) / bpp) + { + if(fb->width == __abs(fb->xpitch) / bpp) + { + __swap(&fb->width, &fb->height); + + if(debug) + printf("WINCE_FixedGeometry: width: %d, height: %d\n", fb->width, fb->height); + } + else + return -1; + } + + return 0; } -static int -GAPI_RenderFillRects(SDL_Renderer * renderer, - const SDL_Rect ** rects, int count) +void WINCE_UpdateYUVTextureData(SDL_Texture* texture) { - // TODO implement - SDL_Unsupported(); - return -1; + WINCE_TextureData* texturedata = (WINCE_TextureData*) texture->driverdata; + SDL_Rect rect; + + rect.x = 0; + rect.y = 0; + rect.w = texture->w; + rect.h = texture->h; + SDL_SW_CopyYUVToRGB(texturedata->yuv, &rect, texturedata->format, texture->w, texture->h, texturedata->pixels, texturedata->pitch); } -/* Video memory is very slow so lets optimize as much as possible */ -static void -updateLine16to16(char *src, int srcXPitch, int srcYPitch, - char *dst, int dstXPitch, int dstYPitch, int width, - int height) +int GAPI_Init(WINCE_RenderData* data, HWND hwnd) { - char *srcLine, *dstLine; - char *srcPix, *dstPix; + if(NULL == data->gapi) + { + const char* preferably = SDL_getenv("SDL_VIDEO_RENDERER"); + if(preferably && 0 != SDL_strcasecmp(preferably, GAPI_RENDER_NAME)) return 0; + + data->gapi = (GapiInfo *) SDL_calloc(1, sizeof(GapiInfo)); + if(NULL == data->gapi) + { + SDL_OutOfMemory(); + return 0; + } - int x, y; + data->gapi->hGapiLib = LoadLibrary(TEXT("\\Windows\\gx.dll")); + if(0 == data->gapi->hGapiLib) + { + data->gapi->hGapiLib = LoadLibrary(TEXT("gx.dll")); + if(0 == data->gapi->hGapiLib) return 0; + } + + // load gapi library +#define LINK(type,name,import) name=(PFN##type)GetProcAddress(data->gapi->hGapiLib,TEXT(import)) + LINK(GXOpenDisplay, data->gapi->GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z"); + LINK(GXCloseDisplay, data->gapi->GXCloseDisplay, "?GXCloseDisplay@@YAHXZ"); + LINK(GXBeginDraw, data->gapi->GXBeginDraw, "?GXBeginDraw@@YAPAXXZ"); + LINK(GXEndDraw, data->gapi->GXEndDraw, "?GXEndDraw@@YAHXZ"); + LINK(GXGetDisplayProperties,data->gapi->GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ"); + LINK(GXSuspend, data->gapi->GXSuspend, "?GXSuspend@@YAHXZ"); + LINK(GXResume, data->gapi->GXResume, "?GXResume@@YAHXZ"); +#undef LINK - //First dumb solution - if (srcXPitch == 2 && dstXPitch == 2) { - srcLine = src; - dstLine = dst; - y = height; - while (y--) { - SDL_memcpy(dstLine, srcLine, width * sizeof(Uint16)); - srcLine += srcYPitch; - dstLine += dstYPitch; - } - } else { - //printf("GAPI uses slow blit path %i, %i\n", dstXPitch, dstYPitch); - srcLine = src; - dstLine = dst; - y = height; - while (y--) { - srcPix = srcLine; - dstPix = dstLine; - x = width; - while (x--) { - *((Uint16 *) dstPix) = *((Uint16 *) srcPix); - dstPix += dstXPitch; - srcPix += srcXPitch; - } - srcLine += srcYPitch; - dstLine += dstYPitch; + int enable = data->gapi->GXGetDisplayProperties && data->gapi->GXCloseDisplay && data->gapi->GXOpenDisplay && + data->gapi->GXBeginDraw && data->gapi->GXEndDraw && data->gapi->GXSuspend && data->gapi->GXResume; + + if(!enable) + { + SDL_SetError("GAPI_Init: error gx.dll: internal error"); + GAPI_Quit(data); + return 0; + } + + if(0 == data->gapi->GXOpenDisplay(hwnd, GX_FULLSCREEN)) + { + SDL_SetError("GAPI_Init: couldn't initialize GAPI"); + GAPI_Quit(data); + return 0; + } + + struct GXDisplayProperties gxProperties = data->gapi->GXGetDisplayProperties(); + + // fill FrameBufferInfo + data->fb.xpitch = gxProperties.cbxPitch; + data->fb.ypitch = gxProperties.cbyPitch; + data->fb.width = gxProperties.cxWidth; + data->fb.height = gxProperties.cyHeight; + data->fb.offset = 0; + + if((gxProperties.ffFormat & kfDirect565) || 16 == gxProperties.cBPP) + data->format = SDL_PIXELFORMAT_RGB565; + else + if((gxProperties.ffFormat & kfDirect555) || 15 == gxProperties.cBPP) + data->format = SDL_PIXELFORMAT_RGB555; + else + data->format = 0; + + // get pixels + GXDeviceInfo gxInfo = { 0 }; + HDC hdc = GetDC(NULL); + + gxInfo.Version = 100; + int result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *) &gxInfo); + ReleaseDC(NULL, hdc); + + if(result > 0) + { + // more debug + if(data->debug) + { + printf("GXDeviceInfo.pvFrameBuffer: %p\n", gxInfo.pvFrameBuffer); + printf("GXDeviceInfo.cxWidth: %d\n", gxInfo.cxWidth); + printf("GXDeviceInfo.cyHeight: %d\n", gxInfo.cyHeight); + printf("GXDeviceInfo.cbStride: %d\n", gxInfo.cbStride); + printf("GXDeviceInfo.cBPP: %d\n", gxInfo.cBPP); + printf("GXDeviceInfo.ffFormat: 0x%x\n", gxInfo.ffFormat); + + printf("GXDeviceInfo.unk:\n"); + int ii; for(ii = 0; ii < sizeof(gxInfo.unknown); ++ii) + printf("0x%02hhX,", gxInfo.unknown[ii]); + printf("\n"); + } + + if(gxInfo.ffFormat && gxInfo.ffFormat != gxProperties.ffFormat) + { + if((gxInfo.ffFormat & kfDirect565) || 16 == gxInfo.cBPP) + data->format = SDL_PIXELFORMAT_RGB565; + else + if((gxInfo.ffFormat & kfDirect555) || 15 == gxInfo.cBPP) + data->format = SDL_PIXELFORMAT_RGB555; + } + + data->pixels = gxInfo.pvFrameBuffer; } + else + { + data->flags |= FB_SKIP_OFFSET; + data->pixels = data->gapi->GXBeginDraw(); + data->gapi->GXEndDraw(); + + if(data->debug) + { + printf("GAPI_Init\n"); + printf("use GXBeginDraw: %p\n", data->pixels); + printf("use skip offset\n"); + } + } + + if(0 == data->format || + 0 > WINCE_FixedGeometry(&data->fb, SDL_BYTESPERPIXEL(data->format), data->debug)) + { + SDL_SetError("GAPI_Init: unknown hardware"); + GAPI_Quit(data); + return 0; + } } + + return data->gapi && data->pixels ? 1 : 0; } -static int -GAPI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_Rect * dstrect) +void GAPI_Quit(WINCE_RenderData* data) { - GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; - int bpp; - int bytespp; - int status; - Uint32 Rmask, Gmask, Bmask, Amask; + if(data->gapi) + { + if(data->gapi->GXCloseDisplay) data->gapi->GXCloseDisplay(); + if(data->gapi->hGapiLib) FreeLibrary(data->gapi->hGapiLib); - if (texture->format != data->format) { - SDL_SetError("Gapi got wrong texture"); - return -1; + SDL_free(data->gapi); + data->gapi = NULL; } +} + +int RAW_Init(WINCE_RenderData* data) +{ + const char* preferably = SDL_getenv("SDL_VIDEO_RENDERER"); + if(preferably && 0 != SDL_strcasecmp(preferably, RAW_RENDER_NAME)) return 0; + + RawFrameBufferInfo rfbi = { 0 }; + HDC hdc = GetDC(NULL); + int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *) &rfbi); + ReleaseDC(NULL, hdc); - GAPI_LOG("GAPI_RenderCopy\n"); + //disable + if(result == 0 || rfbi.pFramePointer == 0 || + rfbi.cxPixels == 0 || rfbi.cyPixels == 0 || + rfbi.cxStride == 0 || rfbi.cyStride == 0) return 0; - if (data->usageFlags & USAGE_GX_FUNCS) { - char *buffer; - buffer = gx.GXBeginDraw(); - if (!(data->usageFlags & USAGE_DATA_PTR_CONSTANT)) { - data->data = buffer; - } + data->flags = FB_RAW_MODE; + + // fill FrameBufferInfo + SDL_memset(&data->fb, 0, sizeof(FrameBufferInfo)); + + data->fb.xpitch = rfbi.cxStride; + data->fb.ypitch = rfbi.cyStride; + data->fb.width = rfbi.cxPixels; + data->fb.height = rfbi.cyPixels; + data->fb.offset = 0; + + if((FORMAT_565 & rfbi.wFormat) || 16 == rfbi.wBPP) + data->format = SDL_PIXELFORMAT_RGB565; + else + if((FORMAT_555 & rfbi.wFormat) || 15 == rfbi.wBPP) + data->format = SDL_PIXELFORMAT_RGB555; + else + data->format = 0; + + if(0 == data->format || + 0 > WINCE_FixedGeometry(&data->fb, SDL_BYTESPERPIXEL(data->format), data->debug)) + { + SDL_SetError("RAW_Init: unknown hardware"); + RAW_Quit(data); + return 0; } - GAPI_LOG("GAPI_RenderCopy blit\n"); - /* If our framebuffer has an xPitch which matches the pixelsize, we - can convert the framebuffer to a SDL_surface and blit there, - otherwise, we have to use our own blitting routine - */ - SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, - &Amask); - bytespp = bpp >> 3; - if (data->xPitch == bytespp && 0) { - SDL_Surface *screen = - SDL_CreateRGBSurfaceFrom(data->data, data->w, data->h, - bpp, data->yPitch, Rmask, Gmask, Bmask, - Amask); - status = - SDL_UpperBlit((SDL_Surface *) texture->driverdata, srcrect, - screen, dstrect); - SDL_FreeSurface(screen); - } else { /* screen is rotated, we have to blit on our own */ - SDL_Surface *surface = (SDL_Surface *) texture->driverdata; + data->pixels = rfbi.pFramePointer; - char *src, *dst; - src = surface->pixels; - src += srcrect->y * surface->pitch + srcrect->x * 2; + return data->pixels ? 1 : 0; +} - dst = data->data + data->offset; - dst += dstrect->y * data->yPitch + dstrect->x * data->xPitch; +void RAW_Quit(WINCE_RenderData* data) +{ +} - updateLine16to16(src, 2, surface->pitch, - dst, data->xPitch, data->yPitch, - srcrect->w, srcrect->h); +void FrameBufferInitialize(FrameBufferInfo* fb) +{ + int orientation = GetFrameBufferOrientation(fb); + // set correct start offset + switch(orientation) + { + case ORIENTATION_UP: + fb->offset = 0; + break; + + case ORIENTATION_LEFT: + fb->offset = __abs(fb->ypitch * (fb->height - 1)); + break; + + case ORIENTATION_RIGHT: + fb->offset = __abs(fb->xpitch * (fb->width - 1)); + break; + + case ORIENTATION_DOWN: + fb->offset = __abs(fb->xpitch * (fb->width - 1) + + fb->ypitch * (fb->height - 1)); + break; + + default: break; } - Uint32 ticks = SDL_GetTicks(); - if (data->usageFlags & USAGE_GX_FUNCS) { - gx.GXEndDraw(); + //if(orientation != ORIENTATION_UP) + switch(orientation) + { + case ORIENTATION_LEFT: FrameBufferRotate(fb, ORIENTATION_RIGHT); break; + case ORIENTATION_RIGHT:FrameBufferRotate(fb, ORIENTATION_LEFT); break; + case ORIENTATION_DOWN: FrameBufferRotate(fb, ORIENTATION_DOWN); break; + + default: break; } - GAPI_LOG("GAPI_RenderCopy %i\n", SDL_GetTicks() - ticks); - return status; } -static void -GAPI_RenderPresent(SDL_Renderer * renderer) +int GetFrameBufferOrientation(const FrameBufferInfo* src) +{ + if(src->xpitch > 0 && src->ypitch > 0) + return ORIENTATION_UP; + else + if(src->xpitch > 0 && src->ypitch < 0) + return ORIENTATION_LEFT; + else + if(src->xpitch < 0 && src->ypitch > 0) + return ORIENTATION_RIGHT; + else + if(src->xpitch < 0 && src->ypitch < 0) + return ORIENTATION_DOWN; + + return ORIENTATION_UNKNOWN; +} + +void FrameBufferRotate(FrameBufferInfo* dst, int orientation) { - /* Nothing todo as we rendered directly to the screen on RenderCopy */ + FrameBufferInfo src; + // copy dst -> src + SDL_memcpy(&src, dst, sizeof(FrameBufferInfo)); + + switch(orientation) + { + case ORIENTATION_LEFT: + dst->width = src.height; + dst->height = src.width; + dst->xpitch = src.ypitch; + dst->ypitch = -src.xpitch; + dst->offset = src.offset + src.xpitch * (src.width - 1); + break; + + case ORIENTATION_RIGHT: + dst->width = src.height; + dst->height = src.width; + dst->xpitch = -src.ypitch; + dst->ypitch = src.xpitch; + dst->offset = src.offset + src.ypitch * (src.height - 1); + break; + + case ORIENTATION_DOWN: + FrameBufferRotate(dst, ORIENTATION_LEFT); + FrameBufferRotate(dst, ORIENTATION_LEFT); + break; + + default: + break; + } } -static void -GAPI_DestroyRenderer(SDL_Renderer * renderer) +void PointerRotate(POINT* pt, const FrameBufferInfo* fb, int orientation) { - GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; + switch(orientation) + { + case ORIENTATION_UP: + break; + + case ORIENTATION_LEFT: + { + int temp = pt->y; + pt->y = fb->height - pt->x; + pt->x = temp; + } + break; + + case ORIENTATION_RIGHT: + { + int temp = pt->x; + pt->x = fb->width - pt->y; + pt->y = temp; + } + break; + + case ORIENTATION_DOWN: + pt->x = fb->width - pt->x; + pt->y = fb->height - pt->y; + break; + + default: break; + } +} - if (data->usageFlags & USAGE_GX_FUNCS) { - gx.GXCloseDisplay(); +const char* GetOrientationName(int orientation) +{ + switch(orientation) + { + case ORIENTATION_UP: return "UP"; + case ORIENTATION_DOWN: return "DOWN"; + case ORIENTATION_LEFT: return "LEFT"; + case ORIENTATION_RIGHT: return "RIGHT"; + default: break; } - if (data) { - SDL_free(data); + return "UNKNOWN"; +} + +int WINCE_GetDMOrientation(void) +{ + DEVMODE sDevMode = {0}; + sDevMode.dmSize = sizeof(DEVMODE); + sDevMode.dmFields = DM_DISPLAYORIENTATION; + + // DMDO_0, DMDO_90, DMDO_180, DMDO_270 + if(DISP_CHANGE_BADMODE != ChangeDisplaySettingsEx(NULL, &sDevMode, 0, CDS_TEST, NULL)) + switch(sDevMode.dmDisplayOrientation) + { + case DMDO_0: return DMDO_0; + case DMDO_90: return DMDO_90; + case DMDO_180: return DMDO_180; + case DMDO_270: return DMDO_270; + default: break; + } + + SDL_SetError("WINCE_GetDMOrientation: ChangeDisplaySettingsEx return BADMODE"); + return -1; +} + +int WINCE_SetDMOrientation(int orientation) +{ + DEVMODE sDevMode = {0}; + sDevMode.dmSize = sizeof(DEVMODE); + sDevMode.dmFields = DM_DISPLAYORIENTATION; + + switch(orientation) + { + case DMDO_0: sDevMode.dmDisplayOrientation = DMDO_0; break; + case DMDO_90: sDevMode.dmDisplayOrientation = DMDO_90; break; + case DMDO_180: sDevMode.dmDisplayOrientation = DMDO_180; break; + case DMDO_270: sDevMode.dmDisplayOrientation = DMDO_270; break; + default: return 0; } - SDL_free(renderer); + + if(DISP_CHANGE_BADMODE != ChangeDisplaySettingsEx(NULL, &sDevMode, 0, CDS_RESET, NULL)) + return 1; + + SDL_SetError("WINCE_SetDMOrientation: ChangeDisplaySettingsEx return BADMODE"); + return -1; +} + +void FrameBufferDumpInfo(const FrameBufferInfo* fb, const char* name) +{ + printf("%s fb.width: %d\n", name, fb->width); + printf("%s fb.height: %d\n", name, fb->height); + printf("%s fb.xpitch: %d\n", name, fb->xpitch); + printf("%s fb.ypitch: %d\n", name, fb->ypitch); + printf("%s fb.offset: %d\n", name, fb->offset); + + int orientation = GetFrameBufferOrientation(fb); + printf("%s fb.orientation: %d, %s\n", name, orientation, GetOrientationName(orientation)); } -#endif /* SDL_VIDEO_RENDER_GAPI */ +void UpdateLine16to16(const FrameBufferInfo* fb, const Uint16* src, Uint16* dst, Uint16 width) +{ + if(2 == fb->xpitch) + { + switch(width) + { + case 1: + *dst = *src; + break; + + case 2: + *((Uint32*) dst) = *((Uint32*) src); + break; + + default: + SDL_memcpy(dst, src, width * 2); + break; + } + } + else + if(-2 == fb->xpitch) + { + while(width--) + *dst-- = *src++; + } + else + { + while(width--) + { + *dst = *src++; + dst += fb->xpitch / 2; + } + } +} -/* vi: set ts=4 sw=4 expandtab: */ +#endif // SDL_VIDEO_RENDER_GAPI diff --git a/src/video/win32/SDL_gapirender.h b/src/video/win32/SDL_gapirender.h index 3b9bb7fcf..8eff78f3d 100644 --- a/src/video/win32/SDL_gapirender.h +++ b/src/video/win32/SDL_gapirender.h @@ -27,7 +27,11 @@ /* SDL surface based renderer implementation */ #if SDL_VIDEO_RENDER_GAPI -extern void GAPI_AddRenderDriver(_THIS); +extern void WINCE_AddRenderDriver(_THIS); +extern int WINCE_Available(void); +extern void WINCE_ShowWindow(_THIS, SDL_Window* window, int visible); +extern int WINCE_GetDMOrientation(void); +extern int WINCE_SetDMOrientation(int orientation); #endif /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_gapirender_c.h b/src/video/win32/SDL_gapirender_c.h index 9af7d01b8..9779473e0 100644 --- a/src/video/win32/SDL_gapirender_c.h +++ b/src/video/win32/SDL_gapirender_c.h @@ -22,100 +22,3 @@ Stefan Klug klug.stefan@gmx.de */ - -#define WIN32_LEAN_AND_MEAN -#include - -/* hi res definitions */ -typedef struct _RawFrameBufferInfo -{ - WORD wFormat; - WORD wBPP; - VOID *pFramePointer; - int cxStride; - int cyStride; - int cxPixels; - int cyPixels; -} RawFrameBufferInfo; - -#define GETRAWFRAMEBUFFER 0x00020001 - -#define FORMAT_565 1 -#define FORMAT_555 2 -#define FORMAT_OTHER 3 - - -/* From gx.h, since it's not really C compliant */ - -struct GXDisplayProperties -{ - DWORD cxWidth; - DWORD cyHeight; // notice lack of 'th' in the word height. - long cbxPitch; // number of bytes to move right one x pixel - can be negative. - long cbyPitch; // number of bytes to move down one y pixel - can be negative. - long cBPP; // # of bits in each pixel - DWORD ffFormat; // format flags. -}; - -struct GXKeyList -{ - short vkUp; // key for up - POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates. - short vkDown; - POINT ptDown; - short vkLeft; - POINT ptLeft; - short vkRight; - POINT ptRight; - short vkA; - POINT ptA; - short vkB; - POINT ptB; - short vkC; - POINT ptC; - short vkStart; - POINT ptStart; -}; - -typedef int (*PFNGXOpenDisplay) (HWND hWnd, DWORD dwFlags); -typedef int (*PFNGXCloseDisplay) (); -typedef void *(*PFNGXBeginDraw) (); -typedef int (*PFNGXEndDraw) (); -typedef int (*PFNGXOpenInput) (); -typedef int (*PFNGXCloseInput) (); -typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties) (); -typedef struct GXKeyList (*PFNGXGetDefaultKeys) (int iOptions); -typedef int (*PFNGXSuspend) (); -typedef int (*PFNGXResume) (); -typedef int (*PFNGXSetViewport) (DWORD dwTop, DWORD dwHeight, - DWORD dwReserved1, DWORD dwReserved2); -typedef BOOL(*PFNGXIsDisplayDRAMBuffer) (); - -struct GapiFunc -{ - PFNGXOpenDisplay GXOpenDisplay; - PFNGXCloseDisplay GXCloseDisplay; - PFNGXBeginDraw GXBeginDraw; - PFNGXEndDraw GXEndDraw; - PFNGXOpenInput GXOpenInput; - PFNGXCloseInput GXCloseInput; - PFNGXGetDisplayProperties GXGetDisplayProperties; - PFNGXGetDefaultKeys GXGetDefaultKeys; - PFNGXSuspend GXSuspend; - PFNGXResume GXResume; - PFNGXSetViewport GXSetViewport; - PFNGXIsDisplayDRAMBuffer GXIsDisplayDRAMBuffer; -} gx; - -#define kfLandscape 0x8 // Screen is rotated 270 degrees -#define kfPalette 0x10 // Pixel values are indexes into a palette -#define kfDirect 0x20 // Pixel values contain actual level information -#define kfDirect555 0x40 // 5 bits each for red, green and blue values in a pixel. -#define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel -#define kfDirect888 0x100 // 8 bits each for red, green and blue values in a pixel. -#define kfDirect444 0x200 // 4 red, 4 green, 4 blue -#define kfDirectInverted 0x400 - -#define GX_FULLSCREEN 0x01 // for OpenDisplay() -#define GX_NORMALKEYS 0x02 -#define GX_LANDSCAPEKEYS 0x03 diff --git a/src/video/win32/SDL_gdirender.c b/src/video/win32/SDL_gdirender.c index d3fff00e2..5c9a3fcf9 100644 --- a/src/video/win32/SDL_gdirender.c +++ b/src/video/win32/SDL_gdirender.c @@ -184,6 +184,8 @@ GDI_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } + windowdata->videodata->render = RENDER_GDI; + renderer->DisplayModeChanged = GDI_DisplayModeChanged; renderer->CreateTexture = GDI_CreateTexture; renderer->QueryTexturePixels = GDI_QueryTexturePixels; @@ -267,6 +269,34 @@ GDI_CreateRenderer(SDL_Window * window, Uint32 flags) } data->current_hbm = 0; +#ifdef _WIN32_WCE + // check size for GDI fullscreen and rotate + if((window->flags & SDL_WINDOW_FULLSCREEN) && + GetSystemMetrics(SM_CXSCREEN) != GetSystemMetrics(SM_CYSCREEN) && + ((GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN) && window->w > window->h) || + (GetSystemMetrics(SM_CXSCREEN) > GetSystemMetrics(SM_CYSCREEN) && window->w < window->h))) + { + int orientation = WINCE_GetDMOrientation(); + switch(orientation) + { + case DMDO_0: orientation = DMDO_90; break; + case DMDO_270: orientation = DMDO_180; break; + case DMDO_90: orientation = DMDO_0; break; + case DMDO_180: orientation = DMDO_270; break; + + default: + GDI_DestroyRenderer(renderer); + return NULL; + } + + if(0 > WINCE_SetDMOrientation(orientation)) + { + GDI_DestroyRenderer(renderer); + return NULL; + } + } +#endif + return renderer; } @@ -416,6 +446,7 @@ GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) WIN_SetError("Couldn't create bitmap"); return -1; } + return 0; } diff --git a/src/video/win32/SDL_win32clipboard.c b/src/video/win32/SDL_win32clipboard.c index 22d54a682..e7e5fd687 100644 --- a/src/video/win32/SDL_win32clipboard.c +++ b/src/video/win32/SDL_win32clipboard.c @@ -95,7 +95,11 @@ WIN_SetClipboardText(_THIS, const char *text) WIN_SetError("Couldn't set clipboard data"); result = -1; } +#ifdef _WIN32_WCE + data->clipboard_count = 0; +#else data->clipboard_count = GetClipboardSequenceNumber(); +#endif } SDL_free(tstr); @@ -149,7 +153,11 @@ WIN_CheckClipboardUpdate(struct SDL_VideoData * data) { DWORD count; +#ifdef _WIN32_WCE + count = 0; +#else count = GetClipboardSequenceNumber(); +#endif if (count != data->clipboard_count) { if (data->clipboard_count) { SDL_SendClipboardUpdate(); diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index f48829a50..067424a35 100755 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -184,6 +184,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_MOUSEMOVE: +#ifdef _WIN32_WCE + /* transform coords for VGA, WVGA... */ + { + SDL_VideoData *videodata = data->videodata; + if(videodata->CoordTransform && + (videodata->render == RENDER_GAPI || videodata->render == RENDER_RAW)) + { + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + videodata->CoordTransform(data->window, &pt); + SDL_SendMouseMotion(data->window, 0, pt.x, pt.y); + break; + } + } +#endif SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam)); break; diff --git a/src/video/win32/SDL_win32modes.c b/src/video/win32/SDL_win32modes.c index 847e08343..992b61517 100644 --- a/src/video/win32/SDL_win32modes.c +++ b/src/video/win32/SDL_win32modes.c @@ -203,10 +203,18 @@ WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect) { SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->desktop_mode.driverdata; +#ifdef _WIN32_WCE + // WINCE: DEVMODE.dmPosition not found, or may be mingw32ce bug + rect->x = 0; + rect->y = 0; + rect->w = display->windows->w; + rect->h = display->windows->h; +#else rect->x = (int)data->DeviceMode.dmPosition.x; rect->y = (int)data->DeviceMode.dmPosition.y; rect->w = data->DeviceMode.dmPelsWidth; rect->h = data->DeviceMode.dmPelsHeight; +#endif return 0; } diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index 2c5d3146d..af21a2ff3 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -30,6 +30,7 @@ #include "SDL_win32video.h" #include "SDL_d3drender.h" #include "SDL_gdirender.h" +#include "SDL_gapirender.h" /* Initialization/Query functions */ static int WIN_VideoInit(_THIS); @@ -48,6 +49,7 @@ WIN_SetError(const char *prefix) SDL_free(message); } + /* WIN32 driver bootstrap functions */ static int @@ -73,6 +75,11 @@ WIN_DeleteDevice(SDL_VideoDevice * device) data->ddraw->lpVtbl->Release(data->ddraw); FreeLibrary(data->ddrawDLL); } +#endif +#ifdef _WIN32_WCE + if(data->hAygShell) { + FreeLibrary(data->hAygShell); + } #endif SDL_free(device->driverdata); SDL_free(device); @@ -138,6 +145,15 @@ WIN_CreateDevice(int devindex) } #endif /* SDL_VIDEO_RENDER_DDRAW */ +#ifdef _WIN32_WCE + data->hAygShell = LoadLibrary(TEXT("\\windows\\aygshell.dll")); + if(0 == data->hAygShell) + data->hAygShell = LoadLibrary(TEXT("aygshell.dll")); + data->SHFullScreen = (0 != data->hAygShell ? + (PFNSHFullScreen) GetProcAddress(data->hAygShell, TEXT("SHFullScreen")) : 0); + data->CoordTransform = NULL; +#endif + /* Set the function pointers */ device->VideoInit = WIN_VideoInit; device->VideoQuit = WIN_VideoQuit; @@ -186,10 +202,13 @@ WIN_CreateDevice(int devindex) } VideoBootStrap WIN32_bootstrap = { +#ifdef _WIN32_WCE + "wince", "SDL WinCE video driver", WINCE_Available, WIN_CreateDevice +#else "win32", "SDL Win32/64 video driver", WIN_Available, WIN_CreateDevice +#endif }; - int WIN_VideoInit(_THIS) { @@ -207,7 +226,7 @@ WIN_VideoInit(_THIS) GDI_AddRenderDriver(_this); #endif #if SDL_VIDEO_RENDER_GAPI - GAPI_AddRenderDriver(_this); + WINCE_AddRenderDriver(_this); #endif WIN_InitKeyboard(_this); diff --git a/src/video/win32/SDL_win32video.h b/src/video/win32/SDL_win32video.h index 6911f49b8..c3b754daa 100644 --- a/src/video/win32/SDL_win32video.h +++ b/src/video/win32/SDL_win32video.h @@ -28,7 +28,9 @@ #define WIN32_LEAN_AND_MEAN #define STRICT +#ifndef UNICODE #define UNICODE +#endif #undef WINVER #define WINVER 0x500 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices() */ #include @@ -63,10 +65,17 @@ #endif extern void WIN_SetError(const char *prefix); +enum { RENDER_NONE, RENDER_D3D, RENDER_DDRAW, RENDER_GDI, RENDER_GAPI, RENDER_RAW }; + +typedef BOOL (*PFNSHFullScreen)(HWND, DWORD); +typedef void (*PFCoordTransform)(SDL_Window*, POINT*); + /* Private display data */ typedef struct SDL_VideoData { + int render; + #if SDL_VIDEO_RENDER_D3D HANDLE d3dDLL; IDirect3D9 *d3d; @@ -75,6 +84,11 @@ typedef struct SDL_VideoData HANDLE ddrawDLL; IDirectDraw *ddraw; #endif +#ifdef _WIN32_WCE + HMODULE hAygShell; + PFNSHFullScreen SHFullScreen; + PFCoordTransform CoordTransform; +#endif DWORD clipboard_count; diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index 0de0bbeb2..425abbeac 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -34,45 +34,13 @@ #include "../../events/SDL_keyboard_c.h" #include "SDL_win32video.h" +#include "SDL_win32window.h" /* This is included after SDL_win32video.h, which includes windows.h */ #include "SDL_syswm.h" +#include "SDL_gapirender.h" -#define SHFS_SHOWTASKBAR 0x0001 -#define SHFS_HIDETASKBAR 0x0002 -#define SHFS_SHOWSIPBUTTON 0x0004 -#define SHFS_HIDESIPBUTTON 0x0008 -#define SHFS_SHOWSTARTICON 0x0010 -#define SHFS_HIDESTARTICON 0x0020 - -#ifdef _WIN32_WCE -// dynamically load aygshell dll because we want SDL to work on HPC and be300 -int aygshell_loaded = 0; -BOOL(WINAPI * SHFullScreen) (HWND hwndRequester, DWORD dwState) = 0; - - -static BOOL -CE_SHFullScreen(HWND hwndRequester, DWORD dwState) -{ - if (SHFullScreen == 0 && aygshell_loaded == 0) { - aygshell_loaded = 0; - void *lib = SDL_LoadObject("aygshell.dll"); - if (lib) { - SHFullScreen = - (BOOL(WINAPI *) (HWND, DWORD)) SDL_LoadFunction(lib, - "SHFullScreen"); - } - } - - if (SHFullScreen) { - SHFullScreen(hwndRequester, dwState); - //printf("SHFullscreen(%i)\n",dwState); - } -} - -#endif - /* Fake window to help with DirectInput events. */ HWND SDL_HelperWindow = NULL; static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher"); @@ -472,32 +440,22 @@ WIN_SetWindowSize(_THIS, SDL_Window * window) void WIN_ShowWindow(_THIS, SDL_Window * window) { +#ifdef _WIN32_WCE + WINCE_ShowWindow(_this, window, 1); +#else HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - ShowWindow(hwnd, SW_SHOW); - -#ifdef _WIN32_WCE - if (window->flags & SDL_WINDOW_FULLSCREEN) { - CE_SHFullScreen(hwnd, - SHFS_HIDESTARTICON | SHFS_HIDETASKBAR | - SHFS_HIDESIPBUTTON); - } #endif } void WIN_HideWindow(_THIS, SDL_Window * window) { +#ifdef _WIN32_WCE + WINCE_ShowWindow(_this, window, 0); +#else HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - ShowWindow(hwnd, SW_HIDE); - -#ifdef _WIN32_WCE - if (window->flags & SDL_WINDOW_FULLSCREEN) { - CE_SHFullScreen(hwnd, - SHFS_SHOWSTARTICON | SHFS_SHOWTASKBAR | - SHFS_SHOWSIPBUTTON); - } #endif } @@ -513,45 +471,33 @@ WIN_RaiseWindow(_THIS, SDL_Window * window) top = HWND_NOTOPMOST; } SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE)); - -#ifdef _WIN32_WCE - if (window->flags & SDL_WINDOW_FULLSCREEN) { - CE_SHFullScreen(hwnd, - SHFS_HIDESTARTICON | SHFS_HIDETASKBAR | - SHFS_HIDESIPBUTTON); - } -#endif } void WIN_MaximizeWindow(_THIS, SDL_Window * window) { HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - - ShowWindow(hwnd, SW_MAXIMIZE); + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; #ifdef _WIN32_WCE - if (window->flags & SDL_WINDOW_FULLSCREEN) { - CE_SHFullScreen(hwnd, - SHFS_HIDESTARTICON | SHFS_HIDETASKBAR | - SHFS_HIDESIPBUTTON); - } + if((window->flags & SDL_WINDOW_FULLSCREEN) && videodata->SHFullScreen) + videodata->SHFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON); #endif + + ShowWindow(hwnd, SW_MAXIMIZE); } void WIN_MinimizeWindow(_THIS, SDL_Window * window) { HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; ShowWindow(hwnd, SW_MINIMIZE); #ifdef _WIN32_WCE - if (window->flags & SDL_WINDOW_FULLSCREEN) { - CE_SHFullScreen(hwnd, - SHFS_SHOWSTARTICON | SHFS_SHOWTASKBAR | - SHFS_SHOWSIPBUTTON); - } + if((window->flags & SDL_WINDOW_FULLSCREEN) && videodata->SHFullScreen) + videodata->SHFullScreen(hwnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON | SHFS_SHOWSIPBUTTON); #endif } @@ -586,6 +532,9 @@ WIN_DestroyWindow(_THIS, SDL_Window * window) SDL_WindowData *data = (SDL_WindowData *) window->driverdata; if (data) { +#ifdef _WIN32_WCE + WINCE_ShowWindow(_this, window, 0); +#endif ReleaseDC(data->hwnd, data->hdc); if (data->created) { DestroyWindow(data->hwnd); diff --git a/src/video/win32/SDL_win32window.h b/src/video/win32/SDL_win32window.h index 58f0f24cf..43eeb01bc 100644 --- a/src/video/win32/SDL_win32window.h +++ b/src/video/win32/SDL_win32window.h @@ -24,6 +24,15 @@ #ifndef _SDL_win32window_h #define _SDL_win32window_h +#ifdef _WIN32_WCE +#define SHFS_SHOWTASKBAR 0x0001 +#define SHFS_HIDETASKBAR 0x0002 +#define SHFS_SHOWSIPBUTTON 0x0004 +#define SHFS_HIDESIPBUTTON 0x0008 +#define SHFS_SHOWSTARTICON 0x0010 +#define SHFS_HIDESTARTICON 0x0020 +#endif + typedef struct { SDL_Window *window;