Commit 8d14ec12 authored by Sam Lantinga's avatar Sam Lantinga

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.
parent 4e19d730
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
......
/*
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 <afletdinov@gmail.com> *
* *
* 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
......@@ -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: */
......@@ -22,100 +22,3 @@
Stefan Klug
klug.stefan@gmx.de
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/* 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
......@@ -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;
}
......
......@@ -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();
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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 <windows.h>
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment