Outofbandcache Ok, got this passing testes, which I guess is a step in the right direction. Before changing unique pointers to rcp, we could only use an image once, as soon as we assigned a new image, the old image would get garbage collected. (this is the actual problem we are trying to solve) This "solves" the problem and allows us to add images to a cache in wasm, and then cycle through the cache, swapping out the render image to be displayed for a given fileAsset. We can replace images & fonts on the fly this way. Problems: 1. overwriting ref & unref in RenderImage, shows that is being reffed and un-reffed constantly (when viewing the attached file with the viewer). Is that expected? doing something similar for Font does not show up the same. I suspect this is related to how we use images when it comes to rendering, just figured i'd check 2. We dont seem to "leak" anything as detectable by our tests, which is good, but our wasm examples show that neither our fonts nor our render images get collected. presumably thats because we would need to manually tell wasm via js that we want to let go of an image? Also @csmartdalton @umberto-sonnino & @luigi-rosso it would be great to see what else is concerning. example file [just_a_box_with_a_tree.riv.zip](https://github.com/rive-app/rive/files/13042414/just_a_box_with_a_tree.riv.zip) Diffs= 1506b069c Outofbandcache (#6049) Co-authored-by: Maxwell Talbot <talbot.maxwell@gmail.com>
diff --git a/.rive_head b/.rive_head index 944467e..a791ccf 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -40f9d91ac8063448c357682ea97d5abbfe71ce1f +1506b069c01a049034052e5de1cbc6a9cf029c2e
diff --git a/cg_renderer/include/cg_factory.hpp b/cg_renderer/include/cg_factory.hpp index f9e21bd..ec4c34d 100644 --- a/cg_renderer/include/cg_factory.hpp +++ b/cg_renderer/include/cg_factory.hpp
@@ -37,7 +37,7 @@ std::unique_ptr<RenderPaint> makeRenderPaint() override; - std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override; + rcp<RenderImage> decodeImage(Span<const uint8_t>) override; }; } // namespace rive
diff --git a/cg_renderer/src/cg_factory.cpp b/cg_renderer/src/cg_factory.cpp index 81e4e2f..fc22574 100644 --- a/cg_renderer/src/cg_factory.cpp +++ b/cg_renderer/src/cg_factory.cpp
@@ -518,9 +518,9 @@ return std::make_unique<CGRenderPaint>(); } -std::unique_ptr<RenderImage> CGFactory::decodeImage(Span<const uint8_t> encoded) +rcp<RenderImage> CGFactory::decodeImage(Span<const uint8_t> encoded) { - return std::make_unique<CGRenderImage>(encoded); + return make_rcp<CGRenderImage>(encoded); } AutoCF<CGImageRef> CGRenderer::FlipCGImageInY(AutoCF<CGImageRef> image)
diff --git a/include/rive/assets/image_asset.hpp b/include/rive/assets/image_asset.hpp index 4791b94..93243fe 100644 --- a/include/rive/assets/image_asset.hpp +++ b/include/rive/assets/image_asset.hpp
@@ -10,7 +10,7 @@ class ImageAsset : public ImageAssetBase { private: - std::unique_ptr<RenderImage> m_RenderImage; + rcp<RenderImage> m_RenderImage; public: ImageAsset() {} @@ -22,7 +22,7 @@ bool decode(Span<const uint8_t>, Factory*) override; std::string fileExtension() const override; RenderImage* renderImage() const { return m_RenderImage.get(); } - void renderImage(std::unique_ptr<RenderImage> renderImage); + void renderImage(rcp<RenderImage> renderImage); }; } // namespace rive
diff --git a/include/rive/factory.hpp b/include/rive/factory.hpp index b5ac3be..7cf4649 100644 --- a/include/rive/factory.hpp +++ b/include/rive/factory.hpp
@@ -56,7 +56,7 @@ virtual std::unique_ptr<RenderPaint> makeRenderPaint() = 0; - virtual std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) = 0; + virtual rcp<RenderImage> decodeImage(Span<const uint8_t>) = 0; virtual rcp<Font> decodeFont(Span<const uint8_t>);
diff --git a/include/rive/refcnt.hpp b/include/rive/refcnt.hpp index 194bcc7..ed2b31b 100644 --- a/include/rive/refcnt.hpp +++ b/include/rive/refcnt.hpp
@@ -123,6 +123,7 @@ return *this; } + // move assignment operator rcp<T>& operator=(rcp<T>&& other) { this->reset(other.release());
diff --git a/include/rive/renderer.hpp b/include/rive/renderer.hpp index 7ca07dc..e595435 100644 --- a/include/rive/renderer.hpp +++ b/include/rive/renderer.hpp
@@ -104,7 +104,7 @@ virtual void invalidateStroke() = 0; }; -class RenderImage +class RenderImage : public RefCnt<RenderImage> { protected: int m_Width = 0;
diff --git a/include/utils/no_op_factory.hpp b/include/utils/no_op_factory.hpp index 1adcb3d..cb5f220 100644 --- a/include/utils/no_op_factory.hpp +++ b/include/utils/no_op_factory.hpp
@@ -35,7 +35,7 @@ std::unique_ptr<RenderPaint> makeRenderPaint() override; - std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override; + rcp<RenderImage> decodeImage(Span<const uint8_t>) override; }; } // namespace rive #endif
diff --git a/skia/renderer/include/skia_factory.hpp b/skia/renderer/include/skia_factory.hpp index c4e2dee..f8c9537 100644 --- a/skia/renderer/include/skia_factory.hpp +++ b/skia/renderer/include/skia_factory.hpp
@@ -37,7 +37,7 @@ std::unique_ptr<RenderPaint> makeRenderPaint() override; - std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override; + rcp<RenderImage> decodeImage(Span<const uint8_t>) override; // // New virtual for access the platform's codecs
diff --git a/skia/renderer/src/skia_factory.cpp b/skia/renderer/src/skia_factory.cpp index 96e70b5..d3ac0d3 100644 --- a/skia/renderer/src/skia_factory.cpp +++ b/skia/renderer/src/skia_factory.cpp
@@ -282,7 +282,7 @@ return std::make_unique<SkiaRenderPaint>(); } -std::unique_ptr<RenderImage> SkiaFactory::decodeImage(Span<const uint8_t> encoded) +rcp<RenderImage> SkiaFactory::decodeImage(Span<const uint8_t> encoded) { sk_sp<SkData> data = SkData::MakeWithCopy(encoded.data(), encoded.size()); auto image = SkImage::MakeFromEncoded(data); @@ -309,5 +309,5 @@ } } - return image ? std::make_unique<SkiaRenderImage>(std::move(image)) : nullptr; + return image ? make_rcp<SkiaRenderImage>(std::move(image)) : nullptr; }
diff --git a/src/assets/font_asset.cpp b/src/assets/font_asset.cpp index f40f32d..d87101d 100644 --- a/src/assets/font_asset.cpp +++ b/src/assets/font_asset.cpp
@@ -8,7 +8,7 @@ bool FontAsset::decode(Span<const uint8_t> data, Factory* factory) { - m_font = factory->decodeFont(data); + font(factory->decodeFont(data)); return m_font != nullptr; } std::string FontAsset::fileExtension() const { return "ttf"; }
diff --git a/src/assets/image_asset.cpp b/src/assets/image_asset.cpp index a513060..37f2ad2 100644 --- a/src/assets/image_asset.cpp +++ b/src/assets/image_asset.cpp
@@ -11,11 +11,11 @@ #ifdef TESTING decodedByteSize = data.size(); #endif - m_RenderImage = factory->decodeImage(data); + renderImage(factory->decodeImage(data)); return m_RenderImage != nullptr; } -void ImageAsset::renderImage(std::unique_ptr<RenderImage> renderImage) +void ImageAsset::renderImage(rcp<RenderImage> renderImage) { m_RenderImage = std::move(renderImage); }
diff --git a/src/shapes/image.cpp b/src/shapes/image.cpp index 6f40b36..df51c66 100644 --- a/src/shapes/image.cpp +++ b/src/shapes/image.cpp
@@ -11,10 +11,15 @@ void Image::draw(Renderer* renderer) { - rive::RenderImage* renderImage; + rive::ImageAsset* asset = this->imageAsset(); - if (asset == nullptr || renderOpacity() == 0.0f || - (renderImage = asset->renderImage()) == nullptr) + if (asset == nullptr || renderOpacity() == 0.0f) + { + return; + } + + rive::RenderImage* renderImage = asset->renderImage(); + if (renderImage == nullptr) { return; }
diff --git a/utils/no_op_factory.cpp b/utils/no_op_factory.cpp index d4739a3..16d20c5 100644 --- a/utils/no_op_factory.cpp +++ b/utils/no_op_factory.cpp
@@ -80,7 +80,4 @@ return rivestd::make_unique<NoOpRenderPaint>(); } -std::unique_ptr<RenderImage> NoOpFactory::decodeImage(Span<const uint8_t>) -{ - return std::unique_ptr<NoOpRenderImage>(); -} +rcp<RenderImage> NoOpFactory::decodeImage(Span<const uint8_t>) { return nullptr; }
diff --git a/viewer/include/viewer/tess/viewer_sokol_factory.hpp b/viewer/include/viewer/tess/viewer_sokol_factory.hpp index e48517a..59421a4 100644 --- a/viewer/include/viewer/tess/viewer_sokol_factory.hpp +++ b/viewer/include/viewer/tess/viewer_sokol_factory.hpp
@@ -6,6 +6,6 @@ class ViewerSokolFactory : public rive::SokolFactory { public: - std::unique_ptr<rive::RenderImage> decodeImage(rive::Span<const uint8_t>) override; + rive::rcp<rive::RenderImage> decodeImage(rive::Span<const uint8_t>) override; }; #endif \ No newline at end of file
diff --git a/viewer/src/sample_tools/sample_atlas_packer.cpp b/viewer/src/sample_tools/sample_atlas_packer.cpp index 9f74cbe..9b5d707 100644 --- a/viewer/src/sample_tools/sample_atlas_packer.cpp +++ b/viewer/src/sample_tools/sample_atlas_packer.cpp
@@ -27,7 +27,7 @@ class AtlasPackerFactory : public NoOpFactory { - std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t> bytes) override + rcp<RenderImage> decodeImage(Span<const uint8_t> bytes) override { auto bitmap = Bitmap::decode(bytes.data(), bytes.size()); if (bitmap) @@ -40,9 +40,7 @@ bitmap->pixelFormat(Bitmap::PixelFormat::RGBA); } - return rivestd::make_unique<AtlasRenderImage>(bitmap->bytes(), - bitmap->width(), - bitmap->height()); + return make_rcp<AtlasRenderImage>(bitmap->bytes(), bitmap->width(), bitmap->height()); } return nullptr; }
diff --git a/viewer/src/tess/viewer_sokol_factory.cpp b/viewer/src/tess/viewer_sokol_factory.cpp index 90a8feb..c8349bd 100644 --- a/viewer/src/tess/viewer_sokol_factory.cpp +++ b/viewer/src/tess/viewer_sokol_factory.cpp
@@ -4,7 +4,7 @@ #include "rive/tess/sokol/sokol_tess_renderer.hpp" #include "sokol_gfx.h" -std::unique_ptr<rive::RenderImage> ViewerSokolFactory::decodeImage(rive::Span<const uint8_t> bytes) +rive::rcp<rive::RenderImage> ViewerSokolFactory::decodeImage(rive::Span<const uint8_t> bytes) { auto bitmap = Bitmap::decode(bytes.data(), bytes.size()); if (bitmap) @@ -26,10 +26,10 @@ new rive::SokolRenderImageResource(bitmap->bytes(), bitmap->width(), bitmap->height())); static rive::Mat2D identity; - return rivestd::make_unique<rive::SokolRenderImage>(imageGpuResource, - bitmap->width(), - bitmap->height(), - identity); + return rive::make_rcp<rive::SokolRenderImage>(imageGpuResource, + bitmap->width(), + bitmap->height(), + identity); } return nullptr; }
diff --git a/viewer/src/viewer_content/image_content.cpp b/viewer/src/viewer_content/image_content.cpp index 6bdb84d..edca917 100644 --- a/viewer/src/viewer_content/image_content.cpp +++ b/viewer/src/viewer_content/image_content.cpp
@@ -8,10 +8,10 @@ class ImageContent : public ViewerContent { - std::unique_ptr<rive::RenderImage> m_image; + rive::rcp<rive::RenderImage> m_image; public: - ImageContent(std::unique_ptr<rive::RenderImage> image) : m_image(std::move(image)) {} + ImageContent(rive::rcp<rive::RenderImage> image) { m_image = std::move(image); } void handleDraw(rive::Renderer* renderer, double) override {