blob: f11a138e7c5ddfa175850f4e45f33c38211668fa [file] [log] [blame] [edit]
/*
* 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(
const TestingWindow::BackendParams& backendParams)
{
class RiveRenderer : public TestingGLRenderer
{
public:
RiveRenderer(const TestingWindow::BackendParams& backendParams) :
m_backendParams(backendParams)
{
m_contextOptions.shaderCompilationMode =
rive::gpu::ShaderCompilationMode::alwaysSynchronous;
if (m_backendParams.msaa)
{
m_contextOptions.disablePixelLocalStorage = true;
}
if (m_backendParams.atomic)
{
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_backendParams.msaa || options.forceMSAA) ? 4u : 0u,
.disableRasterOrdering =
m_backendParams.atomic || options.disableRasterOrdering,
.wireframe = options.wireframe,
.clockwiseFillOverride =
m_backendParams.clockwise || options.clockwiseFillOverride,
.synthesizedFailureType = options.synthesizedFailureType,
};
m_renderContext->beginFrame(frameDescriptor);
}
void flush(int dpiScale) override { flushPLSContext(nullptr); }
rive::gpu::RenderContext* renderContext() const override
{
return m_renderContext.get();
}
rive::gpu::RenderTarget* renderTarget() const override
{
return m_renderTarget.get();
}
void flushPLSContext(
rive::gpu::RenderTarget* offscreenRenderTarget) override
{
m_renderContext->flush({
.renderTarget = offscreenRenderTarget != nullptr
? offscreenRenderTarget
: m_renderTarget.get(),
});
}
private:
const TestingWindow::BackendParams m_backendParams;
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>(backendParams);
}
#endif