WinRT: moved a bit more Direct3D 11.1 code into the SDL_Renderer backend
authorDavid Ludwig <dludwig@pobox.com>
Sat, 02 Feb 2013 21:05:32 -0500
changeset 8401 29ecd2eca4af
parent 8400 1315402d9028
child 8402 d9464231555b
WinRT: moved a bit more Direct3D 11.1 code into the SDL_Renderer backend
src/core/windows/SDL_windows.c
src/core/windows/SDL_windows.h
src/render/direct3d11/SDL_render_d3d11.cpp
src/video/windowsrt/SDL_WinRTApp.cpp
src/video/windowsrt/SDL_winrtrenderer.cpp
src/video/windowsrt/SDL_winrtrenderer.h
src/video/windowsrt/SDL_winrtvideo.cpp
--- a/src/core/windows/SDL_windows.c	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/core/windows/SDL_windows.c	Sat Feb 02 21:05:32 2013 -0500
@@ -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)
 {
--- a/src/core/windows/SDL_windows.h	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/core/windows/SDL_windows.h	Sat Feb 02 21:05:32 2013 -0500
@@ -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);
 
--- a/src/render/direct3d11/SDL_render_d3d11.cpp	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/render/direct3d11/SDL_render_d3d11.cpp	Sat Feb 02 21:05:32 2013 -0500
@@ -62,7 +62,7 @@
 //                          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);
@@ -135,7 +135,7 @@
     //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;
@@ -286,6 +286,51 @@
     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: */
--- a/src/video/windowsrt/SDL_WinRTApp.cpp	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/video/windowsrt/SDL_WinRTApp.cpp	Sat Feb 02 21:05:32 2013 -0500
@@ -33,6 +33,12 @@
 // 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;
--- a/src/video/windowsrt/SDL_winrtrenderer.cpp	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/video/windowsrt/SDL_winrtrenderer.cpp	Sat Feb 02 21:05:32 2013 -0500
@@ -12,6 +12,7 @@
     m_mainTextureHelperSurface(NULL),
     m_loadingComplete(false),
     m_vertexCount(0),
+    m_sdlRenderer(NULL),
     m_sdlRendererData(NULL)
 {
 }
@@ -562,42 +563,7 @@
 // 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.
--- a/src/video/windowsrt/SDL_winrtrenderer.h	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/video/windowsrt/SDL_winrtrenderer.h	Sat Feb 02 21:05:32 2013 -0500
@@ -31,7 +31,8 @@
     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:
--- a/src/video/windowsrt/SDL_winrtvideo.cpp	Sat Feb 02 19:32:44 2013 -0500
+++ b/src/video/windowsrt/SDL_winrtvideo.cpp	Sat Feb 02 21:05:32 2013 -0500
@@ -220,7 +220,10 @@
     // 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());