2026-04-15 22:47:42 +08:00
|
|
|
#include "NativeRendererInternal.h"
|
2026-04-15 08:24:06 +08:00
|
|
|
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
namespace XCEngine::UI::Editor::Host {
|
|
|
|
|
|
2026-04-15 22:47:42 +08:00
|
|
|
using namespace NativeRendererInternal;
|
2026-04-15 08:24:06 +08:00
|
|
|
|
|
|
|
|
bool NativeRenderer::LoadTextureFromFile(
|
|
|
|
|
const std::filesystem::path& path,
|
|
|
|
|
::XCEngine::UI::UITextureHandle& outTexture,
|
|
|
|
|
std::string& outError) {
|
|
|
|
|
outError.clear();
|
|
|
|
|
ReleaseTexture(outTexture);
|
|
|
|
|
|
|
|
|
|
auto texture = std::make_unique<NativeTextureResource>();
|
|
|
|
|
if (!DecodeTextureFile(path, *texture, outError)) {
|
|
|
|
|
outTexture = {};
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outTexture.nativeHandle = reinterpret_cast<std::uintptr_t>(texture.get());
|
|
|
|
|
outTexture.width = texture->width;
|
|
|
|
|
outTexture.height = texture->height;
|
|
|
|
|
outTexture.kind = ::XCEngine::UI::UITextureHandleKind::DescriptorHandle;
|
|
|
|
|
m_liveTextures.insert(texture.get());
|
|
|
|
|
texture.release();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NativeRenderer::LoadTextureFromMemory(
|
|
|
|
|
const std::uint8_t* data,
|
|
|
|
|
std::size_t size,
|
|
|
|
|
::XCEngine::UI::UITextureHandle& outTexture,
|
|
|
|
|
std::string& outError) {
|
|
|
|
|
outError.clear();
|
|
|
|
|
ReleaseTexture(outTexture);
|
|
|
|
|
|
|
|
|
|
auto texture = std::make_unique<NativeTextureResource>();
|
|
|
|
|
if (!DecodeTextureMemory(data, size, *texture, outError)) {
|
|
|
|
|
outTexture = {};
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outTexture.nativeHandle = reinterpret_cast<std::uintptr_t>(texture.get());
|
|
|
|
|
outTexture.width = texture->width;
|
|
|
|
|
outTexture.height = texture->height;
|
|
|
|
|
outTexture.kind = ::XCEngine::UI::UITextureHandleKind::DescriptorHandle;
|
|
|
|
|
m_liveTextures.insert(texture.get());
|
|
|
|
|
texture.release();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NativeRenderer::ReleaseTexture(::XCEngine::UI::UITextureHandle& texture) {
|
|
|
|
|
if (!texture.IsValid()) {
|
|
|
|
|
texture = {};
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto* resource = reinterpret_cast<NativeTextureResource*>(texture.nativeHandle);
|
|
|
|
|
if (resource != nullptr) {
|
|
|
|
|
const auto found = m_liveTextures.find(resource);
|
|
|
|
|
if (found != m_liveTextures.end()) {
|
|
|
|
|
m_liveTextures.erase(found);
|
|
|
|
|
delete resource;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
texture = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NativeRenderer::ResolveTextureBitmap(
|
|
|
|
|
ID2D1RenderTarget& renderTarget,
|
|
|
|
|
NativeTextureResource& texture,
|
|
|
|
|
Microsoft::WRL::ComPtr<ID2D1Bitmap>& outBitmap) {
|
|
|
|
|
outBitmap.Reset();
|
|
|
|
|
if (texture.width == 0u || texture.height == 0u || texture.pixels.empty()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (texture.cachedBitmap && texture.cachedTarget == &renderTarget) {
|
|
|
|
|
outBitmap = texture.cachedBitmap;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Microsoft::WRL::ComPtr<ID2D1Bitmap> bitmap;
|
|
|
|
|
const D2D1_BITMAP_PROPERTIES properties = D2D1::BitmapProperties(
|
|
|
|
|
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
|
|
|
|
|
kBaseDpi,
|
|
|
|
|
kBaseDpi);
|
|
|
|
|
const HRESULT hr = renderTarget.CreateBitmap(
|
|
|
|
|
D2D1::SizeU(texture.width, texture.height),
|
|
|
|
|
texture.pixels.data(),
|
|
|
|
|
texture.width * 4u,
|
|
|
|
|
&properties,
|
|
|
|
|
bitmap.ReleaseAndGetAddressOf());
|
|
|
|
|
if (FAILED(hr) || !bitmap) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (&renderTarget == m_renderTarget.Get()) {
|
|
|
|
|
texture.cachedBitmap = bitmap;
|
|
|
|
|
texture.cachedTarget = &renderTarget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outBitmap = std::move(bitmap);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NativeRenderer::ResolveInteropBitmap(
|
|
|
|
|
const ::XCEngine::UI::UITextureHandle& texture,
|
|
|
|
|
Microsoft::WRL::ComPtr<ID2D1Bitmap>& outBitmap) const {
|
|
|
|
|
return m_windowInterop.ResolveInteropBitmap(texture, outBitmap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace XCEngine::UI::Editor::Host
|