Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
WinRT: moved a bit more Direct3D 11.1 code into the SDL_Renderer backend
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidLudwig committed Feb 3, 2013
1 parent 3cf5761 commit c4590a4
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 41 deletions.
11 changes: 9 additions & 2 deletions src/core/windows/SDL_windows.c
Expand Up @@ -30,17 +30,24 @@

/* Sets an error message based on GetLastError() */
void
WIN_SetError(const char *prefix)
WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
{
TCHAR buffer[1024];
char *message;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0,
buffer, SDL_arraysize(buffer), NULL);
message = WIN_StringToUTF8(buffer);
SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
SDL_free(message);
}

/* Sets an error message based on GetLastError() */
void
WIN_SetError(const char *prefix)
{
WIN_SetErrorFromHRESULT(prefix, GetLastError());
}

HRESULT
WIN_CoInitialize(void)
{
Expand Down
3 changes: 3 additions & 0 deletions src/core/windows/SDL_windows.h
Expand Up @@ -46,6 +46,9 @@
#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1)
#endif

/* Sets an error message based on a given HRESULT */
extern void WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);

/* Sets an error message based on GetLastError() */
extern void WIN_SetError(const char *prefix);

Expand Down
49 changes: 47 additions & 2 deletions src/render/direct3d11/SDL_render_d3d11.cpp
Expand Up @@ -62,7 +62,7 @@ static int D3D11_UpdateViewport(SDL_Renderer * renderer);
// const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
//static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
// Uint32 format, void * pixels, int pitch);
//static void D3D11_RenderPresent(SDL_Renderer * renderer);
static void D3D11_RenderPresent(SDL_Renderer * renderer);
//static void D3D11_DestroyTexture(SDL_Renderer * renderer,
// SDL_Texture * texture);
//static void D3D11_DestroyRenderer(SDL_Renderer * renderer);
Expand Down Expand Up @@ -135,7 +135,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
//renderer->RenderCopy = D3D11_RenderCopy;
//renderer->RenderCopyEx = D3D11_RenderCopyEx;
//renderer->RenderReadPixels = D3D11_RenderReadPixels;
//renderer->RenderPresent = D3D11_RenderPresent;
renderer->RenderPresent = D3D11_RenderPresent;
//renderer->DestroyTexture = D3D11_DestroyTexture;
//renderer->DestroyRenderer = D3D11_DestroyRenderer;
renderer->info = D3D11_RenderDriver.info;
Expand Down Expand Up @@ -286,6 +286,51 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
return 0;
}

static void
D3D11_RenderPresent(SDL_Renderer * renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;

#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = data->swapChain->Present(1, 0);
#else
// The application may optionally specify "dirty" or "scroll"
// rects to improve efficiency in certain scenarios.
// This option is not available on Windows Phone 8, to note.
DXGI_PRESENT_PARAMETERS parameters = {0};
parameters.DirtyRectsCount = 0;
parameters.pDirtyRects = nullptr;
parameters.pScrollRect = nullptr;
parameters.pScrollOffset = nullptr;

// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = data->swapChain->Present1(1, 0, &parameters);
#endif

// Discard the contents of the render target.
// This is a valid operation only when the existing contents will be entirely
// overwritten. If dirty or scroll rects are used, this call should be removed.
data->d3dContext->DiscardView(data->renderTargetView.Get());

// If the device was removed either by a disconnect or a driver upgrade, we
// must recreate all device resources.
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
extern void WINRT_HandleDeviceLost(); // TODO, WinRT: move lost-device handling into the Direct3D 11.1 renderer, as appropriate
WINRT_HandleDeviceLost();
}
else
{
WIN_SetErrorFromHRESULT(__FUNCTION__, hr);
// TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvedge debug info from users' machines
}
}

#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */

/* vi: set ts=4 sw=4 expandtab: */
6 changes: 6 additions & 0 deletions src/video/windowsrt/SDL_WinRTApp.cpp
Expand Up @@ -33,6 +33,12 @@ static SDL_WinRT_MainFunction SDL_WinRT_main = nullptr;
// SDL_CreateWindow().
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;

// HACK: provide a temporary means for the Direct3D 11.1 renderer to handle lost devices, while refactoring is underway
void WINRT_HandleDeviceLost()
{
SDL_WinRTGlobalApp->m_renderer->HandleDeviceLost();
}

using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
Expand Down
38 changes: 2 additions & 36 deletions src/video/windowsrt/SDL_winrtrenderer.cpp
Expand Up @@ -12,6 +12,7 @@ SDL_winrtrenderer::SDL_winrtrenderer() :
m_mainTextureHelperSurface(NULL),
m_loadingComplete(false),
m_vertexCount(0),
m_sdlRenderer(NULL),
m_sdlRendererData(NULL)
{
}
Expand Down Expand Up @@ -562,42 +563,7 @@ void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numr
// Method to deliver the final image to the display.
void SDL_winrtrenderer::Present()
{
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = m_sdlRendererData->swapChain->Present(1, 0);
#else
// The application may optionally specify "dirty" or "scroll"
// rects to improve efficiency in certain scenarios.
// This option is not available on Windows Phone 8, to note.
DXGI_PRESENT_PARAMETERS parameters = {0};
parameters.DirtyRectsCount = 0;
parameters.pDirtyRects = nullptr;
parameters.pScrollRect = nullptr;
parameters.pScrollOffset = nullptr;

// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = m_sdlRendererData->swapChain->Present1(1, 0, &parameters);
#endif

// Discard the contents of the render target.
// This is a valid operation only when the existing contents will be entirely
// overwritten. If dirty or scroll rects are used, this call should be removed.
m_sdlRendererData->d3dContext->DiscardView(m_sdlRendererData->renderTargetView.Get());

// If the device was removed either by a disconnect or a driver upgrade, we
// must recreate all device resources.
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
HandleDeviceLost();
}
else
{
DX::ThrowIfFailed(hr);
}
SDL_RenderPresent(m_sdlRenderer);
}

// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
Expand Down
3 changes: 2 additions & 1 deletion src/video/windowsrt/SDL_winrtrenderer.h
Expand Up @@ -31,7 +31,8 @@ ref class SDL_winrtrenderer
void ResizeMainTexture(int w, int h);

internal:
// Internal SDL rendeerer (likely a temporary addition, for refactoring purposes):
// Internal SDL renderer (likely a temporary addition, for refactoring purposes):
SDL_Renderer * m_sdlRenderer;
D3D11_RenderData * m_sdlRendererData;

protected private:
Expand Down
3 changes: 3 additions & 0 deletions src/video/windowsrt/SDL_winrtvideo.cpp
Expand Up @@ -220,7 +220,10 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
// for refactoring purposes. Initialize the SDL_Renderer
// first in order to give it the opportunity to create key
// resources first.
//
// TODO, WinRT: either make WINRT_CreateWindow not call SDL_CreateRenderer, or have it do error checking if it does call it
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
SDL_WinRTGlobalApp->m_renderer->m_sdlRenderer = renderer;
SDL_WinRTGlobalApp->m_renderer->m_sdlRendererData = (D3D11_RenderData *) renderer->driverdata;
SDL_WinRTGlobalApp->m_renderer->Initialize(CoreWindow::GetForCurrentThread());

Expand Down

0 comments on commit c4590a4

Please sign in to comment.