From 620762dba77047238291e5a75a1a8d0c476babe3 Mon Sep 17 00:00:00 2001 From: hecomi Date: Wed, 9 Nov 2016 19:40:05 +0900 Subject: [PATCH] add logging and use smart pointers for buffers. --- .../Plugins/x86_64/uDesktopDuplication.dll | Bin 35328 -> 38912 bytes Assets/uDesktopDuplication/Scripts/Cursor.cs | 2 + Assets/uDesktopDuplication/Scripts/Lib.cs | 9 +++ Assets/uDesktopDuplication/Scripts/Manager.cs | 16 +++-- .../uDesktopDuplication/Common.cpp | 39 +++++++++++ .../uDesktopDuplication/Common.h | 16 ++++- .../uDesktopDuplication/Cursor.cpp | 37 ++++------ .../uDesktopDuplication/Cursor.h | 6 +- .../uDesktopDuplication/Debug.cpp | 31 +++++++++ .../uDesktopDuplication/Debug.h | 22 ++++++ .../uDesktopDuplication/Monitor.cpp | 44 ++++++------ .../uDesktopDuplication/Monitor.h | 10 +-- .../uDesktopDuplication/MonitorManager.h | 2 + .../uDesktopDuplication/main.cpp | 64 +++++++++--------- .../uDesktopDuplication.vcxproj | 3 + .../uDesktopDuplication.vcxproj.filters | 3 + 16 files changed, 214 insertions(+), 90 deletions(-) create mode 100644 Plugins/uDesktopDuplication/uDesktopDuplication/Common.cpp create mode 100644 Plugins/uDesktopDuplication/uDesktopDuplication/Debug.cpp create mode 100644 Plugins/uDesktopDuplication/uDesktopDuplication/Debug.h diff --git a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll index c111ccd46cb609ff0998e1b7b4e1a03ebc8226ed..1d323d31d36653b9b6a1b45ea2a82ce08c29ae47 100644 GIT binary patch literal 38912 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

tH73o%Z;+Vhb&I-c}S=F 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 literal 35328 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 Q)9}cd4gD+UyC{MG4 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