Compare commits

..

7 Commits

Author SHA1 Message Date
hecomi
63d8f6936d use ComPtr for resources instead of standard smart pointers. 2016-11-12 02:44:20 +09:00
hecomi
e4e4917bcb fix manager non-initialization bug. 2016-11-12 02:05:09 +09:00
hecomi
0e205ecef7 fix zoom bug. 2016-11-12 02:00:04 +09:00
hecomi
cda8024b17 fix break in error image. 2016-11-12 00:40:11 +09:00
hecomi
05085f7d24 fix bug caused when releasing duplication output. 2016-11-10 23:33:19 +09:00
hecomi
52eafbe919 change unsupported texture. 2016-11-10 23:21:04 +09:00
hecomi
be1e0c25bb expand aabb to avoid culling. 2016-11-10 23:06:24 +09:00
16 changed files with 86 additions and 82 deletions

View File

@@ -14,7 +14,7 @@ public class MultipleMonitorCreator : MonoBehaviour
public GameObject gameObject { get; set; }
public Quaternion originalRotation { get; set; }
public uDesktopDuplication.Texture uddTexture { get; set; }
public Vector3 meshBounds;
public Mesh mesh { get; set; }
}
private List<MonitorInfo> monitors_ = new List<MonitorInfo>();
@@ -22,6 +22,7 @@ public class MultipleMonitorCreator : MonoBehaviour
void Start()
{
uDesktopDuplication.Manager.CreateInstance();
Create();
}
@@ -68,16 +69,19 @@ public class MultipleMonitorCreator : MonoBehaviour
{
ResetRemoveTimer();
// Sort monitors in coordinate order
var monitors = uDesktopDuplication.Manager.monitors;
monitors.Sort((a, b) => a.left - b.left);
// Create monitors
for (int i = 0; i < uDesktopDuplication.Manager.monitorCount; ++i) {
// Create monitor obeject
var go = Instantiate(monitorPrefab);
go.name = "Monitor " + i;
// Expand AABB
var mesh = go.GetComponent<MeshFilter>().mesh; // clone
var aabbScale = mesh.bounds.size;
aabbScale.y = Mathf.Max(aabbScale.y, aabbScale.x);
aabbScale.z = Mathf.Max(aabbScale.z, aabbScale.x);
mesh.bounds = new Bounds(mesh.bounds.center, aabbScale);
// Assign monitor
var texture = go.GetComponent<uDesktopDuplication.Texture>();
texture.monitorId = i;
@@ -89,17 +93,17 @@ public class MultipleMonitorCreator : MonoBehaviour
// Set parent as this object
go.transform.SetParent(transform);
// Calc actual size considering mesh size
var bounds = go.GetComponent<MeshFilter>().sharedMesh.bounds.extents * 2f;
// Save
var info = new MonitorInfo();
info.gameObject = go;
info.originalRotation = go.transform.rotation;
info.uddTexture = texture;
info.meshBounds = bounds;
info.mesh = mesh;
monitors_.Add(info);
}
// Sort monitors in coordinate order
monitors_.Sort((a, b) => a.uddTexture.monitor.left - b.uddTexture.monitor.left);
}
void Clear()

View File

@@ -15,13 +15,13 @@ public class MultipleMonitorLayouter : MonoBehaviour
protected virtual void Update()
{
if (updateEveryFrame) {
Layout();
if (updateEveryFrame) {
Layout();
}
}
void LateUpdate()
{
{
margin = Mathf.Max(margin, 0f);
}
@@ -32,7 +32,7 @@ public class MultipleMonitorLayouter : MonoBehaviour
var totalWidth = 0f;
foreach (var info in monitors) {
var width = info.uddTexture.monitor.widthMeter * info.meshBounds.x;
var width = info.uddTexture.monitor.widthMeter * (info.mesh.bounds.extents.x * 2f);
totalWidth += width;
}
totalWidth += margin * (n - 1);
@@ -41,10 +41,10 @@ public class MultipleMonitorLayouter : MonoBehaviour
foreach (var info in creator_.monitors) {
var monitor = info.uddTexture.monitor;
x += (monitor.widthMeter * info.meshBounds.x) / 2;
x += (monitor.widthMeter * info.mesh.bounds.extents.x);
info.gameObject.transform.localPosition = new Vector3(x, 0f, 0f);
info.gameObject.transform.localRotation = info.originalRotation;
x += (monitor.widthMeter * info.meshBounds.x) / 2 + margin;
x += (monitor.widthMeter * info.mesh.bounds.extents.x) + margin;
}
}

View File

@@ -18,7 +18,7 @@ public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
var totalWidth = 0f;
foreach (var info in monitors) {
var width = info.uddTexture.monitor.widthMeter * info.meshBounds.x;
var width = info.uddTexture.monitor.widthMeter * (info.mesh.bounds.extents.x * 2f);
totalWidth += width;
}
totalWidth += margin * (n - 1);
@@ -29,7 +29,7 @@ public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
float angle = -totalAngle / 2;
foreach (var info in monitors) {
var uddTex = info.uddTexture;
var width = uddTex.monitor.widthMeter * info.meshBounds.x;
var width = uddTex.monitor.widthMeter * (info.mesh.bounds.extents.x * 2f);
angle += (width / radius) * 0.5f;
uddTex.transform.localPosition = radius * new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle) - 1f);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -85,6 +85,8 @@ public static class Lib
[DllImport("uDesktopDuplication")]
public static extern IntPtr GetRenderEventFunc();
[DllImport("uDesktopDuplication")]
public static extern int GetId(int id);
[DllImport("uDesktopDuplication")]
public static extern MonitorState GetState(int id);
[DllImport("uDesktopDuplication")]
public static extern void GetName(int id, StringBuilder buf, int len);

View File

@@ -11,21 +11,7 @@ public class Manager : MonoBehaviour
private static Manager instance_;
public static Manager instance
{
get
{
if (instance_) {
return instance_;
}
var manager = FindObjectOfType<Manager>();
if (manager) {
manager.Awake();
return manager;
}
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
get { return CreateInstance(); }
}
private List<Monitor> monitors_ = new List<Monitor>();
@@ -63,6 +49,22 @@ public class Manager : MonoBehaviour
public delegate void ReinitializeHandler();
public static event ReinitializeHandler onReinitialized;
public static Manager CreateInstance()
{
if (instance_) {
return instance_;
}
var manager = FindObjectOfType<Manager>();
if (manager) {
manager.Awake();
return manager;
}
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
void Awake()
{
Lib.SetDebugMode(debugMode);

View File

@@ -13,18 +13,6 @@ struct ID3D11Device;
ID3D11Device* GetDevice();
// Utility
template <class T>
auto MakeUniqueWithReleaser(T* ptr)
{
const auto deleter = [](T* ptr)
{
if (ptr != nullptr) ptr->Release();
};
return std::unique_ptr<T, decltype(deleter)>(ptr, deleter);
}
// Manager getter
class MonitorManager;
const std::unique_ptr<MonitorManager>& GetMonitorManager();

View File

@@ -1,10 +1,13 @@
#include <d3d11.h>
#include <wrl/client.h>
#include "Common.h"
#include "Debug.h"
#include "MonitorManager.h"
#include "Monitor.h"
#include "Cursor.h"
using namespace Microsoft::WRL;
Cursor::Cursor(Monitor* monitor)
: monitor_(monitor)
@@ -24,16 +27,16 @@ void Cursor::UpdateBuffer(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
return;
}
x_ = frameInfo.PointerPosition.Position.x;
y_ = frameInfo.PointerPosition.Position.y;
isVisible_ = frameInfo.PointerPosition.Visible != 0;
timestamp_ = frameInfo.LastMouseUpdateTime;
if (isVisible_)
{
GetMonitorManager()->SetCursorMonitorId(monitor_->GetId());
}
x_ = frameInfo.PointerPosition.Position.x;
y_ = frameInfo.PointerPosition.Position.y;
timestamp_ = frameInfo.LastMouseUpdateTime;
if (!IsCursorOnParentMonitor())
{
return;
@@ -149,9 +152,8 @@ void Cursor::UpdateTexture()
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
ID3D11Texture2D* texture = nullptr;
ComPtr<ID3D11Texture2D> texture;
hr = GetDevice()->CreateTexture2D(&desc, nullptr, &texture);
const auto textureReleaser = MakeUniqueWithReleaser(texture);
if (FAILED(hr))
{
Debug::Error("Cursor::UpdateTexture() => GetDevice()->CreateTexture2D() failed.");
@@ -172,14 +174,14 @@ void Cursor::UpdateTexture()
return;
}
ID3D11DeviceContext* context;
GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture, 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
context->Release();
{
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
}
IDXGISurface* surface = nullptr;
hr = texture->QueryInterface(__uuidof(IDXGISurface), (void**)&surface);
const auto surfaceReleaser = MakeUniqueWithReleaser(surface);
ComPtr<IDXGISurface> surface;
hr = texture.As<IDXGISurface>(&surface);
if (FAILED(hr))
{
Debug::Error("Cursor::UpdateTexture() => texture->QueryInterface() failed.");
@@ -286,10 +288,9 @@ void Cursor::GetTexture(ID3D11Texture2D* texture)
return;
}
ID3D11DeviceContext* context;
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_.get(), GetWidth() * 4, 0);
context->Release();
}

View File

@@ -6,6 +6,8 @@
#include "MonitorManager.h"
#include "Monitor.h"
using namespace Microsoft::WRL;
Monitor::Monitor(int id)
: id_(id)
@@ -28,17 +30,14 @@ void Monitor::Initialize(IDXGIOutput* output)
GetDpiForMonitor(outputDesc_.Monitor, MDT_RAW_DPI, &dpiX_, &dpiY_);
auto output1 = reinterpret_cast<IDXGIOutput1*>(output);
IDXGIOutputDuplication* deskDupl;
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl);
deskDupl_ = std::shared_ptr<IDXGIOutputDuplication>(
deskDupl,
[](IDXGIOutputDuplication* ptr) { ptr->Release(); });
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl_);
// TODO: error check
switch (hr)
{
case S_OK:
state_ = State::Available;
Debug::Log("Monitor::Initialize() => OK.");
break;
case E_INVALIDARG:
state_ = State::InvalidArg;
@@ -73,12 +72,11 @@ void Monitor::Render(UINT timeout)
{
if (!deskDupl_) return;
IDXGIResource* resource = nullptr;
ComPtr<IDXGIResource> resource;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
HRESULT hr;
hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource);
const auto resourceReleaser = MakeUniqueWithReleaser(resource);
if (FAILED(hr))
{
switch (hr)
@@ -107,13 +105,12 @@ void Monitor::Render(UINT timeout)
if (unityTexture_)
{
ID3D11Texture2D* texture;
resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
ComPtr<ID3D11Texture2D> texture;
resource.As<ID3D11Texture2D>(&texture);
ID3D11DeviceContext* context;
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture);
context->Release();
context->CopyResource(unityTexture_, texture.Get());
}
cursor_->UpdateBuffer(frameInfo);
@@ -151,7 +148,7 @@ ID3D11Texture2D* Monitor::GetUnityTexture() const
}
const std::shared_ptr<IDXGIOutputDuplication>& Monitor::GetDeskDupl()
const ComPtr<IDXGIOutputDuplication>& Monitor::GetDeskDupl()
{
return deskDupl_;
}

View File

@@ -2,6 +2,7 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h>
#include <memory>
class Cursor;
@@ -45,7 +46,7 @@ public:
int GetRotation() const;
int GetDpiX() const;
int GetDpiY() const;
const std::shared_ptr<IDXGIOutputDuplication>& GetDeskDupl();
const Microsoft::WRL::ComPtr<IDXGIOutputDuplication>& GetDeskDupl();
const std::unique_ptr<Cursor>& GetCursor();
private:
@@ -53,7 +54,7 @@ private:
UINT dpiX_ = -1, dpiY_ = -1;
State state_ = State::NotSet;
std::unique_ptr<Cursor> cursor_;
std::shared_ptr<IDXGIOutputDuplication> deskDupl_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> deskDupl_;
ID3D11Texture2D* unityTexture_ = nullptr;
DXGI_OUTPUT_DESC outputDesc_;
MONITORINFOEX monitorInfo_;

View File

@@ -1,5 +1,6 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h>
#include <vector>
#include <string>
#include <algorithm>
@@ -12,6 +13,8 @@
#include "Cursor.h"
#include "MonitorManager.h"
using namespace Microsoft::WRL;
MonitorManager::MonitorManager()
{
@@ -30,23 +33,20 @@ void MonitorManager::Initialize()
Finalize();
// Get factory
IDXGIFactory1* factory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory));
const auto factoryReleaser = MakeUniqueWithReleaser(factory);
ComPtr<IDXGIFactory1> factory;
CreateDXGIFactory1(IID_PPV_ARGS(&factory));
// Check all display adapters
int id = 0;
IDXGIAdapter1* adapter;
ComPtr<IDXGIAdapter1> adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
const auto adapterReleaser = MakeUniqueWithReleaser(adapter);
// Search the main monitor from all outputs
IDXGIOutput* output;
ComPtr<IDXGIOutput> output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j)
{
const auto outputReleaser = MakeUniqueWithReleaser(output);
auto monitor = std::make_shared<Monitor>(id++);
monitor->Initialize(output);
monitor->Initialize(output.Get());
monitors_.push_back(monitor);
}
}

View File

@@ -138,6 +138,15 @@ extern "C"
g_manager->SetTimeout(timeout);
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetId(int id)
{
if (!g_manager) return;
if (auto monitor = g_manager->GetMonitor(id))
{
monitor->GetId();
}
}
UNITY_INTERFACE_EXPORT MonitorState UNITY_INTERFACE_API GetState(int id)
{
if (!g_manager) return MonitorState::NotSet;