| /* |
| * Copyright 2023 Rive |
| */ |
| |
| #include "gm.hpp" |
| #include "gmutils.hpp" |
| #include "common/testing_window.hpp" |
| #include "rive/renderer/render_context.hpp" |
| |
| using namespace rivegm; |
| using namespace rive; |
| |
| // Ensures the PLS render target does not get cleared when using |
| // LoadAction::preserveRenderTarget. |
| class PreserveRenderTargetBase : public GM |
| { |
| protected: |
| PreserveRenderTargetBase(const char* name, |
| bool empty, |
| BlendMode blendMode) : |
| GM(64, 64, name), m_empty(empty), m_blendMode(blendMode) |
| {} |
| |
| void run(std::vector<uint8_t>* pixels) override |
| { |
| Paint yellow; |
| yellow->color(0xffffff00); |
| |
| // Set the render target to a cyan background with a yellow circle. |
| auto renderer = |
| TestingWindow::Get()->beginFrame({.clearColor = 0xff008080}); |
| renderer->drawPath(PathBuilder::Circle(32, 32, 20), yellow); |
| |
| // Don't clear to red! |
| if (auto* renderContext = TestingWindow::Get()->renderContext()) |
| { |
| rive::gpu::RenderContext::FrameDescriptor frameDescriptor = |
| renderContext->frameDescriptor(); |
| frameDescriptor.loadAction = |
| rive::gpu::LoadAction::preserveRenderTarget; |
| frameDescriptor.clearColor = 0xffff0000; |
| |
| TestingWindow::Get()->flushPLSContext(); |
| renderContext->beginFrame(std::move(frameDescriptor)); |
| } |
| else |
| { |
| TestingWindow::Get()->endFrame(); |
| renderer = TestingWindow::Get()->beginFrame({ |
| .clearColor = 0xffff0000, |
| .doClear = false, |
| }); |
| } |
| |
| if (!m_empty) |
| { |
| // Add a black circle on top of the preserved yellow one. |
| Paint black; |
| black->color(0xff000000); |
| black->blendMode(m_blendMode); |
| renderer->drawPath(PathBuilder::Circle(32, 32, 8), black); |
| } |
| |
| TestingWindow::Get()->endFrame(pixels); |
| } |
| |
| void onDraw(rive::Renderer*) override { RIVE_UNREACHABLE(); } |
| |
| const bool m_empty; |
| const BlendMode m_blendMode; |
| }; |
| |
| class PreserveRenderTargetGM : public PreserveRenderTargetBase |
| { |
| public: |
| PreserveRenderTargetGM() : |
| PreserveRenderTargetBase("preserverendertarget", |
| false, |
| BlendMode::srcOver) |
| {} |
| }; |
| GMREGISTER(return new PreserveRenderTargetGM) |
| |
| class PreserveRenderTargetBlendModeGM : public PreserveRenderTargetBase |
| { |
| public: |
| PreserveRenderTargetBlendModeGM() : |
| PreserveRenderTargetBase("preserverendertarget_blendmode", |
| false, |
| BlendMode::darken) |
| {} |
| }; |
| GMREGISTER(return new PreserveRenderTargetBlendModeGM) |
| |
| class PreserveRenderTargetEmptyGM : public PreserveRenderTargetBase |
| { |
| public: |
| PreserveRenderTargetEmptyGM() : |
| PreserveRenderTargetBase("preserverendertarget_empty", |
| true, |
| BlendMode::srcOver) |
| {} |
| }; |
| GMREGISTER(return new PreserveRenderTargetEmptyGM) |