do reinitialization from unity.
This commit is contained in:
Binary file not shown.
@@ -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")]
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user