dludwig@8327: /* dludwig@8327: Simple DirectMedia Layer dludwig@8327: Copyright (C) 1997-2012 Sam Lantinga dludwig@8327: dludwig@8327: This software is provided 'as-is', without any express or implied dludwig@8327: warranty. In no event will the authors be held liable for any damages dludwig@8327: arising from the use of this software. dludwig@8327: dludwig@8327: Permission is granted to anyone to use this software for any purpose, dludwig@8327: including commercial applications, and to alter it and redistribute it dludwig@8327: freely, subject to the following restrictions: dludwig@8327: dludwig@8327: 1. The origin of this software must not be misrepresented; you must not dludwig@8327: claim that you wrote the original software. If you use this software dludwig@8327: in a product, an acknowledgment in the product documentation would be dludwig@8327: appreciated but is not required. dludwig@8327: 2. Altered source versions must be plainly marked as such, and must not be dludwig@8327: misrepresented as being the original software. dludwig@8327: 3. This notice may not be removed or altered from any source distribution. dludwig@8327: */ dludwig@8327: #include "SDL_config.h" dludwig@8327: dludwig@8327: #if SDL_VIDEO_DRIVER_WINRT dludwig@8327: dludwig@8327: /* WinRT SDL video driver implementation dludwig@8327: dludwig@8327: Initial work on this was done by David Ludwig (dludwig@pobox.com), and dludwig@8327: was based off of SDL's "dummy" video driver. dludwig@8327: */ dludwig@8327: dludwig@8329: extern "C" { dludwig@8327: #include "SDL_video.h" dludwig@8327: #include "SDL_mouse.h" dludwig@8327: #include "../SDL_sysvideo.h" dludwig@8327: #include "../SDL_pixels_c.h" dludwig@8327: #include "../../events/SDL_events_c.h" dludwig@8400: #include "../../render/SDL_sysrender.h" dludwig@8411: #include "SDL_syswm.h" dludwig@8329: } dludwig@8327: dludwig@8329: #include "SDL_WinRTApp.h" dludwig@8327: #include "SDL_winrtvideo.h" dludwig@8327: #include "SDL_winrtevents_c.h" dludwig@8327: #include "SDL_winrtframebuffer_c.h" dludwig@8374: #include "SDL_winrtmouse.h" dludwig@8327: dludwig@8333: /* On Windows, windows.h defines CreateWindow */ dludwig@8333: #ifdef CreateWindow dludwig@8333: #undef CreateWindow dludwig@8333: #endif dludwig@8333: dludwig@8332: extern SDL_WinRTApp ^ SDL_WinRTGlobalApp; dludwig@8332: dludwig@8368: #define WINRTVID_DRIVER_NAME "winrt" dludwig@8327: dludwig@8327: /* Initialization/Query functions */ dludwig@8327: static int WINRT_VideoInit(_THIS); dludwig@8374: static int WINRT_InitModes(_THIS); dludwig@8327: static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); dludwig@8327: static void WINRT_VideoQuit(_THIS); dludwig@8327: dludwig@8333: /* Window functions */ dludwig@8333: static int WINRT_CreateWindow(_THIS, SDL_Window * window); dludwig@8333: static void WINRT_DestroyWindow(_THIS, SDL_Window * window); dludwig@8411: static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info); dludwig@8333: dludwig@8327: /* WinRT driver bootstrap functions */ dludwig@8327: dludwig@8327: static int dludwig@8327: WINRT_Available(void) dludwig@8327: { dludwig@8328: return (1); dludwig@8327: } dludwig@8327: dludwig@8327: static void dludwig@8327: WINRT_DeleteDevice(SDL_VideoDevice * device) dludwig@8327: { dludwig@8327: SDL_free(device); dludwig@8327: } dludwig@8327: dludwig@8327: static SDL_VideoDevice * dludwig@8327: WINRT_CreateDevice(int devindex) dludwig@8327: { dludwig@8327: SDL_VideoDevice *device; dludwig@8327: dludwig@8327: /* Initialize all variables that we clean on shutdown */ dludwig@8327: device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); dludwig@8327: if (!device) { dludwig@8327: SDL_OutOfMemory(); dludwig@8327: if (device) { dludwig@8327: SDL_free(device); dludwig@8327: } dludwig@8327: return (0); dludwig@8327: } dludwig@8327: dludwig@8327: /* Set the function pointers */ dludwig@8327: device->VideoInit = WINRT_VideoInit; dludwig@8327: device->VideoQuit = WINRT_VideoQuit; dludwig@8333: device->CreateWindow = WINRT_CreateWindow; dludwig@8333: device->DestroyWindow = WINRT_DestroyWindow; dludwig@8327: device->SetDisplayMode = WINRT_SetDisplayMode; dludwig@8327: device->PumpEvents = WINRT_PumpEvents; dludwig@8327: device->CreateWindowFramebuffer = SDL_WINRT_CreateWindowFramebuffer; dludwig@8327: device->UpdateWindowFramebuffer = SDL_WINRT_UpdateWindowFramebuffer; dludwig@8327: device->DestroyWindowFramebuffer = SDL_WINRT_DestroyWindowFramebuffer; dludwig@8411: device->GetWindowWMInfo = WINRT_GetWindowWMInfo; dludwig@8327: dludwig@8327: device->free = WINRT_DeleteDevice; dludwig@8327: dludwig@8327: return device; dludwig@8327: } dludwig@8327: dludwig@8327: VideoBootStrap WINRT_bootstrap = { dludwig@8327: WINRTVID_DRIVER_NAME, "SDL Windows RT video driver", dludwig@8327: WINRT_Available, WINRT_CreateDevice dludwig@8327: }; dludwig@8327: dludwig@8327: int dludwig@8327: WINRT_VideoInit(_THIS) dludwig@8327: { dludwig@8374: if (WINRT_InitModes(_this) < 0) { dludwig@8374: return -1; dludwig@8374: } dludwig@8374: dludwig@8374: WINRT_InitMouse(_this); dludwig@8374: dludwig@8374: return 0; dludwig@8374: } dludwig@8374: dludwig@8374: static int dludwig@8374: WINRT_InitModes(_THIS) dludwig@8374: { dludwig@8329: SDL_DisplayMode mode = SDL_WinRTGlobalApp->GetMainDisplayMode(); dludwig@8329: if (SDL_AddBasicVideoDisplay(&mode) < 0) { dludwig@8329: return -1; dludwig@8374: } dludwig@8374: dludwig@8374: SDL_AddDisplayMode(&_this->displays[0], &mode); dludwig@8327: return 0; dludwig@8327: } dludwig@8327: dludwig@8327: static int dludwig@8327: WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) dludwig@8327: { dludwig@8327: return 0; dludwig@8327: } dludwig@8327: dludwig@8327: void dludwig@8327: WINRT_VideoQuit(_THIS) dludwig@8327: { dludwig@8374: WINRT_QuitMouse(_this); dludwig@8327: } dludwig@8327: dludwig@8333: int dludwig@8333: WINRT_CreateWindow(_THIS, SDL_Window * window) dludwig@8333: { dludwig@8334: // Make sure that only one window gets created, at least until multimonitor dludwig@8334: // support is added. dludwig@8334: if (SDL_WinRTGlobalApp->HasSDLWindowData()) dludwig@8334: { dludwig@8334: SDL_SetError("WinRT only supports one window"); dludwig@8334: return -1; dludwig@8334: } dludwig@8333: dludwig@8411: SDL_WindowData *data = new SDL_WindowData; dludwig@8333: if (!data) { dludwig@8333: SDL_OutOfMemory(); dludwig@8333: return -1; dludwig@8333: } dludwig@8333: data->sdlWindow = window; dludwig@8411: data->coreWindow = new CoreWindow^(CoreWindow::GetForCurrentThread()); dludwig@8333: dludwig@8367: /* Make sure the window is considered to be positioned at {0,0}, dludwig@8367: and is considered fullscreen, shown, and the like. dludwig@8367: */ dludwig@8333: window->x = 0; dludwig@8333: window->y = 0; dludwig@8367: window->flags = dludwig@8367: SDL_WINDOW_FULLSCREEN | dludwig@8367: SDL_WINDOW_SHOWN | dludwig@8367: SDL_WINDOW_BORDERLESS | dludwig@8367: SDL_WINDOW_MAXIMIZED | dludwig@8367: SDL_WINDOW_INPUT_GRABBED; dludwig@8333: dludwig@8367: /* HACK from DLudwig: The following line of code prevents dludwig@8367: SDL_CreateWindow and SDL_UpdateFullscreenMode from trying to resize dludwig@8367: the window after the call to WINRT_CreateWindow returns. dludwig@8367: dludwig@8367: This hack should allow a window to be created in virtually any size, dludwig@8367: and more importantly, it allows a window's framebuffer, as created and dludwig@8367: retrieved via SDL_GetWindowSurface, to be in any size. This can be dludwig@8367: utilized by apps centered around software rendering, such as ports dludwig@8367: of older apps. The app can have SDL create a framebuffer in any size dludwig@8367: it chooses. SDL will scale the framebuffer to the native dludwig@8367: screen size on the GPU (via SDL_UpdateWindowSurface). dludwig@8367: */ dludwig@8367: _this->displays[0].fullscreen_window = window; dludwig@8367: dludwig@8367: /* Further prevent any display resizing, and make sure SDL_GetWindowDisplayMode dludwig@8367: can report the correct size of windows, by creating a new display dludwig@8367: mode in the requested size. To note, if the window is being created in dludwig@8367: the device's native screen size, SDL_AddDisplayMode will do nothing. dludwig@8367: */ dludwig@8367: window->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode(); dludwig@8367: window->fullscreen_mode.w = window->w; dludwig@8367: window->fullscreen_mode.h = window->h; dludwig@8367: SDL_AddDisplayMode(&_this->displays[0], &window->fullscreen_mode); dludwig@8367: dludwig@8367: /* TODO: Consider removing custom display modes in WINRT_DestroyWindow. */ dludwig@8367: dludwig@8367: /* Make sure the WinRT app's IFramworkView can post events on dludwig@8367: behalf of SDL: dludwig@8367: */ dludwig@8333: SDL_WinRTGlobalApp->SetSDLWindowData(data); dludwig@8333: dludwig@8400: /* For now, create a Direct3D 11 renderer up-front. Eventually, this dludwig@8400: won't be done in WINRT_CreateWindow, although it may get done in dludwig@8400: SDL_WINRT_CreateWindowFramebuffer. dludwig@8400: */ dludwig@8400: dludwig@8400: // Link SDL_winrtrenderer to the SDL_Renderer temporarily, dludwig@8400: // for refactoring purposes. Initialize the SDL_Renderer dludwig@8400: // first in order to give it the opportunity to create key dludwig@8400: // resources first. dludwig@8401: // dludwig@8401: // TODO, WinRT: either make WINRT_CreateWindow not call SDL_CreateRenderer, or have it do error checking if it does call it dludwig@8411: dludwig@8411: // HACK: make sure the SDL window references SDL_WindowData data now, in dludwig@8411: // order to allow the SDL_Renderer to be created in WINRT_CreateWindow dludwig@8411: window->driverdata = data; dludwig@8411: dludwig@8400: SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); dludwig@8401: SDL_WinRTGlobalApp->m_renderer->m_sdlRenderer = renderer; dludwig@8400: SDL_WinRTGlobalApp->m_renderer->m_sdlRendererData = (D3D11_RenderData *) renderer->driverdata; dludwig@8400: SDL_WinRTGlobalApp->m_renderer->Initialize(CoreWindow::GetForCurrentThread()); dludwig@8400: dludwig@8367: /* All done! */ dludwig@8333: return 0; dludwig@8333: } dludwig@8333: dludwig@8333: void dludwig@8333: WINRT_DestroyWindow(_THIS, SDL_Window * window) dludwig@8333: { dludwig@8411: SDL_WindowData * data = (SDL_WindowData *) window->driverdata; dludwig@8411: dludwig@8411: if (data) { dludwig@8411: // Delete the reference to the WinRT CoreWindow: dludwig@8411: CoreWindow ^* windowPointer = ((SDL_WindowData *) window->driverdata)->coreWindow; dludwig@8411: if (windowPointer) { dludwig@8411: *windowPointer = nullptr; // Clear the C++/CX reference to the CoreWindow dludwig@8411: delete windowPointer; // Delete the C++/CX reference itself dludwig@8411: } dludwig@8411: dludwig@8411: // Delete the internal window data: dludwig@8411: delete data; dludwig@8411: data = NULL; dludwig@8411: } dludwig@8411: dludwig@8335: if (SDL_WinRTGlobalApp->HasSDLWindowData() && dludwig@8335: SDL_WinRTGlobalApp->GetSDLWindowData()->sdlWindow == window) dludwig@8334: { dludwig@8334: SDL_WinRTGlobalApp->SetSDLWindowData(NULL); dludwig@8334: } dludwig@8333: } dludwig@8333: dludwig@8411: SDL_bool dludwig@8411: WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) dludwig@8411: { dludwig@8411: SDL_WindowData * data = (SDL_WindowData *) window->driverdata; dludwig@8411: CoreWindow ^* windowPointer = data->coreWindow; dludwig@8411: dludwig@8411: if (info->version.major <= SDL_MAJOR_VERSION) { dludwig@8411: info->subsystem = SDL_SYSWM_WINDOWSRT; dludwig@8411: info->info.winrt.window = windowPointer; dludwig@8411: return SDL_TRUE; dludwig@8411: } else { dludwig@8411: SDL_SetError("Application not compiled with SDL %d.%d\n", dludwig@8411: SDL_MAJOR_VERSION, SDL_MINOR_VERSION); dludwig@8411: return SDL_FALSE; dludwig@8411: } dludwig@8411: return SDL_FALSE; dludwig@8411: } dludwig@8333: dludwig@8327: #endif /* SDL_VIDEO_DRIVER_WINRT */ dludwig@8327: dludwig@8327: /* vi: set ts=4 sw=4 expandtab: */