blob: c9da1d0a978c82566797530fd2d6776cd7a68aa9 [file] [edit]
/*
* Copyright 2026 Rive
*/
#pragma once
#ifdef RIVE_CANVAS
#include "common/testing_window.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/render_context_impl.hpp"
#include "rive/renderer/render_canvas.hpp"
#include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/cmd/deferred_replayer.hpp"
#include <assert.h>
#include <memory>
// DeferredFrameSink over TestingWindow. Leaves the screen frame open for the
// caller to present via endFrame.
class TestingWindowFrameSink : public rive::cmd::DeferredFrameSink
{
public:
explicit TestingWindowFrameSink(
const TestingWindow::FrameOptions& options) :
m_rc(TestingWindow::Get()->renderContext()), m_options(options)
{}
rive::Factory* factory() override
{
return TestingWindow::Get()->factory();
}
rive::gpu::RenderContext* renderContext() override { return m_rc; }
// The tools render into the one TestingWindow, so there is a single
// target.
rive::Renderer* beginScreenFrame(uint64_t target) override
{
assert(target == 0);
m_screen = TestingWindow::Get()->beginFrame(m_options);
return m_screen.get();
}
void beginOreFrame() override { TestingWindow::Get()->beginOreFrame(); }
void endOreFrame() override { TestingWindow::Get()->endOreFrame(); }
rive::Renderer* beginCanvasContent(rive::gpu::RenderCanvas* canvas,
uint32_t clearColor) override
{
m_activeCanvas = canvas;
rive::gpu::RenderContext::FrameDescriptor d{};
d.renderTargetWidth = canvas->width();
d.renderTargetHeight = canvas->height();
d.loadAction = rive::gpu::LoadAction::clear;
d.clearColor = clearColor;
// Canvas content is the same frame as the screen content around it, so
// it has to be drawn under the same rules.
d.triangulationThresholds = m_options.triangulationThresholds;
m_rc->beginFrame(d);
m_canvasRenderer = std::make_unique<rive::RiveRenderer>(m_rc);
return m_canvasRenderer.get();
}
void endCanvasContent() override
{
if (m_activeCanvas == nullptr)
return;
void* cb = m_rc->impl()->makeCommandBuffer();
rive::gpu::RenderContext::FlushResources fr{};
fr.renderTarget = m_activeCanvas->renderTarget();
fr.externalCommandBuffer = cb;
m_rc->flush(fr);
m_rc->impl()->commitCommandBuffer(cb);
m_canvasRenderer.reset();
m_activeCanvas = nullptr;
}
private:
rive::gpu::RenderContext* m_rc;
TestingWindow::FrameOptions m_options;
std::unique_ptr<rive::Renderer> m_screen;
std::unique_ptr<rive::RiveRenderer> m_canvasRenderer;
rive::gpu::RenderCanvas* m_activeCanvas = nullptr;
};
#endif // RIVE_CANVAS