do reinitialization from unity.

This commit is contained in:
hecomi
2016-11-06 00:39:07 +09:00
parent 2b108bd4b1
commit 9de5064fbe
10 changed files with 109 additions and 42 deletions
+15 -1
View File
@@ -27,6 +27,18 @@ public enum MonitorRotation
Rotate270 = 4
}
public enum MonitorState
{
NotSet = -1,
Available = 0,
InvalidArg = 1,
AccessDenied = 2,
Unsupported = 3,
CurrentlyNotAvailable = 4,
SessionDisconnected = 5,
AccessLost = 6,
}
public static class Lib
{
public delegate void MessageHandler(Message message);
@@ -36,6 +48,8 @@ public static class Lib
[DllImport("uDesktopDuplication")]
public static extern void FinalizeUDD();
[DllImport("uDesktopDuplication")]
public static extern void Reinitialize();
[DllImport("uDesktopDuplication")]
public static extern void Update();
[DllImport("uDesktopDuplication")]
public static extern Message PopMessage();
@@ -50,7 +64,7 @@ public static class Lib
[DllImport("uDesktopDuplication")]
public static extern IntPtr GetRenderEventFunc();
[DllImport("uDesktopDuplication")]
public static extern bool IsAvailable(int id);
public static extern MonitorState GetState(int id);
[DllImport("uDesktopDuplication")]
public static extern void GetName(int id, StringBuilder buf, int len);
[DllImport("uDesktopDuplication")]
+33 -3
View File
@@ -37,10 +37,12 @@ public class Manager : MonoBehaviour
}
}
[SerializeField, Tooltip("Set Desktop Duplication API timeout (milliseconds).")]
int timeout = 0;
[SerializeField] int desktopDuplicationApiTimeout = 0;
[SerializeField] float retryReinitializationDuration = 0.5f;
private Coroutine renderCoroutine_ = null;
private bool shouldReinitialize = false;
private float reinitializationTimer = 0f;
void Awake()
{
@@ -51,7 +53,7 @@ public class Manager : MonoBehaviour
CreateMonitors();
Lib.SetTimeout(timeout);
Lib.SetTimeout(desktopDuplicationApiTimeout);
}
void OnApplicationQuit()
@@ -75,7 +77,35 @@ public class Manager : MonoBehaviour
void Update()
{
Lib.Update();
ReinitializeIfNeeded();
UpdateMessage();
}
void ReinitializeIfNeeded()
{
for (int i = 0; i < monitors.Count; ++i) {
var monitor = monitors[i];
if (monitor.state == MonitorState.AccessLost ||
monitor.state == MonitorState.AccessDenied) {
if (!shouldReinitialize) {
shouldReinitialize = true;
reinitializationTimer = 0f;
break;
}
}
}
if (shouldReinitialize) {
if (reinitializationTimer > retryReinitializationDuration) {
Lib.Reinitialize();
shouldReinitialize = false;
}
reinitializationTimer += Time.deltaTime;
}
}
void UpdateMessage()
{
var message = Lib.PopMessage();
while (message != Message.None) {
switch (message) {
@@ -21,9 +21,14 @@ public class Monitor
get { return id < Manager.monitorCount; }
}
public MonitorState state
{
get { return Lib.GetState(id); }
}
public bool available
{
get { return Lib.IsAvailable(id); }
get { return state == MonitorState.Available; }
}
public string name
@@ -50,7 +50,6 @@ public class Texture : MonoBehaviour
void Update()
{
Debug.Log(monitor.available);
monitor.shouldBeUpdated = true;
UpdateMaterial();
}
@@ -11,6 +11,7 @@ Monitor::Monitor(int id)
{
}
HRESULT Monitor::Initialize(IDXGIOutput* output)
{
output->GetDesc(&outputDesc_);
@@ -24,23 +25,27 @@ HRESULT Monitor::Initialize(IDXGIOutput* output)
switch (hr)
{
case S_OK:
available_ = true;
state_ = State::Available;
break;
case E_INVALIDARG:
state_ = State::InvalidArg;
break;
case E_ACCESSDENIED:
// For example, when the user presses Ctrl + Alt + Delete and the screen
// switches to admin screen, this error occurs.
// GetMonitorManager()->RequireReinitilization();
state_ = State::AccessDenied;
break;
case DXGI_ERROR_UNSUPPORTED:
// If the display adapter on the computer is running under the Microsoft Hybrid system,
// this error occurs.
state_ = State::Unsupported;
break;
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
// When other application use Desktop Duplication API, this error occurs.
state_ = State::CurrentlyNotAvailable;
break;
case DXGI_ERROR_SESSION_DISCONNECTED:
state_ = State::SessionDisconnected;
break;
}
@@ -61,7 +66,7 @@ HRESULT Monitor::Render(UINT timeout)
{
if (deskDupl_ == nullptr)
{
return 0;
return S_OK;
}
if (unityTexture_ == nullptr) return 0;
@@ -72,7 +77,13 @@ HRESULT Monitor::Render(UINT timeout)
const auto hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource);
if (FAILED(hr))
{
return hr;
// If any monitor setting has changed (e.g. monitor size has changed),
// it is necessary to re-initialize monitors.
if (hr == DXGI_ERROR_ACCESS_LOST)
{
state_ = State::AccessLost;
}
return hr;
}
ID3D11Texture2D* texture;
@@ -98,9 +109,9 @@ int Monitor::GetId() const
}
bool Monitor::IsAvailable() const
MonitorState Monitor::GetState() const
{
return available_;
return state_;
}
@@ -4,9 +4,23 @@
class Cursor;
enum class MonitorState
{
NotSet = -1,
Available = 0,
InvalidArg = 1,
AccessDenied = 2,
Unsupported = 3,
CurrentlyNotAvailable = 4,
SessionDisconnected = 5,
AccessLost = 6,
};
class Monitor
{
public:
using State = MonitorState;
explicit Monitor(int id);
~Monitor();
HRESULT Initialize(IDXGIOutput* output);
@@ -15,7 +29,7 @@ public:
public:
int GetId() const;
bool IsAvailable() const;
State GetState() const;
void SetUnityTexture(ID3D11Texture2D* texture);
ID3D11Texture2D* GetUnityTexture() const;
void GetName(char* buf, int len) const;
@@ -32,7 +46,7 @@ public:
private:
int id_ = -1;
bool available_ = false;
State state_ = State::NotSet;
std::unique_ptr<Cursor> cursor_;
IDXGIOutputDuplication* deskDupl_ = nullptr;
ID3D11Texture2D* unityTexture_ = nullptr;
@@ -59,6 +59,12 @@ void MonitorManager::Finalize()
}
void MonitorManager::RequireReinitilization()
{
isReinitializationRequired_ = true;
}
void MonitorManager::Reinitialize()
{
Initialize();
@@ -86,24 +92,6 @@ void MonitorManager::Update()
}
void MonitorManager::OnRender(int id)
{
if (auto monitor = GetMonitor(id))
{
if (!monitor->IsAvailable()) return;
const auto hr = monitor->Render(timeout_);
// If any monitor setting has changed (e.g. monitor size has changed),
// it is necessary to re-initialize monitors.
if (hr == DXGI_ERROR_ACCESS_LOST)
{
isReinitializationRequired_ = true;
}
}
}
void MonitorManager::SetTimeout(int timeout)
{
timeout_ = timeout;
@@ -13,9 +13,8 @@ class MonitorManager
public:
explicit MonitorManager();
~MonitorManager();
void RequireReinitilization() { isReinitializationRequired_ = true; }
void Reinitialize();
void RequireReinitilization();
void SetCursorMonitorId(int id) { cursorMonitorId_ = id; }
int GetCursorMonitorId() const { return cursorMonitorId_; }
std::shared_ptr<Monitor> GetMonitor(int id) const;
@@ -23,11 +22,9 @@ public:
private:
void Initialize();
void Finalize();
void Reinitialize();
// Setters from Unity
public:
void OnRender(int id);
void Update();
void SetTimeout(int timeout);
int GetTimeout() const;
@@ -79,7 +79,10 @@ extern "C"
void UNITY_INTERFACE_API OnRenderEvent(int id)
{
if (!g_manager) return;
g_manager->OnRender(id);
if (auto monitor = g_manager->GetMonitor(id))
{
monitor->Render(g_manager->GetTimeout());
}
}
UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc()
@@ -87,6 +90,12 @@ extern "C"
return OnRenderEvent;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Reinitialize()
{
if (!g_manager) return;
return g_manager->Reinitialize();
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Update()
{
if (!g_manager) return;
@@ -126,14 +135,14 @@ extern "C"
g_manager->SetTimeout(timeout);
}
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsAvailable(int id)
UNITY_INTERFACE_EXPORT MonitorState UNITY_INTERFACE_API GetState(int id)
{
if (!g_manager) return false;
if (!g_manager) return MonitorState::NotSet;
if (auto monitor = g_manager->GetMonitor(id))
{
return monitor->IsAvailable();
return monitor->GetState();
}
return false;
return MonitorState::NotSet;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len)