WinRT: allow windows in non-native screen sizes. Scaling is applied for such.
authorDavid Ludwig <dludwig@pobox.com>
Sun, 25 Nov 2012 17:34:41 -0500
changeset 8367df577bb2f2d7
parent 8366 dc1f2c7ed164
child 8368 c611e5a2eab4
WinRT: allow windows in non-native screen sizes. Scaling is applied for such.
src/video/windowsrt/SDL_WinRTApp.cpp
src/video/windowsrt/SDL_WinRTApp.h
src/video/windowsrt/SDL_winrtframebuffer.cpp
src/video/windowsrt/SDL_winrtrenderer.cpp
src/video/windowsrt/SDL_winrtrenderer.h
src/video/windowsrt/SDL_winrtvideo.cpp
     1.1 --- a/src/video/windowsrt/SDL_WinRTApp.cpp	Sun Nov 25 14:45:22 2012 -0500
     1.2 +++ b/src/video/windowsrt/SDL_WinRTApp.cpp	Sun Nov 25 17:34:41 2012 -0500
     1.3 @@ -447,6 +447,11 @@
     1.4      m_sdlWindowData = windowData;
     1.5  }
     1.6  
     1.7 +void SDL_WinRTApp::ResizeMainTexture(int w, int h)
     1.8 +{
     1.9 +    m_renderer->ResizeMainTexture(w, h);
    1.10 +}
    1.11 +
    1.12  IFrameworkView^ Direct3DApplicationSource::CreateView()
    1.13  {
    1.14      // TODO, WinRT: see if this function (CreateView) can ever get called
     2.1 --- a/src/video/windowsrt/SDL_WinRTApp.h	Sun Nov 25 14:45:22 2012 -0500
     2.2 +++ b/src/video/windowsrt/SDL_WinRTApp.h	Sun Nov 25 17:34:41 2012 -0500
     2.3 @@ -27,6 +27,7 @@
     2.4      bool HasSDLWindowData() const;
     2.5      void SetSDLWindowData(const SDL_WindowData * windowData);
     2.6      void UpdateWindowFramebuffer(SDL_Surface * surface, SDL_Rect * rects, int numrects);
     2.7 +    void ResizeMainTexture(int w, int h);
     2.8  
     2.9  protected:
    2.10  	// Event Handlers.
     3.1 --- a/src/video/windowsrt/SDL_winrtframebuffer.cpp	Sun Nov 25 14:45:22 2012 -0500
     3.2 +++ b/src/video/windowsrt/SDL_winrtframebuffer.cpp	Sun Nov 25 17:34:41 2012 -0500
     3.3 @@ -53,11 +53,15 @@
     3.4          return -1;
     3.5      }
     3.6  
     3.7 -    /* Save the info and return! */
     3.8 +    /* Save info on the surface */
     3.9      SDL_SetWindowData(window, WINRT_SURFACE, surface);
    3.10      *format = surface_format;
    3.11      *pixels = surface->pixels;
    3.12      *pitch = surface->pitch;
    3.13 +
    3.14 +    /* Make sure a Direct3D texture exists to draw the surface onto */
    3.15 +    SDL_WinRTGlobalApp->ResizeMainTexture(surface->w, surface->h);
    3.16 +
    3.17      return 0;
    3.18  }
    3.19  
     4.1 --- a/src/video/windowsrt/SDL_winrtrenderer.cpp	Sun Nov 25 14:45:22 2012 -0500
     4.2 +++ b/src/video/windowsrt/SDL_winrtrenderer.cpp	Sun Nov 25 17:34:41 2012 -0500
     4.3 @@ -82,48 +82,7 @@
     4.4  			);
     4.5  	});
     4.6  
     4.7 -	auto createMainTextureTask = createCubeTask.then([this] () {
     4.8 -		D3D11_TEXTURE2D_DESC textureDesc = {0};
     4.9 -		textureDesc.Width = (int)m_windowBounds.Width;
    4.10 -		textureDesc.Height = (int)m_windowBounds.Height;
    4.11 -		textureDesc.MipLevels = 1;
    4.12 -		textureDesc.ArraySize = 1;
    4.13 -		textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    4.14 -		textureDesc.SampleDesc.Count = 1;
    4.15 -		textureDesc.SampleDesc.Quality = 0;
    4.16 -		textureDesc.Usage = D3D11_USAGE_DYNAMIC;
    4.17 -		textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    4.18 -		textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    4.19 -		textureDesc.MiscFlags = 0;
    4.20 -
    4.21 -		const int numPixels = (int)m_windowBounds.Width * (int)m_windowBounds.Height;
    4.22 -		std::vector<uint8> initialTexturePixels(numPixels * 4, 0x00);
    4.23 -		D3D11_SUBRESOURCE_DATA initialTextureData = {0};
    4.24 -		initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
    4.25 -		initialTextureData.SysMemPitch = (int)m_windowBounds.Width * 4;
    4.26 -		initialTextureData.SysMemSlicePitch = numPixels * 4;
    4.27 -		DX::ThrowIfFailed(
    4.28 -			m_d3dDevice->CreateTexture2D(
    4.29 -				&textureDesc,
    4.30 -				&initialTextureData,
    4.31 -				&m_mainTexture
    4.32 -				)
    4.33 -			);
    4.34 -
    4.35 -		D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
    4.36 -		resourceViewDesc.Format = textureDesc.Format;
    4.37 -		resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    4.38 -		resourceViewDesc.Texture2D.MostDetailedMip = 0;
    4.39 -		resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
    4.40 -		DX::ThrowIfFailed(
    4.41 -			m_d3dDevice->CreateShaderResourceView(
    4.42 -				m_mainTexture.Get(),
    4.43 -				&resourceViewDesc,
    4.44 -				&m_mainTextureResourceView)
    4.45 -			);
    4.46 -	});
    4.47 -
    4.48 -	auto createMainSamplerTask = createMainTextureTask.then([this] () {
    4.49 +    auto createMainSamplerTask = createCubeTask.then([this] () {
    4.50  		D3D11_SAMPLER_DESC samplerDesc;
    4.51  		samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
    4.52  		samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    4.53 @@ -151,6 +110,48 @@
    4.54  	});
    4.55  }
    4.56  
    4.57 +void SDL_winrtrenderer::ResizeMainTexture(int w, int h)
    4.58 +{
    4.59 +    D3D11_TEXTURE2D_DESC textureDesc = {0};
    4.60 +	textureDesc.Width = w;
    4.61 +	textureDesc.Height = h;
    4.62 +	textureDesc.MipLevels = 1;
    4.63 +	textureDesc.ArraySize = 1;
    4.64 +	textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    4.65 +	textureDesc.SampleDesc.Count = 1;
    4.66 +	textureDesc.SampleDesc.Quality = 0;
    4.67 +	textureDesc.Usage = D3D11_USAGE_DYNAMIC;
    4.68 +	textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    4.69 +	textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    4.70 +	textureDesc.MiscFlags = 0;
    4.71 +
    4.72 +	const int numPixels = textureDesc.Width * textureDesc.Height;
    4.73 +	std::vector<uint8> initialTexturePixels(numPixels * 4, 0x00);
    4.74 +	D3D11_SUBRESOURCE_DATA initialTextureData = {0};
    4.75 +	initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
    4.76 +	initialTextureData.SysMemPitch = textureDesc.Width * 4;
    4.77 +	initialTextureData.SysMemSlicePitch = numPixels * 4;
    4.78 +	DX::ThrowIfFailed(
    4.79 +		m_d3dDevice->CreateTexture2D(
    4.80 +			&textureDesc,
    4.81 +			&initialTextureData,
    4.82 +			&m_mainTexture
    4.83 +			)
    4.84 +		);
    4.85 +
    4.86 +	D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
    4.87 +	resourceViewDesc.Format = textureDesc.Format;
    4.88 +	resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    4.89 +	resourceViewDesc.Texture2D.MostDetailedMip = 0;
    4.90 +	resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
    4.91 +	DX::ThrowIfFailed(
    4.92 +		m_d3dDevice->CreateShaderResourceView(
    4.93 +			m_mainTexture.Get(),
    4.94 +			&resourceViewDesc,
    4.95 +			&m_mainTextureResourceView)
    4.96 +		);
    4.97 +}
    4.98 +
    4.99  void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numrects)
   4.100  {
   4.101  	const float blackColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
   4.102 @@ -171,6 +172,10 @@
   4.103  	{
   4.104  		return;
   4.105  	}
   4.106 +    if (!m_mainTextureResourceView)
   4.107 +    {
   4.108 +        return;
   4.109 +    }
   4.110  
   4.111  	// Update the main texture (for SDL usage):
   4.112  	D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
   4.113 @@ -185,7 +190,9 @@
   4.114  
   4.115  	// TODO, WinRT: only copy over the requested rects (via SDL_BlitSurface, perhaps?)
   4.116  	// TODO, WinRT: do a sanity check on the src and dest data when updating the window surface
   4.117 -	const unsigned int numBytes = (int)m_windowBounds.Width * (int)m_windowBounds.Height * 4;
   4.118 +    D3D11_TEXTURE2D_DESC textureDesc = {0};
   4.119 +    m_mainTexture->GetDesc(&textureDesc);
   4.120 +	const unsigned int numBytes = textureDesc.Width * textureDesc.Height * 4;
   4.121  	memcpy(textureMemory.pData, surface->pixels, numBytes);
   4.122  
   4.123  	m_d3dContext->Unmap(
     5.1 --- a/src/video/windowsrt/SDL_winrtrenderer.h	Sun Nov 25 14:45:22 2012 -0500
     5.2 +++ b/src/video/windowsrt/SDL_winrtrenderer.h	Sun Nov 25 17:34:41 2012 -0500
     5.3 @@ -19,6 +19,7 @@
     5.4  
     5.5  internal:
     5.6  	virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) override;
     5.7 +    void ResizeMainTexture(int w, int h);
     5.8  
     5.9  private:
    5.10  	bool m_loadingComplete;
     6.1 --- a/src/video/windowsrt/SDL_winrtvideo.cpp	Sun Nov 25 14:45:22 2012 -0500
     6.2 +++ b/src/video/windowsrt/SDL_winrtvideo.cpp	Sun Nov 25 17:34:41 2012 -0500
     6.3 @@ -154,14 +154,50 @@
     6.4      SDL_zerop(data);
     6.5      data->sdlWindow = window;
     6.6  
     6.7 -    /* Adjust the window data to match the screen */
     6.8 +    /* Make sure the window is considered to be positioned at {0,0},
     6.9 +       and is considered fullscreen, shown, and the like.
    6.10 +    */
    6.11      window->x = 0;
    6.12      window->y = 0;
    6.13 -    window->w = _this->displays->desktop_mode.w;
    6.14 -    window->h = _this->displays->desktop_mode.h;
    6.15 +    window->flags =
    6.16 +        SDL_WINDOW_FULLSCREEN |
    6.17 +        SDL_WINDOW_SHOWN |
    6.18 +        SDL_WINDOW_BORDERLESS |
    6.19 +        SDL_WINDOW_MAXIMIZED |
    6.20 +        SDL_WINDOW_INPUT_GRABBED;
    6.21  
    6.22 +    /* HACK from DLudwig: The following line of code prevents
    6.23 +       SDL_CreateWindow and SDL_UpdateFullscreenMode from trying to resize
    6.24 +       the window after the call to WINRT_CreateWindow returns.
    6.25 +       
    6.26 +       This hack should allow a window to be created in virtually any size,
    6.27 +       and more importantly, it allows a window's framebuffer, as created and
    6.28 +       retrieved via SDL_GetWindowSurface, to be in any size.  This can be
    6.29 +       utilized by apps centered around software rendering, such as ports
    6.30 +       of older apps.  The app can have SDL create a framebuffer in any size
    6.31 +       it chooses.  SDL will scale the framebuffer to the native
    6.32 +       screen size on the GPU (via SDL_UpdateWindowSurface).
    6.33 +    */
    6.34 +    _this->displays[0].fullscreen_window = window;
    6.35 +
    6.36 +    /* Further prevent any display resizing, and make sure SDL_GetWindowDisplayMode
    6.37 +       can report the correct size of windows, by creating a new display
    6.38 +       mode in the requested size.  To note, if the window is being created in
    6.39 +       the device's native screen size, SDL_AddDisplayMode will do nothing.
    6.40 +    */
    6.41 +    window->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
    6.42 +    window->fullscreen_mode.w = window->w;
    6.43 +    window->fullscreen_mode.h = window->h;
    6.44 +    SDL_AddDisplayMode(&_this->displays[0], &window->fullscreen_mode);
    6.45 +
    6.46 +    /* TODO: Consider removing custom display modes in WINRT_DestroyWindow. */
    6.47 + 
    6.48 +    /* Make sure the WinRT app's IFramworkView can post events on
    6.49 +       behalf of SDL:
    6.50 +    */
    6.51      SDL_WinRTGlobalApp->SetSDLWindowData(data);
    6.52  
    6.53 +    /* All done! */
    6.54      return 0;
    6.55  }
    6.56