From 1effd65aebd3be5fc8d0318f3230b49f147ec683 Mon Sep 17 00:00:00 2001 From: hecomi Date: Thu, 5 Jan 2017 15:16:28 +0900 Subject: [PATCH] add Duplicator class to modularize duplication function #10 --- .../Scripts/MultipleMonitorCreator.cs | 6 +- .../Plugins/x86_64/uDesktopDuplication.dll | Bin 91648 -> 92672 bytes Assets/uDesktopDuplication/Scripts/Lib.cs | 21 +- Assets/uDesktopDuplication/Scripts/Manager.cs | 10 +- Assets/uDesktopDuplication/Scripts/Monitor.cs | 23 +- .../uDesktopDuplication/Duplicator.cpp | 296 ++++++++++++ .../uDesktopDuplication/Duplicator.h | 67 +++ .../uDesktopDuplication/Monitor.cpp | 423 ++---------------- .../uDesktopDuplication/Monitor.h | 52 +-- .../uDesktopDuplication/main.cpp | 11 +- .../uDesktopDuplication.vcxproj | 2 + .../uDesktopDuplication.vcxproj.filters | 2 + 12 files changed, 461 insertions(+), 452 deletions(-) create mode 100644 Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp create mode 100644 Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h diff --git a/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs b/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs index 4a87916..e56d363 100644 --- a/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs +++ b/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs @@ -2,7 +2,7 @@ using UnityEngine.Assertions; using System.Collections.Generic; using MeshForwardDirection = uDesktopDuplication.Texture.MeshForwardDirection; -using MonitorState = uDesktopDuplication.MonitorState; +using DuplicatorState = uDesktopDuplication.DuplicatorState; public class MultipleMonitorCreator : MonoBehaviour { @@ -92,11 +92,11 @@ public class MultipleMonitorCreator : MonoBehaviour if (removeWaitTimer_ > removeWaitDuration) { hasMonitorUnsupportStateChecked_ = true; foreach (var info in monitors) { - if (info.uddTexture.monitor.state == MonitorState.Unsupported) { + if (info.uddTexture.monitor.state == DuplicatorState.Unsupported) { Destroy(info.gameObject); } } - monitors.RemoveAll(info => info.uddTexture.monitor.state == MonitorState.Unsupported); + monitors.RemoveAll(info => info.uddTexture.monitor.state == DuplicatorState.Unsupported); } } } diff --git a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll index 488f3e6c5575897964a9519026ab9071400810b5..96f78f17c34944b90e19e7806be3ac9a78ac82a1 100644 GIT binary patch literal 92672 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 ZK}Sz2Qrx(^Yxm&pY{;>VA^*Qs{|gRcJ&ynY literal 91648 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 Invalid.", id, name); break; - case MonitorState.AccessDenied: + case DuplicatorState.AccessDenied: Debug.LogWarningFormat("[uDD] {0}:{1} => Access Denied.", id, name); break; - case MonitorState.Unsupported: + case DuplicatorState.Unsupported: Debug.LogWarningFormat("[uDD] {0}:{1} => Unsupported.", id, name); break; - case MonitorState.SessionDisconnected: + case DuplicatorState.SessionDisconnected: Debug.LogWarningFormat("[uDD] {0}:{1} => Disconnected.", id, name); break; - case MonitorState.NotSet: + case DuplicatorState.NotSet: Debug.LogErrorFormat("[uDD] {0}:{1} => Something wrong.", id, name); break; default: @@ -53,14 +55,19 @@ public class Monitor get { return id < Manager.monitorCount; } } - public MonitorState state + public DuplicatorState state { get { return Lib.GetState(id); } } public bool available { - get { return state == MonitorState.Available; } + get + { + return + state == DuplicatorState.Ready || + state == DuplicatorState.Running; + } } public string name diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp new file mode 100644 index 0000000..852efc6 --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp @@ -0,0 +1,296 @@ +#pragma once + +#include "Duplicator.h" +#include "Monitor.h" +#include "Device.h" +#include "Common.h" +#include "Debug.h" + +#include "IUnityInterface.h" +#include "IUnityGraphicsD3D11.h" + +using namespace Microsoft::WRL; + + + +Duplicator::Duplicator(Monitor* monitor) + : monitor_(monitor) +{ + InitializeDevice(); + InitializeDuplication(); + CheckUnityAdapter(); +} + + +Duplicator::~Duplicator() +{ + Stop(); +} + + +void Duplicator::InitializeDevice() +{ + device_ = std::make_shared(); + + if (FAILED(device_->Create(monitor_->GetAdapter()))) + { + Debug::Error("Monitor::Initialize() => IsolatedD3D11Device::Create() failed."); + state_ = State::Unknown; + } +} + + +void Duplicator::InitializeDuplication() +{ + ComPtr output1; + if (FAILED(monitor_->GetOutput().As(&output1))) { + return; + } + + auto hr = output1->DuplicateOutput(device_->GetDevice().Get(), &dupl_); + switch (hr) + { + case S_OK: + { + state_ = State::Ready; + const auto rot = static_cast(monitor_->GetRotation()); + Debug::Log("Duplicator::Initialize() => OK."); + Debug::Log(" ID : ", monitor_->GetId()); + Debug::Log(" Size : (", monitor_->GetWidth(), ", ", monitor_->GetHeight(), ")"); + Debug::Log(" DPI : (", monitor_->GetDpiX(), ", ", monitor_->GetDpiY(), ")"); + Debug::Log(" Rot : ", + rot == DXGI_MODE_ROTATION_IDENTITY ? "Landscape" : + rot == DXGI_MODE_ROTATION_ROTATE90 ? "Portrait" : + rot == DXGI_MODE_ROTATION_ROTATE180 ? "Landscape (flipped)" : + rot == DXGI_MODE_ROTATION_ROTATE270 ? "Portrait (flipped)" : + "Unspecified"); + break; + } + case E_INVALIDARG: + { + state_ = State::InvalidArg; + Debug::Error("Duplicator::Initialize() => Invalid arguments."); + break; + } + case E_ACCESSDENIED: + { + // For example, when the user presses Ctrl + Alt + Delete and the screen + // switches to admin screen, this error occurs. + state_ = State::AccessDenied; + Debug::Error("Duplicator::Initialize() => Access denied."); + break; + } + case DXGI_ERROR_UNSUPPORTED: + { + // If the display adapter on the computer is running under the Microsoft Hybrid system, + // this error occurs. + state_ = State::Unsupported; + Debug::Error("Duplicator::Initialize() => Unsupported display."); + break; + } + case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: + { + // When other application use Desktop Duplication API, this error occurs. + state_ = State::CurrentlyNotAvailable; + Debug::Error("Duplicator::Initialize() => Currently not available."); + break; + } + case DXGI_ERROR_SESSION_DISCONNECTED: + { + state_ = State::SessionDisconnected; + Debug::Error("Duplicator::Initialize() => Session disconnected."); + break; + } + default: + { + state_ = State::Unknown; + Debug::Error("Duplicator::Render() => Unknown Error."); + break; + } + } +} + + +void Duplicator::CheckUnityAdapter() +{ + DXGI_ADAPTER_DESC desc; + monitor_->GetAdapter()->GetDesc(&desc); + + const auto unityAdapterLuid = GetUnityAdapterLuid(); + const auto isUnityAdapter = + (desc.AdapterLuid.LowPart == unityAdapterLuid.LowPart) && + (desc.AdapterLuid.HighPart == unityAdapterLuid.HighPart); + + if (!isUnityAdapter) + { + Debug::Error("Duplicator::CheckUnityAdapter() => The adapter is not same as Unity, and now this case is not supported."); + state_ = State::Unsupported; + } +} + + +void Duplicator::Start() +{ + if (state_ != State::Ready) return; + + Stop(); + + thread_ = std::thread([this] + { + state_ = State::Running; + + shouldRun_ = true; + while (shouldRun_) + { + if (!Duplicate()) break; + } + + if (state_ == State::Running) + { + state_ = State::Ready; + } + }); +} + + +void Duplicator::Stop() +{ + shouldRun_ = false; + + if (thread_.joinable()) + { + thread_.join(); + } +} + + +bool Duplicator::IsRunning() const +{ + return state_ == State::Running; +} + + +bool Duplicator::IsError() const +{ + return + state_ != State::Ready && + state_ != State::Running; +} + + +Duplicator::State Duplicator::GetState() const +{ + return state_; +} + + +ComPtr Duplicator::GetDuplication() +{ + return dupl_; +} + + +const Duplicator::Frame& Duplicator::GetFrame() const +{ + std::lock_guard lock(mutex_); + return lastFrame_; +} + + +bool Duplicator::Duplicate() +{ + if (!dupl_ || !device_) return false; + + ComPtr resource; + DXGI_OUTDUPL_FRAME_INFO frameInfo; + const auto hr = dupl_->AcquireNextFrame(INFINITE, &frameInfo, &resource); + + if (FAILED(hr)) + { + switch (hr) + { + case DXGI_ERROR_ACCESS_LOST: + { + // If any monitor setting has changed (e.g. monitor size has changed), + // it is necessary to re-initialize monitors. + Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST."); + state_ = State::AccessLost; + break; + } + case DXGI_ERROR_WAIT_TIMEOUT: + { + // This often occurs when timeout value is small and it is not problem. + // Debug::Log("Monitor::Render() => DXGI_ERROR_WAIT_TIMEOUT."); + break; + } + case DXGI_ERROR_INVALID_CALL: + { + Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL."); + break; + } + case E_INVALIDARG: + { + Debug::Error("Monitor::Render() => E_INVALIDARG."); + break; + } + default: + { + state_ = State::Unknown; + Debug::Error("Monitor::Render() => Unknown Error."); + break; + } + } + return false; + } + + ScopedReleaser releaser([this] + { + const auto hr = dupl_->ReleaseFrame(); + if (FAILED(hr)) + { + switch (hr) + { + case DXGI_ERROR_ACCESS_LOST: + { + Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST."); + state_ = State::AccessLost; + break; + } + case DXGI_ERROR_INVALID_CALL: + { + Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL."); + break; + } + default: + { + state_ = State::Unknown; + Debug::Error("Monitor::Render() => Unknown Error."); + break; + } + } + } + }); + + ComPtr texture; + if (FAILED(resource.As(&texture))) + { + return false; + } + + auto copyTarget = device_->GetCompatibleSharedTexture(texture); + if (!copyTarget) + { + return false; + } + + ComPtr context; + device_->GetDevice()->GetImmediateContext(&context); + context->CopyResource(copyTarget.Get(), texture.Get()); + + { + std::lock_guard lock(mutex_); + lastFrame_ = Frame { copyTarget, frameInfo }; + } + + return true; +} \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h new file mode 100644 index 0000000..86673a2 --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +class Monitor; + + +enum class DuplicatorState +{ + NotSet = -1, + Ready = 0, + Running = 1, + InvalidArg = 2, + AccessDenied = 3, + Unsupported = 4, + CurrentlyNotAvailable = 5, + SessionDisconnected = 6, + AccessLost = 7, + TextureSizeInconsistent = 8, + Unknown = 999, +}; + + +class Duplicator +{ +public: + using State = DuplicatorState; + + struct Frame + { + Microsoft::WRL::ComPtr texture; + DXGI_OUTDUPL_FRAME_INFO info; + }; + + explicit Duplicator(Monitor* monitor); + ~Duplicator(); + void Start(); + void Stop(); + bool IsRunning() const; + bool IsError() const; + State GetState() const; + Microsoft::WRL::ComPtr GetDuplication(); + const Frame& GetFrame() const; + +private: + void InitializeDevice(); + void InitializeDuplication(); + void CheckUnityAdapter(); + bool Duplicate(); + + Monitor* monitor_ = nullptr; + State state_ = State::Ready; + + std::shared_ptr device_; + Microsoft::WRL::ComPtr dupl_; + Frame lastFrame_; + + volatile bool shouldRun_ = false; + std::thread thread_; + mutable std::mutex mutex_; +}; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp index 99763e4..bdad7be 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp @@ -2,6 +2,7 @@ #include #include #include "Monitor.h" +#include "Duplicator.h" #include "Debug.h" #include "Cursor.h" #include "MonitorManager.h" @@ -11,45 +12,6 @@ using namespace Microsoft::WRL; -struct QueueItem -{ - ComPtr Texture; - DXGI_OUTDUPL_FRAME_INFO Info; - - QueueItem() - {} - - QueueItem(const ComPtr &texture - , const DXGI_OUTDUPL_FRAME_INFO &info - ) - : Texture(texture), Info(info) - {} -}; -class TextureQueue -{ - std::queue m_queue; - std::mutex m_mutex; - -public: - void Enqueue(const QueueItem &item) - { - std::lock_guard lk(m_mutex); - m_queue.push(item); - } - - QueueItem Dequeue() - { - std::lock_guard lk(m_mutex); - if (m_queue.empty()) { - return QueueItem(); - } - auto front = m_queue.front(); - m_queue.pop(); - return front; - } -}; - - Monitor::Monitor(int id) : id_(id) { @@ -59,17 +21,6 @@ Monitor::Monitor(int id) Monitor::~Monitor() { - m_stopLoop = true; - - if (deskDupl_) - { - deskDupl_->Release(); - deskDupl_ = nullptr; - } - - if (m_desktopDuplicationThread.joinable()) { - m_desktopDuplicationThread.join(); - } } @@ -78,14 +29,8 @@ void Monitor::Initialize( const ComPtr &output ) { - m_pIsolated = std::make_shared(); - m_textureQueue = std::make_shared(); - - if (FAILED(m_pIsolated->Create(adapter))) - { - Debug::Error("Monitor::Initialize() => IsolatedD3D11Device::Create() failed."); - return; - } + adapter_ = adapter; + output_ = output; if (FAILED(output->GetDesc(&outputDesc_))) { @@ -112,231 +57,21 @@ void Monitor::Initialize( // DPI is set as -1, so the application has to use the appropriate value. } - ComPtr output1; - if (FAILED(output.As(&output1))) { - return; - } - - // use self created device - auto hr = output1->DuplicateOutput(m_pIsolated->GetDevice().Get(), &deskDupl_); - switch (hr) - { - case S_OK: - { - state_ = State::Available; - const auto rot = static_cast(GetRotation()); - Debug::Log("Monitor::Initialize() => OK."); - Debug::Log(" ID : ", GetId()); - Debug::Log(" Size : (", GetWidth(), ", ", GetHeight(), ")"); - Debug::Log(" DPI : (", GetDpiX(), ", ", GetDpiY(), ")"); - Debug::Log(" Rot : ", - rot == DXGI_MODE_ROTATION_IDENTITY ? "Landscape" : - rot == DXGI_MODE_ROTATION_ROTATE90 ? "Portrait" : - rot == DXGI_MODE_ROTATION_ROTATE180 ? "Landscape (flipped)" : - rot == DXGI_MODE_ROTATION_ROTATE270 ? "Portrait (flipped)" : - "Unspecified"); - break; - } - case E_INVALIDARG: - { - state_ = State::InvalidArg; - Debug::Error("Monitor::Initialize() => Invalid arguments."); - break; - } - case E_ACCESSDENIED: - { - // For example, when the user presses Ctrl + Alt + Delete and the screen - // switches to admin screen, this error occurs. - state_ = State::AccessDenied; - Debug::Error("Monitor::Initialize() => Access denied."); - break; - } - case DXGI_ERROR_UNSUPPORTED: - { - // If the display adapter on the computer is running under the Microsoft Hybrid system, - // this error occurs. - state_ = State::Unsupported; - Debug::Error("Monitor::Initialize() => Unsupported display."); - break; - } - case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: - { - // When other application use Desktop Duplication API, this error occurs. - state_ = State::CurrentlyNotAvailable; - Debug::Error("Monitor::Initialize() => Currently not available."); - break; - } - case DXGI_ERROR_SESSION_DISCONNECTED: - { - state_ = State::SessionDisconnected; - Debug::Error("Monitor::Initialize() => Session disconnected."); - break; - } - default: - { - state_ = State::Unknown; - Debug::Error("Monitor::Render() => Unknown Error."); - break; - } - } - - // check adapter - DXGI_ADAPTER_DESC adapterDesc; - adapter->GetDesc(&adapterDesc); - const auto unityAdapterLuid = GetUnityAdapterLuid(); - const auto isUnityAdapter = - adapterDesc.AdapterLuid.HighPart == unityAdapterLuid.HighPart && - adapterDesc.AdapterLuid.LowPart == unityAdapterLuid.LowPart; - - // start desktop duplication thread - m_stopLoop = false; - if (isUnityAdapter) { - m_desktopDuplicationThread = std::thread(std::bind(&Monitor::DuplicateAndCopyLoop, this)); - } - else { - m_desktopDuplicationThread = std::thread(std::bind(&Monitor::DuplicateAndMapLoop, this)); - } + duplicator_ = std::make_shared(this); + if (duplicator_->GetState() == DuplicatorState::Ready) + { + duplicator_->Start(); + } } -void Monitor::Render(UINT timeout) +void Monitor::Render() { - if (!deskDupl_) return; + const auto frame = duplicator_->GetFrame(); // copy + const auto texture = frame.texture; + const auto frameInfo = frame.info; - HRESULT hr; - ComPtr resource; - DXGI_OUTDUPL_FRAME_INFO frameInfo; - - hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource); - if (FAILED(hr)) - { - switch (hr) - { - case DXGI_ERROR_ACCESS_LOST: - { - // If any monitor setting has changed (e.g. monitor size has changed), - // it is necessary to re-initialize monitors. - Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST."); - state_ = State::AccessLost; - break; - } - case DXGI_ERROR_WAIT_TIMEOUT: - { - // This often occurs when timeout value is small and it is not problem. - // Debug::Log("Monitor::Render() => DXGI_ERROR_WAIT_TIMEOUT."); - break; - } - case DXGI_ERROR_INVALID_CALL: - { - Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL."); - break; - } - case E_INVALIDARG: - { - Debug::Error("Monitor::Render() => E_INVALIDARG."); - break; - } - default: - { - state_ = State::Unknown; - Debug::Error("Monitor::Render() => Unknown Error."); - break; - } - } - return; - } - - ID3D11Texture2D* texture; - if (FAILED(resource.CopyTo(&texture))) - { - Debug::Error("Monitor::Render() => resource.As() failed."); - return; - } - - // Get texture - if (unityTexture_) - { - D3D11_TEXTURE2D_DESC srcDesc, dstDesc; - texture->GetDesc(&srcDesc); - unityTexture_->GetDesc(&dstDesc); - if (srcDesc.Width != dstDesc.Width || - srcDesc.Height != dstDesc.Height) - { - Debug::Error("Monitor::Render() => Texture sizes are defferent."); - Debug::Error(" Source : (", srcDesc.Width, ", ", srcDesc.Height, ")"); - Debug::Error(" Dest : (", dstDesc.Width, ", ", dstDesc.Height, ")"); - //Debug::Log(" => Try modifying width/height using reported value from DDA."); - //width_ = srcDesc.Width; - //height_ = srcDesc.Height; - state_ = MonitorState::TextureSizeInconsistent; - //SendMessageToUnity(Message::TextureSizeChanged); - } - else - { - ComPtr context; - GetDevice()->GetImmediateContext(&context); - context->CopyResource(unityTexture_, texture); - } - } - - UpdateMetadata(frameInfo); - - if (frameInfo.PointerPosition.Visible) - { - GetMonitorManager()->SetCursorMonitorId(id_); - } - - if (GetMonitorManager()->GetCursorMonitorId() == id_) - { - UpdateCursor(frameInfo); - } - - if (UseGetPixels()) - { - CopyTextureFromGpuToCpu(texture); - } - - hr = deskDupl_->ReleaseFrame(); - if (FAILED(hr)) - { - switch (hr) - { - case DXGI_ERROR_ACCESS_LOST: - { - Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST."); - state_ = State::AccessLost; - break; - } - case DXGI_ERROR_INVALID_CALL: - { - Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL."); - break; - } - default: - { - state_ = State::Unknown; - Debug::Error("Monitor::Render() => Unknown Error."); - break; - } - } - return; - } - - hasBeenUpdated_ = true; -} - - -void Monitor::CopyTextureFromThread() -{ - QueueItem item; - if (m_textureQueue) { - item=m_textureQueue->Dequeue(); - } - auto texture = item.Texture; - if (!texture) { - return; - } - auto &frameInfo = item.Info; + if (!texture) return; // Get texture if (unityTexture_) @@ -344,7 +79,7 @@ void Monitor::CopyTextureFromThread() D3D11_TEXTURE2D_DESC srcDesc, dstDesc; texture->GetDesc(&srcDesc); unityTexture_->GetDesc(&dstDesc); - if (srcDesc.Width != dstDesc.Width || + if (srcDesc.Width != dstDesc.Width || srcDesc.Height != dstDesc.Height) { Debug::Error("Monitor::Render() => Texture sizes are defferent."); @@ -353,8 +88,9 @@ void Monitor::CopyTextureFromThread() //Debug::Log(" => Try modifying width/height using reported value from DDA."); //width_ = srcDesc.Width; //height_ = srcDesc.Height; - state_ = MonitorState::TextureSizeInconsistent; + //state_ = MonitorState::TextureSizeInconsistent; //SendMessageToUnity(Message::TextureSizeChanged); + return; } else { @@ -385,109 +121,6 @@ void Monitor::CopyTextureFromThread() } -void Monitor::DuplicateAndCopyLoop() -{ - if (!deskDupl_) return; - - while (!m_stopLoop) - { - ComPtr resource; - DXGI_OUTDUPL_FRAME_INFO frameInfo; - - const auto hr = deskDupl_->AcquireNextFrame(INFINITE, &frameInfo, &resource); - if (FAILED(hr)) - { - switch (hr) - { - case DXGI_ERROR_ACCESS_LOST: - { - // If any monitor setting has changed (e.g. monitor size has changed), - // it is necessary to re-initialize monitors. - //Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST."); - state_ = State::AccessLost; - break; - } - case DXGI_ERROR_WAIT_TIMEOUT: - { - // This often occurs when timeout value is small and it is not problem. - // Debug::Log("Monitor::Render() => DXGI_ERROR_WAIT_TIMEOUT."); - break; - } - case DXGI_ERROR_INVALID_CALL: - { - //Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL."); - break; - } - case E_INVALIDARG: - { - //Debug::Error("Monitor::Render() => E_INVALIDARG."); - break; - } - default: - { - state_ = State::Unknown; - //Debug::Error("Monitor::Render() => Unknown Error."); - break; - } - } - continue; - } - - ScopedReleaser releaser([this] - { - const auto hr = deskDupl_->ReleaseFrame(); - if (FAILED(hr)) - { - switch (hr) - { - case DXGI_ERROR_ACCESS_LOST: - { - Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST."); - state_ = State::AccessLost; - break; - } - case DXGI_ERROR_INVALID_CALL: - { - Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL."); - break; - } - default: - { - state_ = State::Unknown; - Debug::Error("Monitor::Render() => Unknown Error."); - break; - } - } - } - }); - - ComPtr texture; - if (FAILED(resource.As(&texture))) { - return; - } - - // copy target - auto copyTarget = m_pIsolated->GetCompatibleSharedTexture(texture); - if (!copyTarget) { - return; - } - - // copy - ComPtr context; - m_pIsolated->GetDevice()->GetImmediateContext(&context); - context->CopyResource(copyTarget.Get(), texture.Get()); - - m_textureQueue->Enqueue(QueueItem(copyTarget, frameInfo)); - } -} - - -void Monitor::DuplicateAndMapLoop() -{ - // not implemented; -} - - void Monitor::UpdateCursor(const DXGI_OUTDUPL_FRAME_INFO& frameInfo) { auto cursor_ = GetMonitorManager()->GetCursor(); @@ -508,7 +141,7 @@ void Monitor::UpdateMoveRects(const DXGI_OUTDUPL_FRAME_INFO& frameInfo) { moveRectSize_ = metaData_.Size(); - const auto hr = deskDupl_->GetFrameMoveRects( + const auto hr = GetDeskDupl()->GetFrameMoveRects( moveRectSize_, metaData_.As(), &moveRectSize_); @@ -552,7 +185,7 @@ void Monitor::UpdateDirtyRects(const DXGI_OUTDUPL_FRAME_INFO& frameInfo) { dirtyRectSize_ = metaData_.Size() - moveRectSize_; - const auto hr = deskDupl_->GetFrameDirtyRects( + const auto hr = GetDeskDupl()->GetFrameDirtyRects( dirtyRectSize_, metaData_.As(moveRectSize_ /* offset */), &dirtyRectSize_); @@ -598,9 +231,21 @@ int Monitor::GetId() const } -MonitorState Monitor::GetState() const +ComPtr Monitor::GetAdapter() { - return state_; + return adapter_; +} + + +ComPtr Monitor::GetOutput() +{ + return output_; +} + + +DuplicatorState Monitor::GetDuplicatorState() const +{ + return duplicator_->GetState(); } @@ -616,9 +261,9 @@ ID3D11Texture2D* Monitor::GetUnityTexture() const } -IDXGIOutputDuplication* Monitor::GetDeskDupl() +ComPtr Monitor::GetDeskDupl() { - return deskDupl_; + return duplicator_->GetDuplication(); } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h index f46ee56..5346f0c 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h @@ -8,38 +8,27 @@ #include #include "Common.h" -enum class MonitorState -{ - NotSet = -1, - Available = 0, - InvalidArg = 1, - AccessDenied = 2, - Unsupported = 3, - CurrentlyNotAvailable = 4, - SessionDisconnected = 5, - AccessLost = 6, - TextureSizeInconsistent = 7, - Unknown = 999, -}; + +enum class DuplicatorState; + class Monitor { class ThreadedDesktopDuplicator *m_threaded = nullptr; public: - using State = MonitorState; - explicit Monitor(int id); ~Monitor(); void Initialize( const Microsoft::WRL::ComPtr &adapter, const Microsoft::WRL::ComPtr &output); - void CopyTextureFromThread(); - void Render(UINT timeout = 0); + void Render(); public: int GetId() const; - State GetState() const; + Microsoft::WRL::ComPtr GetAdapter(); + Microsoft::WRL::ComPtr GetOutput(); + DuplicatorState GetDuplicatorState() const; void SetUnityTexture(ID3D11Texture2D* texture); ID3D11Texture2D* GetUnityTexture() const; void GetName(char* buf, int len) const; @@ -54,7 +43,7 @@ public: int GetRotation() const; int GetDpiX() const; int GetDpiY() const; - IDXGIOutputDuplication* GetDeskDupl(); + Microsoft::WRL::ComPtr GetDeskDupl(); int GetMoveRectCount() const; DXGI_OUTDUPL_MOVE_RECT* GetMoveRects() const; int GetDirtyRectCount() const; @@ -63,14 +52,6 @@ public: bool UseGetPixels() const; bool GetPixels(BYTE* output, int x, int y, int width, int height); -private: - void DuplicateAndCopyLoop(); - void DuplicateAndMapLoop(); - std::shared_ptr m_pIsolated; - std::thread m_desktopDuplicationThread; - volatile bool m_stopLoop = false; - std::shared_ptr m_textureQueue; - private: void UpdateCursor(const DXGI_OUTDUPL_FRAME_INFO& frameInfo); void UpdateMetadata(const DXGI_OUTDUPL_FRAME_INFO& frameInfo); @@ -79,18 +60,25 @@ private: void CopyTextureFromGpuToCpu(ID3D11Texture2D* texture); int id_ = -1; + UINT dpiX_ = -1, dpiY_ = -1; int width_ = -1, height_ = -1; + bool hasBeenUpdated_ = false; bool useGetPixels_ = false; - State state_ = State::NotSet; - IDXGIOutputDuplication* deskDupl_ = nullptr; - ID3D11Texture2D* unityTexture_ = nullptr; + + Microsoft::WRL::ComPtr output_; + Microsoft::WRL::ComPtr adapter_; DXGI_OUTPUT_DESC outputDesc_; MONITORINFOEX monitorInfo_; - Buffer metaData_; + + std::shared_ptr duplicator_; + + ID3D11Texture2D* unityTexture_ = nullptr; Microsoft::WRL::ComPtr textureForGetPixels_; Buffer bufferForGetPixels_; + + Buffer metaData_; UINT moveRectSize_ = 0; - UINT dirtyRectSize_ = 0;; + UINT dirtyRectSize_ = 0; }; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp index 3a0e8ee..c6fdf44 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp @@ -12,6 +12,7 @@ #include "Common.h" #include "Debug.h" #include "Monitor.h" +#include "Duplicator.h" #include "Cursor.h" #include "MonitorManager.h" @@ -106,7 +107,7 @@ extern "C" if (!g_manager) return; if (auto monitor = g_manager->GetMonitor(id)) { - monitor->CopyTextureFromThread(); + monitor->Render(); } } @@ -196,14 +197,14 @@ extern "C" } } - UNITY_INTERFACE_EXPORT MonitorState UNITY_INTERFACE_API GetState(int id) + UNITY_INTERFACE_EXPORT DuplicatorState UNITY_INTERFACE_API GetState(int id) { - if (!g_manager) return MonitorState::NotSet; + if (!g_manager) return DuplicatorState::NotSet; if (auto monitor = g_manager->GetMonitor(id)) { - return monitor->GetState(); + return monitor->GetDuplicatorState(); } - return MonitorState::NotSet; + return DuplicatorState::NotSet; } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len) diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj index df33c95..75c6e21 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj @@ -142,6 +142,7 @@ copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).pdb" "$(Soluti + @@ -151,6 +152,7 @@ copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).pdb" "$(Soluti + diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters index eb8cef5..e0646f0 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters @@ -21,6 +21,7 @@ + @@ -30,5 +31,6 @@ + \ No newline at end of file