Mercurial > sdl-ios-xcode
view src/video/win32/SDL_gapirender.c @ 5004:0c72ae7b7cb2
Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Changed the CAS return value to bool, so it's efficient with OSAtomicCompareAndSwap32Barrier()
Added an atomic test adapted from code by Michael Davidsaver
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 16 Jan 2011 15:16:39 -0800 |
parents | aa8888658021 |
children |
line wrap: on
line source
/*************************************************************************** * 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_win32window.h" #include "../SDL_yuv_sw_c.h" // 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; }; // 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 = { WINCE_CreateRenderer, { GAPI_RENDER_NAME, (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD), (SDL_TEXTUREMODULATE_NONE), (SDL_BLENDMODE_NONE), (SDL_SCALEMODE_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_RenderDriver RAW_RenderDriver = { WINCE_CreateRenderer, { RAW_RENDER_NAME, (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD), (SDL_TEXTUREMODULATE_NONE), (SDL_BLENDMODE_NONE), (SDL_SCALEMODE_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 } }; int WINCE_Available(void) { const char* preferably = SDL_getenv("SDL_VIDEO_RENDERER"); // 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(render_raw != 0 && rfbi.cxPixels != 0 && rfbi.cyPixels != 0 && rfbi.pFramePointer != 0 && rfbi.cxStride != 0 && rfbi.cyStride != 0) render_raw = 1; if(preferably && 0 == SDL_strcasecmp(preferably, RAW_RENDER_NAME)) return 0 != render_raw; // 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; } void WINCE_AddRenderDriver(_THIS) { HDC hdc; HMODULE render_gapi; int render_raw, ii; const char* preferably = SDL_getenv("SDL_VIDEO_RENDERER"); // raw check RawFrameBufferInfo rfbi = { 0 }; hdc = GetDC(NULL); render_raw = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *) &rfbi); ReleaseDC(NULL, hdc); if(render_raw != 0 && rfbi.cxPixels != 0 && rfbi.cyPixels != 0 && rfbi.pFramePointer != 0 && rfbi.cxStride != 0 && rfbi.cyStride != 0) render_raw = 1; // 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); 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); } } } SDL_Renderer* WINCE_CreateRenderer(SDL_Window* window, Uint32 flags) { 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; if(!(window->flags & SDL_WINDOW_FULLSCREEN)) window->flags |= SDL_WINDOW_FULLSCREEN; if(!SDL_PixelFormatEnumToMasks(displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { SDL_SetError("Unknown display format"); 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; } renderer = (SDL_Renderer*) SDL_calloc(1, sizeof(SDL_Renderer)); if(!renderer) { SDL_OutOfMemory(); return NULL; } data = (WINCE_RenderData*) SDL_calloc(1, sizeof(WINCE_RenderData)); if(!data) { WINCE_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } // initialize internal engine if(!RAW_Init(data) && !GAPI_Init(data, windowdata->hwnd)) { WINCE_DestroyRenderer(renderer); return NULL; } // 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; 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) { WINCE_RenderData *renderdata = (WINCE_RenderData*) renderer->driverdata; if(renderdata) { if(renderdata->gapi) GAPI_Quit(renderdata); else RAW_Quit(renderdata); 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; } texturedata->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); texturedata->pixels = SDL_malloc(texture->h * texturedata->pitch); if(NULL == texturedata->pixels) { SDL_OutOfMemory(); return -1; } if(SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 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; } texture->driverdata = texturedata; 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; } } int WINCE_QueryTexturePixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch) { WINCE_TextureData* texturedata = (WINCE_TextureData*) texture->driverdata; if(texturedata->yuv) return SDL_SW_QueryYUVTexturePixels(texturedata->yuv, pixels, pitch); *pixels = texturedata->pixels; *pitch = texturedata->pitch; return 0; } 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; if(texturedata->yuv) { if(SDL_SW_UpdateYUVTexture(texturedata->yuv, rect, pixels, pitch) < 0) return -1; WINCE_UpdateYUVTextureData(texture); return 0; } 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; if(texturedata->yuv) return SDL_SW_LockYUVTexture(texturedata->yuv, rect, dirty, pixels, pitch); *pixels = (void *) ((unsigned char*) texturedata->pixels + rect->y * texturedata->pitch + rect->x * SDL_BYTESPERPIXEL(texture->format)); *pitch = texturedata->pitch; } void WINCE_UnlockTexture(SDL_Renderer* renderer, SDL_Texture* texture) { WINCE_TextureData *texturedata = (WINCE_TextureData*) texture->driverdata; if(texturedata->yuv) { SDL_SW_UnlockYUVTexture(texturedata->yuv); WINCE_UpdateYUVTextureData(texture); } } 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; if((dstdata->flags & FB_SUSPENDED) || 0 >= srect->w || 0 >= srect->h) return; // 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 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; } } // unlock gapi if(dstdata->gapi) dstdata->gapi->GXEndDraw(); return 0; } void WINCE_RenderPresent(SDL_Renderer* renderer) { } int WINCE_RenderDrawPoints(SDL_Renderer* renderer, const SDL_Point* points, int count) { SDL_Unsupported(); return -1; } int WINCE_RenderDrawLines(SDL_Renderer* renderer, const SDL_Point* points, int count) { SDL_Unsupported(); return -1; } 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; } void WINCE_SetupOrientation(WINCE_RenderData* data, int width, int height) { 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; // scale define data->scale = maxW2 / maxW1; // 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; } // debug if(data->debug) { printf("\n"); printf("user video width: %d\n", width); printf("user video height: %d\n", height); FrameBufferDumpInfo(&data->fb, "user"); } } 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); } } } void WINCE_PointerCoordinateTransform(SDL_Window* window, POINT* pt) { WINCE_RenderData* data = (WINCE_RenderData*) window->renderer->driverdata; 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; } if(data->userOrientation != ORIENTATION_UP) FrameBufferRotate(&data->fb, data->userOrientation); } void WINCE_LandscapeTransform(WINCE_RenderData* data, int width, int height) { 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); } void WINCE_SquareTransform(WINCE_RenderData* data, int width, int height) { WINCE_PortraitTransform(data, width, height); } int WINCE_FixedGeometry(FrameBufferInfo* fb, int bpp, int debug) { // 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; } void WINCE_UpdateYUVTextureData(SDL_Texture* texture) { 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); } int GAPI_Init(WINCE_RenderData* data, HWND hwnd) { 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; } 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 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; } void GAPI_Quit(WINCE_RenderData* data) { if(data->gapi) { if(data->gapi->GXCloseDisplay) data->gapi->GXCloseDisplay(); if(data->gapi->hGapiLib) FreeLibrary(data->gapi->hGapiLib); 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); //disable if(result == 0 || rfbi.pFramePointer == 0 || rfbi.cxPixels == 0 || rfbi.cyPixels == 0 || rfbi.cxStride == 0 || rfbi.cyStride == 0) return 0; 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; } data->pixels = rfbi.pFramePointer; return data->pixels ? 1 : 0; } void RAW_Quit(WINCE_RenderData* data) { } 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; } //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; } } 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) { 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; } } void PointerRotate(POINT* pt, const FrameBufferInfo* fb, int orientation) { 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; } } 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; } 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; } 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)); } 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; } } } #endif // SDL_VIDEO_RENDER_GAPI