WinRT: fixed bug: SDL_RenderReadPixels didn't work with certain orientations of the physical display

main
David Ludwig 2013-12-10 22:34:08 -05:00
parent 679259473e
commit 446a270487
1 changed files with 77 additions and 66 deletions

View File

@ -630,12 +630,46 @@ D3D11_ConvertDipsToPixels(float dips)
} }
#endif #endif
#if WINAPI_FAMILY == WINAPI_FAMILY_APP #if WINAPI_FAMILY == WINAPI_FAMILY_APP
// TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var // TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var
extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative; extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
#endif #endif
static DXGI_MODE_ROTATION
D3D11_GetRotationForOrientation(Windows::Graphics::Display::DisplayOrientations orientation)
{
switch (orientation)
{
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
//
// Windows Phone rotations
//
case DisplayOrientations::Landscape:
return DXGI_MODE_ROTATION_ROTATE90;
case DisplayOrientations::Portrait:
return DXGI_MODE_ROTATION_IDENTITY;
case DisplayOrientations::LandscapeFlipped:
return DXGI_MODE_ROTATION_ROTATE270;
case DisplayOrientations::PortraitFlipped:
return DXGI_MODE_ROTATION_ROTATE180;
#else
//
// Non-Windows-Phone rotations (ex: Windows 8, Windows RT)
//
case DisplayOrientations::Landscape:
return DXGI_MODE_ROTATION_IDENTITY;
case DisplayOrientations::Portrait:
return DXGI_MODE_ROTATION_ROTATE270;
case DisplayOrientations::LandscapeFlipped:
return DXGI_MODE_ROTATION_ROTATE180;
case DisplayOrientations::PortraitFlipped:
return DXGI_MODE_ROTATION_ROTATE90;
#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
default:
return DXGI_MODE_ROTATION_UNSPECIFIED;
}
}
// Initialize all resources that change when the window's size changes. // Initialize all resources that change when the window's size changes.
// TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32 // TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
@ -811,31 +845,9 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
// Set the proper orientation for the swap chain, and generate the // Set the proper orientation for the swap chain, and generate the
// 3D matrix transformation for rendering to the rotated swap chain. // 3D matrix transformation for rendering to the rotated swap chain.
// //
// To note, his operation is not necessary on Windows Phone, nor is it // To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
// even supported there. It's only needed in Windows 8/RT. // on Windows Phone, nor is it supported there. It's only needed in Windows 8/RT.
DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; DXGI_MODE_ROTATION rotation = D3D11_GetRotationForOrientation(data->orientation);
switch (data->orientation)
{
case DisplayOrientations::Landscape:
rotation = DXGI_MODE_ROTATION_IDENTITY;
break;
case DisplayOrientations::Portrait:
rotation = DXGI_MODE_ROTATION_ROTATE270;
break;
case DisplayOrientations::LandscapeFlipped:
rotation = DXGI_MODE_ROTATION_ROTATE180;
break;
case DisplayOrientations::PortraitFlipped:
rotation = DXGI_MODE_ROTATION_ROTATE90;
break;
default:
throw ref new Platform::FailureException();
}
result = data->swapChain->SetRotation(rotation); result = data->swapChain->SetRotation(rotation);
if (FAILED(result)) { if (FAILED(result)) {
WIN_SetErrorFromHRESULT(__FUNCTION__, result); WIN_SetErrorFromHRESULT(__FUNCTION__, result);
@ -1223,7 +1235,7 @@ D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView; rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
return 0; return 0;
} }
static int static int
D3D11_UpdateViewport(SDL_Renderer * renderer) D3D11_UpdateViewport(SDL_Renderer * renderer)
@ -1237,50 +1249,24 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
return 0; return 0;
} }
switch (data->orientation) // Make sure the SDL viewport gets rotated to that of the physical display's orientation.
// Keep in mind here that the Y-axis will be been inverted (from Direct3D's
// default coordinate system) so rotations will be done in the opposite
// direction of the DXGI_MODE_ROTATION enumeration.
switch (D3D11_GetRotationForOrientation(data->orientation))
{ {
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP case DXGI_MODE_ROTATION_IDENTITY:
//
// Windows Phone rotations
//
case DisplayOrientations::Landscape:
// 270-degree (-90 degree) Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(-XM_PIDIV2));
break;
case DisplayOrientations::Portrait:
// 0-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixIdentity()); XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixIdentity());
break; break;
case DisplayOrientations::LandscapeFlipped: case DXGI_MODE_ROTATION_ROTATE270:
// 90-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PIDIV2)); XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PIDIV2));
break; break;
case DisplayOrientations::PortraitFlipped: case DXGI_MODE_ROTATION_ROTATE180:
// 180-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PI));
break;
#else
//
// Non-Windows-Phone rotations (ex: Windows 8, Windows RT)
//
case DisplayOrientations::Landscape:
// 0-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixIdentity());
break;
case DisplayOrientations::Portrait:
// 90-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PIDIV2));
break;
case DisplayOrientations::LandscapeFlipped:
// 180-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PI)); XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PI));
break; break;
case DisplayOrientations::PortraitFlipped: case DXGI_MODE_ROTATION_ROTATE90:
// 270-degree (-90 degree) Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(-XM_PIDIV2)); XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(-XM_PIDIV2));
break; break;
#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
default: default:
SDL_SetError("An unknown DisplayOrientation is being used"); SDL_SetError("An unknown DisplayOrientation is being used");
return -1; return -1;
@ -1314,6 +1300,7 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
// for Windows Phone devices. // for Windows Phone devices.
// //
SDL_FRect orientationAlignedViewport; SDL_FRect orientationAlignedViewport;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
const bool swapDimensions = const bool swapDimensions =
data->orientation == DisplayOrientations::Landscape || data->orientation == DisplayOrientations::Landscape ||
@ -1830,10 +1817,34 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
// Copy the desired portion of the back buffer to the staging texture: // Copy the desired portion of the back buffer to the staging texture:
D3D11_BOX srcBox; D3D11_BOX srcBox;
srcBox.left = rect->x; switch (D3D11_GetRotationForOrientation(data->orientation)) {
srcBox.right = rect->x + rect->w; case DXGI_MODE_ROTATION_IDENTITY:
srcBox.top = rect->y; srcBox.left = rect->x;
srcBox.bottom = rect->y + rect->h; srcBox.right = rect->x + rect->w;
srcBox.top = rect->y;
srcBox.bottom = rect->y + rect->h;
break;
case DXGI_MODE_ROTATION_ROTATE270:
srcBox.left = rect->y;
srcBox.right = rect->y + rect->h;
srcBox.top = renderer->viewport.w - rect->x - rect->w;
srcBox.bottom = renderer->viewport.w - rect->x;
break;
case DXGI_MODE_ROTATION_ROTATE180:
srcBox.left = renderer->viewport.w - rect->x - rect->w;
srcBox.right = renderer->viewport.w - rect->x;
srcBox.top = renderer->viewport.h - rect->y - rect->h;
srcBox.bottom = renderer->viewport.h - rect->y;
break;
case DXGI_MODE_ROTATION_ROTATE90:
srcBox.left = renderer->viewport.h - rect->y - rect->h;
srcBox.right = renderer->viewport.h - rect->y;
srcBox.top = rect->x;
srcBox.bottom = rect->x + rect->h;
break;
default:
return SDL_SetError("The physical display is in an unknown or unsupported orientation");
}
srcBox.front = 0; srcBox.front = 0;
srcBox.back = 1; srcBox.back = 1;
data->d3dContext->CopySubresourceRegion( data->d3dContext->CopySubresourceRegion(