Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

WinRT: allow windows in non-native screen sizes. Scaling is applied f…

…or such.
  • Loading branch information
DavidLudwig committed Nov 25, 2012
1 parent 69340f8 commit 2c2aeb0da4eb06d568cc553670f7805512f884f6
@@ -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
@@ -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.
@@ -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;
}

@@ -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<uint8> 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<uint8> 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(
@@ -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;
@@ -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;
}

0 comments on commit 2c2aeb0

Please sign in to comment.