diff --git a/configure.in b/configure.in index d8b1bcf8..4648823e 100644 --- a/configure.in +++ b/configure.in @@ -2077,6 +2077,18 @@ CheckWIN32() ]) fi + AC_MSG_CHECKING(Windows CE) + have_wince=no + AC_TRY_COMPILE([ +#ifndef _WIN32_WCE +#error This is not Windows CE +#endif + ],[ + ],[ + have_wince=yes + ]) + AC_MSG_RESULT($have_wince) + dnl See if the user wants to redirect standard output to files AC_ARG_ENABLE(stdio-redirect, AC_HELP_STRING([--enable-stdio-redirect], [Redirect STDIO to files on Win32 [[default=yes]]]), @@ -2094,6 +2106,7 @@ AC_HELP_STRING([--enable-directx], [use DirectX for Win32 audio/video [[default= , enable_directx=yes) if test x$enable_directx = xyes; then AC_CHECK_HEADER(d3d9.h, have_d3d=yes) + AC_CHECK_HEADER(ddraw.h, have_ddraw=yes) AC_CHECK_HEADER(dsound.h, have_dsound=yes) AC_CHECK_HEADER(dinput.h, have_dinput=yes) fi @@ -2556,6 +2569,18 @@ AC_HELP_STRING([--enable-render-gdi], [enable the GDI render driver [[default=ye if test x$enable_render_gdi = xyes; then AC_DEFINE(SDL_VIDEO_RENDER_GDI) fi + AC_ARG_ENABLE(render-gapi, +AC_HELP_STRING([--enable-render-gapi], [enable the GAPI/RAWFRAMEBUFFER render driver [[default=yes]]]), + , enable_render_gapi=yes) + if test x$enable_render_gapi = xyes -a x$have_wince = xyes; then + AC_DEFINE(SDL_VIDEO_RENDER_GAPI) + fi + AC_ARG_ENABLE(render-ddraw, +AC_HELP_STRING([--enable-render-ddraw], [enable the Mobile DirectDraw render driver [[default=yes]]]), + , enable_render_ddraw=yes) + if test x$enable_render_ddraw = xyes -a x$have_wince = xyes -a x$have_ddraw = xyes; then + AC_DEFINE(SDL_VIDEO_RENDER_DDRAW) + fi AC_ARG_ENABLE(render-d3d, AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[default=yes]]]), , enable_render_d3d=yes) diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index c0219359..68ac2809 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -278,7 +278,6 @@ #undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC #undef SDL_VIDEO_DRIVER_DUMMY #undef SDL_VIDEO_DRIVER_FBCON -#undef SDL_VIDEO_DRIVER_GAPI #undef SDL_VIDEO_DRIVER_GEM #undef SDL_VIDEO_DRIVER_IPOD #undef SDL_VIDEO_DRIVER_NANOX @@ -312,6 +311,8 @@ #undef SDL_VIDEO_RENDER_OGL #undef SDL_VIDEO_RENDER_OGL_ES #undef SDL_VIDEO_RENDER_X11 +#undef SDL_VIDEO_RENDER_GAPI +#undef SDL_VIDEO_RENDER_DDRAW /* Enable OpenGL support */ #undef SDL_VIDEO_OPENGL diff --git a/src/video/win32/SDL_ceddrawrender.c b/src/video/win32/SDL_ceddrawrender.c new file mode 100644 index 00000000..29db3ccb --- /dev/null +++ b/src/video/win32/SDL_ceddrawrender.c @@ -0,0 +1,831 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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 +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_RENDER_DDRAW + +#include "SDL_win32video.h" +#include "../SDL_yuv_sw_c.h" + +#if 0 +#define DDRAW_LOG(...) printf(__VA_ARGS__) +#else +#define DDRAW_LOG(...) +#endif + + +/* DirectDraw renderer implementation */ + +static SDL_Renderer *DDRAW_CreateRenderer(SDL_Window * window, Uint32 flags); +static int DDRAW_DisplayModeChanged(SDL_Renderer * renderer); +static int DDRAW_CreateTexture(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DDRAW_QueryTexturePixels(SDL_Renderer * renderer, + SDL_Texture * texture, void **pixels, + int *pitch); +static int DDRAW_SetTextureColorMod(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DDRAW_SetTextureAlphaMod(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DDRAW_SetTextureBlendMode(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DDRAW_SetTextureScaleMode(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DDRAW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, + int pitch); +static int DDRAW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, int markDirty, + void **pixels, int *pitch); +static void DDRAW_UnlockTexture(SDL_Renderer * renderer, + SDL_Texture * texture); +static void DDRAW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, + int numrects, const SDL_Rect * rects); +static int DDRAW_RenderPoint(SDL_Renderer * renderer, int x, int y); +static int DDRAW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, + int y2); +static int DDRAW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); +static int DDRAW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_Rect * dstrect); +static void DDRAW_RenderPresent(SDL_Renderer * renderer); +static void DDRAW_DestroyTexture(SDL_Renderer * renderer, + SDL_Texture * texture); +static void DDRAW_DestroyRenderer(SDL_Renderer * renderer); + + +SDL_RenderDriver DDRAW_RenderDriver = { + DDRAW_CreateRenderer, + { + "ddraw", + (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | + SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | + SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED), + (SDL_TEXTUREMODULATE_NONE), + (SDL_BLENDMODE_NONE), + (SDL_TEXTURESCALEMODE_NONE), + 0, + {0}, + 0, + 0} +}; + +typedef struct +{ + IDirectDraw *ddraw; + IDirectDrawSurface *primary; +} DDRAW_RenderData; + +typedef struct +{ + RECT lock; + IDirectDrawSurface *surface; +} DDRAW_TextureData; + + +static void +DDRAW_SetError(const char *prefix, HRESULT result) +{ + const char *error; + + switch (result) { + case DDERR_CANTCREATEDC: + error = "CANTCREATEDC"; + break; + case DDERR_CANTLOCKSURFACE: + error = "CANTLOCKSURFACE"; + break; + case DDERR_CLIPPERISUSINGHWND: + error = "CLIPPERISUSINGHWND"; + break; + case DDERR_COLORKEYNOTSET: + error = "COLORKEYNOTSET"; + break; + case DDERR_CURRENTLYNOTAVAIL: + error = "CURRENTLYNOTAVAIL"; + break; + case DDERR_DCALREADYCREATED: + error = "DCALREADYCREATED"; + break; + case DDERR_DEVICEDOESNTOWNSURFACE: + error = "DEVICEDOESNTOWNSURFACE"; + break; + case DDERR_DIRECTDRAWALREADYCREATED: + error = "DIRECTDRAWALREADYCREATED"; + break; + case DDERR_EXCLUSIVEMODEALREADYSET: + error = "EXCLUSIVEMODEALREADYSET"; + break; + case DDERR_GENERIC: + error = "GENERIC"; + break; + case DDERR_HEIGHTALIGN: + error = "HEIGHTALIGN"; + break; + case DDERR_IMPLICITLYCREATED: + error = "IMPLICITLYCREATED"; + break; + case DDERR_INCOMPATIBLEPRIMARY: + error = "INCOMPATIBLEPRIMARY"; + break; + case DDERR_INVALIDCAPS: + error = "INVALIDCAPS"; + break; + case DDERR_INVALIDCLIPLIST: + error = "INVALIDCLIPLIST"; + break; + case DDERR_INVALIDMODE: + error = "INVALIDMODE"; + break; + case DDERR_INVALIDOBJECT: + error = "INVALIDOBJECT"; + break; + case DDERR_INVALIDPARAMS: + error = "INVALIDPARAMS"; + break; + case DDERR_INVALIDPIXELFORMAT: + error = "INVALIDPIXELFORMAT"; + break; + case DDERR_INVALIDPOSITION: + error = "INVALIDPOSITION"; + break; + case DDERR_INVALIDRECT: + error = "INVALIDRECT"; + break; + case DDERR_LOCKEDSURFACES: + error = "LOCKEDSURFACES"; + break; + case DDERR_MOREDATA: + error = "MOREDATA"; + break; + case DDERR_NOALPHAHW: + error = "NOALPHAHW"; + break; + case DDERR_NOBLTHW: + error = "NOBLTHW"; + break; + case DDERR_NOCLIPLIST: + error = "NOCLIPLIST"; + break; + case DDERR_NOCLIPPERATTACHED: + error = "NOCLIPPERATTACHED"; + break; + case DDERR_NOCOLORCONVHW: + error = "NOCOLORCONVHW"; + break; + case DDERR_NOCOLORKEYHW: + error = "NOCOLORKEYHW"; + break; + case DDERR_NOCOOPERATIVELEVELSET: + error = "NOCOOPERATIVELEVELSET"; + break; + case DDERR_NODC: + error = "NODC"; + break; + case DDERR_NOFLIPHW: + error = "NOFLIPHW"; + break; + case DDERR_NOOVERLAYDEST: + error = "NOOVERLAYDEST"; + break; + case DDERR_NOOVERLAYHW: + error = "NOOVERLAYHW"; + break; + case DDERR_NOPALETTEATTACHED: + error = "NOPALETTEATTACHED"; + break; + case DDERR_NOPALETTEHW: + error = "NOPALETTEHW"; + break; + case DDERR_NORASTEROPHW: + error = "NORASTEROPHW"; + break; + case DDERR_NOSTRETCHHW: + error = "NOSTRETCHHW"; + break; + case DDERR_NOTAOVERLAYSURFACE: + error = "NOTAOVERLAYSURFACE"; + break; + case DDERR_NOTFLIPPABLE: + error = "NOTFLIPPABLE"; + break; + case DDERR_NOTFOUND: + error = "NOTFOUND"; + break; + case DDERR_NOTLOCKED: + error = "NOTLOCKED"; + break; + case DDERR_NOTPALETTIZED: + error = "NOTPALETTIZED"; + break; + case DDERR_NOVSYNCHW: + error = "NOVSYNCHW"; + break; + case DDERR_NOZOVERLAYHW: + error = "NOZOVERLAYHW"; + break; + case DDERR_OUTOFCAPS: + error = "OUTOFCAPS"; + break; + case DDERR_OUTOFMEMORY: + error = "OUTOFMEMORY"; + break; + case DDERR_OUTOFVIDEOMEMORY: + error = "OUTOFVIDEOMEMORY"; + break; + case DDERR_OVERLAPPINGRECTS: + error = "OVERLAPPINGRECTS"; + break; + case DDERR_OVERLAYNOTVISIBLE: + error = "OVERLAYNOTVISIBLE"; + break; + case DDERR_PALETTEBUSY: + error = "PALETTEBUSY"; + break; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + error = "PRIMARYSURFACEALREADYEXISTS"; + break; + case DDERR_REGIONTOOSMALL: + error = "REGIONTOOSMALL"; + break; + case DDERR_SURFACEBUSY: + error = "SURFACEBUSY"; + break; + case DDERR_SURFACELOST: + error = "SURFACELOST"; + break; + case DDERR_TOOBIGHEIGHT: + error = "TOOBIGHEIGHT"; + break; + case DDERR_TOOBIGSIZE: + error = "TOOBIGSIZE"; + break; + case DDERR_TOOBIGWIDTH: + error = "TOOBIGWIDTH"; + break; + case DDERR_UNSUPPORTED: + error = "UNSUPPORTED"; + break; + case DDERR_UNSUPPORTEDFORMAT: + error = "UNSUPPORTEDFORMAT"; + break; + case DDERR_VERTICALBLANKINPROGRESS: + error = "VERTICALBLANKINPROGRESS"; + break; + case DDERR_VIDEONOTACTIVE: + error = "VIDEONOTACTIVE"; + break; + case DDERR_WASSTILLDRAWING: + error = "WASSTILLDRAWING"; + break; + case DDERR_WRONGMODE: + error = "WRONGMODE"; + break; + default: + error = "UNKNOWN"; + break; + } + SDL_SetError("%s: %s", prefix, error); +} + +static SDL_bool +PixelFormatToDDPIXELFORMAT(Uint32 format, LPDDPIXELFORMAT dst) +{ + SDL_zerop(dst); + dst->dwSize = sizeof(*dst); + + if (SDL_ISPIXELFORMAT_FOURCC(format)) { + dst->dwFlags = DDPF_FOURCC; + dst->dwFourCC = format; + } else if (SDL_ISPIXELFORMAT_INDEXED(format)) { + SDL_SetError("Indexed pixelformats are not supported."); + return SDL_FALSE; + } else { + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + if (!SDL_PixelFormatEnumToMasks + (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + SDL_SetError("pixelformat not supported"); + return SDL_FALSE; + } + + if (!Rmask && !Gmask && !Bmask) { + dst->dwFlags = DDPF_ALPHA; + dst->dwAlphaBitDepth = bpp; + } else { + dst->dwFlags = DDPF_RGB; + dst->dwRGBBitCount = bpp; + dst->dwRBitMask = Rmask; + dst->dwGBitMask = Gmask; + dst->dwBBitMask = Bmask; + + if (Amask) { + dst->dwFlags |= DDPF_ALPHAPIXELS; + dst->dwRGBAlphaBitMask = Amask; + } + } + } + + return SDL_TRUE; +} + +static SDL_bool +DDRAW_IsTextureFormatAvailable(IDirectDraw * ddraw, Uint32 display_format, + Uint32 texture_format) +{ + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + if (SDL_ISPIXELFORMAT_FOURCC(texture_format)) { + //TODO I don't expect DDRAW to support all 4CC formats, but I don't know which ones + return SDL_TRUE; + } + //These are only basic checks + if (SDL_ISPIXELFORMAT_INDEXED(texture_format)) { + return SDL_FALSE; + } + + if (!SDL_PixelFormatEnumToMasks + (texture_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + return SDL_FALSE; + } + + switch (bpp) { + case 4: + case 8: + case 16: + case 24: + case 32: + break; + default: + return SDL_FALSE; + } + + return SDL_TRUE; +} + +void +DDRAW_AddRenderDriver(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + SDL_RendererInfo *info = &DDRAW_RenderDriver.info; + SDL_DisplayMode *mode = &SDL_CurrentDisplay.desktop_mode; + + if (data->ddraw) { + int i; + int formats[] = { + SDL_PIXELFORMAT_INDEX8, + SDL_PIXELFORMAT_RGB332, + SDL_PIXELFORMAT_RGB444, + SDL_PIXELFORMAT_RGB555, + SDL_PIXELFORMAT_ARGB4444, + SDL_PIXELFORMAT_ARGB1555, + SDL_PIXELFORMAT_RGB565, + SDL_PIXELFORMAT_RGB888, + SDL_PIXELFORMAT_ARGB8888, + SDL_PIXELFORMAT_ARGB2101010, + }; + + for (i = 0; i < SDL_arraysize(formats); ++i) { + if (DDRAW_IsTextureFormatAvailable + (data->ddraw, mode->format, formats[i])) { + info->texture_formats[info->num_texture_formats++] = + formats[i]; + } + } + + //TODO the fourcc formats should get fetched from IDirectDraw::GetFourCCCodes + info->texture_formats[info->num_texture_formats++] = + SDL_PIXELFORMAT_YV12; + info->texture_formats[info->num_texture_formats++] = + SDL_PIXELFORMAT_IYUV; + info->texture_formats[info->num_texture_formats++] = + SDL_PIXELFORMAT_YUY2; + info->texture_formats[info->num_texture_formats++] = + SDL_PIXELFORMAT_UYVY; + info->texture_formats[info->num_texture_formats++] = + SDL_PIXELFORMAT_YVYU; + + SDL_AddRenderDriver(0, &DDRAW_RenderDriver); + } +} + +SDL_Renderer * +DDRAW_CreateRenderer(SDL_Window * window, Uint32 flags) +{ + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata; + SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; + SDL_Renderer *renderer; + DDRAW_RenderData *data; + HRESULT result; + DDSURFACEDESC ddsd; + + renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); + if (!renderer) { + SDL_OutOfMemory(); + return NULL; + } + + data = (DDRAW_RenderData *) SDL_calloc(1, sizeof(*data)); + if (!data) { + DDRAW_DestroyRenderer(renderer); + SDL_OutOfMemory(); + return NULL; + } + data->ddraw = videodata->ddraw; + + renderer->DisplayModeChanged = DDRAW_DisplayModeChanged; + renderer->CreateTexture = DDRAW_CreateTexture; + renderer->QueryTexturePixels = DDRAW_QueryTexturePixels; + + renderer->SetTextureColorMod = DDRAW_SetTextureColorMod; + renderer->SetTextureAlphaMod = DDRAW_SetTextureAlphaMod; + renderer->SetTextureBlendMode = DDRAW_SetTextureBlendMode; + renderer->SetTextureScaleMode = DDRAW_SetTextureScaleMode; + renderer->UpdateTexture = DDRAW_UpdateTexture; + renderer->LockTexture = DDRAW_LockTexture; + renderer->UnlockTexture = DDRAW_UnlockTexture; + renderer->DirtyTexture = DDRAW_DirtyTexture; + renderer->RenderPoint = DDRAW_RenderPoint; + renderer->RenderLine = DDRAW_RenderLine; + renderer->RenderFill = DDRAW_RenderFill; + renderer->RenderCopy = DDRAW_RenderCopy; + renderer->RenderPresent = DDRAW_RenderPresent; + renderer->DestroyTexture = DDRAW_DestroyTexture; + renderer->DestroyRenderer = DDRAW_DestroyRenderer; + renderer->info = DDRAW_RenderDriver.info; + renderer->window = window->id; + renderer->driverdata = data; + + renderer->info.flags = SDL_RENDERER_ACCELERATED; + + SDL_zero(ddsd); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + + if (window->flags & SDL_WINDOW_FULLSCREEN) { + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + } else { + //TODO handle non fullscreen + SDL_SetError("DirectDraw renderer has only fullscreen implemented"); + DDRAW_DestroyRenderer(renderer); + return NULL; + } + + if (flags & SDL_RENDERER_PRESENTFLIP2) { + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; + ddsd.dwBackBufferCount = 2; + } else if (flags & SDL_RENDERER_PRESENTFLIP3) { + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; + ddsd.dwBackBufferCount = 3; + } else if (flags & SDL_RENDERER_PRESENTCOPY) { + //TODO what is the best approximation to this mode + } else { + + } + + if (flags & SDL_RENDERER_PRESENTVSYNC) { + SDL_SetError("DirectDraw renderer with v-sync is not implemented"); + DDRAW_DestroyRenderer(renderer); + return NULL; + } + + result = + data->ddraw->lpVtbl->SetCooperativeLevel(data->ddraw, + windowdata->hwnd, + DDSCL_NORMAL); + if (result != DD_OK) { + DDRAW_SetError("CreateDevice()", result); + DDRAW_DestroyRenderer(renderer); + return NULL; + } + + result = + data->ddraw->lpVtbl->CreateSurface(data->ddraw, &ddsd, &data->primary, + NULL); + if (result != DD_OK) { + DDRAW_SetError("CreateDevice()", result); + DDRAW_DestroyRenderer(renderer); + return NULL; + } + + return renderer; +} + +static int +DDRAW_Reset(SDL_Renderer * renderer) +{ + //TODO implement + /*D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; + HRESULT result; + + result = IDirect3DDevice9_Reset(data->device, &data->pparams); + if (FAILED(result)) { + if (result == D3DERR_DEVICELOST) { + /* Don't worry about it, we'll reset later... * + return 0; + } else { + D3D_SetError("Reset()", result); + return -1; + } + } + IDirect3DDevice9_SetVertexShader(data->device, NULL); + IDirect3DDevice9_SetFVF(data->device, + D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, + D3DCULL_NONE); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); */ + return 0; +} + +static int +DDRAW_DisplayModeChanged(SDL_Renderer * renderer) +{ + //TODO implement + /*D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; + SDL_Window *window = SDL_GetWindowFromID(renderer->window); + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + + data->pparams.BackBufferWidth = window->w; + data->pparams.BackBufferHeight = window->h; + if (window->flags & SDL_WINDOW_FULLSCREEN) { + data->pparams.BackBufferFormat = + PixelFormatToD3DFMT(display->fullscreen_mode.format); + } else { + data->pparams.BackBufferFormat = D3DFMT_UNKNOWN; + } + return D3D_Reset(renderer); */ + return 0; +} + +static int +DDRAW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + DDRAW_RenderData *renderdata = (DDRAW_RenderData *) renderer->driverdata; + SDL_Window *window = SDL_GetWindowFromID(renderer->window); + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + Uint32 display_format = display->current_mode.format; + DDRAW_TextureData *data; + DDSURFACEDESC ddsd; + HRESULT result; + + data = (DDRAW_TextureData *) SDL_calloc(1, sizeof(*data)); + if (!data) { + SDL_OutOfMemory(); + return -1; + } + + SDL_zero(ddsd); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.dwWidth = texture->w; + ddsd.dwHeight = texture->h; + + + if (!PixelFormatToDDPIXELFORMAT(texture->format, &ddsd.ddpfPixelFormat)) { + SDL_free(data); + return -1; + } + + texture->driverdata = data; + + result = + renderdata->ddraw->lpVtbl->CreateSurface(renderdata->ddraw, &ddsd, + &data->surface, NULL); + if (result != DD_OK) { + SDL_free(data); + DDRAW_SetError("CreateTexture", result); + return -1; + } + + return 0; +} + +static int +DDRAW_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, + void **pixels, int *pitch) +{ + //TODO implement + SDL_SetError("QueryTexturePixels is not implemented"); + return -1; +} + +static int +DDRAW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + return 0; +} + +static int +DDRAW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + return 0; +} + +static int +DDRAW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) +{ + switch (texture->blendMode) { + case SDL_BLENDMODE_NONE: + return 0; + default: + SDL_Unsupported(); + texture->blendMode = SDL_BLENDMODE_NONE; + return -1; + } +} + +static int +DDRAW_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) +{ + switch (texture->scaleMode) { + case SDL_TEXTURESCALEMODE_NONE: + default: + SDL_Unsupported(); + texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; + return -1; + } + return 0; +} + +static int +DDRAW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, int pitch) +{ + DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata; + + //TODO implement + SDL_SetError("UpdateTexture is not implemented"); + return 0; +} + +static int +DDRAW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, int markDirty, void **pixels, + int *pitch) +{ + DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata; + HRESULT result; + DDSURFACEDESC ddsd; + + SDL_zero(ddsd); + ddsd.dwSize = sizeof(ddsd); + + /** + * On a Axim x51v locking a subrect returns the startaddress of the whole surface, + * wheras on my ASUS MyPal 696 the startaddress of the locked area is returned, + * thats why I always lock the whole surface and calculate the pixels pointer by hand. + * This shouldn't be a speed problem, as multiple locks aren't available on DDraw Mobile + * see http://msdn.microsoft.com/en-us/library/ms858221.aspx + */ + + result = data->surface->lpVtbl->Lock(data->surface, NULL, &ddsd, 0, NULL); + if (result != DD_OK) { + DDRAW_SetError("LockRect()", result); + return -1; + } + + *pixels = ddsd.lpSurface + rect->y * ddsd.lPitch + rect->x * ddsd.lXPitch; + *pitch = ddsd.lPitch; + return 0; +} + +static void +DDRAW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata; + + data->surface->lpVtbl->Unlock(data->surface, NULL); +} + +static void +DDRAW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, + int numrects, const SDL_Rect * rects) +{ +} + +static void +DDRAW_SetBlendMode(DDRAW_RenderData * data, int blendMode) +{ + switch (blendMode) { + + } +} + +static int +DDRAW_RenderPoint(SDL_Renderer * renderer, int x, int y) +{ + return -1; +} + +static int +DDRAW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) +{ + return -1; +} + +static int +DDRAW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + return -1; +} + +static int +DDRAW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect) +{ + DDRAW_RenderData *data = (DDRAW_RenderData *) renderer->driverdata; + DDRAW_TextureData *texturedata = + (DDRAW_TextureData *) texture->driverdata; + HRESULT result; + RECT srcr; + RECT dstr; + DDBLTFX bltfx; + + srcr.left = srcrect->x; + srcr.top = srcrect->y; + srcr.right = srcrect->x + srcrect->w; + srcr.bottom = srcrect->y + srcrect->h; + + dstr.left = dstrect->x; + dstr.top = dstrect->y; + dstr.right = dstrect->x + dstrect->w; + dstr.bottom = dstrect->y + dstrect->h; + + SDL_zero(bltfx); + bltfx.dwSize = sizeof(bltfx); + bltfx.dwROP = SRCCOPY; + + data->primary->lpVtbl->Blt(data->primary, &dstr, texturedata->surface, + &srcr, DDBLT_ROP, &bltfx); + + return 0; +} + +static void +DDRAW_RenderPresent(SDL_Renderer * renderer) +{ + DDRAW_RenderData *data = (DDRAW_RenderData *) renderer->driverdata; + HRESULT result; + + return; + + result = + data->primary->lpVtbl->Flip(data->primary, NULL, DDFLIP_INTERVAL1); + if (result != DD_OK) { + DDRAW_SetError("Present()", result); + } +} + +static void +DDRAW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + DDRAW_TextureData *data = (DDRAW_TextureData *) texture->driverdata; + + if (!data) { + return; + } + + data->surface->lpVtbl->Release(data->surface); + SDL_free(data); + texture->driverdata = NULL; +} + +static void +DDRAW_DestroyRenderer(SDL_Renderer * renderer) +{ + DDRAW_RenderData *data = (DDRAW_RenderData *) renderer->driverdata; + + if (data) { + data->primary->lpVtbl->Release(data->primary); + SDL_free(data); + } + SDL_free(renderer); +} + +#endif /* SDL_VIDEO_RENDER_DDRAW */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_ceddrawrender.h b/src/video/win32/SDL_ceddrawrender.h new file mode 100644 index 00000000..873825e0 --- /dev/null +++ b/src/video/win32/SDL_ceddrawrender.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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 +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_RENDER_DDRAW +extern void DDRAW_AddRenderDriver(_THIS); +#endif + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_gapirender.c b/src/video/win32/SDL_gapirender.c new file mode 100644 index 00000000..30908d03 --- /dev/null +++ b/src/video/win32/SDL_gapirender.c @@ -0,0 +1,646 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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 +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_RENDER_GAPI + +#include "SDL_win32video.h" +//#include "../SDL_sysvideo.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 */ + +static SDL_Renderer *GAPI_CreateRenderer(SDL_Window * window, Uint32 flags); +static int GAPI_RenderPoint(SDL_Renderer * renderer, int x, int y); +static int GAPI_RenderLine(SDL_Renderer * renderer, int x1, int y1, + int x2, int y2); +static int GAPI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); +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); + + +SDL_RenderDriver GAPI_RenderDriver = { + GAPI_CreateRenderer, + { + "gapi", + (SDL_RENDERER_SINGLEBUFFER), + } +}; + +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_SetError("%s: %s", prefix, error); +} + +void +GAPI_AddRenderDriver(_THIS) +{ + /* 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 + + 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 + } + + SDL_AddRenderDriver(0, &GAPI_RenderDriver); +} + +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; + + + +typedef struct +{ + 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 */ + + void *data; + Uint32 usageFlags; /* these flags contain options to define screen handling and to reliably workarounds */ + + Uint32 format; /* pixel format as defined in SDL_pixels.h */ + +} GAPI_RenderData; + + +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; + } +} + +static GAPI_RenderData * +FillRenderDataRawFramebuffer(SDL_Window * window) +{ + RawFrameBufferInfo rbi; + GAPI_RenderData *renderdata; + HDC hdc; + + //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 (!(result > 0)) { + 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; + } + + + renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(*renderdata)); + if (!renderdata) { + 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); + 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); + 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; + +} + + +static GAPI_RenderData * +FillRenderDataGAPI(SDL_Window * window) +{ + GAPI_RenderData *renderdata; + struct GXDisplayProperties gxdp; + int tmp; + +#ifdef _ARM_ + WCHAR oemstr[100]; +#endif + + if (!g_hGapiLib) { + return NULL; + } + + renderdata = (GAPI_RenderData *) SDL_calloc(1, sizeof(GAPI_RenderData)); + if (!renderdata) { + SDL_OutOfMemory(); + return NULL; + } + + 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 + { + 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; + } + } + } +#endif + + + if (renderdata->format == SDL_PIXELFORMAT_UNKNOWN) { + SDL_SetError("Gapi Pixelformat is unknown"); + SDL_free(renderdata); + return NULL; + } + + /* Gapi always returns values in standard orientation, so we manually apply + the current orientation + */ + + DEVMODE settings; + SDL_memset(&settings, 0, sizeof(DEVMODE)); + settings.dmSize = sizeof(DEVMODE); + + settings.dmFields = DM_DISPLAYORIENTATION; + ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL); + + if (settings.dmDisplayOrientation == DMDO_90) { + + tmp = renderdata->w; + renderdata->w = renderdata->h; + renderdata->h = tmp; + + tmp = renderdata->xPitch; + renderdata->xPitch = -renderdata->yPitch; + renderdata->yPitch = tmp; + + renderdata->offset = -renderdata->w * renderdata->xPitch; + + } else if (settings.dmDisplayOrientation == DMDO_180) { + + renderdata->xPitch = -renderdata->xPitch; + renderdata->yPitch = -renderdata->yPitch; + + renderdata->offset = -renderdata->h * renderdata->yPitch + - renderdata->w * renderdata->xPitch; + + } else if (settings.dmDisplayOrientation == DMDO_270) { + + tmp = renderdata->w; + renderdata->w = renderdata->h; + renderdata->h = tmp; + + tmp = renderdata->xPitch; + renderdata->xPitch = renderdata->yPitch; + renderdata->yPitch = -tmp; + + renderdata->offset = -renderdata->h * renderdata->yPitch; + + } + + 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; + } + + return renderdata; + +} + + +/* 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) +{ + /* 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); + + return res; +} + +void * +GetFramebuffer() +{ + +} + + +SDL_Renderer * +GAPI_CreateRenderer(SDL_Window * window, Uint32 flags) +{ + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + 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; + + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + SDL_SetError("Gapi supports only fullscreen windows"); + return NULL; + } + + if (!SDL_PixelFormatEnumToMasks + (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + SDL_SetError("Unknown display format"); + return NULL; + } + + renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); + if (!renderer) { + SDL_OutOfMemory(); + return NULL; + } + + data = FillRenderData(window); + if (!data) { + GAPI_DestroyRenderer(renderer); + SDL_OutOfMemory(); + return NULL; + } + + renderer->RenderPoint = GAPI_RenderPoint; + renderer->RenderLine = GAPI_RenderLine; + renderer->RenderFill = GAPI_RenderFill; + 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->id; + 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 + + if (data->usageFlags & USAGE_GX_FUNCS) { + if (gx.GXOpenDisplay(windowdata->hwnd, GX_FULLSCREEN) == 0) { + GAPI_DestroyRenderer(renderer); + return NULL; + } + } + + return renderer; +} + +static int +GAPI_RenderPoint(SDL_Renderer * renderer, int x, int y) +{ + //TODO implement + return -1; +} + +static int +GAPI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) +{ + //TODO implement + return -11; +} + +static int +GAPI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + //TODO implement + return -1; +} + +/* 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) +{ + char *srcLine, *dstLine; + char *srcPix, *dstPix; + + int x, y; + + //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; + } + } +} + +static int +GAPI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_Rect * dstrect) +{ + GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; + int bpp; + int bytespp; + int status; + Uint32 Rmask, Gmask, Bmask, Amask; + + if (texture->format != data->format) { + SDL_SetError("Gapi got wrong texture"); + return -1; + } + + GAPI_LOG("GAPI_RenderCopy\n"); + + if (data->usageFlags & USAGE_GX_FUNCS) { + char *buffer; + buffer = gx.GXBeginDraw(); + if (!(data->usageFlags & USAGE_DATA_PTR_CONSTANT)) { + data->data = buffer; + } + } + + 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; + + char *src, *dst; + src = surface->pixels; + src += srcrect->y * surface->pitch + srcrect->x * 2; + + dst = data->data + data->offset; + dst += dstrect->y * data->yPitch + dstrect->x * data->xPitch; + + updateLine16to16(src, 2, surface->pitch, + dst, data->xPitch, data->yPitch, + srcrect->w, srcrect->h); + + } + + Uint32 ticks = SDL_GetTicks(); + if (data->usageFlags & USAGE_GX_FUNCS) { + gx.GXEndDraw(); + } + GAPI_LOG("GAPI_RenderCopy %i\n", SDL_GetTicks() - ticks); + return status; +} + +static void +GAPI_RenderPresent(SDL_Renderer * renderer) +{ + /* Nothing todo as we rendered directly to the screen on RenderCopy */ +} + +static void +GAPI_DestroyRenderer(SDL_Renderer * renderer) +{ + GAPI_RenderData *data = (GAPI_RenderData *) renderer->driverdata; + + if (data->usageFlags & USAGE_GX_FUNCS) { + gx.GXCloseDisplay(); + } + + if (data) { + SDL_free(data); + } + SDL_free(renderer); +} + +#endif /* SDL_VIDEO_RENDER_GAPI */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_gapirender.h b/src/video/win32/SDL_gapirender.h new file mode 100644 index 00000000..b517a515 --- /dev/null +++ b/src/video/win32/SDL_gapirender.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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 +*/ +#include "SDL_config.h" + +/* SDL surface based renderer implementation */ + +#if SDL_VIDEO_RENDER_GAPI +extern void GAPI_AddRenderDriver(_THIS); +#endif + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_gapirender_c.h b/src/video/win32/SDL_gapirender_c.h new file mode 100644 index 00000000..25dff673 --- /dev/null +++ b/src/video/win32/SDL_gapirender_c.h @@ -0,0 +1,121 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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 +*/ + +#define WIN32_LEAN_AND_MEAN +#include + +/* hi res definitions */ +typedef struct _RawFrameBufferInfo +{ + WORD wFormat; + WORD wBPP; + VOID *pFramePointer; + int cxStride; + int cyStride; + int cxPixels; + int cyPixels; +} RawFrameBufferInfo; + +#define GETRAWFRAMEBUFFER 0x00020001 + +#define FORMAT_565 1 +#define FORMAT_555 2 +#define FORMAT_OTHER 3 + + +/* From gx.h, since it's not really C compliant */ + +struct GXDisplayProperties +{ + DWORD cxWidth; + DWORD cyHeight; // notice lack of 'th' in the word height. + long cbxPitch; // number of bytes to move right one x pixel - can be negative. + long cbyPitch; // number of bytes to move down one y pixel - can be negative. + long cBPP; // # of bits in each pixel + DWORD ffFormat; // format flags. +}; + +struct GXKeyList +{ + short vkUp; // key for up + POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates. + short vkDown; + POINT ptDown; + short vkLeft; + POINT ptLeft; + short vkRight; + POINT ptRight; + short vkA; + POINT ptA; + short vkB; + POINT ptB; + short vkC; + POINT ptC; + short vkStart; + POINT ptStart; +}; + +typedef int (*PFNGXOpenDisplay) (HWND hWnd, DWORD dwFlags); +typedef int (*PFNGXCloseDisplay) (); +typedef void *(*PFNGXBeginDraw) (); +typedef int (*PFNGXEndDraw) (); +typedef int (*PFNGXOpenInput) (); +typedef int (*PFNGXCloseInput) (); +typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties) (); +typedef struct GXKeyList (*PFNGXGetDefaultKeys) (int iOptions); +typedef int (*PFNGXSuspend) (); +typedef int (*PFNGXResume) (); +typedef int (*PFNGXSetViewport) (DWORD dwTop, DWORD dwHeight, + DWORD dwReserved1, DWORD dwReserved2); +typedef BOOL(*PFNGXIsDisplayDRAMBuffer) (); + +struct GapiFunc +{ + PFNGXOpenDisplay GXOpenDisplay; + PFNGXCloseDisplay GXCloseDisplay; + PFNGXBeginDraw GXBeginDraw; + PFNGXEndDraw GXEndDraw; + PFNGXOpenInput GXOpenInput; + PFNGXCloseInput GXCloseInput; + PFNGXGetDisplayProperties GXGetDisplayProperties; + PFNGXGetDefaultKeys GXGetDefaultKeys; + PFNGXSuspend GXSuspend; + PFNGXResume GXResume; + PFNGXSetViewport GXSetViewport; + PFNGXIsDisplayDRAMBuffer GXIsDisplayDRAMBuffer; +} gx; + +#define kfLandscape 0x8 // Screen is rotated 270 degrees +#define kfPalette 0x10 // Pixel values are indexes into a palette +#define kfDirect 0x20 // Pixel values contain actual level information +#define kfDirect555 0x40 // 5 bits each for red, green and blue values in a pixel. +#define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel +#define kfDirect888 0x100 // 8 bits each for red, green and blue values in a pixel. +#define kfDirect444 0x200 // 4 red, 4 green, 4 blue +#define kfDirectInverted 0x400 + +#define GX_FULLSCREEN 0x01 // for OpenDisplay() +#define GX_NORMALKEYS 0x02 +#define GX_LANDSCAPEKEYS 0x03 diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index c38da64d..4c301602 100644 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -473,6 +473,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) int x, y; int w, h; int style; + BOOL menu; /* If we allow resizing, let the resize happen naturally */ if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_RESIZABLE) { @@ -491,15 +492,19 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) size.bottom = h; size.right = w; + + style = GetWindowLong(hwnd, GWL_STYLE); +#ifdef _WIN32_WCE + menu = FALSE; +#else /* DJM - according to the docs for GetMenu(), the return value is undefined if hwnd is a child window. Aparently it's too difficult for MS to check inside their function, so I have to do it here. */ - style = GetWindowLong(hwnd, GWL_STYLE); - AdjustWindowRect(&size, style, - style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) - != NULL); + menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); +#endif + AdjustWindowRectEx(&size, style, menu, 0); w = size.right - size.left; h = size.bottom - size.top; diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index 22e57426..28f60f28 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -59,6 +59,12 @@ WIN_DeleteDevice(SDL_VideoDevice * device) IDirect3D9_Release(data->d3d); FreeLibrary(data->d3dDLL); } +#endif +#if SDL_VIDEO_RENDER_DDRAW + if (data->ddraw) { + data->ddraw->lpVtbl->Release(data->ddraw); + FreeLibrary(data->ddrawDLL); + } #endif if (data->wintabDLL) { FreeLibrary(data->wintabDLL); @@ -106,6 +112,24 @@ WIN_CreateDevice(int devindex) } } #endif /* SDL_VIDEO_RENDER_D3D */ +#if SDL_VIDEO_RENDER_DDRAW + data->ddrawDLL = LoadLibrary(TEXT("ddraw.dll")); + if (data->ddrawDLL) { + IDirectDraw *(WINAPI * DDCreate) (GUID FAR * lpGUID, + LPDIRECTDRAW FAR * lplpDD, + IUnknown FAR * pUnkOuter); + + DDCreate = + (IDirectDraw * + (WINAPI *) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *)) + GetProcAddress(data->ddrawDLL, TEXT("DirectDrawCreate")); + if (!DDCreate || DDCreate(NULL, &data->ddraw, NULL) != DD_OK) { + FreeLibrary(data->ddrawDLL); + data->ddrawDLL = NULL; + data->ddraw = NULL; + } + } +#endif /* SDL_VIDEO_RENDER_DDRAW */ data->wintabDLL = LoadLibrary(TEXT("WINTAB32.DLL")); if (data->wintabDLL) { @@ -188,9 +212,15 @@ WIN_VideoInit(_THIS) #if SDL_VIDEO_RENDER_D3D D3D_AddRenderDriver(_this); #endif +#if SDL_VIDEO_RENDER_DDRAW + DDRAW_AddRenderDriver(_this); +#endif #if SDL_VIDEO_RENDER_GDI GDI_AddRenderDriver(_this); #endif +#if SDL_VIDEO_RENDER_GAPI + GAPI_AddRenderDriver(_this); +#endif g_hCtx = SDL_malloc(sizeof(HCTX)); WIN_InitKeyboard(_this); diff --git a/src/video/win32/SDL_win32video.h b/src/video/win32/SDL_win32video.h index eb6f5624..9454193c 100644 --- a/src/video/win32/SDL_win32video.h +++ b/src/video/win32/SDL_win32video.h @@ -37,6 +37,12 @@ #include "d3d9.h" #endif +#if SDL_VIDEO_RENDER_DDRAW +/* WIN32_LEAN_AND_MEAN was defined, so we have to include this by hand */ +#include +#include "ddraw.h" +#endif + #include "wactab/wintab.h" #define PACKETDATA ( PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_CURSOR) #define PACKETMODE 0 @@ -66,6 +72,11 @@ typedef struct SDL_VideoData HANDLE d3dDLL; IDirect3D9 *d3d; #endif +#if SDL_VIDEO_RENDER_DDRAW + HANDLE ddrawDLL; + IDirectDraw *ddraw; +#endif + /* *INDENT-OFF* */ /* Function pointers for the Wacom API */ HANDLE wintabDLL; diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index cec70488..a8e40b49 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -38,6 +38,41 @@ /* This is included after SDL_win32video.h, which includes windows.h */ #include "SDL_syswm.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 + extern HCTX *g_hCtx; /* the table of tablet event contexts, each windows has to have it's own tablet context */ static Uint32 highestId = 0; /* the highest id of the tablet context */ @@ -385,6 +420,7 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window) RECT rect; DWORD style; HWND top; + BOOL menu; int x, y; /* Figure out what the window area will be */ @@ -398,9 +434,12 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window) rect.top = 0; rect.right = window->w; rect.bottom = window->h; - AdjustWindowRectEx(&rect, style, - (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != - NULL), 0); +#ifdef _WIN32_WCE + menu = FALSE; +#else + menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); +#endif + AdjustWindowRectEx(&rect, style, menu, 0); if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { @@ -425,6 +464,7 @@ WIN_SetWindowSize(_THIS, SDL_Window * window) RECT rect; DWORD style; HWND top; + BOOL menu; int w, h; /* Figure out what the window area will be */ @@ -438,9 +478,12 @@ WIN_SetWindowSize(_THIS, SDL_Window * window) rect.top = 0; rect.right = window->w; rect.bottom = window->h; - AdjustWindowRectEx(&rect, style, - (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != - NULL), 0); +#ifdef _WIN32_WCE + menu = FALSE; +#else + menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); +#endif + AdjustWindowRectEx(&rect, style, menu, 0); w = (rect.right - rect.left); h = (rect.bottom - rect.top); @@ -453,6 +496,14 @@ WIN_ShowWindow(_THIS, SDL_Window * window) 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 @@ -461,6 +512,14 @@ WIN_HideWindow(_THIS, SDL_Window * window) 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 } void @@ -475,6 +534,14 @@ 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 @@ -483,6 +550,14 @@ WIN_MaximizeWindow(_THIS, SDL_Window * window) HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; ShowWindow(hwnd, SW_MAXIMIZE); + +#ifdef _WIN32_WCE + if (window->flags & SDL_WINDOW_FULLSCREEN) { + CE_SHFullScreen(hwnd, + SHFS_HIDESTARTICON | SHFS_HIDETASKBAR | + SHFS_HIDESIPBUTTON); + } +#endif } void @@ -491,6 +566,14 @@ WIN_MinimizeWindow(_THIS, SDL_Window * window) HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; ShowWindow(hwnd, SW_MINIMIZE); + +#ifdef _WIN32_WCE + if (window->flags & SDL_WINDOW_FULLSCREEN) { + CE_SHFullScreen(hwnd, + SHFS_SHOWSTARTICON | SHFS_SHOWTASKBAR | + SHFS_SHOWSIPBUTTON); + } +#endif } void @@ -579,12 +662,18 @@ SDL_HelperWindowCreate(void) return -1; } + HWND hWndParent = NULL; +#ifndef _WIN32_WCE + /* WinCE doesn't have HWND_MESSAGE */ + hWndParent = HWND_MESSAGE; +#endif + /* Create the window. */ SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName, SDL_HelperWindowName, - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, + WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, HWND_MESSAGE, NULL, + CW_USEDEFAULT, hWndParent, NULL, hInstance, NULL); if (SDL_HelperWindow == NULL) { UnregisterClass(SDL_HelperWindowClassName, hInstance);