From 2c2aeb0da4eb06d568cc553670f7805512f884f6 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Sun, 25 Nov 2012 17:34:41 -0500 Subject: [PATCH] WinRT: allow windows in non-native screen sizes. Scaling is applied for such. --- src/video/windowsrt/SDL_WinRTApp.cpp | 5 ++ src/video/windowsrt/SDL_WinRTApp.h | 1 + src/video/windowsrt/SDL_winrtframebuffer.cpp | 6 +- src/video/windowsrt/SDL_winrtrenderer.cpp | 93 +++++++++++--------- src/video/windowsrt/SDL_winrtrenderer.h | 1 + src/video/windowsrt/SDL_winrtvideo.cpp | 42 ++++++++- 6 files changed, 101 insertions(+), 47 deletions(-) diff --git a/src/video/windowsrt/SDL_WinRTApp.cpp b/src/video/windowsrt/SDL_WinRTApp.cpp index dc8cac9b9..15ee94973 100644 --- a/src/video/windowsrt/SDL_WinRTApp.cpp +++ b/src/video/windowsrt/SDL_WinRTApp.cpp @@ -447,6 +447,11 @@ void SDL_WinRTApp::SetSDLWindowData(const SDL_WindowData* windowData) m_sdlWindowData = windowData; } +void SDL_WinRTApp::ResizeMainTexture(int w, int h) +{ + m_renderer->ResizeMainTexture(w, h); +} + IFrameworkView^ Direct3DApplicationSource::CreateView() { // TODO, WinRT: see if this function (CreateView) can ever get called diff --git a/src/video/windowsrt/SDL_WinRTApp.h b/src/video/windowsrt/SDL_WinRTApp.h index 333f734ba..48c1b7713 100644 --- a/src/video/windowsrt/SDL_WinRTApp.h +++ b/src/video/windowsrt/SDL_WinRTApp.h @@ -27,6 +27,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo bool HasSDLWindowData() const; void SetSDLWindowData(const SDL_WindowData * windowData); void UpdateWindowFramebuffer(SDL_Surface * surface, SDL_Rect * rects, int numrects); + void ResizeMainTexture(int w, int h); protected: // Event Handlers. diff --git a/src/video/windowsrt/SDL_winrtframebuffer.cpp b/src/video/windowsrt/SDL_winrtframebuffer.cpp index ae6132ac3..a53945454 100644 --- a/src/video/windowsrt/SDL_winrtframebuffer.cpp +++ b/src/video/windowsrt/SDL_winrtframebuffer.cpp @@ -53,11 +53,15 @@ int SDL_WINRT_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * forma return -1; } - /* Save the info and return! */ + /* Save info on the surface */ SDL_SetWindowData(window, WINRT_SURFACE, surface); *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; + + /* Make sure a Direct3D texture exists to draw the surface onto */ + SDL_WinRTGlobalApp->ResizeMainTexture(surface->w, surface->h); + return 0; } diff --git a/src/video/windowsrt/SDL_winrtrenderer.cpp b/src/video/windowsrt/SDL_winrtrenderer.cpp index 2e2ab206c..99a7824f1 100644 --- a/src/video/windowsrt/SDL_winrtrenderer.cpp +++ b/src/video/windowsrt/SDL_winrtrenderer.cpp @@ -82,48 +82,7 @@ void SDL_winrtrenderer::CreateDeviceResources() ); }); - auto createMainTextureTask = createCubeTask.then([this] () { - D3D11_TEXTURE2D_DESC textureDesc = {0}; - textureDesc.Width = (int)m_windowBounds.Width; - textureDesc.Height = (int)m_windowBounds.Height; - textureDesc.MipLevels = 1; - textureDesc.ArraySize = 1; - textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - textureDesc.SampleDesc.Count = 1; - textureDesc.SampleDesc.Quality = 0; - textureDesc.Usage = D3D11_USAGE_DYNAMIC; - textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - textureDesc.MiscFlags = 0; - - const int numPixels = (int)m_windowBounds.Width * (int)m_windowBounds.Height; - std::vector initialTexturePixels(numPixels * 4, 0x00); - D3D11_SUBRESOURCE_DATA initialTextureData = {0}; - initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]); - initialTextureData.SysMemPitch = (int)m_windowBounds.Width * 4; - initialTextureData.SysMemSlicePitch = numPixels * 4; - DX::ThrowIfFailed( - m_d3dDevice->CreateTexture2D( - &textureDesc, - &initialTextureData, - &m_mainTexture - ) - ); - - D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; - resourceViewDesc.Format = textureDesc.Format; - resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - resourceViewDesc.Texture2D.MostDetailedMip = 0; - resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; - DX::ThrowIfFailed( - m_d3dDevice->CreateShaderResourceView( - m_mainTexture.Get(), - &resourceViewDesc, - &m_mainTextureResourceView) - ); - }); - - auto createMainSamplerTask = createMainTextureTask.then([this] () { + auto createMainSamplerTask = createCubeTask.then([this] () { D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; @@ -151,6 +110,48 @@ void SDL_winrtrenderer::CreateDeviceResources() }); } +void SDL_winrtrenderer::ResizeMainTexture(int w, int h) +{ + D3D11_TEXTURE2D_DESC textureDesc = {0}; + textureDesc.Width = w; + textureDesc.Height = h; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + textureDesc.SampleDesc.Count = 1; + textureDesc.SampleDesc.Quality = 0; + textureDesc.Usage = D3D11_USAGE_DYNAMIC; + textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + textureDesc.MiscFlags = 0; + + const int numPixels = textureDesc.Width * textureDesc.Height; + std::vector initialTexturePixels(numPixels * 4, 0x00); + D3D11_SUBRESOURCE_DATA initialTextureData = {0}; + initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]); + initialTextureData.SysMemPitch = textureDesc.Width * 4; + initialTextureData.SysMemSlicePitch = numPixels * 4; + DX::ThrowIfFailed( + m_d3dDevice->CreateTexture2D( + &textureDesc, + &initialTextureData, + &m_mainTexture + ) + ); + + D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; + resourceViewDesc.Format = textureDesc.Format; + resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + resourceViewDesc.Texture2D.MostDetailedMip = 0; + resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; + DX::ThrowIfFailed( + m_d3dDevice->CreateShaderResourceView( + m_mainTexture.Get(), + &resourceViewDesc, + &m_mainTextureResourceView) + ); +} + void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) { const float blackColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -171,6 +172,10 @@ void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numr { return; } + if (!m_mainTextureResourceView) + { + return; + } // Update the main texture (for SDL usage): D3D11_MAPPED_SUBRESOURCE textureMemory = {0}; @@ -185,7 +190,9 @@ void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numr // TODO, WinRT: only copy over the requested rects (via SDL_BlitSurface, perhaps?) // TODO, WinRT: do a sanity check on the src and dest data when updating the window surface - const unsigned int numBytes = (int)m_windowBounds.Width * (int)m_windowBounds.Height * 4; + D3D11_TEXTURE2D_DESC textureDesc = {0}; + m_mainTexture->GetDesc(&textureDesc); + const unsigned int numBytes = textureDesc.Width * textureDesc.Height * 4; memcpy(textureMemory.pData, surface->pixels, numBytes); m_d3dContext->Unmap( diff --git a/src/video/windowsrt/SDL_winrtrenderer.h b/src/video/windowsrt/SDL_winrtrenderer.h index bcdce2bac..7d39a26fa 100644 --- a/src/video/windowsrt/SDL_winrtrenderer.h +++ b/src/video/windowsrt/SDL_winrtrenderer.h @@ -19,6 +19,7 @@ ref class SDL_winrtrenderer sealed : public Direct3DBase internal: virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) override; + void ResizeMainTexture(int w, int h); private: bool m_loadingComplete; diff --git a/src/video/windowsrt/SDL_winrtvideo.cpp b/src/video/windowsrt/SDL_winrtvideo.cpp index 16a0474b9..66c36357f 100644 --- a/src/video/windowsrt/SDL_winrtvideo.cpp +++ b/src/video/windowsrt/SDL_winrtvideo.cpp @@ -154,14 +154,50 @@ WINRT_CreateWindow(_THIS, SDL_Window * window) SDL_zerop(data); data->sdlWindow = window; - /* Adjust the window data to match the screen */ + /* Make sure the window is considered to be positioned at {0,0}, + and is considered fullscreen, shown, and the like. + */ window->x = 0; window->y = 0; - window->w = _this->displays->desktop_mode.w; - window->h = _this->displays->desktop_mode.h; + window->flags = + SDL_WINDOW_FULLSCREEN | + SDL_WINDOW_SHOWN | + SDL_WINDOW_BORDERLESS | + SDL_WINDOW_MAXIMIZED | + SDL_WINDOW_INPUT_GRABBED; + /* HACK from DLudwig: The following line of code prevents + SDL_CreateWindow and SDL_UpdateFullscreenMode from trying to resize + the window after the call to WINRT_CreateWindow returns. + + This hack should allow a window to be created in virtually any size, + and more importantly, it allows a window's framebuffer, as created and + retrieved via SDL_GetWindowSurface, to be in any size. This can be + utilized by apps centered around software rendering, such as ports + of older apps. The app can have SDL create a framebuffer in any size + it chooses. SDL will scale the framebuffer to the native + screen size on the GPU (via SDL_UpdateWindowSurface). + */ + _this->displays[0].fullscreen_window = window; + + /* Further prevent any display resizing, and make sure SDL_GetWindowDisplayMode + can report the correct size of windows, by creating a new display + mode in the requested size. To note, if the window is being created in + the device's native screen size, SDL_AddDisplayMode will do nothing. + */ + window->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode(); + window->fullscreen_mode.w = window->w; + window->fullscreen_mode.h = window->h; + SDL_AddDisplayMode(&_this->displays[0], &window->fullscreen_mode); + + /* TODO: Consider removing custom display modes in WINRT_DestroyWindow. */ + + /* Make sure the WinRT app's IFramworkView can post events on + behalf of SDL: + */ SDL_WinRTGlobalApp->SetSDLWindowData(data); + /* All done! */ return 0; }