feat: support create texture from memory

This commit is contained in:
Nomango 2023-09-12 01:17:22 +08:00
parent 2fa346783a
commit 4b9f4b11f9
8 changed files with 137 additions and 6 deletions

View File

@ -33,6 +33,8 @@ struct KGE_API BinaryData
BinaryData();
BinaryData(void* buffer, uint32_t size);
bool IsValid() const;
};
@ -42,6 +44,12 @@ inline BinaryData::BinaryData()
{
}
inline BinaryData::BinaryData(void* buffer, uint32_t size)
: buffer(buffer)
, size(size)
{
}
inline bool BinaryData::IsValid() const
{
return buffer != nullptr && size != 0;

View File

@ -63,6 +63,10 @@ public:
HRESULT CreateBitmapDecoderFromResource(_Out_ ComPtr<IWICBitmapDecoder>& decoder, _In_ void* data,
DWORD data_size) override;
HRESULT CreateBitmapSourceFromMemory(_Out_ ComPtr<IWICBitmapSource>& source, _In_ UINT width, _In_ UINT height,
_In_ UINT cbStride, _In_ UINT cbBufferSize, _In_ BYTE* buffer,
_In_ REFWICPixelFormatGUID cPixelFormat);
HRESULT CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat>& text_format, _In_ LPCWSTR family,
_In_ ComPtr<IDWriteFontCollection> collection, DWRITE_FONT_WEIGHT weight,
DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) override;
@ -401,6 +405,23 @@ void D2DDeviceResources::ResetTextRenderingParams(HMONITOR monitor)
}
}
HRESULT D2DDeviceResources::CreateBitmapSourceFromMemory(_Out_ ComPtr<IWICBitmapSource>& source, _In_ UINT width,
_In_ UINT height, _In_ UINT cbStride, _In_ UINT cbBufferSize,
_In_ BYTE* buffer, _In_ REFWICPixelFormatGUID cPixelFormat)
{
if (!imaging_factory_)
return E_UNEXPECTED;
ComPtr<IWICBitmap> output;
HRESULT hr = imaging_factory_->CreateBitmapFromMemory(width, height, cPixelFormat, cbStride, cbBufferSize, buffer, &output);
if (SUCCEEDED(hr))
{
source = output;
}
return hr;
}
HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter>& converter,
_In_opt_ ComPtr<IWICBitmapSource> source,
_In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither,

View File

@ -35,12 +35,16 @@ KGE_API ID2DDeviceResources : public IUnknown
public:
virtual HRESULT Initialize(_In_ ComPtr<IDXGIDevice> dxgi_device, _In_ ComPtr<IDXGISwapChain> dxgi_swap_chain) = 0;
virtual HRESULT CreateBitmapSourceFromMemory(_Out_ ComPtr<IWICBitmapSource> & source, _In_ UINT width,
_In_ UINT height, _In_ UINT cbStride, _In_ UINT cbBufferSize,
_In_ BYTE * buffer, _In_ REFWICPixelFormatGUID cPixelFormat) = 0;
virtual HRESULT CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter> & converter,
_In_opt_ ComPtr<IWICBitmapSource> source, _In_ REFWICPixelFormatGUID format,
WICBitmapDitherType dither, _In_opt_ ComPtr<IWICPalette> palette,
double alpha_threshold_percent, WICBitmapPaletteType palette_translate) = 0;
virtual HRESULT CreateBitmapFromConverter(_Out_ ComPtr<ID2D1Bitmap> & bitmap,
virtual HRESULT CreateBitmapFromConverter(_Out_ ComPtr<ID2D1Bitmap> & bitmap,
_In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
_In_ ComPtr<IWICFormatConverter> converter) = 0;
@ -56,11 +60,11 @@ public:
virtual HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ LPCWSTR text, UINT32 length,
_In_ ComPtr<IDWriteTextFormat> text_format) = 0;
virtual HRESULT CreateFontCollectionFromFiles(_Out_ ComPtr<IDWriteFontCollection> & font_collection,
virtual HRESULT CreateFontCollectionFromFiles(_Out_ ComPtr<IDWriteFontCollection> & font_collection,
const Vector<String>& file_paths) = 0;
virtual HRESULT CreateFontCollectionFromBinaryData(_Out_ ComPtr<IDWriteFontCollection> & font_collection,
const Vector<BinaryData>& data) = 0;
const Vector<BinaryData>& data) = 0;
virtual HRESULT GetFontFamilyNames(_Out_ Vector<String> & family_names,
_In_ ComPtr<IDWriteFontCollection> font_collection) = 0;
@ -124,9 +128,8 @@ protected:
ComPtr<IDWriteFactory> dwrite_factory_;
};
extern ComPtr<ID2DDeviceResources> GetD2DDeviceResources();
}
}
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -37,6 +37,21 @@ namespace kiwano
using namespace kiwano::graphics::directx;
inline const GUID& ConvertPixelFormat(PixelFormat format, UINT& stride)
{
switch (format)
{
case PixelFormat::Bpp32RGB:
stride = 3;
return GUID_WICPixelFormat32bppRGB;
case PixelFormat::Bpp32RGBA:
stride = 4;
return GUID_WICPixelFormat32bppRGB;
default:
return GUID_WICPixelFormatDontCare;
}
}
Renderer& Renderer::GetInstance()
{
return RendererImpl::GetInstance();
@ -300,6 +315,55 @@ void RendererImpl::CreateTexture(Texture& texture, const BinaryData& data)
KGE_SET_STATUS_IF_FAILED(hr, texture, "Load texture failed");
}
void RendererImpl::CreateTexture(Texture& texture, const PixelSize& size, const BinaryData& data, PixelFormat format)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
hr = data.IsValid() ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
UINT stride = 0;
const auto& wicFormat = ConvertPixelFormat(format, stride);
ComPtr<IWICBitmapSource> source;
hr = d2d_res_->CreateBitmapSourceFromMemory(source, UINT(size.x), UINT(size.y), UINT(size.x) * stride,
UINT(data.size), reinterpret_cast<BYTE*>(data.buffer),
wicFormat);
if (SUCCEEDED(hr))
{
ComPtr<IWICFormatConverter> converter;
hr = d2d_res_->CreateBitmapConverter(converter, source, GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone, nullptr, 0.f,
WICBitmapPaletteTypeMedianCut);
if (SUCCEEDED(hr))
{
ComPtr<ID2D1Bitmap> bitmap;
hr = d2d_res_->CreateBitmapFromConverter(bitmap, nullptr, converter);
if (SUCCEEDED(hr))
{
NativePtr::Set(texture, bitmap);
texture.SetSize({ bitmap->GetSize().width, bitmap->GetSize().height });
texture.SetSizeInPixels({ bitmap->GetPixelSize().width, bitmap->GetPixelSize().height });
}
}
}
}
}
KGE_SET_STATUS_IF_FAILED(hr, texture, "Load texture from memory failed");
}
void RendererImpl::CreateGifImage(GifImage& gif, const String& file_path)
{
HRESULT hr = S_OK;

View File

@ -36,6 +36,8 @@ public:
void CreateTexture(Texture& texture, const BinaryData& data) override;
void CreateTexture(Texture& texture, const PixelSize& size, const BinaryData& data, PixelFormat format);
void CreateGifImage(GifImage& gif, const String& file_path) override;
void CreateGifImage(GifImage& gif, const BinaryData& data) override;

View File

@ -91,6 +91,14 @@ public:
/// @param[in] data 图片二进制数据
virtual void CreateTexture(Texture& texture, const BinaryData& data) = 0;
/// \~chinese
/// @brief 从内存加载位图纹理资源
/// @param[out] texture 纹理
/// @param[in] size 位图大小
/// @param[in] data 位图二进制数据
/// @param[in] format 像素格式
virtual void CreateTexture(Texture& texture, const PixelSize& size, const BinaryData& data, PixelFormat format) = 0;
/// \~chinese
/// @brief 创建GIF图像内部资源
/// @param[out] gif GIF图像

View File

@ -62,6 +62,16 @@ TexturePtr Texture::Preload(const Resource& res)
return ptr;
}
TexturePtr Texture::Preload(const PixelSize& size, const BinaryData& data, PixelFormat format)
{
TexturePtr ptr = MakePtr<Texture>();
if (ptr)
{
Renderer::GetInstance().CreateTexture(*ptr, size, data, format);
}
return ptr;
}
Texture::Texture(const String& file_path)
: Texture()
{

View File

@ -47,6 +47,17 @@ enum class InterpolationMode
/// @brief 像素大小
typedef math::Vec2T<uint32_t> PixelSize;
/**
* \~chinese
* @brief
* @details
*/
enum class PixelFormat
{
Bpp32RGB,
Bpp32RGBA,
};
/**
* \~chinese
* @brief
@ -62,6 +73,10 @@ public:
/// @brief 预加载图片资源
static TexturePtr Preload(const Resource& res);
/// \~chinese
/// @brief 从内存加载位图纹理
static TexturePtr Preload(const PixelSize& size, const BinaryData& data, PixelFormat format);
Texture();
/// \~chinese