Compare commits

..

10 Commits

Author SHA1 Message Date
hecomi
808a71ed6d remove unnecessary codes. 2017-01-08 00:09:24 +09:00
hecomi
da072aa9f3 draw cursor texture to unity texture instead of cached texture. 2017-01-08 00:02:41 +09:00
hecomi
7237d283ef add error messages. 2017-01-07 23:10:13 +09:00
hecomi
4a28b5f341 tweak shared texture. 2017-01-07 23:02:48 +09:00
hecomi
10091be4b3 lock shared texture. 2017-01-07 15:28:13 +09:00
hecomi
c41fe42aa3 check frame id. 2017-01-07 13:48:38 +09:00
hecomi
c0e1967e2e modify duplicator state handling. 2017-01-07 13:26:28 +09:00
hecomi
f5a8a83c7e change member name. 2017-01-07 13:18:11 +09:00
hecomi
c251de3a30 add debug timer macro. 2017-01-07 01:15:33 +09:00
hecomi
b0877a49ed tweak code. 2017-01-07 00:53:37 +09:00
11 changed files with 112 additions and 70 deletions

View File

@@ -62,16 +62,16 @@ void Cursor::UpdateBuffer(Duplicator* duplicator, const DXGI_OUTDUPL_FRAME_INFO&
}
void Cursor::Draw(
void Cursor::UpdateTexture(
Duplicator* duplicator,
const ComPtr<ID3D11Texture2D>& targetTexture)
const ComPtr<ID3D11Texture2D>& desktopTexture)
{
auto monitor = duplicator->GetMonitor();
// Check desktop texure
if (targetTexture == nullptr)
if (desktopTexture == nullptr)
{
Debug::Error("Cursor::UpdateTexture() => target texture is null.");
Debug::Error("Cursor::UpdateTexture() => Desktop texture is null.");
return;
}
@@ -97,6 +97,7 @@ void Cursor::Draw(
// Check buffers
if (!bgraBuffer_ || !buffer_)
{
Debug::Error("Cursor::UpdateTexture() => no buffer.");
return;
}
@@ -193,7 +194,7 @@ void Cursor::Draw(
return;
}
D3D11_BOX capturedImageArea
capturedImageArea_ = D3D11_BOX
{
static_cast<UINT>(capturedImageLeft),
static_cast<UINT>(capturedImageTop),
@@ -217,7 +218,7 @@ void Cursor::Draw(
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
if (FAILED(duplicator->GetDevice()->CreateTexture2D(&desc, nullptr, &texture)))
{
@@ -230,7 +231,7 @@ void Cursor::Draw(
{
ComPtr<ID3D11DeviceContext> context;
duplicator->GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, targetTexture.Get(), 0, &capturedImageArea);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, desktopTexture.Get(), 0, &capturedImageArea_);
}
// Get mapped surface to access pixels in CPU
@@ -358,12 +359,6 @@ void Cursor::Draw(
}
}
{
ComPtr<ID3D11DeviceContext> context;
duplicator->GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(targetTexture.Get(), 0, &capturedImageArea, bgraBuffer_.Get(), capturedImageWidth * 4, 0);
}
if (FAILED(surface->Unmap()))
{
Debug::Error("Cursor::UpdateTexture() => surface->Unmap() failed.");
@@ -372,6 +367,21 @@ void Cursor::Draw(
}
void Cursor::Draw(const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture)
{
if (texture == nullptr)
{
Debug::Error("Cursor::UpdateTexture() => Desktop texture is null.");
return;
}
const auto capturedImageWidth = capturedImageArea_.right - capturedImageArea_.left;
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(texture.Get(), 0, &capturedImageArea_, bgraBuffer_.Get(), capturedImageWidth * 4, 0);
}
void Cursor::GetTexture(ID3D11Texture2D* texture)
{
if (!bgraBuffer_)

View File

@@ -17,9 +17,10 @@ public:
void UpdateBuffer(
Duplicator* duplicator,
const DXGI_OUTDUPL_FRAME_INFO& frameInfo);
void Draw(
Duplicator* duplicator,
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& targetTexture);
void UpdateTexture(
Duplicator* duplicator,
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& desktopTexture);
void Draw(const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture);
void GetTexture(ID3D11Texture2D* texture);
bool IsVisible() const;
@@ -38,4 +39,5 @@ private:
Buffer<BYTE> bgraBuffer_;
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo_;
LARGE_INTEGER timestamp_;
D3D11_BOX capturedImageArea_;
};

View File

@@ -1,10 +1,18 @@
#pragma once
#include <time.h>
#include <fstream>
#include <sstream>
#include <mutex>
#include "Common.h"
#include "IUnityInterface.h"
// Debug flag
#define UDD_DEBUG_ON
// Logging
class Debug
{
@@ -133,4 +141,20 @@ private:
static DebugLogFuncPtr logFunc_;
static DebugLogFuncPtr errFunc_;
static std::mutex mutex_;
};
};
#ifdef UDD_DEBUG_ON
#define UDD_FUNCTION_SCOPE_TIMER \
ScopedTimer _timer_##__COUNTER__([](std::chrono::microseconds us) \
{ \
Debug::Log(__FUNCTION__, "@", __FILE__, ":", __LINE__, " => ", us.count(), " [us]"); \
});
#define UDD_SCOPE_TIMER(Name) \
ScopedTimer _timer_##__COUNTER__([](std::chrono::microseconds us) \
{ \
Debug::Log(#Name, " => ", us.count(), " [us]"); \
});
#else
#define UDD_FUNCTION_SCOPE_TIMER
#endif

View File

@@ -7,6 +7,7 @@
#include "IUnityGraphicsD3D11.h"
#include "Device.h"
#include "Debug.h"
#include "Common.h"
#pragma comment(lib, "d3d11.lib")
@@ -14,8 +15,7 @@ using namespace Microsoft::WRL;
IsolatedD3D11Device::IsolatedD3D11Device(UINT cachedTextureNum)
: cachedTextures_(cachedTextureNum)
IsolatedD3D11Device::IsolatedD3D11Device()
{
}
@@ -65,42 +65,33 @@ ComPtr<ID3D11Device> IsolatedD3D11Device::GetDevice()
}
ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(
const ComPtr<ID3D11Texture2D>& src,
UINT index)
Microsoft::WRL::ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(
const ComPtr<ID3D11Texture2D>& src)
{
if (index < 0 || index >= cachedTextures_.size())
{
Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => ", index, " is out of cachedTextures range.");
return nullptr;
}
auto& cachedTexture = cachedTextures_.at(index);
D3D11_TEXTURE2D_DESC srcDesc;
src->GetDesc(&srcDesc);
// check if the format and size of the current texture are same as the source one
if (cachedTexture)
if (cachedSharedTexture_)
{
D3D11_TEXTURE2D_DESC targetDesc;
cachedTexture->GetDesc(&targetDesc);
cachedSharedTexture_->GetDesc(&targetDesc);
if (targetDesc.Format == srcDesc.Format &&
targetDesc.Width == srcDesc.Width &&
targetDesc.Height == srcDesc.Height)
{
return cachedTexture;
return cachedSharedTexture_;
}
}
// for sharing this texture with unity device
srcDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedTexture)))
if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedSharedTexture_)))
{
Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => Creating shared texture failed.");
return nullptr;
}
return cachedTexture;
return cachedSharedTexture_;
}

View File

@@ -1,6 +1,8 @@
#pragma once
#include <atomic>
#include <vector>
#include <memory>
#include <d3d11.h>
#include <wrl/client.h>
@@ -9,16 +11,15 @@
class IsolatedD3D11Device
{
public:
explicit IsolatedD3D11Device(UINT cachedTextureNum);
IsolatedD3D11Device();
~IsolatedD3D11Device();
HRESULT Create(const Microsoft::WRL::ComPtr<IDXGIAdapter>& adapter);
Microsoft::WRL::ComPtr<ID3D11Device> GetDevice();
Microsoft::WRL::ComPtr<ID3D11Texture2D> GetCompatibleSharedTexture(
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src,
UINT index);
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src);
private:
Microsoft::WRL::ComPtr<ID3D11Device> device_;
std::vector<Microsoft::WRL::ComPtr<ID3D11Texture2D>> cachedTextures_;
Microsoft::WRL::ComPtr<ID3D11Texture2D> cachedSharedTexture_;
};

View File

@@ -33,8 +33,7 @@ Duplicator::~Duplicator()
void Duplicator::InitializeDevice()
{
const UINT cachedTextureNum = 2;
device_ = std::make_shared<IsolatedD3D11Device>(cachedTextureNum);
device_ = std::make_shared<IsolatedD3D11Device>();
if (FAILED(device_->Create(monitor_->GetAdapter())))
{
@@ -162,7 +161,12 @@ void Duplicator::Start()
});
const auto timeout = static_cast<UINT>(frameMilliSeconds);
if (!Duplicate(timeout)) break;
Duplicate(timeout);
if (state_ != State::Running)
{
break;
}
}
if (state_ == State::Running)
@@ -229,9 +233,9 @@ const Duplicator::Frame& Duplicator::GetLastFrame() const
}
bool Duplicator::Duplicate(UINT timeout)
void Duplicator::Duplicate(UINT timeout)
{
if (!dupl_ || !device_) return false;
if (!dupl_ || !device_) return;
ComPtr<IDXGIResource> resource;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
@@ -247,31 +251,32 @@ bool Duplicator::Duplicate(UINT timeout)
// it is necessary to re-initialize monitors.
Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST.");
state_ = State::AccessLost;
return false;
break;
}
case DXGI_ERROR_WAIT_TIMEOUT:
{
// This often occurs when timeout value is small and it is not problem.
// Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_WAIT_TIMEOUT.");
return true;
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL.");
return false;
break;
}
case E_INVALIDARG:
{
Debug::Error("Duplicator::Duplicate() => E_INVALIDARG.");
return false;
break;
}
default:
{
state_ = State::Unknown;
Debug::Error("Duplicator::Duplicate() => Unknown Error.");
return false;
break;
}
}
return;
}
ScopedReleaser releaser([this]
@@ -305,31 +310,37 @@ bool Duplicator::Duplicate(UINT timeout)
ComPtr<ID3D11Texture2D> texture;
if (FAILED(resource.As(&texture)))
{
return false;
Debug::Error("Duplicator::Duplicate() => IDXGIResource could not be converted to ID3D11Texture2D.");
return;
}
auto sharedTexture = device_->GetCompatibleSharedTexture(texture, frame % 2);
auto sharedTexture = device_->GetCompatibleSharedTexture(texture);
if (!sharedTexture)
{
return false;
Debug::Error("Duplicator::Duplicate() => Shared texture is null.");
return;
}
ComPtr<ID3D11DeviceContext> context;
device_->GetDevice()->GetImmediateContext(&context);
context->CopyResource(sharedTexture.Get(), texture.Get());
{
UDD_SCOPE_TIMER(CopyResource);
ComPtr<ID3D11DeviceContext> context;
device_->GetDevice()->GetImmediateContext(&context);
context->CopyResource(sharedTexture.Get(), texture.Get());
}
UpdateCursor(sharedTexture, frameInfo);
UpdateMetadata(frameInfo.TotalMetadataBufferSize);
{
std::lock_guard<std::mutex> lock(mutex_);
lastFrame_.frame = frame++;
lastFrame_.texture = sharedTexture;
lastFrame_.info = frameInfo;
lastFrame_.metaData = metaData_;
lastFrame_ = Frame
{
lastFrameId_++,
sharedTexture,
frameInfo,
metaData_
};
}
return true;
}
@@ -348,7 +359,7 @@ void Duplicator::UpdateCursor(
{
auto cursor = manager->GetCursor();
cursor->UpdateBuffer(this, frameInfo);
cursor->Draw(this, texture);
cursor->UpdateTexture(this, texture);
}
}

View File

@@ -44,7 +44,7 @@ public:
struct Frame
{
UINT frame = 0;
UINT id;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
DXGI_OUTDUPL_FRAME_INFO info;
Metadata metaData;
@@ -67,7 +67,7 @@ private:
void InitializeDuplication();
void CheckUnityAdapter();
bool Duplicate(UINT timeout);
void Duplicate(UINT timeout);
void UpdateCursor(
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture,
@@ -82,7 +82,7 @@ private:
std::shared_ptr<class IsolatedD3D11Device> device_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> dupl_;
Frame lastFrame_;
UINT frame = 0;
UINT lastFrameId_ = 0;
volatile bool shouldRun_ = false;
std::thread thread_;

View File

@@ -71,15 +71,14 @@ void Monitor::Finalize()
void Monitor::Render()
{
const auto& frame = duplicator_->GetLastFrame();
const auto& texture = frame.texture;
if (!texture) return;
if (frame.id == lastFrameId_) return;
lastFrameId_ = frame.id;
// Get texture
if (unityTexture_)
{
D3D11_TEXTURE2D_DESC srcDesc, dstDesc;
texture->GetDesc(&srcDesc);
frame.texture->GetDesc(&srcDesc);
unityTexture_->GetDesc(&dstDesc);
if (srcDesc.Width != dstDesc.Width ||
srcDesc.Height != dstDesc.Height)
@@ -93,7 +92,10 @@ void Monitor::Render()
{
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture.Get());
context->CopyResource(unityTexture_, frame.texture.Get());
auto cursor = GetMonitorManager()->GetCursor();
cursor->Draw(unityTexture_);
}
}

View File

@@ -70,6 +70,7 @@ private:
MONITORINFOEX monitorInfo_;
std::shared_ptr<class Duplicator> duplicator_;
UINT lastFrameId_ = -1;
ID3D11Texture2D* unityTexture_ = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> textureForGetPixels_;