101 lines
3.6 KiB
C++
101 lines
3.6 KiB
C++
#include "D3D12WindowInteropInternal.h"
|
|
|
|
#include <XCEngine/RHI/D3D12/D3D12Texture.h>
|
|
#include <XCEngine/RHI/RHITexture.h>
|
|
|
|
namespace XCEngine::UI::Editor::Host {
|
|
|
|
using namespace D3D12WindowInteropInternal;
|
|
|
|
bool D3D12WindowInteropContext::PrepareSourceTextures(
|
|
const ::XCEngine::UI::UIDrawData& drawData) {
|
|
ClearSourceTextures();
|
|
if (m_windowRenderer == nullptr || m_d3d11On12Device == nullptr || m_d2dDeviceContext == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
std::vector<::XCEngine::UI::UITextureHandle> textureHandles = {};
|
|
CollectInteropTextureHandles(drawData, textureHandles);
|
|
m_activeSourceTextures.reserve(textureHandles.size());
|
|
|
|
for (const ::XCEngine::UI::UITextureHandle& textureHandle : textureHandles) {
|
|
auto* texture =
|
|
reinterpret_cast<::XCEngine::RHI::RHITexture*>(textureHandle.resourceHandle);
|
|
auto* nativeTexture = dynamic_cast<::XCEngine::RHI::D3D12Texture*>(texture);
|
|
if (nativeTexture == nullptr || nativeTexture->GetResource() == nullptr) {
|
|
m_lastError = "Failed to resolve a D3D12 source texture for UI composition.";
|
|
ClearSourceTextures();
|
|
return false;
|
|
}
|
|
|
|
D3D11_RESOURCE_FLAGS resourceFlags = {};
|
|
resourceFlags.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
|
|
SourceTextureResource resource = {};
|
|
resource.key = textureHandle.resourceHandle;
|
|
HRESULT hr = m_d3d11On12Device->CreateWrappedResource(
|
|
nativeTexture->GetResource(),
|
|
&resourceFlags,
|
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
|
IID_PPV_ARGS(resource.wrappedResource.ReleaseAndGetAddressOf()));
|
|
if (FAILED(hr) || resource.wrappedResource == nullptr) {
|
|
m_lastError = HrToInteropString("ID3D11On12Device::CreateWrappedResource(source)", hr);
|
|
ClearSourceTextures();
|
|
return false;
|
|
}
|
|
|
|
Microsoft::WRL::ComPtr<IDXGISurface> dxgiSurface = {};
|
|
hr = resource.wrappedResource.As(&dxgiSurface);
|
|
if (FAILED(hr) || dxgiSurface == nullptr) {
|
|
m_lastError = HrToInteropString("ID3D11Resource::QueryInterface(IDXGISurface)", hr);
|
|
ClearSourceTextures();
|
|
return false;
|
|
}
|
|
|
|
const D2D1_BITMAP_PROPERTIES1 bitmapProperties =
|
|
BuildD2DBitmapProperties(
|
|
nativeTexture->GetDesc().Format,
|
|
D2D1_BITMAP_OPTIONS_NONE);
|
|
hr = m_d2dDeviceContext->CreateBitmapFromDxgiSurface(
|
|
dxgiSurface.Get(),
|
|
&bitmapProperties,
|
|
resource.bitmap.ReleaseAndGetAddressOf());
|
|
if (FAILED(hr) || resource.bitmap == nullptr) {
|
|
m_lastError = HrToInteropString("ID2D1DeviceContext::CreateBitmapFromDxgiSurface(source)", hr);
|
|
ClearSourceTextures();
|
|
return false;
|
|
}
|
|
|
|
m_activeBitmaps.emplace(resource.key, resource.bitmap);
|
|
m_activeSourceTextures.push_back(std::move(resource));
|
|
}
|
|
|
|
m_lastError.clear();
|
|
return true;
|
|
}
|
|
|
|
void D3D12WindowInteropContext::ClearSourceTextures() {
|
|
m_activeBitmaps.clear();
|
|
m_activeSourceTextures.clear();
|
|
}
|
|
|
|
bool D3D12WindowInteropContext::ResolveInteropBitmap(
|
|
const ::XCEngine::UI::UITextureHandle& texture,
|
|
Microsoft::WRL::ComPtr<ID2D1Bitmap>& outBitmap) const {
|
|
outBitmap.Reset();
|
|
if (!IsInteropTextureHandle(texture)) {
|
|
return false;
|
|
}
|
|
|
|
const auto found = m_activeBitmaps.find(texture.resourceHandle);
|
|
if (found == m_activeBitmaps.end() || found->second == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
outBitmap = found->second;
|
|
return true;
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::Host
|