diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplication.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplication.cpp new file mode 100644 index 0000000..c90741b --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplication.cpp @@ -0,0 +1,424 @@ +#include +#include +#include +#include + +#include "IUnityInterface.h" +#include "IUnityGraphicsD3D11.h" +#include "Duplication.h" + + +Duplication::Duplication(IUnityInterfaces* unity) + : unity_(unity) + , device_(unity->Get()->GetDevice()) +{ + Initialize(); +} + + +Duplication::~Duplication() +{ + Finalize(); + unity_ = nullptr; +} + + +void Duplication::Initialize() +{ + Finalize(); + + // Get factory + IDXGIFactory1* factory; + CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast(&factory)); + + // Check all display adapters + int id = 0; + IDXGIAdapter1* adapter; + for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i) + { + // Search the main monitor from all outputs + IDXGIOutput* output; + for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j) + { + Monitor monitor; + monitor.id = id++; + + output->GetDesc(&monitor.outputDesc); + monitor.monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor.outputDesc.Monitor, &monitor.monitorInfo); + + auto output1 = reinterpret_cast(output); + output1->DuplicateOutput(device_, &monitor.deskDupl); + output->Release(); + + monitors_.push_back(monitor); + } + + adapter->Release(); + } + + factory->Release(); +} + + +void Duplication::Finalize() +{ + // Release all duplicaitons + for (auto& monitor : monitors_) + { + monitor.deskDupl->Release(); + } + monitors_.clear(); +} + + +bool Duplication::IsValidId(int id) const +{ + return id >= 0 && id < monitors_.size(); +} + + +void Duplication::OnRender(int id) +{ + errorCode_ = 0; + errorMessage_ = ""; + + if (!IsValidId(id)) return; + auto& monitor = monitors_[id]; + + if (monitor.deskDupl == nullptr || monitor.texture == nullptr) return; + + IDXGIResource* resource = nullptr; + DXGI_OUTDUPL_FRAME_INFO frameInfo; + + errorCode_ = monitor.deskDupl->AcquireNextFrame(timeout_, &frameInfo, &resource); + if (FAILED(errorCode_)) + { + if (errorCode_ == DXGI_ERROR_ACCESS_LOST) + { + Initialize(); + errorMessage_ = "[IDXGIOutputDuplication::AcquireNextFrame()] Access lost."; + } + else + { + errorMessage_ = "[IDXGIOutputDuplication::AcquireNextFrame()] Maybe timeout."; + } + return; + } + + ID3D11Texture2D* texture; + resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast(&texture)); + + ID3D11DeviceContext* context; + device_->GetImmediateContext(&context); + context->CopyResource(monitor.texture, texture); + + if (!UpdateMouse(frameInfo, monitor)) + { + errorCode_ = -999; + errorMessage_ = "[UpdateMouse()] failed."; + } + + resource->Release(); + monitor.deskDupl->ReleaseFrame(); +} + + +bool Duplication::UpdateMouse(const DXGI_OUTDUPL_FRAME_INFO& frameInfo, Monitor& monitor) +{ + auto& pointer = monitor.pointer; + pointer.isVisible = frameInfo.PointerPosition.Visible != 0; + pointer.x = frameInfo.PointerPosition.Position.x; + pointer.y = frameInfo.PointerPosition.Position.y; + + // Pointer type + const auto pointerType = pointer.shapeInfo.Type; + const bool isMono = pointerType == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME; + const bool isColorMask = pointerType == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR; + + if (pointer.isVisible) + { + mouseMonitor_ = monitor.id; + } + + if (mouseMonitor_ != monitor.id) { + return true; + } + + // Increase the buffer size if needed + if (frameInfo.PointerShapeBufferSize > pointer.apiBufferSize) + { + if (pointer.apiBuffer) delete[] pointer.apiBuffer; + pointer.apiBuffer = new BYTE[frameInfo.PointerShapeBufferSize]; + pointer.apiBufferSize = frameInfo.PointerShapeBufferSize; + } + if (!pointer.apiBuffer) return true; + + // Get information about the mouse pointer if needed + if (frameInfo.PointerShapeBufferSize != 0) + { + UINT bufferSize; + monitor.deskDupl->GetFramePointerShape( + frameInfo.PointerShapeBufferSize, + reinterpret_cast(pointer.apiBuffer), + &bufferSize, + &pointer.shapeInfo); + } + + // Size + const auto w = pointer.shapeInfo.Width; + const auto h = pointer.shapeInfo.Height / (isMono ? 2 : 1); + const auto p = pointer.shapeInfo.Pitch; + + // Convert the buffer given by API into BGRA32 + const auto bgraBufferSize = w * h * 4; + if (bgraBufferSize > pointer.bgra32BufferSize) + { + if (pointer.bgra32Buffer) delete[] pointer.bgra32Buffer; + pointer.bgra32Buffer = new BYTE[bgraBufferSize]; + pointer.bgra32BufferSize = bgraBufferSize; + } + if (!pointer.bgra32Buffer) return true; + + // If masked, copy the desktop image and merge it with masked image. + if (isMono || isColorMask) + { + HRESULT hr; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = w; + desc.Height = h; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + + ID3D11DeviceContext* context; + device_->GetImmediateContext(&context); + + ID3D11Texture2D* texture = nullptr; + hr = device_->CreateTexture2D(&desc, nullptr, &texture); + if (FAILED(hr)) + { + return false; + } + + D3D11_BOX box; + box.front = 0; + box.back = 1; + box.left = pointer.x; + box.top = pointer.y; + box.right = pointer.x + w; + box.bottom = pointer.y + h; + context->CopySubresourceRegion(texture, 0, 0, 0, 0, monitor.texture, 0, &box); + + IDXGISurface* surface = nullptr; + hr = texture->QueryInterface(__uuidof(IDXGISurface), (void**)&surface); + texture->Release(); + if (FAILED(hr)) + { + return false; + } + + DXGI_MAPPED_RECT mappedSurface; + hr = surface->Map(&mappedSurface, DXGI_MAP_READ); + if (FAILED(hr)) + { + surface->Release(); + return false; + } + + // Finally, get the texture behind the mouse pointer. + const auto desktop32 = reinterpret_cast(mappedSurface.pBits); + const UINT desktopPitch = mappedSurface.Pitch / sizeof(UINT); + + // Access RGBA values at the same time + auto output32 = reinterpret_cast(pointer.bgra32Buffer); + + if (isMono) + { + for (UINT row = 0; row < h; ++row) + { + BYTE mask = 0x80; + for (UINT col = 0; col < w; ++col) + { + const int i = row * w + col; + const BYTE andMask = pointer.apiBuffer[col / 8 + row * p] & mask; + const BYTE xorMask = pointer.apiBuffer[col / 8 + (row + h) * p] & mask; + const UINT andMask32 = andMask ? 0xFFFFFFFF : 0xFF000000; + const UINT xorMask32 = xorMask ? 0x00FFFFFF : 0x00000000; + output32[i] = (desktop32[row * desktopPitch + col] & andMask32) ^ xorMask32; + mask = (mask == 0x01) ? 0x80 : (mask >> 1); + } + } + } + else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR + { + const auto buffer32 = reinterpret_cast(pointer.apiBuffer); + + for (UINT row = 0; row < h; ++row) + { + for (UINT col = 0; col < w; ++col) + { + const int i = row * w + col; + const int j = row * p / sizeof(UINT) + col; + + UINT mask = 0xFF000000 & buffer32[j]; + if (mask) + { + output32[i] = (desktop32[row * desktopPitch + col] ^ buffer32[j]) | 0xFF000000; + } + else + { + output32[i] = buffer32[j] | 0xFF000000; + } + } + } + } + + hr = surface->Unmap(); + surface->Release(); + if (FAILED(hr)) + { + return false; + } + } + else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR + { + auto output32 = reinterpret_cast(pointer.bgra32Buffer); + const auto buffer32 = reinterpret_cast(pointer.apiBuffer); + for (UINT i = 0; i < w * h; ++i) + { + output32[i] = buffer32[i]; + } + } + + return true; +} + + +void Duplication::UpdatePointerTexture(int id, ID3D11Texture2D* ptr) +{ + if (!IsValidId(id)) return; + const auto& pointer = monitors_[id].pointer; + if (!pointer.bgra32Buffer) return; + ID3D11DeviceContext* context; + device_->GetImmediateContext(&context); + context->UpdateSubresource(ptr, 0, nullptr, pointer.bgra32Buffer, pointer.shapeInfo.Width * 4, 0); +} + + +void Duplication::SetTimeout(int timeout) +{ + timeout_ = timeout; +} + + +void Duplication::SetTexturePtr(int id, void* texture) +{ + if (!IsValidId(id)) return; + monitors_[id].texture = reinterpret_cast(texture); +} + + +int Duplication::GetMonitorCount() const +{ + return static_cast(monitors_.size()); +} + + +void Duplication::GetName(int id, char* buf, int len) const +{ + if (!IsValidId(id)) return; + strcpy_s(buf, len, monitors_[id].monitorInfo.szDevice); +} + + +bool Duplication::IsPrimary(int id) const +{ + if (!IsValidId(id)) return false; + return monitors_[id].monitorInfo.dwFlags == MONITORINFOF_PRIMARY; +} + + +int Duplication::GetWidth(int id) const +{ + if (!IsValidId(id)) return -1; + const auto rect = monitors_[id].monitorInfo.rcMonitor; + return rect.right - rect.left; +} + + +int Duplication::GetHeight(int id) const +{ + if (!IsValidId(id)) return -1; + const auto rect = monitors_[id].monitorInfo.rcMonitor; + return rect.bottom - rect.top; +} + + +int Duplication::IsPointerVisible(int id) const +{ + if (!IsValidId(id)) return false; + return monitors_[id].pointer.isVisible; +} + + +int Duplication::GetPointerX(int id) const +{ + if (!IsValidId(id)) return -1; + return monitors_[id].pointer.x; +} + + +int Duplication::GetPointerY(int id) const +{ + if (!IsValidId(id)) return -1; + return monitors_[id].pointer.y; +} + + +int Duplication::GetPointerShapeWidth(int id) const +{ + if (!IsValidId(id)) return -1; + return monitors_[id].pointer.shapeInfo.Width; +} + + +int Duplication::GetPointerShapeHeight(int id) const +{ + if (!IsValidId(id)) return -1; + const auto& info = monitors_[id].pointer.shapeInfo; + return (info.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME) ? info.Height / 2 : info.Height; +} + + +int Duplication::GetPointerShapePitch(int id) const +{ + if (!IsValidId(id)) return -1; + return monitors_[id].pointer.shapeInfo.Pitch; +} + + +int Duplication::GetPointerShapeType(int id) const +{ + if (!IsValidId(id)) return -1; + return monitors_[id].pointer.shapeInfo.Type; +} + + +int Duplication::GetErrorCode() const +{ + return errorCode_; +} + + +void Duplication::GetErrorMessage(char* buf, int len) const +{ + strcpy_s(buf, len, errorMessage_.c_str()); +} \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplication.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplication.h new file mode 100644 index 0000000..1eba567 --- /dev/null +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplication.h @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +struct IUnityInterfaces; + +struct Pointer +{ + bool isVisible = false; + int x = -1; + int y = -1; + BYTE* apiBuffer = nullptr; + UINT apiBufferSize = 0; + BYTE* bgra32Buffer = nullptr; + UINT bgra32BufferSize = 0; + DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo; +}; + +struct Monitor +{ + int id = -1; + IDXGIOutputDuplication* deskDupl = nullptr; + ID3D11Texture2D* texture = nullptr; + DXGI_OUTPUT_DESC outputDesc; + MONITORINFOEX monitorInfo; + Pointer pointer; +}; + +class Duplication +{ +public: + explicit Duplication(IUnityInterfaces* unity); + ~Duplication(); + void OnRender(int id); + +public: + void UpdatePointerTexture(int id, ID3D11Texture2D* ptr); + void SetTimeout(int timeout); + void SetTexturePtr(int id, void* texture); + +public: + int GetMonitorCount() const; + void GetName(int id, char* buf, int len) const; + bool IsPrimary(int id) const; + int GetWidth(int id) const; + int GetHeight(int id) const; + int IsPointerVisible(int id) const; + int GetPointerX(int id) const; + int GetPointerY(int id) const; + int GetPointerShapeWidth(int id) const; + int GetPointerShapeHeight(int id) const; + int GetPointerShapePitch(int id) const; + int GetPointerShapeType(int id) const; + int GetErrorCode() const; + void GetErrorMessage(char* buf, int len) const; + +private: + void Initialize(); + void Finalize(); + bool UpdateMouse(const DXGI_OUTDUPL_FRAME_INFO& frameInfo, Monitor& monitor); + + bool IsValidId(int id) const; + + IUnityInterfaces* unity_ = nullptr; + ID3D11Device* device_ = nullptr; + int mouseMonitor_ = 0; + int timeout_ = 10; + HRESULT errorCode_ = 0; + std::string errorMessage_ = ""; + std::vector monitors_; +}; \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp index 511dcc0..4ee35df 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/main.cpp @@ -2,331 +2,36 @@ #include #include #include +#include #include "IUnityInterface.h" #include "IUnityGraphics.h" -#include "IUnityGraphicsD3D11.h" +#include "Duplication.h" #pragma comment(lib, "dxgi.lib") namespace { - struct Monitor - { - int id = -1; - IDXGIOutputDuplication* deskDupl = nullptr; - ID3D11Texture2D* texture = nullptr; - DXGI_OUTPUT_DESC outputDesc; - MONITORINFOEX monitorInfo; - - struct Pointer - { - bool isVisible = false; - int x = -1; - int y = -1; - BYTE* apiBuffer = nullptr; - UINT apiBufferSize = 0; - BYTE* bgra32Buffer = nullptr; - UINT bgra32BufferSize = 0; - DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo; - }; - Pointer pointer; - }; - - IUnityInterfaces* g_unity = nullptr; - int g_mouseMonitor = 0; - int g_timeout = 10; - HRESULT g_errorCode = 0; - std::string g_errorMessage = ""; - std::vector g_monitors; + std::unique_ptr g_dupl; } extern "C" { - void FinalizeDuplication() - { - for (auto& monitor : g_monitors) - { - monitor.deskDupl->Release(); - } - g_monitors.clear(); - } - - void InitializeDuplication() - { - FinalizeDuplication(); - - IDXGIFactory1* factory; - CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast(&factory)); - - // Check all display adapters. - int id = 0; - IDXGIAdapter1* adapter; - for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i) - { - // Search the main monitor from all outputs. - IDXGIOutput* output; - for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j) - { - Monitor monitor; - monitor.id = id++; - - output->GetDesc(&monitor.outputDesc); - monitor.monitorInfo.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(monitor.outputDesc.Monitor, &monitor.monitorInfo); - - auto device = g_unity->Get()->GetDevice(); - auto output1 = reinterpret_cast(output); - output1->DuplicateOutput(device, &monitor.deskDupl); - output->Release(); - - g_monitors.push_back(monitor); - } - - adapter->Release(); - } - - factory->Release(); - } - UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { - g_unity = unityInterfaces; - InitializeDuplication(); + g_dupl = std::make_unique(unityInterfaces); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload() { - g_unity = nullptr; - FinalizeDuplication(); - } - - bool IsValidMonitorId(int id) - { - return id >= 0 && id < g_monitors.size(); - } - - bool UpdateMouse(const DXGI_OUTDUPL_FRAME_INFO& frameInfo, Monitor& monitor) - { - auto& pointer = monitor.pointer; - pointer.isVisible = frameInfo.PointerPosition.Visible != 0; - pointer.x = frameInfo.PointerPosition.Position.x; - pointer.y = frameInfo.PointerPosition.Position.y; - - // Pointer type - const auto pointerType = pointer.shapeInfo.Type; - const bool isMono = pointerType == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME; - const bool isColorMask = pointerType == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR; - - if (pointer.isVisible) - { - g_mouseMonitor = monitor.id; - } - - if (g_mouseMonitor != monitor.id) { - return true; - } - - // Increase the buffer size if needed - if (frameInfo.PointerShapeBufferSize > pointer.apiBufferSize) - { - if (pointer.apiBuffer) delete[] pointer.apiBuffer; - pointer.apiBuffer = new BYTE[frameInfo.PointerShapeBufferSize]; - pointer.apiBufferSize = frameInfo.PointerShapeBufferSize; - } - if (!pointer.apiBuffer) return true; - - // Get information about the mouse pointer if needed - if (frameInfo.PointerShapeBufferSize != 0) - { - UINT bufferSize; - monitor.deskDupl->GetFramePointerShape( - frameInfo.PointerShapeBufferSize, - reinterpret_cast(pointer.apiBuffer), - &bufferSize, - &pointer.shapeInfo); - } - - // Size - const auto w = pointer.shapeInfo.Width; - const auto h = pointer.shapeInfo.Height / (isMono ? 2 : 1); - const auto p = pointer.shapeInfo.Pitch; - - // Convert the buffer given by API into BGRA32 - const auto bgraBufferSize = w * h * 4; - if (bgraBufferSize > pointer.bgra32BufferSize) - { - if (pointer.bgra32Buffer) delete[] pointer.bgra32Buffer; - pointer.bgra32Buffer = new BYTE[bgraBufferSize]; - pointer.bgra32BufferSize = bgraBufferSize; - } - if (!pointer.bgra32Buffer) return true; - - // If masked, copy the desktop image and merge it with masked image. - if (isMono || isColorMask) - { - HRESULT hr; - - D3D11_TEXTURE2D_DESC desc; - desc.Width = w; - desc.Height = h; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - desc.MiscFlags = 0; - - ID3D11DeviceContext* context; - auto device = g_unity->Get()->GetDevice(); - device->GetImmediateContext(&context); - - ID3D11Texture2D* texture = nullptr; - hr = device->CreateTexture2D(&desc, nullptr, &texture); - if (FAILED(hr)) - { - return false; - } - - D3D11_BOX box; - box.front = 0; - box.back = 1; - box.left = pointer.x; - box.top = pointer.y; - box.right = pointer.x + w; - box.bottom = pointer.y + h; - context->CopySubresourceRegion(texture, 0, 0, 0, 0, monitor.texture, 0, &box); - - IDXGISurface* surface = nullptr; - hr = texture->QueryInterface(__uuidof(IDXGISurface), (void**)&surface); - texture->Release(); - if (FAILED(hr)) - { - return false; - } - - DXGI_MAPPED_RECT mappedSurface; - hr = surface->Map(&mappedSurface, DXGI_MAP_READ); - if (FAILED(hr)) - { - surface->Release(); - return false; - } - - // Finally, get the texture behind the mouse pointer. - const auto desktop32 = reinterpret_cast(mappedSurface.pBits); - const UINT desktopPitch = mappedSurface.Pitch / sizeof(UINT); - - // Access RGBA values at the same time - auto output32 = reinterpret_cast(pointer.bgra32Buffer); - - if (isMono) - { - for (UINT row = 0; row < h; ++row) - { - BYTE mask = 0x80; - for (UINT col = 0; col < w; ++col) - { - const int i = row * w + col; - const BYTE andMask = pointer.apiBuffer[col / 8 + row * p] & mask; - const BYTE xorMask = pointer.apiBuffer[col / 8 + (row + h) * p] & mask; - const UINT andMask32 = andMask ? 0xFFFFFFFF : 0xFF000000; - const UINT xorMask32 = xorMask ? 0x00FFFFFF : 0x00000000; - output32[i] = (desktop32[row * desktopPitch + col] & andMask32) ^ xorMask32; - mask = (mask == 0x01) ? 0x80 : (mask >> 1); - } - } - } - else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR - { - const auto buffer32 = reinterpret_cast(pointer.apiBuffer); - - for (UINT row = 0; row < h; ++row) - { - for (UINT col = 0; col < w; ++col) - { - const int i = row * w + col; - const int j = row * p / sizeof(UINT) + col; - - UINT mask = 0xFF000000 & buffer32[j]; - if (mask) - { - output32[i] = (desktop32[row * desktopPitch + col] ^ buffer32[j]) | 0xFF000000; - } - else - { - output32[i] = buffer32[j] | 0xFF000000; - } - } - } - } - - hr = surface->Unmap(); - surface->Release(); - if (FAILED(hr)) - { - return false; - } - } - else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR - { - auto output32 = reinterpret_cast(pointer.bgra32Buffer); - const auto buffer32 = reinterpret_cast(pointer.apiBuffer); - for (UINT i = 0; i < w * h; ++i) - { - output32[i] = buffer32[i]; - } - } - - return true; + g_dupl.reset(); } void UNITY_INTERFACE_API OnRenderEvent(int id) { - if (!IsValidMonitorId(id)) return; - auto& monitor = g_monitors[id]; - - if (monitor.deskDupl == nullptr || monitor.texture == nullptr) return; - - IDXGIResource* resource = nullptr; - DXGI_OUTDUPL_FRAME_INFO frameInfo; - - g_errorCode = monitor.deskDupl->AcquireNextFrame(g_timeout, &frameInfo, &resource); - if (FAILED(g_errorCode)) - { - if (g_errorCode == DXGI_ERROR_ACCESS_LOST) - { - InitializeDuplication(); - g_errorMessage = "[IDXGIOutputDuplication::AcquireNextFrame()] Access lost."; - } - else - { - g_errorMessage = "[IDXGIOutputDuplication::AcquireNextFrame()] Maybe timeout."; - } - return; - } - - ID3D11Texture2D* texture; - resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast(&texture)); - - ID3D11DeviceContext* context; - auto device = g_unity->Get()->GetDevice(); - device->GetImmediateContext(&context); - context->CopyResource(monitor.texture, texture); - - if (!UpdateMouse(frameInfo, monitor)) - { - g_errorCode = -999; - g_errorMessage = "[UpdateMouse()] failed."; - } - - resource->Release(); - monitor.deskDupl->ReleaseFrame(); + g_dupl->OnRender(id); } UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc() @@ -336,112 +41,87 @@ extern "C" UNITY_INTERFACE_EXPORT size_t UNITY_INTERFACE_API GetMonitorCount() { - return g_monitors.size(); + return g_dupl->GetMonitorCount(); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTimeout(int timeout) { - g_timeout = timeout; + g_dupl->SetTimeout(timeout); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len) { - if (!IsValidMonitorId(id)) return; - strcpy_s(buf, len, g_monitors[id].monitorInfo.szDevice); + g_dupl->GetName(id, buf, len); } UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsPrimary(int id) { - if (!IsValidMonitorId(id)) return false; - return g_monitors[id].monitorInfo.dwFlags == MONITORINFOF_PRIMARY; + return g_dupl->IsPrimary(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth(int id) { - if (!IsValidMonitorId(id)) return -1; - const auto rect = g_monitors[id].monitorInfo.rcMonitor; - return rect.right - rect.left; + return g_dupl->GetWidth(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight(int id) { - if (!IsValidMonitorId(id)) return -1; - const auto rect = g_monitors[id].monitorInfo.rcMonitor; - return rect.bottom - rect.top; + return g_dupl->GetHeight(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible(int id) { - if (!IsValidMonitorId(id)) return false; - return g_monitors[id].pointer.isVisible; + return g_dupl->IsPointerVisible(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX(int id) { - if (!IsValidMonitorId(id)) return -1; - return g_monitors[id].pointer.x; + return g_dupl->GetPointerX(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY(int id) { - if (!IsValidMonitorId(id)) return -1; - return g_monitors[id].pointer.y; + return g_dupl->GetPointerY(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerShapeWidth(int id) { - if (!IsValidMonitorId(id)) return -1; - return g_monitors[id].pointer.shapeInfo.Width; + return g_dupl->GetPointerShapeWidth(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerShapeHeight(int id) { - if (!IsValidMonitorId(id)) return -1; - const auto& info = g_monitors[id].pointer.shapeInfo; - return (info.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME) ? info.Height / 2 : info.Height; + return g_dupl->GetPointerShapeHeight(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerShapePitch(int id) { - if (!IsValidMonitorId(id)) return -1; - return g_monitors[id].pointer.shapeInfo.Pitch; + return g_dupl->GetPointerShapePitch(id); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerShapeType(int id) { - if (!IsValidMonitorId(id)) return -1; - return g_monitors[id].pointer.shapeInfo.Type; + return g_dupl->GetPointerShapeType(id); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UpdatePointerTexture(int id, ID3D11Texture2D* ptr) { - if (!IsValidMonitorId(id)) return; - const auto& pointer = g_monitors[id].pointer; - if (!pointer.bgra32Buffer) return; - auto device = g_unity->Get()->GetDevice(); - ID3D11DeviceContext* context; - device->GetImmediateContext(&context); - context->UpdateSubresource(ptr, 0, nullptr, pointer.bgra32Buffer, pointer.shapeInfo.Width * 4, 0); + g_dupl->UpdatePointerTexture(id, ptr); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(int id, void* texture) { - if (!IsValidMonitorId(id)) return; - g_monitors[id].texture = reinterpret_cast(texture); + g_dupl->SetTexturePtr(id, texture); } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetErrorCode() { - const auto code = g_errorCode; - g_errorCode = 0; - return static_cast(code); + return g_dupl->GetErrorCode(); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetErrorMessage(char* buf, int len) { - const auto message = g_errorMessage; - g_errorMessage = ""; - strcpy_s(buf, len, message.c_str()); + g_dupl->GetErrorMessage(buf, len); } } \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj index af212d0..ce95a48 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/uDesktopDuplication.vcxproj @@ -122,9 +122,11 @@ + +