diff --git a/Assets/uDesktopDuplication/Examples/Scripts/Loupe.cs b/Assets/uDesktopDuplication/Examples/Scripts/Loupe.cs index 5b4eac8..741cfa9 100644 --- a/Assets/uDesktopDuplication/Examples/Scripts/Loupe.cs +++ b/Assets/uDesktopDuplication/Examples/Scripts/Loupe.cs @@ -21,7 +21,7 @@ public class Loupe : MonoBehaviour // To get other monitor textures, set dirty flag. foreach (var target in uDesktopDuplication.Manager.monitors) { - target.CreateTexture(); + target.CreateTextureIfNeeded(); target.shouldBeUpdated = true; } diff --git a/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs b/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs index 4f0db6b..43364c4 100644 --- a/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs +++ b/Assets/uDesktopDuplication/Examples/Scripts/MultipleMonitorCreator.cs @@ -112,7 +112,7 @@ public class MultipleMonitorCreator : MonoBehaviour go.name = "Monitor " + i; // Expand AABB - var mesh = go.GetComponent().mesh; // clone + var mesh = go.GetComponent().sharedMesh; var aabbScale = mesh.bounds.size; aabbScale.y = Mathf.Max(aabbScale.y, aabbScale.x); aabbScale.z = Mathf.Max(aabbScale.z, aabbScale.x); diff --git a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll index 3e587b8..1a03337 100644 Binary files a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll and b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll differ diff --git a/Assets/uDesktopDuplication/Scripts/Lib.cs b/Assets/uDesktopDuplication/Scripts/Lib.cs index a6ef6e6..fb17848 100644 --- a/Assets/uDesktopDuplication/Scripts/Lib.cs +++ b/Assets/uDesktopDuplication/Scripts/Lib.cs @@ -78,6 +78,8 @@ public static class Lib [DllImport("uDesktopDuplication")] public static extern int GetMonitorCount(); [DllImport("uDesktopDuplication")] + public static extern bool HasMonitorCountChanged(); + [DllImport("uDesktopDuplication")] public static extern int GetCursorMonitorId(); [DllImport("uDesktopDuplication")] public static extern int GetTotalWidth(); diff --git a/Assets/uDesktopDuplication/Scripts/Manager.cs b/Assets/uDesktopDuplication/Scripts/Manager.cs index d350f54..c0ff113 100644 --- a/Assets/uDesktopDuplication/Scripts/Manager.cs +++ b/Assets/uDesktopDuplication/Scripts/Manager.cs @@ -13,6 +13,19 @@ public class Manager : MonoBehaviour get { return CreateInstance(); } } + public static Manager CreateInstance() + { + if (instance_) { + return instance_; + } + + var manager = FindObjectOfType(); + if (manager) return manager; + + var go = new GameObject("uDesktopDuplicationManager"); + return go.AddComponent(); + } + private List monitors_ = new List(); static public List monitors { @@ -48,22 +61,6 @@ public class Manager : MonoBehaviour public delegate void ReinitializeHandler(); public static event ReinitializeHandler onReinitialized; - public static Manager CreateInstance() - { - if (instance_) { - return instance_; - } - - var manager = FindObjectOfType(); - if (manager) { - manager.Awake(); - return manager; - } - - var go = new GameObject("uDesktopDuplicationManager"); - return go.AddComponent(); - } - public static Monitor GetMonitor(int id) { if (id < 0 || id >= Manager.monitors.Count) { @@ -77,18 +74,21 @@ public class Manager : MonoBehaviour { Lib.SetDebugMode(debugMode); Lib.InitializeUDD(); + Lib.SetTimeout(desktopDuplicationApiTimeout); - if (instance_ != null) return; + if (instance_ != null) { + Destroy(gameObject); + return; + } instance_ = this; CreateMonitors(); - - Lib.SetTimeout(desktopDuplicationApiTimeout); } void OnApplicationQuit() { Lib.FinalizeUDD(); + DestroyMonitors(); } void OnEnable() @@ -124,20 +124,30 @@ public class Manager : MonoBehaviour void ReinitializeIfNeeded() { + bool reinitializeNeeded = false; + for (int i = 0; i < monitors.Count; ++i) { var monitor = monitors[i]; - if (monitor.state == MonitorState.NotSet || + if ( + monitor.state == MonitorState.NotSet || monitor.state == MonitorState.AccessLost || monitor.state == MonitorState.AccessDenied || - monitor.state == MonitorState.SessionDisconnected) { - if (!shouldReinitialize_) { - shouldReinitialize_ = true; - reinitializationTimer_ = 0f; - break; - } + monitor.state == MonitorState.SessionDisconnected + ) { + reinitializeNeeded = true; + break; } } + if (Lib.HasMonitorCountChanged()) { + reinitializeNeeded = true; + } + + if (!shouldReinitialize_ && reinitializeNeeded) { + shouldReinitialize_ = true; + reinitializationTimer_ = 0f; + } + if (shouldReinitialize_) { if (reinitializationTimer_ > retryReinitializationDuration) { Reinitialize(); @@ -182,12 +192,20 @@ public class Manager : MonoBehaviour void CreateMonitors() { - monitors.Clear(); + DestroyMonitors(); for (int i = 0; i < monitorCount; ++i) { monitors.Add(new Monitor(i)); } } + void DestroyMonitors() + { + for (int i = 0; i < monitors.Count; ++i) { + monitors[i].DestroyTexture(); + } + monitors.Clear(); + } + void ReinitializeMonitors() { for (int i = 0; i < monitorCount; ++i) { @@ -202,7 +220,7 @@ public class Manager : MonoBehaviour void RecreateTextures() { for (int i = 0; i < monitorCount; ++i) { - monitors[i].CreateTexture(); + monitors[i].CreateTextureIfNeeded(); } } } diff --git a/Assets/uDesktopDuplication/Scripts/Monitor.cs b/Assets/uDesktopDuplication/Scripts/Monitor.cs index 04e8a07..4811bf7 100644 --- a/Assets/uDesktopDuplication/Scripts/Monitor.cs +++ b/Assets/uDesktopDuplication/Scripts/Monitor.cs @@ -38,6 +38,11 @@ public class Monitor } } + ~Monitor() + { + DestroyTexture(); + } + public int id { get; @@ -203,21 +208,24 @@ public class Monitor set; } - private static Texture2D errorTexture; + private static Texture2D errorTexture_; private static readonly string errorTexturePath = "uDesktopDuplication/Textures/NotAvailable"; + private Texture2D errorTexture + { + get + { + return errorTexture_ ?? + (errorTexture_ = Resources.Load(errorTexturePath)); + } + } private Texture2D texture_; public Texture2D texture { get { - if (!available) { - return errorTexture ?? - (errorTexture = Resources.Load(errorTexturePath)); - } - if (texture_ == null) { - CreateTexture(); - } + if (!available) return errorTexture; + if (texture_ == null) CreateTextureIfNeeded(); return texture_; } } @@ -235,7 +243,7 @@ public class Monitor Lib.GetCursorTexture(id, ptr); } - public void CreateTexture() + public void CreateTextureIfNeeded() { if (!available) return; @@ -243,13 +251,8 @@ public class Monitor var h = isHorizontal ? height : width; bool shouldCreate = true; - if (texture_) { - if (texture_.width != w || texture_.height != h) { - Object.DestroyImmediate(texture_); - texture_ = null; - } else { - shouldCreate = false; - } + if (texture_ && texture_.width == w && texture_.height == h) { + shouldCreate = false; } if (w <= 0 || h <= 0) { @@ -257,13 +260,29 @@ public class Monitor } if (shouldCreate) { - texture_ = new Texture2D(w, h, TextureFormat.BGRA32, false); + CreateTexture(); + } + } + + void CreateTexture() + { + DestroyTexture(); + var w = isHorizontal ? width : height; + var h = isHorizontal ? height : width; + texture_ = new Texture2D(w, h, TextureFormat.BGRA32, false); + } + + public void DestroyTexture() + { + if (texture_) { + Object.Destroy(texture_); + texture_ = null; } } public void Reinitialize() { - CreateTexture(); + CreateTextureIfNeeded(); } } diff --git a/Assets/uDesktopDuplication/Scripts/Texture.cs b/Assets/uDesktopDuplication/Scripts/Texture.cs index dfb3ac8..7860bec 100644 --- a/Assets/uDesktopDuplication/Scripts/Texture.cs +++ b/Assets/uDesktopDuplication/Scripts/Texture.cs @@ -118,6 +118,11 @@ public class Texture : MonoBehaviour } } + void OnDisable() + { + Destroy(material); + } + void Update() { monitor.shouldBeUpdated = true; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp index 5c79d00..94b73d2 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp @@ -53,16 +53,21 @@ void Cursor::UpdateBuffer(const DXGI_OUTDUPL_FRAME_INFO& frameInfo) apiBufferSize_ = frameInfo.PointerShapeBufferSize; apiBuffer_ = std::make_unique(apiBufferSize_); } - if (!apiBuffer_) return; + + if (!apiBuffer_) + { + return; + } // Get mouse pointer information UINT bufferSize; DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo; const auto hr = monitor_->GetDeskDupl()->GetFramePointerShape( apiBufferSize_, - reinterpret_cast(apiBuffer_.get()), + apiBuffer_.get(), &bufferSize, &shapeInfo); + if (FAILED(hr)) { Debug::Error("Cursor::UpdateBuffer() => GetFramePointerShape() failed."); @@ -149,13 +154,12 @@ void Cursor::UpdateTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.MiscFlags = 0; - ID3D11Texture2D* texture; + ComPtr texture; if (FAILED(GetDevice()->CreateTexture2D(&desc, nullptr, &texture))) { Debug::Error("Cursor::UpdateTexture() => GetDevice()->CreateTexture2D() failed."); return; } - const auto textureReleaser = MakeUniqueWithReleaser(texture); D3D11_BOX box; box.front = 0; @@ -171,18 +175,18 @@ void Cursor::UpdateTexture() return; } - ID3D11DeviceContext* context; - GetDevice()->GetImmediateContext(&context); - context->CopySubresourceRegion(texture, 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box); - context->Release(); + { + ComPtr context; + GetDevice()->GetImmediateContext(&context); + context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box); + } - IDXGISurface* surface; - if (FAILED(texture->QueryInterface(&surface))) + ComPtr surface; + if (FAILED(texture.As(&surface))) { Debug::Error("Cursor::UpdateTexture() => texture->QueryInterface() failed."); return; } - const auto surfaceReleaser = MakeUniqueWithReleaser(surface); DXGI_MAPPED_RECT mappedSurface; if (FAILED(surface->Map(&mappedSurface, DXGI_MAP_READ))) @@ -282,10 +286,9 @@ void Cursor::GetTexture(ID3D11Texture2D* texture) return; } - ID3D11DeviceContext* context; + ComPtr context; GetDevice()->GetImmediateContext(&context); context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_.get(), GetWidth() * 4, 0); - context->Release(); } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp index 93c51aa..7b4e7d0 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp @@ -21,6 +21,7 @@ Monitor::~Monitor() if (deskDupl_) { deskDupl_->Release(); + deskDupl_ = nullptr; } } @@ -113,7 +114,7 @@ void Monitor::Render(UINT timeout) { if (!deskDupl_) return; - IDXGIResource* resource; + ComPtr resource; DXGI_OUTDUPL_FRAME_INFO frameInfo; const auto hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource); @@ -181,10 +182,9 @@ void Monitor::Render(UINT timeout) } else { - ID3D11DeviceContext* context; + ComPtr context; GetDevice()->GetImmediateContext(&context); context->CopyResource(unityTexture_, texture); - context->Release(); } } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.cpp index 729b33b..faa12a9 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.cpp @@ -33,11 +33,8 @@ void MonitorManager::Initialize() { Finalize(); - ComPtr factory; - ComPtr adapter; - ComPtr output; - // Get factory + ComPtr factory; if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) { Debug::Error("MonitorManager::Initialize() => CreateDXGIFactory1() failed."); @@ -46,9 +43,11 @@ void MonitorManager::Initialize() // Check all display adapters int id = 0; + ComPtr adapter; for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i) { // Search the main monitor from all outputs + ComPtr output; for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j) { auto monitor = std::make_shared(id++); @@ -79,31 +78,27 @@ void MonitorManager::Reinitialize() } -void MonitorManager::CheckMonitorNumbers() +bool MonitorManager::HasMonitorCountChanged() const { ComPtr factory; - ComPtr adapter; - ComPtr output; - if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) { - Debug::Error("MonitorManager::CheckMonitorNumbers() => CreateDXGIFactory1() failed."); - return; + Debug::Error("MonitorManager::CheckMonitorConnection() => CreateDXGIFactory1() failed."); + return false; } int id = 0; + ComPtr adapter; for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i) { + ComPtr output; for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j) { id++; } } - if (GetMonitorCount() != id) - { - RequireReinitilization(); - } + return monitors_.size() != id; } @@ -119,8 +114,6 @@ std::shared_ptr MonitorManager::GetMonitor(int id) const void MonitorManager::Update() { - CheckMonitorNumbers(); - if (isReinitializationRequired_) { Reinitialize(); @@ -146,6 +139,7 @@ int MonitorManager::GetMonitorCount() const return static_cast(monitors_.size()); } + int MonitorManager::GetTotalWidth() const { std::vector lefts, rights; @@ -159,6 +153,7 @@ int MonitorManager::GetTotalWidth() const return maxRight - minLeft; } + int MonitorManager::GetTotalHeight() const { std::vector tops, bottoms; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h b/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h index e4bc07c..34692ee 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h @@ -16,7 +16,7 @@ public: explicit MonitorManager(); ~MonitorManager(); void Reinitialize(); - void CheckMonitorNumbers(); + bool HasMonitorCountChanged() const; void RequireReinitilization(); void SetCursorMonitorId(int id) { cursorMonitorId_ = id; } int GetCursorMonitorId() const { return cursorMonitorId_; } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp index a6ee4fb..7d391df 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp @@ -115,6 +115,12 @@ extern "C" return g_manager->GetMonitorCount(); } + UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API HasMonitorCountChanged() + { + if (!g_manager) return false; + return g_manager->HasMonitorCountChanged(); + } + UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorMonitorId() { if (!g_manager) return -1;