modify timing to fetch metadata and add it to frame data #10

This commit is contained in:
hecomi
2017-01-05 19:03:29 +09:00
parent cfbd218374
commit 9ed24dd3b1
6 changed files with 166 additions and 123 deletions
@@ -54,8 +54,30 @@ template <class T>
class Buffer
{
public:
Buffer() {}
~Buffer() {}
Buffer()
{
}
Buffer<T>& operator=(const Buffer& other)
{
if (&other == this) return *this;
value_.reset();
size_ = 0;
ExpandIfNeeded(other.size_);
memcpy_s(value_.get(), size_, other.value_.get(), other.size_);
return *this;
}
~Buffer()
{
}
bool Empty() const
{
return !value_;
}
void ExpandIfNeeded(UINT size)
{
@@ -3,7 +3,6 @@
#include "Duplicator.h"
#include "Monitor.h"
#include "Device.h"
#include "Common.h"
#include "Debug.h"
#include "IUnityInterface.h"
@@ -213,30 +212,30 @@ bool Duplicator::Duplicate()
{
// If any monitor setting has changed (e.g. monitor size has changed),
// it is necessary to re-initialize monitors.
Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST.");
Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST.");
state_ = State::AccessLost;
break;
}
case DXGI_ERROR_WAIT_TIMEOUT:
{
// This often occurs when timeout value is small and it is not problem.
// Debug::Log("Monitor::Render() => DXGI_ERROR_WAIT_TIMEOUT.");
// Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_WAIT_TIMEOUT.");
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL.");
Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL.");
break;
}
case E_INVALIDARG:
{
Debug::Error("Monitor::Render() => E_INVALIDARG.");
Debug::Error("Duplicator::Duplicate() => E_INVALIDARG.");
break;
}
default:
{
state_ = State::Unknown;
Debug::Error("Monitor::Render() => Unknown Error.");
Debug::Error("Duplicator::Duplicate() => Unknown Error.");
break;
}
}
@@ -252,19 +251,19 @@ bool Duplicator::Duplicate()
{
case DXGI_ERROR_ACCESS_LOST:
{
Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST.");
Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST.");
state_ = State::AccessLost;
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL.");
Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL.");
break;
}
default:
{
state_ = State::Unknown;
Debug::Error("Monitor::Render() => Unknown Error.");
Debug::Error("Duplicator::Duplicate() => Unknown Error.");
break;
}
}
@@ -289,8 +288,115 @@ bool Duplicator::Duplicate()
{
std::lock_guard<std::mutex> lock(mutex_);
lastFrame_ = Frame { copyTarget, frameInfo };
lastFrame_.texture = copyTarget;
lastFrame_.info = frameInfo;
}
UpdateMetadata();
return true;
}
void Duplicator::UpdateMetadata()
{
metaData_.buffer.ExpandIfNeeded(lastFrame_.info.TotalMetadataBufferSize);
if (!metaData_.buffer.Empty())
{
UpdateMoveRects();
UpdateDirtyRects();
}
{
std::lock_guard<std::mutex> lock(mutex_);
lastFrame_.metaData = metaData_;
}
}
void Duplicator::UpdateMoveRects()
{
metaData_.moveRectSize = metaData_.buffer.Size();
const auto hr = dupl_->GetFrameMoveRects(
metaData_.moveRectSize,
metaData_.buffer.As<DXGI_OUTDUPL_MOVE_RECT>(),
&metaData_.moveRectSize);
if (FAILED(hr))
{
switch (hr)
{
case DXGI_ERROR_ACCESS_LOST:
{
Debug::Log("Duplicator::UpdateMoveRects() => DXGI_ERROR_ACCESS_LOST.");
break;
}
case DXGI_ERROR_MORE_DATA:
{
Debug::Error("Duplicator::UpdateMoveRects() => DXGI_ERROR_MORE_DATA.");
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Duplicator::UpdateMoveRects() => DXGI_ERROR_INVALID_CALL.");
break;
}
case E_INVALIDARG:
{
Debug::Error("Duplicator::UpdateMoveRects() => E_INVALIDARG.");
break;
}
default:
{
Debug::Error("Duplicator::UpdateMoveRects() => Unknown Error.");
break;
}
}
return;
}
}
void Duplicator::UpdateDirtyRects()
{
metaData_.dirtyRectSize = metaData_.buffer.Size() - metaData_.moveRectSize;
const auto hr = dupl_->GetFrameDirtyRects(
metaData_.dirtyRectSize,
metaData_.buffer.As<RECT>(metaData_.moveRectSize /* offset */),
&metaData_.dirtyRectSize);
if (FAILED(hr))
{
switch (hr)
{
case DXGI_ERROR_ACCESS_LOST:
{
Debug::Log("Duplicator::UpdateDirtyRects() => DXGI_ERROR_ACCESS_LOST.");
break;
}
case DXGI_ERROR_MORE_DATA:
{
Debug::Error("Duplicator::UpdateDirtyRects() => DXGI_ERROR_MORE_DATA.");
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Duplicator::UpdateDirtyRects() => DXGI_ERROR_INVALID_CALL.");
break;
}
case E_INVALIDARG:
{
Debug::Error("Duplicator::UpdateDirtyRects() => E_INVALIDARG.");
break;
}
default:
{
Debug::Error("Duplicator::UpdateDirtyRects() => Unknown Error.");
break;
}
}
return;
}
}
@@ -7,6 +7,8 @@
#include <mutex>
#include <wrl/client.h>
#include "Common.h"
class Monitor;
@@ -32,10 +34,18 @@ class Duplicator
public:
using State = DuplicatorState;
struct Metadata
{
Buffer<BYTE> buffer;
UINT moveRectSize = 0;
UINT dirtyRectSize = 0;
};
struct Frame
{
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
DXGI_OUTDUPL_FRAME_INFO info;
Metadata metaData;
};
explicit Duplicator(Monitor* monitor);
@@ -52,7 +62,11 @@ private:
void InitializeDevice();
void InitializeDuplication();
void CheckUnityAdapter();
bool Duplicate();
void UpdateMetadata();
void UpdateMoveRects();
void UpdateDirtyRects();
Monitor* monitor_ = nullptr;
State state_ = State::Ready;
@@ -64,4 +78,6 @@ private:
volatile bool shouldRun_ = false;
std::thread thread_;
mutable std::mutex mutex_;
Metadata metaData_;
};
@@ -67,9 +67,9 @@ void Monitor::Initialize(
void Monitor::Render()
{
const auto frame = duplicator_->GetFrame(); // copy
const auto& frame = duplicator_->GetFrame();
const auto texture = frame.texture;
const auto frameInfo = frame.info;
const auto& frameInfo = frame.info;
if (!texture) return;
@@ -100,8 +100,6 @@ void Monitor::Render()
}
}
UpdateMetadata(frameInfo);
if (frameInfo.PointerPosition.Visible)
{
GetMonitorManager()->SetCursorMonitorId(id_);
@@ -129,102 +127,6 @@ void Monitor::UpdateCursor(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
}
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 = GetDeskDupl()->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 = GetDeskDupl()->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_;
@@ -341,25 +243,29 @@ int Monitor::GetHeight() const
int Monitor::GetMoveRectCount() const
{
return moveRectSize_ / sizeof(DXGI_OUTDUPL_MOVE_RECT);
const auto& metaData = duplicator_->GetFrame().metaData;
return metaData.moveRectSize / sizeof(DXGI_OUTDUPL_MOVE_RECT);
}
DXGI_OUTDUPL_MOVE_RECT* Monitor::GetMoveRects() const
{
return metaData_.As<DXGI_OUTDUPL_MOVE_RECT>();
const auto& metaData = duplicator_->GetFrame().metaData;
return metaData.buffer.As<DXGI_OUTDUPL_MOVE_RECT>();
}
int Monitor::GetDirtyRectCount() const
{
return dirtyRectSize_ / sizeof(RECT);
const auto& metaData = duplicator_->GetFrame().metaData;
return metaData.dirtyRectSize / sizeof(RECT);
}
RECT* Monitor::GetDirtyRects() const
{
return metaData_.As<RECT>(moveRectSize_);
const auto& metaData = duplicator_->GetFrame().metaData;
return metaData.buffer.As<RECT>(metaData.moveRectSize);
}
@@ -54,9 +54,6 @@ public:
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);
void CopyTextureFromGpuToCpu(ID3D11Texture2D* texture);
int id_ = -1;
@@ -77,8 +74,4 @@ private:
ID3D11Texture2D* unityTexture_ = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> textureForGetPixels_;
Buffer<BYTE> bufferForGetPixels_;
Buffer<BYTE> metaData_;
UINT moveRectSize_ = 0;
UINT dirtyRectSize_ = 0;
};