blob: 8d0d9f0a8644a73ace523effa468f5d98cf19898 [file]
/*
* Copyright 2025 Rive
*/
#pragma once
#include "rive/refcnt.hpp"
#include "rive/renderer/render_target.hpp"
#include "rive/renderer/rive_render_image.hpp"
namespace rive::gpu
{
// The image half of a RenderCanvas. A recording refers to a canvas by this
// object, so the identity is fixed at creation while the texture waits for the
// device that ends up replaying.
class RenderCanvasImage : public RiveRenderImage
{
public:
RenderCanvasImage(uint32_t width, uint32_t height) :
RiveRenderImage(width, height)
{}
using RiveRenderImage::resetTexture;
};
// A GPU texture that can be used as both a render target (for rendering into)
// and a render image (for compositing into Rive draws). Enables off-screen
// rendering for 3D content (Ore), cached 2D content, or any render-to-texture
// use case.
//
// Construction allocates nothing. RenderContextImpl::ensureCanvasBacking
// installs the pixels, which is what lets a recording hand out a canvas with
// no device in reach and leave the allocation to whoever replays it.
class RenderCanvas : public RefCnt<RenderCanvas>
{
public:
RenderCanvas(uint32_t width, uint32_t height) :
RenderCanvas(make_rcp<RenderCanvasImage>(width, height), width, height)
{}
// A deferred canvas hands its backing to the replay thread on the way out.
virtual ~RenderCanvas() = default;
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
bool isBacked() const { return m_renderTarget != nullptr; }
void setBacking(rcp<Texture> texture, rcp<RenderTarget> renderTarget)
{
assert(!isBacked());
m_renderImage->resetTexture(std::move(texture));
m_renderTarget = std::move(renderTarget);
}
// Use as a RenderImage for compositing into Rive draws.
RiveRenderImage* renderImage() { return m_renderImage.get(); }
// Use as a RenderTarget for rendering into this texture.
RenderTarget* renderTarget() { return m_renderTarget.get(); }
protected:
RenderCanvas(rcp<RenderCanvasImage> image,
uint32_t width,
uint32_t height) :
m_renderImage(std::move(image)), m_width(width), m_height(height)
{}
rcp<RenderTarget> releaseRenderTarget()
{
return std::move(m_renderTarget);
}
private:
rcp<RenderCanvasImage> m_renderImage;
rcp<RenderTarget> m_renderTarget;
uint32_t m_width;
uint32_t m_height;
};
} // namespace rive::gpu