diff --git a/src/kiwano/core/BinaryData.h b/src/kiwano/core/BinaryData.h index 98990856..b9f98c9b 100644 --- a/src/kiwano/core/BinaryData.h +++ b/src/kiwano/core/BinaryData.h @@ -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; diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.cpp b/src/kiwano/render/DirectX/D2DDeviceResources.cpp index e061349c..6cd2e507 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.cpp +++ b/src/kiwano/render/DirectX/D2DDeviceResources.cpp @@ -63,6 +63,10 @@ public: HRESULT CreateBitmapDecoderFromResource(_Out_ ComPtr& decoder, _In_ void* data, DWORD data_size) override; + HRESULT CreateBitmapSourceFromMemory(_Out_ ComPtr& source, _In_ UINT width, _In_ UINT height, + _In_ UINT cbStride, _In_ UINT cbBufferSize, _In_ BYTE* buffer, + _In_ REFWICPixelFormatGUID cPixelFormat); + HRESULT CreateTextFormat(_Out_ ComPtr& text_format, _In_ LPCWSTR family, _In_ ComPtr 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& 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 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& converter, _In_opt_ ComPtr source, _In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.h b/src/kiwano/render/DirectX/D2DDeviceResources.h index 985227fe..7c00daec 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.h +++ b/src/kiwano/render/DirectX/D2DDeviceResources.h @@ -35,12 +35,16 @@ KGE_API ID2DDeviceResources : public IUnknown public: virtual HRESULT Initialize(_In_ ComPtr dxgi_device, _In_ ComPtr dxgi_swap_chain) = 0; + virtual HRESULT CreateBitmapSourceFromMemory(_Out_ ComPtr & 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 & converter, _In_opt_ ComPtr source, _In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, _In_opt_ ComPtr palette, double alpha_threshold_percent, WICBitmapPaletteType palette_translate) = 0; - virtual HRESULT CreateBitmapFromConverter(_Out_ ComPtr & bitmap, + virtual HRESULT CreateBitmapFromConverter(_Out_ ComPtr & bitmap, _In_opt_ const D2D1_BITMAP_PROPERTIES* properties, _In_ ComPtr converter) = 0; @@ -56,11 +60,11 @@ public: virtual HRESULT CreateTextLayout(_Out_ ComPtr & text_layout, _In_ LPCWSTR text, UINT32 length, _In_ ComPtr text_format) = 0; - virtual HRESULT CreateFontCollectionFromFiles(_Out_ ComPtr & font_collection, + virtual HRESULT CreateFontCollectionFromFiles(_Out_ ComPtr & font_collection, const Vector& file_paths) = 0; virtual HRESULT CreateFontCollectionFromBinaryData(_Out_ ComPtr & font_collection, - const Vector& data) = 0; + const Vector& data) = 0; virtual HRESULT GetFontFamilyNames(_Out_ Vector & family_names, _In_ ComPtr font_collection) = 0; @@ -124,9 +128,8 @@ protected: ComPtr dwrite_factory_; }; - extern ComPtr GetD2DDeviceResources(); -} -} +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp index 48484b71..c5975a9d 100644 --- a/src/kiwano/render/DirectX/RendererImpl.cpp +++ b/src/kiwano/render/DirectX/RendererImpl.cpp @@ -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 source; + hr = d2d_res_->CreateBitmapSourceFromMemory(source, UINT(size.x), UINT(size.y), UINT(size.x) * stride, + UINT(data.size), reinterpret_cast(data.buffer), + wicFormat); + + if (SUCCEEDED(hr)) + { + ComPtr converter; + hr = d2d_res_->CreateBitmapConverter(converter, source, GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, nullptr, 0.f, + WICBitmapPaletteTypeMedianCut); + + if (SUCCEEDED(hr)) + { + ComPtr 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; diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h index a534605c..b57bd811 100644 --- a/src/kiwano/render/DirectX/RendererImpl.h +++ b/src/kiwano/render/DirectX/RendererImpl.h @@ -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; diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h index 5be17bcd..25d87311 100644 --- a/src/kiwano/render/Renderer.h +++ b/src/kiwano/render/Renderer.h @@ -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图像 diff --git a/src/kiwano/render/Texture.cpp b/src/kiwano/render/Texture.cpp index 1c10be9c..5d70714e 100644 --- a/src/kiwano/render/Texture.cpp +++ b/src/kiwano/render/Texture.cpp @@ -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(); + if (ptr) + { + Renderer::GetInstance().CreateTexture(*ptr, size, data, format); + } + return ptr; +} + Texture::Texture(const String& file_path) : Texture() { diff --git a/src/kiwano/render/Texture.h b/src/kiwano/render/Texture.h index e837e26c..4c18a34c 100644 --- a/src/kiwano/render/Texture.h +++ b/src/kiwano/render/Texture.h @@ -47,6 +47,17 @@ enum class InterpolationMode /// @brief 像素大小 typedef math::Vec2T 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