123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Copyright (c) Microsoft Corporation. All rights reserved
- #include "DisplayManager.h"
- using namespace DirectX;
- //
- // Constructor NULLs out vars
- //
- DISPLAYMANAGER::DISPLAYMANAGER() : m_Device(nullptr),
- m_DeviceContext(nullptr),
- m_MoveSurf(nullptr),
- m_VertexShader(nullptr),
- m_PixelShader(nullptr),
- m_InputLayout(nullptr),
- m_RTV(nullptr),
- m_SamplerLinear(nullptr),
- m_DirtyVertexBufferAlloc(nullptr),
- m_DirtyVertexBufferAllocSize(0)
- {
- }
- //
- // Destructor calls CleanRefs to destroy everything
- //
- DISPLAYMANAGER::~DISPLAYMANAGER()
- {
- CleanRefs();
- if (m_DirtyVertexBufferAlloc) {
- delete [] m_DirtyVertexBufferAlloc;
- m_DirtyVertexBufferAlloc = nullptr;
- }
- }
- //
- // Initialize D3D variables
- //
- void DISPLAYMANAGER::InitD3D(DX_RESOURCES* Data)
- {
- m_Device = Data->Device;
- m_DeviceContext = Data->Context;
- m_VertexShader = Data->VertexShader;
- m_PixelShader = Data->PixelShader;
- m_InputLayout = Data->InputLayout;
- m_SamplerLinear = Data->SamplerLinear;
- m_Device->AddRef();
- m_DeviceContext->AddRef();
- m_VertexShader->AddRef();
- m_PixelShader->AddRef();
- m_InputLayout->AddRef();
- m_SamplerLinear->AddRef();
- }
- //
- // Process a given frame and its metadata
- //
- DUPL_RETURN DISPLAYMANAGER::ProcessFrame(_In_ FRAME_DATA* Data, _Inout_ ID3D11Texture2D* SharedSurf, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc)
- {
- DUPL_RETURN Ret = DUPL_RETURN_SUCCESS;
- // Process dirties and moves
- if (Data->FrameInfo.TotalMetadataBufferSize) {
- D3D11_TEXTURE2D_DESC Desc;
- Data->Frame->GetDesc(&Desc);
- if (Data->MoveCount) {
- Ret = CopyMove(SharedSurf, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(Data->MetaData), Data->MoveCount, OffsetX, OffsetY, DeskDesc, Desc.Width, Desc.Height);
- if (Ret != DUPL_RETURN_SUCCESS) {
- return Ret;
- }
- }
- if (Data->DirtyCount) {
- Ret = CopyDirty(Data->Frame, SharedSurf, reinterpret_cast<RECT*>(Data->MetaData + (Data->MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT))), Data->DirtyCount, OffsetX, OffsetY, DeskDesc);
- }
- }
- return Ret;
- }
- //
- // Returns D3D device being used
- //
- ID3D11Device* DISPLAYMANAGER::GetDevice()
- {
- return m_Device;
- }
- //
- // Set appropriate source and destination rects for move rects
- //
- void DISPLAYMANAGER::SetMoveRect(_Out_ RECT* SrcRect, _Out_ RECT* DestRect, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ DXGI_OUTDUPL_MOVE_RECT* MoveRect, INT TexWidth, INT TexHeight)
- {
- switch (DeskDesc->Rotation) {
- case DXGI_MODE_ROTATION_UNSPECIFIED:
- case DXGI_MODE_ROTATION_IDENTITY: {
- SrcRect->left = MoveRect->SourcePoint.x;
- SrcRect->top = MoveRect->SourcePoint.y;
- SrcRect->right = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left;
- SrcRect->bottom = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top;
- *DestRect = MoveRect->DestinationRect;
- break;
- }
- case DXGI_MODE_ROTATION_ROTATE90: {
- SrcRect->left = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top);
- SrcRect->top = MoveRect->SourcePoint.x;
- SrcRect->right = TexHeight - MoveRect->SourcePoint.y;
- SrcRect->bottom = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left;
- DestRect->left = TexHeight - MoveRect->DestinationRect.bottom;
- DestRect->top = MoveRect->DestinationRect.left;
- DestRect->right = TexHeight - MoveRect->DestinationRect.top;
- DestRect->bottom = MoveRect->DestinationRect.right;
- break;
- }
- case DXGI_MODE_ROTATION_ROTATE180: {
- SrcRect->left = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left);
- SrcRect->top = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top);
- SrcRect->right = TexWidth - MoveRect->SourcePoint.x;
- SrcRect->bottom = TexHeight - MoveRect->SourcePoint.y;
- DestRect->left = TexWidth - MoveRect->DestinationRect.right;
- DestRect->top = TexHeight - MoveRect->DestinationRect.bottom;
- DestRect->right = TexWidth - MoveRect->DestinationRect.left;
- DestRect->bottom = TexHeight - MoveRect->DestinationRect.top;
- break;
- }
- case DXGI_MODE_ROTATION_ROTATE270: {
- SrcRect->left = MoveRect->SourcePoint.x;
- SrcRect->top = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left);
- SrcRect->right = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top;
- SrcRect->bottom = TexWidth - MoveRect->SourcePoint.x;
- DestRect->left = MoveRect->DestinationRect.top;
- DestRect->top = TexWidth - MoveRect->DestinationRect.right;
- DestRect->right = MoveRect->DestinationRect.bottom;
- DestRect->bottom = TexWidth - MoveRect->DestinationRect.left;
- break;
- }
- default: {
- RtlZeroMemory(DestRect, sizeof(RECT));
- RtlZeroMemory(SrcRect, sizeof(RECT));
- break;
- }
- }
- }
- //
- // Copy move rectangles
- //
- DUPL_RETURN DISPLAYMANAGER::CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(MoveCount) DXGI_OUTDUPL_MOVE_RECT* MoveBuffer, UINT MoveCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, INT TexWidth, INT TexHeight)
- {
- D3D11_TEXTURE2D_DESC FullDesc;
- SharedSurf->GetDesc(&FullDesc);
- // Make new intermediate surface to copy into for moving
- if (!m_MoveSurf) {
- D3D11_TEXTURE2D_DESC MoveDesc;
- MoveDesc = FullDesc;
- MoveDesc.Width = DeskDesc->DesktopCoordinates.right - DeskDesc->DesktopCoordinates.left;
- MoveDesc.Height = DeskDesc->DesktopCoordinates.bottom - DeskDesc->DesktopCoordinates.top;
- MoveDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
- MoveDesc.MiscFlags = 0;
- HRESULT hr = m_Device->CreateTexture2D(&MoveDesc, nullptr, &m_MoveSurf);
- if (FAILED(hr)) {
- return ProcessFailure(m_Device, L"Failed to create staging texture for move rects", L"Error", hr, SystemTransitionsExpectedErrors);
- }
- }
- for (UINT i = 0; i < MoveCount; ++i) {
- RECT SrcRect;
- RECT DestRect;
- SetMoveRect(&SrcRect, &DestRect, DeskDesc, &(MoveBuffer[i]), TexWidth, TexHeight);
- // Copy rect out of shared surface
- D3D11_BOX Box;
- Box.left = SrcRect.left + DeskDesc->DesktopCoordinates.left - OffsetX;
- Box.top = SrcRect.top + DeskDesc->DesktopCoordinates.top - OffsetY;
- Box.front = 0;
- Box.right = SrcRect.right + DeskDesc->DesktopCoordinates.left - OffsetX;
- Box.bottom = SrcRect.bottom + DeskDesc->DesktopCoordinates.top - OffsetY;
- Box.back = 1;
- m_DeviceContext->CopySubresourceRegion(m_MoveSurf, 0, SrcRect.left, SrcRect.top, 0, SharedSurf, 0, &Box);
- // Copy back to shared surface
- Box.left = SrcRect.left;
- Box.top = SrcRect.top;
- Box.front = 0;
- Box.right = SrcRect.right;
- Box.bottom = SrcRect.bottom;
- Box.back = 1;
- m_DeviceContext->CopySubresourceRegion(SharedSurf, 0, DestRect.left + DeskDesc->DesktopCoordinates.left - OffsetX, DestRect.top + DeskDesc->DesktopCoordinates.top - OffsetY, 0, m_MoveSurf, 0, &Box);
- }
- return DUPL_RETURN_SUCCESS;
- }
- //
- // Sets up vertices for dirty rects for rotated desktops
- //
- #pragma warning(push)
- #pragma warning(disable:__WARNING_USING_UNINIT_VAR) // false positives in SetDirtyVert due to tool bug
- void DISPLAYMANAGER::SetDirtyVert(_Out_writes_(NUMVERTICES) VERTEX* Vertices, _In_ RECT* Dirty, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ D3D11_TEXTURE2D_DESC* FullDesc, _In_ D3D11_TEXTURE2D_DESC* ThisDesc)
- {
- INT CenterX = FullDesc->Width / 2;
- INT CenterY = FullDesc->Height / 2;
- INT Width = DeskDesc->DesktopCoordinates.right - DeskDesc->DesktopCoordinates.left;
- INT Height = DeskDesc->DesktopCoordinates.bottom - DeskDesc->DesktopCoordinates.top;
- // Rotation compensated destination rect
- RECT DestDirty = *Dirty;
- // Set appropriate coordinates compensated for rotation
- switch (DeskDesc->Rotation) {
- case DXGI_MODE_ROTATION_ROTATE90: {
- DestDirty.left = Width - Dirty->bottom;
- DestDirty.top = Dirty->left;
- DestDirty.right = Width - Dirty->top;
- DestDirty.bottom = Dirty->right;
- Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- break;
- }
- case DXGI_MODE_ROTATION_ROTATE180: {
- DestDirty.left = Width - Dirty->right;
- DestDirty.top = Height - Dirty->bottom;
- DestDirty.right = Width - Dirty->left;
- DestDirty.bottom = Height - Dirty->top;
- Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- break;
- }
- case DXGI_MODE_ROTATION_ROTATE270: {
- DestDirty.left = Dirty->top;
- DestDirty.top = Height - Dirty->right;
- DestDirty.right = Dirty->bottom;
- DestDirty.bottom = Height - Dirty->left;
- Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- break;
- }
- default:
- assert(false); // drop through
- case DXGI_MODE_ROTATION_UNSPECIFIED:
- case DXGI_MODE_ROTATION_IDENTITY: {
- Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
- Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
- break;
- }
- }
- // Set positions
- Vertices[0].Pos = XMFLOAT3((DestDirty.left + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX),
- -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY),
- 0.0f);
- Vertices[1].Pos = XMFLOAT3((DestDirty.left + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX),
- -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY),
- 0.0f);
- Vertices[2].Pos = XMFLOAT3((DestDirty.right + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX),
- -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY),
- 0.0f);
- Vertices[3].Pos = Vertices[2].Pos;
- Vertices[4].Pos = Vertices[1].Pos;
- Vertices[5].Pos = XMFLOAT3((DestDirty.right + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX),
- -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY),
- 0.0f);
- Vertices[3].TexCoord = Vertices[2].TexCoord;
- Vertices[4].TexCoord = Vertices[1].TexCoord;
- }
- #pragma warning(pop) // re-enable __WARNING_USING_UNINIT_VAR
- //
- // Copies dirty rectangles
- //
- DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(DirtyCount) RECT* DirtyBuffer, UINT DirtyCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc)
- {
- HRESULT hr;
- D3D11_TEXTURE2D_DESC FullDesc;
- SharedSurf->GetDesc(&FullDesc);
- D3D11_TEXTURE2D_DESC ThisDesc;
- SrcSurface->GetDesc(&ThisDesc);
- if (!m_RTV) {
- hr = m_Device->CreateRenderTargetView(SharedSurf, nullptr, &m_RTV);
- if (FAILED(hr)) {
- return ProcessFailure(m_Device, L"Failed to create render target view for dirty rects", L"Error", hr, SystemTransitionsExpectedErrors);
- }
- }
- D3D11_SHADER_RESOURCE_VIEW_DESC ShaderDesc;
- ShaderDesc.Format = ThisDesc.Format;
- ShaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- ShaderDesc.Texture2D.MostDetailedMip = ThisDesc.MipLevels - 1;
- ShaderDesc.Texture2D.MipLevels = ThisDesc.MipLevels;
- // Create new shader resource view
- ID3D11ShaderResourceView* ShaderResource = nullptr;
- hr = m_Device->CreateShaderResourceView(SrcSurface, &ShaderDesc, &ShaderResource);
- if (FAILED(hr)) {
- return ProcessFailure(m_Device, L"Failed to create shader resource view for dirty rects", L"Error", hr, SystemTransitionsExpectedErrors);
- }
- FLOAT BlendFactor[4] = {0.f, 0.f, 0.f, 0.f};
- m_DeviceContext->OMSetBlendState(nullptr, BlendFactor, 0xFFFFFFFF);
- m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr);
- m_DeviceContext->VSSetShader(m_VertexShader, nullptr, 0);
- m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0);
- m_DeviceContext->PSSetShaderResources(0, 1, &ShaderResource);
- m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerLinear);
- m_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- // Create space for vertices for the dirty rects if the current space isn't large enough
- UINT BytesNeeded = sizeof(VERTEX) * NUMVERTICES * DirtyCount;
- if (BytesNeeded > m_DirtyVertexBufferAllocSize) {
- if (m_DirtyVertexBufferAlloc) {
- delete [] m_DirtyVertexBufferAlloc;
- }
- m_DirtyVertexBufferAlloc = new (std::nothrow) BYTE[BytesNeeded];
- if (!m_DirtyVertexBufferAlloc) {
- m_DirtyVertexBufferAllocSize = 0;
- return ProcessFailure(nullptr, L"Failed to allocate memory for dirty vertex buffer.", L"Error", E_OUTOFMEMORY);
- }
- m_DirtyVertexBufferAllocSize = BytesNeeded;
- }
- // Fill them in
- VERTEX* DirtyVertex = reinterpret_cast<VERTEX*>(m_DirtyVertexBufferAlloc);
- for (UINT i = 0; i < DirtyCount; ++i, DirtyVertex += NUMVERTICES) {
- SetDirtyVert(DirtyVertex, &(DirtyBuffer[i]), OffsetX, OffsetY, DeskDesc, &FullDesc, &ThisDesc);
- }
- // Create vertex buffer
- D3D11_BUFFER_DESC BufferDesc;
- RtlZeroMemory(&BufferDesc, sizeof(BufferDesc));
- BufferDesc.Usage = D3D11_USAGE_DEFAULT;
- BufferDesc.ByteWidth = BytesNeeded;
- BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- BufferDesc.CPUAccessFlags = 0;
- D3D11_SUBRESOURCE_DATA InitData;
- RtlZeroMemory(&InitData, sizeof(InitData));
- InitData.pSysMem = m_DirtyVertexBufferAlloc;
- ID3D11Buffer* VertBuf = nullptr;
- hr = m_Device->CreateBuffer(&BufferDesc, &InitData, &VertBuf);
- if (FAILED(hr)) {
- return ProcessFailure(m_Device, L"Failed to create vertex buffer in dirty rect processing", L"Error", hr, SystemTransitionsExpectedErrors);
- }
- UINT Stride = sizeof(VERTEX);
- UINT Offset = 0;
- m_DeviceContext->IASetVertexBuffers(0, 1, &VertBuf, &Stride, &Offset);
- D3D11_VIEWPORT VP;
- VP.Width = static_cast<FLOAT>(FullDesc.Width);
- VP.Height = static_cast<FLOAT>(FullDesc.Height);
- VP.MinDepth = 0.0f;
- VP.MaxDepth = 1.0f;
- VP.TopLeftX = 0.0f;
- VP.TopLeftY = 0.0f;
- m_DeviceContext->RSSetViewports(1, &VP);
- m_DeviceContext->Draw(NUMVERTICES * DirtyCount, 0);
- VertBuf->Release();
- VertBuf = nullptr;
- ShaderResource->Release();
- ShaderResource = nullptr;
- return DUPL_RETURN_SUCCESS;
- }
- //
- // Clean all references
- //
- void DISPLAYMANAGER::CleanRefs()
- {
- if (m_DeviceContext) {
- m_DeviceContext->Release();
- m_DeviceContext = nullptr;
- }
- if (m_Device) {
- m_Device->Release();
- m_Device = nullptr;
- }
- if (m_MoveSurf) {
- m_MoveSurf->Release();
- m_MoveSurf = nullptr;
- }
- if (m_VertexShader) {
- m_VertexShader->Release();
- m_VertexShader = nullptr;
- }
- if (m_PixelShader) {
- m_PixelShader->Release();
- m_PixelShader = nullptr;
- }
- if (m_InputLayout) {
- m_InputLayout->Release();
- m_InputLayout = nullptr;
- }
- if (m_SamplerLinear) {
- m_SamplerLinear->Release();
- m_SamplerLinear = nullptr;
- }
- if (m_RTV) {
- m_RTV->Release();
- m_RTV = nullptr;
- }
- }
|