diff --git a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll index c111ccd..1d323d3 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/Cursor.cs b/Assets/uDesktopDuplication/Scripts/Cursor.cs index e14ec89..a918a4c 100644 --- a/Assets/uDesktopDuplication/Scripts/Cursor.cs +++ b/Assets/uDesktopDuplication/Scripts/Cursor.cs @@ -1,4 +1,5 @@ using UnityEngine; +using UnityEngine.Assertions; using System.Collections.Generic; namespace uDesktopDuplication @@ -53,6 +54,7 @@ public class Cursor : MonoBehaviour } var cursorTexture = textures_[key]; + Assert.IsNotNull(cursorTexture); monitor.GetCursorTexture(cursorTexture.GetNativeTexturePtr()); uddTexture_.material.SetTexture("_CursorTex", cursorTexture); } diff --git a/Assets/uDesktopDuplication/Scripts/Lib.cs b/Assets/uDesktopDuplication/Scripts/Lib.cs index 69eed92..b6ac70b 100644 --- a/Assets/uDesktopDuplication/Scripts/Lib.cs +++ b/Assets/uDesktopDuplication/Scripts/Lib.cs @@ -42,6 +42,7 @@ public enum MonitorState public static class Lib { public delegate void MessageHandler(Message message); + public delegate void DebugLogDelegate(string str); [DllImport("uDesktopDuplication")] public static extern void InitializeUDD(); @@ -54,6 +55,14 @@ public static class Lib [DllImport("uDesktopDuplication")] public static extern Message PopMessage(); [DllImport("uDesktopDuplication")] + public static extern void EnableDebug(); + [DllImport("uDesktopDuplication")] + public static extern void DisableDebug(); + [DllImport("uDesktopDuplication")] + public static extern void SetLogFunc(DebugLogDelegate func); + [DllImport("uDesktopDuplication")] + public static extern void SetErrorFunc(DebugLogDelegate func); + [DllImport("uDesktopDuplication")] public static extern int GetMonitorCount(); [DllImport("uDesktopDuplication")] public static extern int GetCursorMonitorId(); diff --git a/Assets/uDesktopDuplication/Scripts/Manager.cs b/Assets/uDesktopDuplication/Scripts/Manager.cs index 08ba353..135e83f 100644 --- a/Assets/uDesktopDuplication/Scripts/Manager.cs +++ b/Assets/uDesktopDuplication/Scripts/Manager.cs @@ -61,6 +61,9 @@ public class Manager : MonoBehaviour public delegate void ReinitializeHandler(); public static event ReinitializeHandler onReinitialized; + private Lib.DebugLogDelegate logFunc = msg => Debug.Log(msg); + private Lib.DebugLogDelegate errorFunc = msg => Debug.LogError(msg); + void Awake() { Lib.InitializeUDD(); @@ -81,10 +84,16 @@ public class Manager : MonoBehaviour void OnEnable() { renderCoroutine_ = StartCoroutine(OnRender()); + + Lib.SetLogFunc(logFunc); + Lib.SetErrorFunc(errorFunc); } void OnDisable() { + Lib.SetLogFunc(null); + Lib.SetErrorFunc(null); + if (renderCoroutine_ != null) { StopCoroutine(renderCoroutine_); renderCoroutine_ = null; @@ -96,12 +105,6 @@ public class Manager : MonoBehaviour Lib.Update(); ReinitializeIfNeeded(); UpdateMessage(); - - /* - foreach (var monitor in monitors_) { - Debug.LogFormat("[{0}] {1}", monitor.id, monitor.state); - } - */ } [ContextMenu("Reinitialize")] @@ -168,6 +171,7 @@ public class Manager : MonoBehaviour void CreateMonitors() { + monitors.Clear(); for (int i = 0; i < monitorCount; ++i) { monitors.Add(new Monitor(i)); } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Common.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Common.cpp new file mode 100644 index 0000000..4016dea --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Common.cpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +#include "IUnityInterface.h" +#include "IUnityGraphicsD3D11.h" +#include "Common.h" + + +extern IUnityInterfaces* g_unity; +extern std::unique_ptr g_manager; +extern std::queue g_messages; + + +IUnityInterfaces* GetUnity() +{ + return g_unity; +} + + +ID3D11Device* GetDevice() +{ + return GetUnity()->Get()->GetDevice(); +} + + +const std::unique_ptr& GetMonitorManager() +{ + return g_manager; +} + + +void SendMessageToUnity(Message message) +{ + g_messages.push(message); +} \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Common.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Common.h index 2d8408c..088026c 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Common.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Common.h @@ -1,15 +1,27 @@ +#pragma once + #include -#include "IUnityInterface.h" +#include -class MonitorManager; +// Unity interface and ID3D11Device getters +struct IUnityInterfaces; IUnityInterfaces* GetUnity(); + +struct ID3D11Device; ID3D11Device* GetDevice(); + + +// Manager getter +class MonitorManager; const std::unique_ptr& GetMonitorManager(); + +// Message is pooled and fetch from Unity. enum class Message { None = -1, Reinitialized = 0, }; + void SendMessageToUnity(Message message); \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp index 6ecbcbc..a9d03de 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.cpp @@ -13,16 +13,6 @@ Cursor::Cursor(Monitor* monitor) Cursor::~Cursor() { - if (apiBuffer_ != nullptr) - { - delete[] apiBuffer_; - apiBuffer_ = nullptr; - } - if (bgra32Buffer_ != nullptr) - { - delete[] bgra32Buffer_; - bgra32Buffer_ = nullptr; - } } @@ -51,23 +41,21 @@ void Cursor::UpdateBuffer(const DXGI_OUTDUPL_FRAME_INFO& frameInfo) // Increase the buffer size if needed if (frameInfo.PointerShapeBufferSize > apiBufferSize_) { - if (apiBuffer_) delete[] apiBuffer_; - apiBuffer_ = new BYTE[frameInfo.PointerShapeBufferSize]; apiBufferSize_ = frameInfo.PointerShapeBufferSize; + apiBuffer_ = std::make_unique(apiBufferSize_); } - if (apiBuffer_ == nullptr) return; + if (!apiBuffer_) return; // Get mouse pointer information UINT bufferSize; const auto hr = monitor_->GetDeskDupl()->GetFramePointerShape( - frameInfo.PointerShapeBufferSize, - reinterpret_cast(apiBuffer_), + apiBufferSize_, + reinterpret_cast(apiBuffer_.get()), &bufferSize, &shapeInfo_); if (FAILED(hr)) { - delete[] apiBuffer_; - apiBuffer_ = nullptr; + apiBuffer_.reset(); apiBufferSize_ = 0; } } @@ -88,11 +76,10 @@ void Cursor::UpdateTexture() const UINT bgraBufferSize = w * h * 4; if (bgraBufferSize > bgra32BufferSize_) { - if (bgra32Buffer_) delete[] bgra32Buffer_; - bgra32Buffer_ = new BYTE[bgraBufferSize]; bgra32BufferSize_ = bgraBufferSize; + bgra32Buffer_ = std::make_unique(bgra32BufferSize_); } - if (bgra32Buffer_ == nullptr) return; + if (!bgra32Buffer_) return; // If masked, copy the desktop image and merge it with masked image. if (isMono || isColorMask) @@ -153,7 +140,7 @@ void Cursor::UpdateTexture() const UINT desktopPitch = mappedSurface.Pitch / sizeof(UINT); // Access RGBA values at the same time - auto output32 = reinterpret_cast(bgra32Buffer_); + auto output32 = reinterpret_cast(bgra32Buffer_.get()); if (isMono) { @@ -174,7 +161,7 @@ void Cursor::UpdateTexture() } else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR { - const auto buffer32 = reinterpret_cast(apiBuffer_); + const auto buffer32 = reinterpret_cast(apiBuffer_.get()); for (int row = 0; row < h; ++row) { @@ -205,8 +192,8 @@ void Cursor::UpdateTexture() } else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR { - auto output32 = reinterpret_cast(bgra32Buffer_); - const auto buffer32 = reinterpret_cast(apiBuffer_); + auto output32 = reinterpret_cast(bgra32Buffer_.get()); + const auto buffer32 = reinterpret_cast(apiBuffer_.get()); for (int i = 0; i < w * h; ++i) { output32[i] = buffer32[i]; @@ -222,7 +209,7 @@ void Cursor::GetTexture(ID3D11Texture2D* texture) if (bgra32Buffer_ == nullptr || texture == nullptr) return; ID3D11DeviceContext* context; GetDevice()->GetImmediateContext(&context); - context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_, shapeInfo_.Width * 4, 0); + context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_.get(), shapeInfo_.Width * 4, 0); context->Release(); } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.h index 3839a13..54447ab 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Cursor.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -26,9 +28,9 @@ private: bool isVisible_ = false; int x_ = -1; int y_ = -1; - BYTE* apiBuffer_ = nullptr; + std::unique_ptr apiBuffer_ = nullptr; UINT apiBufferSize_ = 0; - BYTE* bgra32Buffer_ = nullptr; + std::unique_ptr bgra32Buffer_ = nullptr; UINT bgra32BufferSize_ = 0; DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo_; LARGE_INTEGER timestamp_; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Debug.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Debug.cpp new file mode 100644 index 0000000..8d77452 --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Debug.cpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "Debug.h" + + +#define INIT_STATIC_MEMBER(Member, Value) \ + decltype(Debug::Member) Debug::Member = Value; +INIT_STATIC_MEMBER(enabled_, true) +INIT_STATIC_MEMBER(logFunc_, nullptr) +INIT_STATIC_MEMBER(errFunc_, nullptr) + + +void Debug::Log(const char* msg) +{ + if (!enabled_ || logFunc_ == nullptr) return; + + char buf[256]; + sprintf_s(buf, 256, "[uDD::Log] %s", msg); + logFunc_(buf); +} + + +void Debug::Error(const char* msg) +{ + if (!enabled_ || errFunc_ == nullptr) return; + + char buf[256]; + sprintf_s(buf, 256, "[uDD::Err] %s", msg); + errFunc_(buf); +} \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Debug.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Debug.h new file mode 100644 index 0000000..1a9e681 --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Debug.h @@ -0,0 +1,22 @@ +#pragma once + +// Logging +class Debug +{ +public: + static void Enable() { enabled_ = true; } + static void Disable() { enabled_ = false; } + + using DebugLogFuncPtr = void(*)(const char*); + static void SetLogFunc(DebugLogFuncPtr func) { logFunc_ = func; } + static void SetErrorFunc(DebugLogFuncPtr func) { errFunc_ = func; } + +public: + static void Log(const char* msg); + static void Error(const char* msg); + +private: + static bool enabled_; + static DebugLogFuncPtr logFunc_; + static DebugLogFuncPtr errFunc_; +}; \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp index 8806f27..9c1e1ea 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp @@ -1,6 +1,7 @@ #include #include #include "Common.h" +#include "Debug.h" #include "Cursor.h" #include "MonitorManager.h" #include "Monitor.h" @@ -13,7 +14,7 @@ Monitor::Monitor(int id) } -HRESULT Monitor::Initialize(IDXGIOutput* output) +void Monitor::Initialize(IDXGIOutput* output) { output->GetDesc(&outputDesc_); monitorInfo_.cbSize = sizeof(MONITORINFOEX); @@ -22,7 +23,11 @@ HRESULT Monitor::Initialize(IDXGIOutput* output) GetDpiForMonitor(outputDesc_.Monitor, MDT_RAW_DPI, &dpiX_, &dpiY_); auto output1 = reinterpret_cast(output); - const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl_); + IDXGIOutputDuplication* deskDupl; + const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl); + deskDupl_ = std::shared_ptr( + deskDupl, + [](IDXGIOutputDuplication* ptr) { ptr->Release(); }); // TODO: error check switch (hr) @@ -51,31 +56,23 @@ HRESULT Monitor::Initialize(IDXGIOutput* output) state_ = State::SessionDisconnected; break; } - - return hr; } Monitor::~Monitor() { - if (deskDupl_ != nullptr) - { - deskDupl_->Release(); - } } -HRESULT Monitor::Render(UINT timeout) +void Monitor::Render(UINT timeout) { - if (deskDupl_ == nullptr) - { - return S_OK; - } + if (!deskDupl_) return; IDXGIResource* resource = nullptr; DXGI_OUTDUPL_FRAME_INFO frameInfo; + HRESULT hr; - const auto hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource); + hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource); if (FAILED(hr)) { switch (hr) @@ -83,16 +80,23 @@ HRESULT Monitor::Render(UINT timeout) 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: break; } - return hr; + return; } if (unityTexture_) @@ -111,9 +115,11 @@ HRESULT Monitor::Render(UINT timeout) cursor_->UpdateBuffer(frameInfo); cursor_->UpdateTexture(); - deskDupl_->ReleaseFrame(); - - return S_OK; + hr = deskDupl_->ReleaseFrame(); + if (FAILED(hr)) + { + Debug::Error("Monitor::Render() => ReleaseFrame() failed."); + } } @@ -141,7 +147,7 @@ ID3D11Texture2D* Monitor::GetUnityTexture() const } -IDXGIOutputDuplication* Monitor::GetDeskDupl() +const std::shared_ptr& Monitor::GetDeskDupl() { return deskDupl_; } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h index a1810b8..39a67d0 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -23,8 +25,8 @@ public: explicit Monitor(int id); ~Monitor(); - HRESULT Initialize(IDXGIOutput* output); - HRESULT Render(UINT timeout = 0); + void Initialize(IDXGIOutput* output); + void Render(UINT timeout = 0); void GetCursorTexture(ID3D11Texture2D* texture); public: @@ -43,7 +45,7 @@ public: int GetRotation() const; int GetDpiX() const; int GetDpiY() const; - IDXGIOutputDuplication* GetDeskDupl(); + const std::shared_ptr& GetDeskDupl(); const std::unique_ptr& GetCursor(); private: @@ -51,7 +53,7 @@ private: UINT dpiX_ = -1, dpiY_ = -1; State state_ = State::NotSet; std::unique_ptr cursor_; - IDXGIOutputDuplication* deskDupl_ = nullptr; + std::shared_ptr deskDupl_; ID3D11Texture2D* unityTexture_ = nullptr; DXGI_OUTPUT_DESC outputDesc_; MONITORINFOEX monitorInfo_; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h b/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h index e15be66..92fc877 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/MonitorManager.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp index 38699c7..95e812e 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp @@ -7,9 +7,9 @@ #include "IUnityInterface.h" #include "IUnityGraphics.h" -#include "IUnityGraphicsD3D11.h" #include "Common.h" +#include "Debug.h" #include "Monitor.h" #include "Cursor.h" #include "MonitorManager.h" @@ -18,36 +18,10 @@ #pragma comment(lib, "Shcore.lib") -namespace -{ - IUnityInterfaces* g_unity = nullptr; - std::unique_ptr g_manager; - std::queue g_messages; -} - - -IUnityInterfaces* GetUnity() -{ - return g_unity; -} - - -ID3D11Device* GetDevice() -{ - return GetUnity()->Get()->GetDevice(); -} - - -const std::unique_ptr& GetMonitorManager() -{ - return g_manager; -} - - -void SendMessageToUnity(Message message) -{ - g_messages.push(message); -} +IUnityInterfaces* g_unity = nullptr; +std::unique_ptr g_manager; +std::unique_ptr g_debug; +std::queue g_messages; extern "C" @@ -57,12 +31,14 @@ extern "C" if (g_unity && !g_manager) { g_manager = std::make_unique(); + g_debug = std::make_unique(); } } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API FinalizeUDD() { g_manager.reset(); + g_debug.reset(); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) @@ -103,7 +79,7 @@ extern "C" g_manager->Update(); } - UNITY_INTERFACE_EXPORT Message PopMessage() + UNITY_INTERFACE_EXPORT Message UNITY_INTERFACE_API PopMessage() { if (g_messages.empty()) return Message::None; @@ -112,6 +88,30 @@ extern "C" return message; } + UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API EnableDebug() + { + if (!g_debug) return; + g_debug->Enable(); + } + + UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API DisableDebug() + { + if (!g_debug) return; + g_debug->Disable(); + } + + UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetLogFunc(Debug::DebugLogFuncPtr func) + { + if (!g_debug) return; + g_debug->SetLogFunc(func); + } + + UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetErrorFunc(Debug::DebugLogFuncPtr func) + { + if (!g_debug) return; + g_debug->SetErrorFunc(func); + } + UNITY_INTERFACE_EXPORT size_t UNITY_INTERFACE_API GetMonitorCount() { if (!g_manager) return 0; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj index 3b524d6..dd75d00 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj @@ -126,6 +126,8 @@ + + @@ -133,6 +135,7 @@ + diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters index bcdb742..48179e2 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj.filters @@ -19,11 +19,14 @@ + + + \ No newline at end of file