implement dirty rects and move rects.
This commit is contained in:
@@ -33,50 +33,67 @@ template <class T>
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer() {}
|
||||
~Buffer() {}
|
||||
Buffer() {}
|
||||
~Buffer() {}
|
||||
|
||||
void ExpandIfNeeded(UINT size)
|
||||
{
|
||||
if (size > size_)
|
||||
{
|
||||
size_ = size;
|
||||
value_ = std::make_unique<T[]>(size);
|
||||
}
|
||||
}
|
||||
void ExpandIfNeeded(UINT size)
|
||||
{
|
||||
if (size > size_)
|
||||
{
|
||||
size_ = size;
|
||||
value_ = std::make_unique<T[]>(size);
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
value_.reset();
|
||||
size_ = 0;
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
value_.reset();
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
UINT Size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
UINT Size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
T* Get() const
|
||||
{
|
||||
return value_.get();
|
||||
}
|
||||
T* Get() const
|
||||
{
|
||||
return value_.get();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return value_ != nullptr;
|
||||
}
|
||||
T* Get(UINT offset) const
|
||||
{
|
||||
return (value_.get() + offset);
|
||||
}
|
||||
|
||||
T operator [](UINT index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
Debug::Error("Array index out of range: ", index, size_);
|
||||
return T(0);
|
||||
}
|
||||
return value_[index];
|
||||
}
|
||||
template <class U>
|
||||
U* As() const
|
||||
{
|
||||
return reinterpret_cast<U*>(Get());
|
||||
}
|
||||
|
||||
template <class U>
|
||||
U* As(UINT offset) const
|
||||
{
|
||||
return reinterpret_cast<U*>(Get(offset));
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return value_ != nullptr;
|
||||
}
|
||||
|
||||
T operator [](UINT index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
Debug::Error("Array index out of range: ", index, size_);
|
||||
return T(0);
|
||||
}
|
||||
return value_[index];
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<T[]> value_;
|
||||
UINT size_ = 0;
|
||||
std::unique_ptr<T[]> value_;
|
||||
UINT size_ = 0;
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <d3d11.h>
|
||||
#include <ShellScalingAPI.h>
|
||||
#include "Common.h"
|
||||
#include "Debug.h"
|
||||
#include "Cursor.h"
|
||||
#include "MonitorManager.h"
|
||||
@@ -50,7 +49,7 @@ void Monitor::Initialize(IDXGIOutput* output)
|
||||
if (FAILED(GetDpiForMonitor(outputDesc_.Monitor, MDT_RAW_DPI, &dpiX_, &dpiY_)))
|
||||
{
|
||||
Debug::Error("Monitor::Initialize() => GetDpiForMonitor() failed.");
|
||||
// DPI is set as -1, so the application has to use the appropriate value.
|
||||
// DPI is set as -1, so the application has to use the appropriate value.
|
||||
}
|
||||
|
||||
auto output1 = reinterpret_cast<IDXGIOutput1*>(output);
|
||||
@@ -156,7 +155,7 @@ void Monitor::Render(UINT timeout)
|
||||
return;
|
||||
}
|
||||
|
||||
// Get texture
|
||||
// Get texture
|
||||
if (unityTexture_)
|
||||
{
|
||||
ID3D11Texture2D* texture;
|
||||
@@ -189,8 +188,8 @@ void Monitor::Render(UINT timeout)
|
||||
}
|
||||
}
|
||||
|
||||
cursor_->UpdateBuffer(frameInfo);
|
||||
cursor_->UpdateTexture();
|
||||
UpdateMetadata(frameInfo);
|
||||
UpdateCursor(frameInfo);
|
||||
|
||||
if (FAILED(deskDupl_->ReleaseFrame()))
|
||||
{
|
||||
@@ -199,6 +198,109 @@ void Monitor::Render(UINT timeout)
|
||||
}
|
||||
|
||||
|
||||
void Monitor::UpdateCursor(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
|
||||
{
|
||||
cursor_->UpdateBuffer(frameInfo);
|
||||
cursor_->UpdateTexture();
|
||||
}
|
||||
|
||||
|
||||
void Monitor::UpdateMetadata(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
|
||||
{
|
||||
metaData_.ExpandIfNeeded(frameInfo.TotalMetadataBufferSize);
|
||||
UpdateMoveRects(frameInfo);
|
||||
UpdateDirtyRects(frameInfo);
|
||||
}
|
||||
|
||||
|
||||
void Monitor::UpdateMoveRects(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
|
||||
{
|
||||
moveRectSize_ = metaData_.Size();
|
||||
|
||||
const auto hr = deskDupl_->GetFrameMoveRects(
|
||||
moveRectSize_,
|
||||
metaData_.As<DXGI_OUTDUPL_MOVE_RECT>(),
|
||||
&moveRectSize_);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
switch (hr)
|
||||
{
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
{
|
||||
Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST (GetFrameMoveRects()).");
|
||||
break;
|
||||
}
|
||||
case DXGI_ERROR_MORE_DATA:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => DXGI_ERROR_MORE_DATA (GetFrameMoveRects()).");
|
||||
break;
|
||||
}
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL (GetFrameMoveRects()).");
|
||||
break;
|
||||
}
|
||||
case E_INVALIDARG:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => E_INVALIDARG (GetFrameMoveRects()).");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => Unknown Error (GetFrameMoveRects()).");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Monitor::UpdateDirtyRects(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
|
||||
{
|
||||
dirtyRectSize_ = metaData_.Size() - moveRectSize_;
|
||||
|
||||
const auto hr = deskDupl_->GetFrameDirtyRects(
|
||||
dirtyRectSize_,
|
||||
metaData_.As<RECT>(moveRectSize_ /* offset */),
|
||||
&dirtyRectSize_);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
switch (hr)
|
||||
{
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
{
|
||||
Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST (GetFrameDirtyRects()).");
|
||||
break;
|
||||
}
|
||||
case DXGI_ERROR_MORE_DATA:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => DXGI_ERROR_MORE_DATA (GetFrameDirtyRects()).");
|
||||
break;
|
||||
}
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL (GetFrameDirtyRects()).");
|
||||
break;
|
||||
}
|
||||
case E_INVALIDARG:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => E_INVALIDARG (GetFrameDirtyRects()).");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => Unknown Error (GetFrameDirtyRects()).");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Monitor::GetId() const
|
||||
{
|
||||
return id_;
|
||||
@@ -304,4 +406,28 @@ int Monitor::GetWidth() const
|
||||
int Monitor::GetHeight() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
|
||||
int Monitor::GetMoveRectCount() const
|
||||
{
|
||||
return moveRectSize_ / sizeof(DXGI_OUTDUPL_MOVE_RECT);
|
||||
}
|
||||
|
||||
|
||||
DXGI_OUTDUPL_MOVE_RECT* Monitor::GetMoveRects() const
|
||||
{
|
||||
return metaData_.As<DXGI_OUTDUPL_MOVE_RECT>();
|
||||
}
|
||||
|
||||
|
||||
int Monitor::GetDirtyRectCount() const
|
||||
{
|
||||
return dirtyRectSize_ / sizeof(RECT);
|
||||
}
|
||||
|
||||
|
||||
RECT* Monitor::GetDirtyRects() const
|
||||
{
|
||||
return metaData_.As<RECT>(moveRectSize_);
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <dxgi1_2.h>
|
||||
#include <wrl/client.h>
|
||||
#include <memory>
|
||||
#include "Common.h"
|
||||
|
||||
class Cursor;
|
||||
|
||||
@@ -50,8 +51,17 @@ public:
|
||||
int GetDpiY() const;
|
||||
IDXGIOutputDuplication* GetDeskDupl();
|
||||
const std::unique_ptr<Cursor>& GetCursor();
|
||||
int GetMoveRectCount() const;
|
||||
DXGI_OUTDUPL_MOVE_RECT* GetMoveRects() const;
|
||||
int GetDirtyRectCount() const;
|
||||
RECT* GetDirtyRects() const;
|
||||
|
||||
private:
|
||||
void UpdateCursor(const DXGI_OUTDUPL_FRAME_INFO& frameInfo);
|
||||
void UpdateMetadata(const DXGI_OUTDUPL_FRAME_INFO& frameInfo);
|
||||
void UpdateMoveRects(const DXGI_OUTDUPL_FRAME_INFO& frameInfo);
|
||||
void UpdateDirtyRects(const DXGI_OUTDUPL_FRAME_INFO& frameInfo);
|
||||
|
||||
int id_ = -1;
|
||||
UINT dpiX_ = -1, dpiY_ = -1;
|
||||
int width_ = -1, height_ = -1;
|
||||
@@ -61,4 +71,7 @@ private:
|
||||
ID3D11Texture2D* unityTexture_ = nullptr;
|
||||
DXGI_OUTPUT_DESC outputDesc_;
|
||||
MONITORINFOEX monitorInfo_;
|
||||
Buffer<BYTE> metaData_;
|
||||
UINT moveRectSize_ = 0;
|
||||
UINT dirtyRectSize_ = 0;;
|
||||
};
|
||||
@@ -383,4 +383,40 @@ extern "C"
|
||||
monitor->SetUnityTexture(d3d11Texture);
|
||||
}
|
||||
}
|
||||
|
||||
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetMoveRectCount(int id)
|
||||
{
|
||||
if (!g_manager) return -1;
|
||||
if (auto monitor = g_manager->GetMonitor(id))
|
||||
{
|
||||
return monitor->GetMoveRectCount();
|
||||
}
|
||||
}
|
||||
|
||||
UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetMoveRects(int id)
|
||||
{
|
||||
if (!g_manager) return nullptr;
|
||||
if (auto monitor = g_manager->GetMonitor(id))
|
||||
{
|
||||
return monitor->GetMoveRects();
|
||||
}
|
||||
}
|
||||
|
||||
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetDirtyRectCount(int id)
|
||||
{
|
||||
if (!g_manager) return -1;
|
||||
if (auto monitor = g_manager->GetMonitor(id))
|
||||
{
|
||||
return monitor->GetDirtyRectCount();
|
||||
}
|
||||
}
|
||||
|
||||
UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetDirtyRects(int id)
|
||||
{
|
||||
if (!g_manager) return nullptr;
|
||||
if (auto monitor = g_manager->GetMonitor(id))
|
||||
{
|
||||
return monitor->GetDirtyRects();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user