| /* |
| * Copyright 2022 Rive |
| */ |
| |
| #pragma once |
| |
| #include "rive/math/raw_path.hpp" |
| #include "rive/renderer.hpp" |
| #include "rive/renderer/gpu.hpp" |
| #include "rive/renderer/draw.hpp" |
| #include "rive/renderer/render_context.hpp" |
| #include <vector> |
| |
| namespace rive::gpu |
| { |
| class RenderContext; |
| } // namespace rive::gpu |
| |
| namespace rive |
| { |
| class GrInnerFanTriangulator; |
| class RiveRenderPath; |
| class RiveRenderPaint; |
| |
| // Renderer implementation for Rive's pixel local storage renderer. |
| class RiveRenderer : public Renderer |
| { |
| public: |
| RiveRenderer(gpu::RenderContext*); |
| ~RiveRenderer() override; |
| |
| void save() override; |
| void restore() override; |
| void transform(const Mat2D& matrix) override; |
| void drawPath(RenderPath*, RenderPaint*) override; |
| void clipPath(RenderPath*) override; |
| void drawImage(const RenderImage*, |
| ImageSampler, |
| BlendMode, |
| float opacity) override; |
| void drawImageMesh(const RenderImage*, |
| ImageSampler, |
| rcp<RenderBuffer> vertices_f32, |
| rcp<RenderBuffer> uvCoords_f32, |
| rcp<RenderBuffer> indices_u16, |
| uint32_t vertexCount, |
| uint32_t indexCount, |
| BlendMode, |
| float opacity) override; |
| |
| // Determines if a path is an axis-aligned rectangle that can be represented |
| // by rive::AABB. |
| static bool IsAABB(const RawPath&, AABB* result); |
| |
| #ifdef TESTING |
| bool hasClipRect() const |
| { |
| return m_stack.back().clipRectInverseMatrix != nullptr; |
| } |
| const AABB& getClipRect() const { return m_stack.back().clipRect; } |
| const Mat2D& getClipRectMatrix() const |
| { |
| return m_stack.back().clipRectMatrix; |
| } |
| #endif |
| |
| private: |
| void clipRectImpl(AABB, const RiveRenderPath* originalPath); |
| void clipPathImpl(const RiveRenderPath*); |
| |
| // Clips and pushes the given draw to m_context. If the clipped draw is too |
| // complex to be supported by the GPU buffers, even after a logical flush, |
| // then nothing is drawn. |
| void clipAndPushDraw(gpu::DrawUniquePtr); |
| |
| // Pushes any necessary clip updates to m_internalDrawBatch and sets the |
| // Draw's clipID and clipRectInverseMatrix, if any. Returns failure if the |
| // operation failed, at which point the caller should issue a logical flush |
| // and try again. |
| enum class ApplyClipResult |
| { |
| success, |
| failure, |
| clipEmpty, |
| }; |
| [[nodiscard]] ApplyClipResult applyClip(gpu::Draw*); |
| |
| struct RenderState |
| { |
| Mat2D matrix; |
| size_t clipStackHeight = 0; |
| AABB clipRect; |
| Mat2D clipRectMatrix; |
| const gpu::ClipRectInverseMatrix* clipRectInverseMatrix = nullptr; |
| bool clipIsEmpty = false; |
| }; |
| std::vector<RenderState> m_stack{1}; |
| |
| struct ClipElement |
| { |
| ClipElement() = default; |
| ClipElement(const Mat2D&, const RiveRenderPath*, FillRule); |
| ~ClipElement(); |
| |
| void reset(const Mat2D&, const RiveRenderPath*, FillRule); |
| bool isEquivalent(const Mat2D&, const RiveRenderPath*) const; |
| |
| Mat2D matrix; |
| uint64_t rawPathMutationID; |
| AABB pathBounds; |
| rcp<const RiveRenderPath> path; |
| FillRule fillRule; // Bc RiveRenderPath fillRule can mutate during the |
| // artboard draw process. |
| uint32_t clipID; |
| }; |
| std::vector<ClipElement> m_clipStack; |
| |
| gpu::RenderContext* const m_context; |
| |
| std::vector<gpu::DrawUniquePtr> m_internalDrawBatch; |
| |
| // Path of the rectangle [0, 0, 1, 1]. Used to draw images. |
| rcp<RiveRenderPath> m_unitRectPath; |
| |
| // Used to build coarse path interiors for the "interior triangulation" |
| // algorithm. |
| RawPath m_scratchPath; |
| }; |
| } // namespace rive |