blob: f97277ff1fbc562c1cd1e8ef056546f799cc7cad [file] [log] [blame]
/*
* Copyright 2022 Rive
*/
#include "testing_gl_renderer.hpp"
#ifndef RIVE_TOOLS_NO_GL
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/gl/render_context_gl_impl.hpp"
#include "rive/renderer/gl/render_target_gl.hpp"
TestingGLRenderer::~TestingGLRenderer() {}
std::unique_ptr<TestingGLRenderer> TestingGLRenderer::Make(
TestingWindow::RendererFlags rendererFlags)
{
return TestingGLRenderer::MakePLS(rendererFlags);
}
std::unique_ptr<TestingGLRenderer> TestingGLRenderer::MakePLS(
TestingWindow::RendererFlags rendererFlags)
{
class RiveRenderer : public TestingGLRenderer
{
public:
RiveRenderer(TestingWindow::RendererFlags rendererFlags) :
m_rendererFlags(rendererFlags)
{
if (m_rendererFlags & TestingWindow::RendererFlags::useMSAA)
{
m_contextOptions.disablePixelLocalStorage = true;
}
if (m_rendererFlags &
TestingWindow::RendererFlags::disableRasterOrdering)
{
m_contextOptions.disableFragmentShaderInterlock = true;
}
}
void init(void* getGLProcAddress) override
{
m_renderContext =
rive::gpu::RenderContextGLImpl::MakeContext(m_contextOptions);
}
rive::Factory* factory() override { return m_renderContext.get(); }
std::unique_ptr<rive::Renderer> reset(int width,
int height,
uint32_t targetTextureID) override
{
if (targetTextureID == 0)
{
// Render directly to the default framebuffer.
GLint sampleCount;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glGetIntegerv(GL_SAMPLES, &sampleCount);
m_renderTarget =
rive::make_rcp<rive::gpu::FramebufferRenderTargetGL>(
width,
height,
0,
sampleCount);
}
else
{
// Render to targetTextureID.
auto renderTarget =
rive::make_rcp<rive::gpu::TextureRenderTargetGL>(width,
height);
renderTarget->setTargetTexture(targetTextureID);
m_renderTarget = std::move(renderTarget);
}
return std::make_unique<rive::RiveRenderer>(m_renderContext.get());
}
void beginFrame(const TestingWindow::FrameOptions& options) override
{
// For testing, reset GPU resources to their initial sizes every
// frame. This will stress intermediate flushes more, as well as
// creating more consistency when rendering in multiple threads and
// a nondeterministic order.
m_renderContext->releaseResources();
rive::gpu::RenderContext::FrameDescriptor frameDescriptor = {
.renderTargetWidth = m_renderTarget->width(),
.renderTargetHeight = m_renderTarget->height(),
.loadAction = options.doClear
? rive::gpu::LoadAction::clear
: rive::gpu::LoadAction::preserveRenderTarget,
.clearColor = options.clearColor,
.msaaSampleCount =
(m_rendererFlags & TestingWindow::RendererFlags::useMSAA)
? 4
: 0,
.disableRasterOrdering =
(m_rendererFlags &
TestingWindow::RendererFlags::disableRasterOrdering),
.wireframe = options.wireframe,
.clockwiseFillOverride =
(m_rendererFlags &
TestingWindow::RendererFlags::clockwiseFillOverride) ||
options.clockwiseFillOverride};
m_renderContext->beginFrame(frameDescriptor);
}
void flush(int dpiScale) override { flushPLSContext(); }
rive::gpu::RenderContext* renderContext() const override
{
return m_renderContext.get();
}
rive::gpu::RenderTarget* renderTarget() const override
{
return m_renderTarget.get();
}
void flushPLSContext() override
{
m_renderContext->flush({.renderTarget = m_renderTarget.get()});
}
private:
const TestingWindow::RendererFlags m_rendererFlags;
rive::gpu::RenderContextGLImpl::ContextOptions m_contextOptions;
std::unique_ptr<rive::gpu::RenderContext> m_renderContext;
rive::rcp<rive::gpu::RenderTargetGL> m_renderTarget;
};
return std::make_unique<RiveRenderer>(rendererFlags);
}
#endif