add logging and use smart pointers for buffers.

This commit is contained in:
hecomi
2016-11-09 19:40:05 +09:00
parent 43ba445623
commit 620762dba7
16 changed files with 214 additions and 90 deletions
@@ -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);
}
@@ -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();
+10 -6
View File
@@ -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));
}
@@ -0,0 +1,39 @@
#pragma once
#include <queue>
#include <unordered_map>
#include <iostream>
#include <d3d11.h>
#include "IUnityInterface.h"
#include "IUnityGraphicsD3D11.h"
#include "Common.h"
extern IUnityInterfaces* g_unity;
extern std::unique_ptr<MonitorManager> g_manager;
extern std::queue<Message> g_messages;
IUnityInterfaces* GetUnity()
{
return g_unity;
}
ID3D11Device* GetDevice()
{
return GetUnity()->Get<IUnityGraphicsD3D11>()->GetDevice();
}
const std::unique_ptr<MonitorManager>& GetMonitorManager()
{
return g_manager;
}
void SendMessageToUnity(Message message)
{
g_messages.push(message);
}
@@ -1,15 +1,27 @@
#pragma once
#include <memory>
#include "IUnityInterface.h"
#include <string>
class MonitorManager;
// Unity interface and ID3D11Device getters
struct IUnityInterfaces;
IUnityInterfaces* GetUnity();
struct ID3D11Device;
ID3D11Device* GetDevice();
// Manager getter
class MonitorManager;
const std::unique_ptr<MonitorManager>& GetMonitorManager();
// Message is pooled and fetch from Unity.
enum class Message
{
None = -1,
Reinitialized = 0,
};
void SendMessageToUnity(Message message);
@@ -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<BYTE[]>(apiBufferSize_);
}
if (apiBuffer_ == nullptr) return;
if (!apiBuffer_) return;
// Get mouse pointer information
UINT bufferSize;
const auto hr = monitor_->GetDeskDupl()->GetFramePointerShape(
frameInfo.PointerShapeBufferSize,
reinterpret_cast<void*>(apiBuffer_),
apiBufferSize_,
reinterpret_cast<void*>(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<BYTE[]>(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<UINT*>(bgra32Buffer_);
auto output32 = reinterpret_cast<UINT*>(bgra32Buffer_.get());
if (isMono)
{
@@ -174,7 +161,7 @@ void Cursor::UpdateTexture()
}
else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR
{
const auto buffer32 = reinterpret_cast<UINT*>(apiBuffer_);
const auto buffer32 = reinterpret_cast<UINT*>(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<UINT*>(bgra32Buffer_);
const auto buffer32 = reinterpret_cast<UINT*>(apiBuffer_);
auto output32 = reinterpret_cast<UINT*>(bgra32Buffer_.get());
const auto buffer32 = reinterpret_cast<UINT*>(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();
}
@@ -1,3 +1,5 @@
#pragma once
#include <d3d11.h>
#include <dxgi1_2.h>
#include <memory>
@@ -26,9 +28,9 @@ private:
bool isVisible_ = false;
int x_ = -1;
int y_ = -1;
BYTE* apiBuffer_ = nullptr;
std::unique_ptr<BYTE[]> apiBuffer_ = nullptr;
UINT apiBufferSize_ = 0;
BYTE* bgra32Buffer_ = nullptr;
std::unique_ptr<BYTE[]> bgra32Buffer_ = nullptr;
UINT bgra32BufferSize_ = 0;
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo_;
LARGE_INTEGER timestamp_;
@@ -0,0 +1,31 @@
#pragma once
#include <cstdio>
#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);
}
@@ -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_;
};
@@ -1,6 +1,7 @@
#include <d3d11.h>
#include <ShellScalingAPI.h>
#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<IDXGIOutput1*>(output);
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl_);
IDXGIOutputDuplication* deskDupl;
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl);
deskDupl_ = std::shared_ptr<IDXGIOutputDuplication>(
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<IDXGIOutputDuplication>& Monitor::GetDeskDupl()
{
return deskDupl_;
}
@@ -1,3 +1,5 @@
#pragma once
#include <d3d11.h>
#include <dxgi1_2.h>
#include <memory>
@@ -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<IDXGIOutputDuplication>& GetDeskDupl();
const std::unique_ptr<Cursor>& GetCursor();
private:
@@ -51,7 +53,7 @@ private:
UINT dpiX_ = -1, dpiY_ = -1;
State state_ = State::NotSet;
std::unique_ptr<Cursor> cursor_;
IDXGIOutputDuplication* deskDupl_ = nullptr;
std::shared_ptr<IDXGIOutputDuplication> deskDupl_;
ID3D11Texture2D* unityTexture_ = nullptr;
DXGI_OUTPUT_DESC outputDesc_;
MONITORINFOEX monitorInfo_;
@@ -1,3 +1,5 @@
#pragma once
#include <d3d11.h>
#include <dxgi1_2.h>
#include <vector>
@@ -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<MonitorManager> g_manager;
std::queue<Message> g_messages;
}
IUnityInterfaces* GetUnity()
{
return g_unity;
}
ID3D11Device* GetDevice()
{
return GetUnity()->Get<IUnityGraphicsD3D11>()->GetDevice();
}
const std::unique_ptr<MonitorManager>& GetMonitorManager()
{
return g_manager;
}
void SendMessageToUnity(Message message)
{
g_messages.push(message);
}
IUnityInterfaces* g_unity = nullptr;
std::unique_ptr<MonitorManager> g_manager;
std::unique_ptr<Debug> g_debug;
std::queue<Message> g_messages;
extern "C"
@@ -57,12 +31,14 @@ extern "C"
if (g_unity && !g_manager)
{
g_manager = std::make_unique<MonitorManager>();
g_debug = std::make_unique<Debug>();
}
}
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;
@@ -126,6 +126,8 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Common.cpp" />
<ClCompile Include="Debug.cpp" />
<ClCompile Include="MonitorManager.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="Monitor.cpp" />
@@ -133,6 +135,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="Common.h" />
<ClInclude Include="Debug.h" />
<ClInclude Include="MonitorManager.h" />
<ClInclude Include="include\IUnityGraphics.h" />
<ClInclude Include="include\IUnityGraphicsD3D11.h" />
@@ -19,11 +19,14 @@
<ClInclude Include="Cursor.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="MonitorManager.h" />
<ClInclude Include="Debug.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Monitor.cpp" />
<ClCompile Include="Cursor.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="MonitorManager.cpp" />
<ClCompile Include="Common.cpp" />
<ClCompile Include="Debug.cpp" />
</ItemGroup>
</Project>