2026-04-15 22:47:42 +08:00
|
|
|
#include "D3D12WindowInteropInternal.h"
|
2026-04-15 08:24:06 +08:00
|
|
|
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
2026-04-15 22:47:42 +08:00
|
|
|
namespace XCEngine::UI::Editor::Host::D3D12WindowInteropInternal {
|
2026-04-15 08:24:06 +08:00
|
|
|
|
|
|
|
|
std::string HrToInteropString(const char* operation, HRESULT hr) {
|
|
|
|
|
char buffer[128] = {};
|
|
|
|
|
sprintf_s(buffer, "%s failed with hr=0x%08X.", operation, static_cast<unsigned int>(hr));
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D2D1_BITMAP_PROPERTIES1 BuildD2DBitmapProperties(
|
|
|
|
|
DXGI_FORMAT format,
|
|
|
|
|
D2D1_BITMAP_OPTIONS options) {
|
|
|
|
|
return D2D1::BitmapProperties1(
|
|
|
|
|
options,
|
|
|
|
|
D2D1::PixelFormat(format, D2D1_ALPHA_MODE_IGNORE),
|
|
|
|
|
96.0f,
|
|
|
|
|
96.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsInteropTextureHandle(const ::XCEngine::UI::UITextureHandle& texture) {
|
|
|
|
|
return texture.kind == ::XCEngine::UI::UITextureHandleKind::ShaderResourceView &&
|
|
|
|
|
texture.resourceHandle != 0u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CollectInteropTextureHandles(
|
|
|
|
|
const ::XCEngine::UI::UIDrawData& drawData,
|
|
|
|
|
std::vector<::XCEngine::UI::UITextureHandle>& outTextures) {
|
|
|
|
|
outTextures.clear();
|
|
|
|
|
std::unordered_set<std::uintptr_t> seenKeys = {};
|
|
|
|
|
for (const ::XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
|
|
|
|
for (const ::XCEngine::UI::UIDrawCommand& command : drawList.GetCommands()) {
|
|
|
|
|
if (!IsInteropTextureHandle(command.texture) ||
|
|
|
|
|
!seenKeys.insert(command.texture.resourceHandle).second) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outTextures.push_back(command.texture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 22:47:42 +08:00
|
|
|
} // namespace XCEngine::UI::Editor::Host::D3D12WindowInteropInternal
|
2026-04-15 08:24:06 +08:00
|
|
|
|
|
|
|
|
namespace XCEngine::UI::Editor::Host {
|
|
|
|
|
|
|
|
|
|
bool D3D12WindowInteropContext::Attach(
|
|
|
|
|
D3D12WindowRenderer& windowRenderer,
|
|
|
|
|
ID2D1Factory1& d2dFactory) {
|
|
|
|
|
if (m_windowRenderer != &windowRenderer) {
|
|
|
|
|
Detach();
|
|
|
|
|
m_windowRenderer = &windowRenderer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_d2dFactory = &d2dFactory;
|
|
|
|
|
if (!EnsureInterop()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HasBackBufferTargets()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RebuildBackBufferTargets();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void D3D12WindowInteropContext::Detach() {
|
|
|
|
|
ReleaseInteropState();
|
|
|
|
|
m_windowRenderer = nullptr;
|
|
|
|
|
m_d2dFactory = nullptr;
|
|
|
|
|
m_lastError.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12WindowRenderer* D3D12WindowInteropContext::GetWindowRenderer() const {
|
|
|
|
|
return m_windowRenderer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID3D11On12Device* D3D12WindowInteropContext::GetD3D11On12Device() const {
|
|
|
|
|
return m_d3d11On12Device.Get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID3D11DeviceContext* D3D12WindowInteropContext::GetD3D11DeviceContext() const {
|
|
|
|
|
return m_d3d11DeviceContext.Get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID2D1DeviceContext* D3D12WindowInteropContext::GetD2DDeviceContext() const {
|
|
|
|
|
return m_d2dDeviceContext.Get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID2D1SolidColorBrush* D3D12WindowInteropContext::GetInteropBrush() const {
|
|
|
|
|
return m_interopBrush.Get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string& D3D12WindowInteropContext::GetLastError() const {
|
|
|
|
|
return m_lastError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace XCEngine::UI::Editor::Host
|