WinRT: fixed a window-surface-updating bug (WinRT/DLudwig #25, http://bit.ly/RkawRR)
authorDavid Ludwig <dludwig@pobox.com>
Sun, 09 Dec 2012 22:43:34 -0500
changeset 8375 e33eb49b7f42
parent 8374 0294dc45d39d
child 8376 a607bff42803
WinRT: fixed a window-surface-updating bug (WinRT/DLudwig #25, http://bit.ly/RkawRR)
src/video/windowsrt/SDL_winrtframebuffer.cpp
src/video/windowsrt/SDL_winrtrenderer.cpp
src/video/windowsrt/SDL_winrtrenderer.h
--- a/src/video/windowsrt/SDL_winrtframebuffer.cpp	Mon Dec 03 22:36:00 2012 -0500
+++ b/src/video/windowsrt/SDL_winrtframebuffer.cpp	Sun Dec 09 22:43:34 2012 -0500
@@ -34,7 +34,7 @@
 int SDL_WINRT_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
 {
     SDL_Surface *surface;
-    const Uint32 surface_format = SDL_PIXELFORMAT_ARGB8888;
+    const Uint32 surface_format = SDL_PIXELFORMAT_RGB888;
     int w, h;
     int bpp;
     Uint32 Rmask, Gmask, Bmask, Amask;
--- a/src/video/windowsrt/SDL_winrtrenderer.cpp	Mon Dec 03 22:36:00 2012 -0500
+++ b/src/video/windowsrt/SDL_winrtrenderer.cpp	Sun Dec 09 22:43:34 2012 -0500
@@ -9,11 +9,20 @@
 
 // Constructor.
 SDL_winrtrenderer::SDL_winrtrenderer() :
+    m_mainTextureHelperSurface(NULL),
     m_loadingComplete(false),
 	m_vertexCount(0)
 {
 }
 
+SDL_winrtrenderer::~SDL_winrtrenderer()
+{
+    if (m_mainTextureHelperSurface) {
+        SDL_FreeSurface(m_mainTextureHelperSurface);
+        m_mainTextureHelperSurface = NULL;
+    }
+}
+
 // Initialize the Direct3D resources required to run.
 void SDL_winrtrenderer::Initialize(CoreWindow^ window)
 {
@@ -372,12 +381,14 @@
 
 void SDL_winrtrenderer::ResizeMainTexture(int w, int h)
 {
+    const int pixelSizeInBytes = 4;
+
     D3D11_TEXTURE2D_DESC textureDesc = {0};
 	textureDesc.Width = w;
 	textureDesc.Height = h;
 	textureDesc.MipLevels = 1;
 	textureDesc.ArraySize = 1;
-	textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+	textureDesc.Format = DXGI_FORMAT_B8G8R8X8_UNORM;
 	textureDesc.SampleDesc.Count = 1;
 	textureDesc.SampleDesc.Quality = 0;
 	textureDesc.Usage = D3D11_USAGE_DYNAMIC;
@@ -385,12 +396,21 @@
 	textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
 	textureDesc.MiscFlags = 0;
 
-	const int numPixels = textureDesc.Width * textureDesc.Height;
-	std::vector<uint8> initialTexturePixels(numPixels * 4, 0x00);
+    const int numPixels = textureDesc.Width * textureDesc.Height;
+    std::vector<uint8> initialTexturePixels(numPixels * pixelSizeInBytes, 0x00);
+
+    // Fill the texture with a non-black color, for debugging purposes:
+    //for (int i = 0; i < (numPixels * pixelSizeInBytes); i += pixelSizeInBytes) {
+    //    initialTexturePixels[i+0] = 0xff;
+    //    initialTexturePixels[i+1] = 0xff;
+    //    initialTexturePixels[i+2] = 0x00;
+    //    initialTexturePixels[i+3] = 0xff;
+    //}
+
 	D3D11_SUBRESOURCE_DATA initialTextureData = {0};
 	initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
-	initialTextureData.SysMemPitch = textureDesc.Width * 4;
-	initialTextureData.SysMemSlicePitch = numPixels * 4;
+	initialTextureData.SysMemPitch = textureDesc.Width * pixelSizeInBytes;
+	initialTextureData.SysMemSlicePitch = numPixels * pixelSizeInBytes;
 	DX::ThrowIfFailed(
 		m_d3dDevice->CreateTexture2D(
 			&textureDesc,
@@ -399,6 +419,20 @@
 			)
 		);
 
+    if (m_mainTextureHelperSurface) {
+        SDL_FreeSurface(m_mainTextureHelperSurface);
+        m_mainTextureHelperSurface = NULL;
+    }
+    m_mainTextureHelperSurface = SDL_CreateRGBSurfaceFrom(
+        NULL,
+        textureDesc.Width, textureDesc.Height,
+        (pixelSizeInBytes * 8),
+        0,      // Use an nil pitch for now.  This'll be filled in when updating the texture.
+        0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);    // TODO, WinRT: calculate masks given the Direct3D-defined pixel format of the texture
+    if (m_mainTextureHelperSurface == NULL) {
+        DX::ThrowIfFailed(E_FAIL);  // TODO, WinRT: generate a better error here, taking into account who's calling this function.
+    }
+
 	D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
 	resourceViewDesc.Format = textureDesc.Format;
 	resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
@@ -429,7 +463,7 @@
 
 void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numrects)
 {
-	const float blackColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+	const float blackColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
 	m_d3dContext->ClearRenderTargetView(
 		m_renderTargetView.Get(),
 		blackColor
@@ -445,7 +479,8 @@
         return;
     }
 
-	// Update the main texture (for SDL usage):
+	// Update the main texture (for SDL usage).  Start by mapping the SDL
+    // window's main texture to CPU-accessible memory:
 	D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
 	DX::ThrowIfFailed(
 		m_d3dContext->Map(
@@ -456,13 +491,15 @@
 			&textureMemory)
 		);
 
-	// 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
-    D3D11_TEXTURE2D_DESC textureDesc = {0};
-    m_mainTexture->GetDesc(&textureDesc);
-	const unsigned int numBytes = textureDesc.Width * textureDesc.Height * 4;
-	memcpy(textureMemory.pData, surface->pixels, numBytes);
+    // Copy pixel data to the locked texture's memory:
+    m_mainTextureHelperSurface->pixels = textureMemory.pData;
+    m_mainTextureHelperSurface->pitch = textureMemory.RowPitch;
+    SDL_BlitSurface(surface, NULL, m_mainTextureHelperSurface, NULL);
+	// TODO, WinRT: only update the requested rects (passed to SDL_UpdateWindowSurface), rather than everything
 
+    // Clean up a bit, then commit the texture's memory back to Direct3D:
+    m_mainTextureHelperSurface->pixels = NULL;
+    m_mainTextureHelperSurface->pitch = 0;
 	m_d3dContext->Unmap(
 		m_mainTexture.Get(),
 		0);
--- a/src/video/windowsrt/SDL_winrtrenderer.h	Mon Dec 03 22:36:00 2012 -0500
+++ b/src/video/windowsrt/SDL_winrtrenderer.h	Sun Dec 09 22:43:34 2012 -0500
@@ -16,6 +16,7 @@
 	SDL_winrtrenderer();
 
 public:
+    virtual ~SDL_winrtrenderer();
 	virtual void Initialize(Windows::UI::Core::CoreWindow^ window);
 	virtual void HandleDeviceLost();
 	virtual void CreateDeviceResources();
@@ -42,6 +43,9 @@
 	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_mainTextureResourceView;
 	Microsoft::WRL::ComPtr<ID3D11SamplerState> m_mainSampler;
 
+    // UpdateWindowSurface helper objects
+    SDL_Surface * m_mainTextureHelperSurface;
+
 	// Cached renderer properties.
 	D3D_FEATURE_LEVEL m_featureLevel;
 	Windows::Foundation::Size m_renderTargetSize;