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();
BinaryData(void* buffer, uint32_t size);
bool IsValid() const; 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 inline bool BinaryData::IsValid() const
{ {
return buffer != nullptr && size != 0; return buffer != nullptr && size != 0;

View File

@ -63,6 +63,10 @@ public:
HRESULT CreateBitmapDecoderFromResource(_Out_ ComPtr<IWICBitmapDecoder>& decoder, _In_ void* data, HRESULT CreateBitmapDecoderFromResource(_Out_ ComPtr<IWICBitmapDecoder>& decoder, _In_ void* data,
DWORD data_size) override; 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, HRESULT CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat>& text_format, _In_ LPCWSTR family,
_In_ ComPtr<IDWriteFontCollection> collection, DWRITE_FONT_WEIGHT weight, _In_ ComPtr<IDWriteFontCollection> collection, DWRITE_FONT_WEIGHT weight,
DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) override; 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, HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter>& converter,
_In_opt_ ComPtr<IWICBitmapSource> source, _In_opt_ ComPtr<IWICBitmapSource> source,
_In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, _In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither,

View File

@ -35,12 +35,16 @@ KGE_API ID2DDeviceResources : public IUnknown
public: public:
virtual HRESULT Initialize(_In_ ComPtr<IDXGIDevice> dxgi_device, _In_ ComPtr<IDXGISwapChain> dxgi_swap_chain) = 0; 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, virtual HRESULT CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter> & converter,
_In_opt_ ComPtr<IWICBitmapSource> source, _In_ REFWICPixelFormatGUID format, _In_opt_ ComPtr<IWICBitmapSource> source, _In_ REFWICPixelFormatGUID format,
WICBitmapDitherType dither, _In_opt_ ComPtr<IWICPalette> palette, WICBitmapDitherType dither, _In_opt_ ComPtr<IWICPalette> palette,
double alpha_threshold_percent, WICBitmapPaletteType palette_translate) = 0; 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_opt_ const D2D1_BITMAP_PROPERTIES* properties,
_In_ ComPtr<IWICFormatConverter> converter) = 0; _In_ ComPtr<IWICFormatConverter> converter) = 0;
@ -56,11 +60,11 @@ public:
virtual HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ LPCWSTR text, UINT32 length, virtual HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ LPCWSTR text, UINT32 length,
_In_ ComPtr<IDWriteTextFormat> text_format) = 0; _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; const Vector<String>& file_paths) = 0;
virtual HRESULT CreateFontCollectionFromBinaryData(_Out_ ComPtr<IDWriteFontCollection> & font_collection, 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, virtual HRESULT GetFontFamilyNames(_Out_ Vector<String> & family_names,
_In_ ComPtr<IDWriteFontCollection> font_collection) = 0; _In_ ComPtr<IDWriteFontCollection> font_collection) = 0;
@ -124,9 +128,8 @@ protected:
ComPtr<IDWriteFactory> dwrite_factory_; ComPtr<IDWriteFactory> dwrite_factory_;
}; };
extern ComPtr<ID2DDeviceResources> GetD2DDeviceResources(); extern ComPtr<ID2DDeviceResources> GetD2DDeviceResources();
} } // namespace directx
} } // namespace graphics
} // namespace kiwano } // namespace kiwano

View File

@ -37,6 +37,21 @@ namespace kiwano
using namespace kiwano::graphics::directx; 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() Renderer& Renderer::GetInstance()
{ {
return RendererImpl::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"); 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) void RendererImpl::CreateGifImage(GifImage& gif, const String& file_path)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;

View File

@ -36,6 +36,8 @@ public:
void CreateTexture(Texture& texture, const BinaryData& data) override; 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 String& file_path) override;
void CreateGifImage(GifImage& gif, const BinaryData& data) override; void CreateGifImage(GifImage& gif, const BinaryData& data) override;

View File

@ -91,6 +91,14 @@ public:
/// @param[in] data 图片二进制数据 /// @param[in] data 图片二进制数据
virtual void CreateTexture(Texture& texture, const BinaryData& data) = 0; 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 /// \~chinese
/// @brief 创建GIF图像内部资源 /// @brief 创建GIF图像内部资源
/// @param[out] gif GIF图像 /// @param[out] gif GIF图像

View File

@ -62,6 +62,16 @@ TexturePtr Texture::Preload(const Resource& res)
return ptr; 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::Texture(const String& file_path)
: Texture() : Texture()
{ {

View File

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