WinRT: moved a bit more Direct3D 11.1 code into the SDL_Renderer backend

This commit is contained in:
David Ludwig 2013-02-02 21:05:32 -05:00
parent f7b08ae60b
commit b9299763b6
7 changed files with 72 additions and 41 deletions

View file

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

View file

@ -46,6 +46,9 @@
#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1) #define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1)
#endif #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() */ /* Sets an error message based on GetLastError() */
extern void WIN_SetError(const char *prefix); extern void WIN_SetError(const char *prefix);

View file

@ -62,7 +62,7 @@ static int D3D11_UpdateViewport(SDL_Renderer * renderer);
// const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip); // const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
//static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, //static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
// Uint32 format, void * pixels, int pitch); // 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, //static void D3D11_DestroyTexture(SDL_Renderer * renderer,
// SDL_Texture * texture); // SDL_Texture * texture);
//static void D3D11_DestroyRenderer(SDL_Renderer * renderer); //static void D3D11_DestroyRenderer(SDL_Renderer * renderer);
@ -135,7 +135,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
//renderer->RenderCopy = D3D11_RenderCopy; //renderer->RenderCopy = D3D11_RenderCopy;
//renderer->RenderCopyEx = D3D11_RenderCopyEx; //renderer->RenderCopyEx = D3D11_RenderCopyEx;
//renderer->RenderReadPixels = D3D11_RenderReadPixels; //renderer->RenderReadPixels = D3D11_RenderReadPixels;
//renderer->RenderPresent = D3D11_RenderPresent; renderer->RenderPresent = D3D11_RenderPresent;
//renderer->DestroyTexture = D3D11_DestroyTexture; //renderer->DestroyTexture = D3D11_DestroyTexture;
//renderer->DestroyRenderer = D3D11_DestroyRenderer; //renderer->DestroyRenderer = D3D11_DestroyRenderer;
renderer->info = D3D11_RenderDriver.info; renderer->info = D3D11_RenderDriver.info;
@ -286,6 +286,51 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
return 0; 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 */ #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View file

@ -33,6 +33,12 @@ static SDL_WinRT_MainFunction SDL_WinRT_main = nullptr;
// SDL_CreateWindow(). // SDL_CreateWindow().
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr; 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;
using namespace Windows::ApplicationModel::Core; using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation; using namespace Windows::ApplicationModel::Activation;

View file

@ -12,6 +12,7 @@ SDL_winrtrenderer::SDL_winrtrenderer() :
m_mainTextureHelperSurface(NULL), m_mainTextureHelperSurface(NULL),
m_loadingComplete(false), m_loadingComplete(false),
m_vertexCount(0), m_vertexCount(0),
m_sdlRenderer(NULL),
m_sdlRendererData(NULL) m_sdlRendererData(NULL)
{ {
} }
@ -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. // Method to deliver the final image to the display.
void SDL_winrtrenderer::Present() void SDL_winrtrenderer::Present()
{ {
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP SDL_RenderPresent(m_sdlRenderer);
// 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);
}
} }
// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels. // Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.

View file

@ -31,7 +31,8 @@ internal:
void ResizeMainTexture(int w, int h); void ResizeMainTexture(int w, int h);
internal: 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; D3D11_RenderData * m_sdlRendererData;
protected private: protected private:

View file

@ -220,7 +220,10 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
// for refactoring purposes. Initialize the SDL_Renderer // for refactoring purposes. Initialize the SDL_Renderer
// first in order to give it the opportunity to create key // first in order to give it the opportunity to create key
// resources first. // 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_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->m_sdlRendererData = (D3D11_RenderData *) renderer->driverdata;
SDL_WinRTGlobalApp->m_renderer->Initialize(CoreWindow::GetForCurrentThread()); SDL_WinRTGlobalApp->m_renderer->Initialize(CoreWindow::GetForCurrentThread());