fix crash bugs and memory leaks.

This commit is contained in:
hecomi
2016-11-15 21:50:35 +09:00
parent 58e14d76d8
commit e83f43d7fd
12 changed files with 129 additions and 81 deletions
@@ -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;
}
@@ -112,7 +112,7 @@ public class MultipleMonitorCreator : MonoBehaviour
go.name = "Monitor " + i;
// Expand AABB
var mesh = go.GetComponent<MeshFilter>().mesh; // clone
var mesh = go.GetComponent<MeshFilter>().sharedMesh;
var aabbScale = mesh.bounds.size;
aabbScale.y = Mathf.Max(aabbScale.y, aabbScale.x);
aabbScale.z = Mathf.Max(aabbScale.z, aabbScale.x);
@@ -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();
+46 -28
View File
@@ -13,6 +13,19 @@ public class Manager : MonoBehaviour
get { return CreateInstance(); }
}
public static Manager CreateInstance()
{
if (instance_) {
return instance_;
}
var manager = FindObjectOfType<Manager>();
if (manager) return manager;
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
private List<Monitor> monitors_ = new List<Monitor>();
static public List<Monitor> 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<Manager>();
if (manager) {
manager.Awake();
return manager;
}
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
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();
}
}
}
+37 -18
View File
@@ -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<Texture2D>(errorTexturePath));
}
}
private Texture2D texture_;
public Texture2D texture
{
get
{
if (!available) {
return errorTexture ??
(errorTexture = Resources.Load<Texture2D>(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();
}
}
@@ -118,6 +118,11 @@ public class Texture : MonoBehaviour
}
}
void OnDisable()
{
Destroy(material);
}
void Update()
{
monitor.shouldBeUpdated = true;
@@ -53,16 +53,21 @@ void Cursor::UpdateBuffer(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
apiBufferSize_ = frameInfo.PointerShapeBufferSize;
apiBuffer_ = std::make_unique<BYTE[]>(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<void*>(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<ID3D11Texture2D> 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<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
}
IDXGISurface* surface;
if (FAILED(texture->QueryInterface<IDXGISurface>(&surface)))
ComPtr<IDXGISurface> 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<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_.get(), GetWidth() * 4, 0);
context->Release();
}
@@ -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<IDXGIResource> 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<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture);
context->Release();
}
}
@@ -33,11 +33,8 @@ void MonitorManager::Initialize()
{
Finalize();
ComPtr<IDXGIFactory1> factory;
ComPtr<IDXGIAdapter1> adapter;
ComPtr<IDXGIOutput> output;
// Get factory
ComPtr<IDXGIFactory1> 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<IDXGIAdapter1> adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
// Search the main monitor from all outputs
ComPtr<IDXGIOutput> output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j)
{
auto monitor = std::make_shared<Monitor>(id++);
@@ -79,31 +78,27 @@ void MonitorManager::Reinitialize()
}
void MonitorManager::CheckMonitorNumbers()
bool MonitorManager::HasMonitorCountChanged() const
{
ComPtr<IDXGIFactory1> factory;
ComPtr<IDXGIAdapter1> adapter;
ComPtr<IDXGIOutput> 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<IDXGIAdapter1> adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
ComPtr<IDXGIOutput> 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<Monitor> MonitorManager::GetMonitor(int id) const
void MonitorManager::Update()
{
CheckMonitorNumbers();
if (isReinitializationRequired_)
{
Reinitialize();
@@ -146,6 +139,7 @@ int MonitorManager::GetMonitorCount() const
return static_cast<int>(monitors_.size());
}
int MonitorManager::GetTotalWidth() const
{
std::vector<int> lefts, rights;
@@ -159,6 +153,7 @@ int MonitorManager::GetTotalWidth() const
return maxRight - minLeft;
}
int MonitorManager::GetTotalHeight() const
{
std::vector<int> tops, bottoms;
@@ -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_; }
@@ -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;