src/video/windowsrt/SDL_winrtvideo.cpp
author David Ludwig <dludwig@pobox.com>
Sat, 09 Feb 2013 14:35:06 -0500
changeset 8411 aca0591bc58f
parent 8401 29ecd2eca4af
child 8412 59f1191a5cca
permissions -rw-r--r--
WinRT: provided access, via SDL_GetWindowWMInfo, to SDL's WinRT CoreWindow
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINRT
    24 
    25 /* WinRT SDL video driver implementation
    26 
    27    Initial work on this was done by David Ludwig (dludwig@pobox.com), and
    28    was based off of SDL's "dummy" video driver.
    29  */
    30 
    31 extern "C" {
    32 #include "SDL_video.h"
    33 #include "SDL_mouse.h"
    34 #include "../SDL_sysvideo.h"
    35 #include "../SDL_pixels_c.h"
    36 #include "../../events/SDL_events_c.h"
    37 #include "../../render/SDL_sysrender.h"
    38 #include "SDL_syswm.h"
    39 }
    40 
    41 #include "SDL_WinRTApp.h"
    42 #include "SDL_winrtvideo.h"
    43 #include "SDL_winrtevents_c.h"
    44 #include "SDL_winrtframebuffer_c.h"
    45 #include "SDL_winrtmouse.h"
    46 
    47 /* On Windows, windows.h defines CreateWindow */
    48 #ifdef CreateWindow
    49 #undef CreateWindow
    50 #endif
    51 
    52 extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
    53 
    54 #define WINRTVID_DRIVER_NAME "winrt"
    55 
    56 /* Initialization/Query functions */
    57 static int WINRT_VideoInit(_THIS);
    58 static int WINRT_InitModes(_THIS);
    59 static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
    60 static void WINRT_VideoQuit(_THIS);
    61 
    62 /* Window functions */
    63 static int WINRT_CreateWindow(_THIS, SDL_Window * window);
    64 static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
    65 static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
    66 
    67 /* WinRT driver bootstrap functions */
    68 
    69 static int
    70 WINRT_Available(void)
    71 {
    72     return (1);
    73 }
    74 
    75 static void
    76 WINRT_DeleteDevice(SDL_VideoDevice * device)
    77 {
    78     SDL_free(device);
    79 }
    80 
    81 static SDL_VideoDevice *
    82 WINRT_CreateDevice(int devindex)
    83 {
    84     SDL_VideoDevice *device;
    85 
    86     /* Initialize all variables that we clean on shutdown */
    87     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    88     if (!device) {
    89         SDL_OutOfMemory();
    90         if (device) {
    91             SDL_free(device);
    92         }
    93         return (0);
    94     }
    95 
    96     /* Set the function pointers */
    97     device->VideoInit = WINRT_VideoInit;
    98     device->VideoQuit = WINRT_VideoQuit;
    99     device->CreateWindow = WINRT_CreateWindow;
   100     device->DestroyWindow = WINRT_DestroyWindow;
   101     device->SetDisplayMode = WINRT_SetDisplayMode;
   102     device->PumpEvents = WINRT_PumpEvents;
   103     device->CreateWindowFramebuffer = SDL_WINRT_CreateWindowFramebuffer;
   104     device->UpdateWindowFramebuffer = SDL_WINRT_UpdateWindowFramebuffer;
   105     device->DestroyWindowFramebuffer = SDL_WINRT_DestroyWindowFramebuffer;
   106     device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
   107 
   108     device->free = WINRT_DeleteDevice;
   109 
   110     return device;
   111 }
   112 
   113 VideoBootStrap WINRT_bootstrap = {
   114     WINRTVID_DRIVER_NAME, "SDL Windows RT video driver",
   115     WINRT_Available, WINRT_CreateDevice
   116 };
   117 
   118 int
   119 WINRT_VideoInit(_THIS)
   120 {
   121     if (WINRT_InitModes(_this) < 0) {
   122         return -1;
   123     }
   124 
   125     WINRT_InitMouse(_this);
   126 
   127     return 0;
   128 }
   129 
   130 static int
   131 WINRT_InitModes(_THIS)
   132 {
   133     SDL_DisplayMode mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
   134     if (SDL_AddBasicVideoDisplay(&mode) < 0) {
   135         return -1;
   136     }
   137 
   138     SDL_AddDisplayMode(&_this->displays[0], &mode);
   139     return 0;
   140 }
   141 
   142 static int
   143 WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   144 {
   145     return 0;
   146 }
   147 
   148 void
   149 WINRT_VideoQuit(_THIS)
   150 {
   151     WINRT_QuitMouse(_this);
   152 }
   153 
   154 int
   155 WINRT_CreateWindow(_THIS, SDL_Window * window)
   156 {
   157     // Make sure that only one window gets created, at least until multimonitor
   158     // support is added.
   159     if (SDL_WinRTGlobalApp->HasSDLWindowData())
   160     {
   161         SDL_SetError("WinRT only supports one window");
   162         return -1;
   163     }
   164 
   165     SDL_WindowData *data = new SDL_WindowData;
   166     if (!data) {
   167         SDL_OutOfMemory();
   168         return -1;
   169     }
   170     data->sdlWindow = window;
   171     data->coreWindow = new CoreWindow^(CoreWindow::GetForCurrentThread());
   172 
   173     /* Make sure the window is considered to be positioned at {0,0},
   174        and is considered fullscreen, shown, and the like.
   175     */
   176     window->x = 0;
   177     window->y = 0;
   178     window->flags =
   179         SDL_WINDOW_FULLSCREEN |
   180         SDL_WINDOW_SHOWN |
   181         SDL_WINDOW_BORDERLESS |
   182         SDL_WINDOW_MAXIMIZED |
   183         SDL_WINDOW_INPUT_GRABBED;
   184 
   185     /* HACK from DLudwig: The following line of code prevents
   186        SDL_CreateWindow and SDL_UpdateFullscreenMode from trying to resize
   187        the window after the call to WINRT_CreateWindow returns.
   188        
   189        This hack should allow a window to be created in virtually any size,
   190        and more importantly, it allows a window's framebuffer, as created and
   191        retrieved via SDL_GetWindowSurface, to be in any size.  This can be
   192        utilized by apps centered around software rendering, such as ports
   193        of older apps.  The app can have SDL create a framebuffer in any size
   194        it chooses.  SDL will scale the framebuffer to the native
   195        screen size on the GPU (via SDL_UpdateWindowSurface).
   196     */
   197     _this->displays[0].fullscreen_window = window;
   198 
   199     /* Further prevent any display resizing, and make sure SDL_GetWindowDisplayMode
   200        can report the correct size of windows, by creating a new display
   201        mode in the requested size.  To note, if the window is being created in
   202        the device's native screen size, SDL_AddDisplayMode will do nothing.
   203     */
   204     window->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
   205     window->fullscreen_mode.w = window->w;
   206     window->fullscreen_mode.h = window->h;
   207     SDL_AddDisplayMode(&_this->displays[0], &window->fullscreen_mode);
   208 
   209     /* TODO: Consider removing custom display modes in WINRT_DestroyWindow. */
   210  
   211     /* Make sure the WinRT app's IFramworkView can post events on
   212        behalf of SDL:
   213     */
   214     SDL_WinRTGlobalApp->SetSDLWindowData(data);
   215 
   216     /* For now, create a Direct3D 11 renderer up-front.  Eventually, this
   217        won't be done in WINRT_CreateWindow, although it may get done in
   218        SDL_WINRT_CreateWindowFramebuffer.
   219     */
   220 
   221     // Link SDL_winrtrenderer to the SDL_Renderer temporarily,
   222     // for refactoring purposes.  Initialize the SDL_Renderer
   223     // first in order to give it the opportunity to create key
   224     // resources first.
   225     //
   226     // TODO, WinRT: either make WINRT_CreateWindow not call SDL_CreateRenderer, or have it do error checking if it does call it
   227 
   228     // HACK: make sure the SDL window references SDL_WindowData data now, in
   229     // order to allow the SDL_Renderer to be created in WINRT_CreateWindow
   230     window->driverdata = data;
   231 
   232     SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
   233     SDL_WinRTGlobalApp->m_renderer->m_sdlRenderer = renderer;
   234     SDL_WinRTGlobalApp->m_renderer->m_sdlRendererData = (D3D11_RenderData *) renderer->driverdata;
   235     SDL_WinRTGlobalApp->m_renderer->Initialize(CoreWindow::GetForCurrentThread());
   236 
   237     /* All done! */
   238     return 0;
   239 }
   240 
   241 void
   242 WINRT_DestroyWindow(_THIS, SDL_Window * window)
   243 {
   244     SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
   245 
   246     if (data) {
   247         // Delete the reference to the WinRT CoreWindow:
   248         CoreWindow ^* windowPointer = ((SDL_WindowData *) window->driverdata)->coreWindow;
   249         if (windowPointer) {
   250             *windowPointer = nullptr;   // Clear the C++/CX reference to the CoreWindow
   251             delete windowPointer;       // Delete the C++/CX reference itself
   252         }
   253 
   254         // Delete the internal window data:
   255         delete data;
   256         data = NULL;
   257     }
   258 
   259     if (SDL_WinRTGlobalApp->HasSDLWindowData() &&
   260         SDL_WinRTGlobalApp->GetSDLWindowData()->sdlWindow == window)
   261     {
   262         SDL_WinRTGlobalApp->SetSDLWindowData(NULL);
   263     }
   264 }
   265 
   266 SDL_bool
   267 WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   268 {
   269     SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
   270     CoreWindow ^* windowPointer = data->coreWindow;
   271 
   272     if (info->version.major <= SDL_MAJOR_VERSION) {
   273         info->subsystem = SDL_SYSWM_WINDOWSRT;
   274         info->info.winrt.window = windowPointer;
   275         return SDL_TRUE;
   276     } else {
   277         SDL_SetError("Application not compiled with SDL %d.%d\n",
   278                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   279         return SDL_FALSE;
   280     }
   281     return SDL_FALSE;
   282 }
   283 
   284 #endif /* SDL_VIDEO_DRIVER_WINRT */
   285 
   286 /* vi: set ts=4 sw=4 expandtab: */