From 28b0354fdf6fdce308ca284e6dac7bbe952eee9f Mon Sep 17 00:00:00 2001 From: rivessamr Date: Fri, 30 Aug 2024 17:55:08 +0000 Subject: [PATCH] Namespace corrections to rive instead of gpu Diffs= bdd2e9bfd Namespace corrections to rive instead of gpu (#8006) Co-authored-by: rivessamr --- .rive_head | 2 +- renderer/include/rive/renderer/draw.hpp | 8 +- .../renderer/gl/render_context_gl_impl.hpp | 6 +- .../include/rive/renderer/render_context.hpp | 6 +- .../rive/renderer/rive_render_factory.hpp | 4 +- .../include/rive/renderer/rive_renderer.hpp | 22 +- renderer/src/draw.cpp | 1 + renderer/src/{pls.cpp => gpu.cpp} | 1 + renderer/src/gradient.cpp | 184 +++++++++++++++++ renderer/src/gradient.hpp | 110 ++++++++++ renderer/src/render_context.cpp | 1 + renderer/src/rive_render_factory.cpp | 10 +- renderer/src/rive_render_paint.cpp | 191 +----------------- renderer/src/rive_render_paint.hpp | 114 +---------- renderer/src/rive_render_path.cpp | 6 +- renderer/src/rive_render_path.hpp | 4 +- renderer/src/rive_renderer.cpp | 82 ++++---- 17 files changed, 397 insertions(+), 355 deletions(-) rename renderer/src/{pls.cpp => gpu.cpp} (99%) create mode 100644 renderer/src/gradient.cpp create mode 100644 renderer/src/gradient.hpp diff --git a/.rive_head b/.rive_head index bc9413ce..d2916745 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -cc4f27b8fe70240d8cc452ecc01de069cea0a0bd +bdd2e9bfdccb09db3cfea5aca30d926053fc1491 diff --git a/renderer/include/rive/renderer/draw.hpp b/renderer/include/rive/renderer/draw.hpp index f76048e8..26c052a3 100644 --- a/renderer/include/rive/renderer/draw.hpp +++ b/renderer/include/rive/renderer/draw.hpp @@ -13,11 +13,15 @@ #include "rive/shapes/paint/stroke_join.hpp" #include "rive/refcnt.hpp" -namespace rive::gpu +namespace rive { -class Draw; class RiveRenderPath; class RiveRenderPaint; +} // namespace rive + +namespace rive::gpu +{ +class Draw; class RenderContext; class Gradient; diff --git a/renderer/include/rive/renderer/gl/render_context_gl_impl.hpp b/renderer/include/rive/renderer/gl/render_context_gl_impl.hpp index c8f7d648..8e258138 100644 --- a/renderer/include/rive/renderer/gl/render_context_gl_impl.hpp +++ b/renderer/include/rive/renderer/gl/render_context_gl_impl.hpp @@ -9,10 +9,14 @@ #include "rive/renderer/render_context_helper_impl.hpp" #include -namespace rive::gpu +namespace rive { class RiveRenderPath; class RiveRenderPaint; +} // namespace rive + +namespace rive::gpu +{ class RenderTargetGL; // OpenGL backend implementation of RenderContextImpl. diff --git a/renderer/include/rive/renderer/render_context.hpp b/renderer/include/rive/renderer/render_context.hpp index d6e6df20..da009e2b 100644 --- a/renderer/include/rive/renderer/render_context.hpp +++ b/renderer/include/rive/renderer/render_context.hpp @@ -19,6 +19,8 @@ class RenderContextTest; namespace rive { class RawPath; +class RiveRenderPaint; +class RiveRenderPath; } // namespace rive namespace rive::gpu @@ -32,10 +34,8 @@ class MidpointFanPathDraw; class StencilClipReset; class Draw; class Gradient; -class RiveRenderPaint; -class RiveRenderPath; -class RiveRenderPathDraw; class RenderContextImpl; +class RiveRenderPathDraw; // Used as a key for complex gradients. class GradientContentKey diff --git a/renderer/include/rive/renderer/rive_render_factory.hpp b/renderer/include/rive/renderer/rive_render_factory.hpp index b6b176dd..f28b0121 100644 --- a/renderer/include/rive/renderer/rive_render_factory.hpp +++ b/renderer/include/rive/renderer/rive_render_factory.hpp @@ -6,7 +6,7 @@ #include "rive/factory.hpp" -namespace rive::gpu +namespace rive { // Partial rive::Factory implementation for the PLS objects that are backend-agnostic. class RiveRenderFactory : public Factory @@ -33,4 +33,4 @@ class RiveRenderFactory : public Factory rcp makeRenderPaint() override; }; -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/include/rive/renderer/rive_renderer.hpp b/renderer/include/rive/renderer/rive_renderer.hpp index 10f85365..dd83a812 100644 --- a/renderer/include/rive/renderer/rive_renderer.hpp +++ b/renderer/include/rive/renderer/rive_renderer.hpp @@ -11,22 +11,22 @@ #include "rive/renderer/render_context.hpp" #include -namespace rive +namespace rive::gpu { -class GrInnerFanTriangulator; -}; +class RenderContext; +} // namespace rive::gpu -namespace rive::gpu +namespace rive { +class GrInnerFanTriangulator; class RiveRenderPath; class RiveRenderPaint; -class RenderContext; // Renderer implementation for Rive's pixel local storage renderer. class RiveRenderer : public Renderer { public: - RiveRenderer(RenderContext*); + RiveRenderer(gpu::RenderContext*); ~RiveRenderer() override; void save() override; @@ -59,13 +59,13 @@ class RiveRenderer : public Renderer // 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(DrawUniquePtr); + void clipAndPushDraw(gpu::DrawUniquePtr); // Pushes any necessary clip updates to m_internalDrawBatch and sets the Draw's clipID and // clipRectInverseMatrix, if any. // Returns false if the operation failed, at which point the caller should issue a logical flush // and try again. - [[nodiscard]] bool applyClip(Draw*); + [[nodiscard]] bool applyClip(gpu::Draw*); struct RenderState { @@ -97,9 +97,9 @@ class RiveRenderer : public Renderer }; std::vector m_clipStack; - RenderContext* const m_context; + gpu::RenderContext* const m_context; - std::vector m_internalDrawBatch; + std::vector m_internalDrawBatch; // Path of the rectangle [0, 0, 1, 1]. Used to draw images. rcp m_unitRectPath; @@ -107,4 +107,4 @@ class RiveRenderer : public Renderer // Used to build coarse path interiors for the "interior triangulation" algorithm. RawPath m_scratchPath; }; -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/src/draw.cpp b/renderer/src/draw.cpp index 19c37ef5..577a0331 100644 --- a/renderer/src/draw.cpp +++ b/renderer/src/draw.cpp @@ -10,6 +10,7 @@ #include "rive_render_paint.hpp" #include "rive/math/wangs_formula.hpp" #include "rive/renderer/rive_render_image.hpp" +#include "gradient.hpp" #include "shaders/constants.glsl" namespace rive::gpu diff --git a/renderer/src/pls.cpp b/renderer/src/gpu.cpp similarity index 99% rename from renderer/src/pls.cpp rename to renderer/src/gpu.cpp index bd6c5d27..962f5846 100644 --- a/renderer/src/pls.cpp +++ b/renderer/src/gpu.cpp @@ -8,6 +8,7 @@ #include "shaders/constants.glsl" #include "rive/renderer/rive_render_image.hpp" #include "rive_render_paint.hpp" +#include "gradient.hpp" #include "generated/shaders/draw_path.exports.h" diff --git a/renderer/src/gradient.cpp b/renderer/src/gradient.cpp new file mode 100644 index 00000000..02eec2fb --- /dev/null +++ b/renderer/src/gradient.cpp @@ -0,0 +1,184 @@ +/* + * Copyright 2022 Rive + */ + +#include "gradient.hpp" + +#include "rive/renderer/rive_render_image.hpp" + +namespace rive::gpu +{ +// Ensure the given gradient stops are in a format expected by PLS. +static bool validate_gradient_stops(const ColorInt colors[], // [count] + const float stops[], // [count] + size_t count) +{ + // Stops cannot be empty. + if (count == 0) + { + return false; + } + for (size_t i = 0; i < count; ++i) + { + // Stops must be finite, real numbers in the range [0, 1]. + if (!(0 <= stops[i] && stops[i] <= 1)) + { + return false; + } + } + for (size_t i = 1; i < count; ++i) + { + // Stops must be ordered. + if (!(stops[i - 1] <= stops[i])) + { + return false; + } + } + return true; +} + +rcp Gradient::MakeLinear(float sx, + float sy, + float ex, + float ey, + const ColorInt colors[], // [count] + const float stops[], // [count] + size_t count) +{ + if (!validate_gradient_stops(colors, stops, count)) + { + return nullptr; + } + + float2 start = {sx, sy}; + float2 end = {ex, ey}; + GradDataArray newColors(colors, count); + GradDataArray newStops(stops, count); + + // If the stops don't begin and end on 0 and 1, transform the gradient so they do. This allows + // us to take full advantage of the gradient's range of pixels in the texture. + float firstStop = stops[0]; + float lastStop = stops[count - 1]; + if ((firstStop != 0 || lastStop != 1) && lastStop - firstStop > math::EPSILON) + { + // Tighten the endpoints to align with the mininum and maximum gradient stops. + float4 newEndpoints = simd::precise_mix(start.xyxy, + end.xyxy, + float4{firstStop, firstStop, lastStop, lastStop}); + start = newEndpoints.xy; + end = newEndpoints.zw; + newStops[0] = 0; + newStops[count - 1] = 1; + if (count > 2) + { + // Transform the stops into the range defined by the new endpoints. + float m = 1.f / (lastStop - firstStop); + float a = -firstStop * m; + for (size_t i = 1; i < count - 1; ++i) + { + newStops[i] = stops[i] * m + a; + } + + // Clamp the interior stops so they remain monotonically increasing. newStops[0] and + // newStops[count - 1] are already 0 and 1, so this also ensures they stay within 0..1. + for (size_t i = 1; i < count - 1; ++i) + { + newStops[i] = fmaxf(newStops[i - 1], newStops[i]); + } + for (size_t i = count - 2; i != 0; --i) + { + newStops[i] = fminf(newStops[i], newStops[i + 1]); + } + } + assert(validate_gradient_stops(newColors.get(), newStops.get(), count)); + } + + float2 v = end - start; + v *= 1.f / simd::dot(v, v); // dot(v, end - start) == 1 + return rcp(new Gradient(gpu::PaintType::linearGradient, + std::move(newColors), + std::move(newStops), + count, + v.x, + v.y, + -simd::dot(v, start))); +} + +rcp Gradient::MakeRadial(float cx, + float cy, + float radius, + const ColorInt colors[], // [count] + const float stops[], // [count] + size_t count) +{ + if (!validate_gradient_stops(colors, stops, count)) + { + return nullptr; + } + + GradDataArray newColors(colors, count); + GradDataArray newStops(stops, count); + + // If the stops don't end on 1, scale the gradient so they do. This allows us to take better + // advantage of the gradient's full range of pixels in the texture. + // + // TODO: If we want to take full advantage of the gradient texture pixels, we could add an inner + // radius that specifies where t=0 begins (instead of assuming it begins at the center). + float lastStop = stops[count - 1]; + if (lastStop != 1 && lastStop > math::EPSILON) + { + // Update the gradient to finish on 1. + newStops[count - 1] = 1; + + // Scale the radius to align with the final stop. + radius *= lastStop; + + // Scale the stops into the range defined by the new radius. + float inverseLastStop = 1.f / lastStop; + for (size_t i = 0; i < count - 1; ++i) + { + newStops[i] = stops[i] * inverseLastStop; + } + + if (count > 1) + { + // Clamp the stops so they remain monotonically increasing. newStops[count - 1] is + // already 1, so this also ensures they stay within 0..1. + newStops[0] = fmaxf(0, newStops[0]); + for (size_t i = 1; i < count - 1; ++i) + { + newStops[i] = fmaxf(newStops[i - 1], newStops[i]); + } + for (size_t i = count - 2; i != -1; --i) + { + newStops[i] = fminf(newStops[i], newStops[i + 1]); + } + } + + assert(validate_gradient_stops(newColors.get(), newStops.get(), count)); + } + + return rcp(new Gradient(gpu::PaintType::radialGradient, + std::move(newColors), + std::move(newStops), + count, + cx, + cy, + radius)); +} + +bool Gradient::isOpaque() const +{ + if (m_isOpaque == gpu::TriState::unknown) + { + ColorInt allColors = ~0; + for (int i = 0; i < m_count; ++i) + { + allColors &= m_colors[i]; + } + m_isOpaque = colorAlpha(allColors) == 0xff ? gpu::TriState::yes : gpu::TriState::no; + } + return m_isOpaque == gpu::TriState::yes; +} + +} // namespace rive::gpu diff --git a/renderer/src/gradient.hpp b/renderer/src/gradient.hpp new file mode 100644 index 00000000..ab179c0d --- /dev/null +++ b/renderer/src/gradient.hpp @@ -0,0 +1,110 @@ +/* + * Copyright 2022 Rive + */ + +#pragma once + +#include "rive/renderer/gpu.hpp" +#include "rive/renderer.hpp" +#include + +namespace rive::gpu +{ +// Copies an array of colors or stops for a gradient. +// Stores the data locally if there are 4 values or fewer. +// Spills onto the heap if there are >4 values. +template class GradDataArray +{ +public: + static_assert(std::is_pod_v); + + GradDataArray(const T data[], size_t count) + { + m_data = count <= m_localData.size() ? m_localData.data() : new T[count]; + memcpy(m_data, data, count * sizeof(T)); + } + + GradDataArray(GradDataArray&& other) + { + if (other.m_data == other.m_localData.data()) + { + m_localData = other.m_localData; + m_data = m_localData.data(); + } + else + { + m_data = other.m_data; + other.m_data = other.m_localData.data(); // Don't delete[] other.m_data. + } + } + + ~GradDataArray() + { + if (m_data != m_localData.data()) + { + delete[] m_data; + } + } + + const T* get() const { return m_data; } + const T operator[](size_t i) const { return m_data[i]; } + T& operator[](size_t i) { return m_data[i]; } + +private: + std::array m_localData; + T* m_data; +}; + +// RenderShader implementation for Rive's pixel local storage renderer. +class Gradient : public lite_rtti_override +{ +public: + static rcp MakeLinear(float sx, + float sy, + float ex, + float ey, + const ColorInt colors[], // [count] + const float stops[], // [count] + size_t count); + + static rcp MakeRadial(float cx, + float cy, + float radius, + const ColorInt colors[], // [count] + const float stops[], // [count] + size_t count); + + PaintType paintType() const { return m_paintType; } + const float* coeffs() const { return m_coeffs.data(); } + const ColorInt* colors() const { return m_colors.get(); } + const float* stops() const { return m_stops.get(); } + size_t count() const { return m_count; } + bool isOpaque() const; + +private: + Gradient(PaintType paintType, + GradDataArray&& colors, // [count] + GradDataArray&& stops, // [count] + size_t count, + float coeffX, + float coeffY, + float coeffZ) : + m_paintType(paintType), + m_colors(std::move(colors)), + m_stops(std::move(stops)), + m_count(count), + m_coeffs{coeffX, coeffY, coeffZ} + { + assert(paintType == gpu::PaintType::linearGradient || + paintType == gpu::PaintType::radialGradient); + } + + PaintType m_paintType; // Specifically, linearGradient or radialGradient. + GradDataArray m_colors; + GradDataArray m_stops; + size_t m_count; + std::array m_coeffs; + mutable gpu::TriState m_isOpaque = gpu::TriState::unknown; +}; + +} // namespace rive::gpu diff --git a/renderer/src/render_context.cpp b/renderer/src/render_context.cpp index 28eb6c42..142597c8 100644 --- a/renderer/src/render_context.cpp +++ b/renderer/src/render_context.cpp @@ -6,6 +6,7 @@ #include "gr_inner_fan_triangulator.hpp" #include "intersection_board.hpp" +#include "gradient.hpp" #include "rive_render_paint.hpp" #include "rive/renderer/draw.hpp" #include "rive/renderer/rive_render_image.hpp" diff --git a/renderer/src/rive_render_factory.cpp b/renderer/src/rive_render_factory.cpp index b1eda670..c8e6263e 100644 --- a/renderer/src/rive_render_factory.cpp +++ b/renderer/src/rive_render_factory.cpp @@ -3,12 +3,12 @@ */ #include "rive/renderer/rive_render_factory.hpp" - +#include "gradient.hpp" #include "rive_render_paint.hpp" #include "rive_render_path.hpp" #include "rive/renderer/rive_renderer.hpp" -namespace rive::gpu +namespace rive { rcp RiveRenderFactory::makeLinearGradient(float sx, float sy, @@ -19,7 +19,7 @@ rcp RiveRenderFactory::makeLinearGradient(float sx, size_t count) { - return Gradient::MakeLinear(sx, sy, ex, ey, colors, stops, count); + return gpu::Gradient::MakeLinear(sx, sy, ex, ey, colors, stops, count); } rcp RiveRenderFactory::makeRadialGradient(float cx, @@ -30,7 +30,7 @@ rcp RiveRenderFactory::makeRadialGradient(float cx, size_t count) { - return Gradient::MakeRadial(cx, cy, radius, colors, stops, count); + return gpu::Gradient::MakeRadial(cx, cy, radius, colors, stops, count); } rcp RiveRenderFactory::makeRenderPath(RawPath& rawPath, FillRule fillRule) @@ -41,4 +41,4 @@ rcp RiveRenderFactory::makeRenderPath(RawPath& rawPath, FillRule fil rcp RiveRenderFactory::makeEmptyRenderPath() { return make_rcp(); } rcp RiveRenderFactory::makeRenderPaint() { return make_rcp(); } -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/src/rive_render_paint.cpp b/renderer/src/rive_render_paint.cpp index ba54e27f..fc54b0d4 100644 --- a/renderer/src/rive_render_paint.cpp +++ b/renderer/src/rive_render_paint.cpp @@ -3,191 +3,18 @@ */ #include "rive_render_paint.hpp" - #include "rive/renderer/rive_render_image.hpp" +#include "gradient.hpp" -namespace rive::gpu +namespace rive { RiveRenderPaint::RiveRenderPaint() {} RiveRenderPaint::~RiveRenderPaint() {} -// Ensure the given gradient stops are in a format expected by PLS. -static bool validate_gradient_stops(const ColorInt colors[], // [count] - const float stops[], // [count] - size_t count) -{ - // Stops cannot be empty. - if (count == 0) - { - return false; - } - for (size_t i = 0; i < count; ++i) - { - // Stops must be finite, real numbers in the range [0, 1]. - if (!(0 <= stops[i] && stops[i] <= 1)) - { - return false; - } - } - for (size_t i = 1; i < count; ++i) - { - // Stops must be ordered. - if (!(stops[i - 1] <= stops[i])) - { - return false; - } - } - return true; -} - -rcp Gradient::MakeLinear(float sx, - float sy, - float ex, - float ey, - const ColorInt colors[], // [count] - const float stops[], // [count] - size_t count) -{ - if (!validate_gradient_stops(colors, stops, count)) - { - return nullptr; - } - - float2 start = {sx, sy}; - float2 end = {ex, ey}; - GradDataArray newColors(colors, count); - GradDataArray newStops(stops, count); - - // If the stops don't begin and end on 0 and 1, transform the gradient so they do. This allows - // us to take full advantage of the gradient's range of pixels in the texture. - float firstStop = stops[0]; - float lastStop = stops[count - 1]; - if ((firstStop != 0 || lastStop != 1) && lastStop - firstStop > math::EPSILON) - { - // Tighten the endpoints to align with the mininum and maximum gradient stops. - float4 newEndpoints = simd::precise_mix(start.xyxy, - end.xyxy, - float4{firstStop, firstStop, lastStop, lastStop}); - start = newEndpoints.xy; - end = newEndpoints.zw; - newStops[0] = 0; - newStops[count - 1] = 1; - if (count > 2) - { - // Transform the stops into the range defined by the new endpoints. - float m = 1.f / (lastStop - firstStop); - float a = -firstStop * m; - for (size_t i = 1; i < count - 1; ++i) - { - newStops[i] = stops[i] * m + a; - } - - // Clamp the interior stops so they remain monotonically increasing. newStops[0] and - // newStops[count - 1] are already 0 and 1, so this also ensures they stay within 0..1. - for (size_t i = 1; i < count - 1; ++i) - { - newStops[i] = fmaxf(newStops[i - 1], newStops[i]); - } - for (size_t i = count - 2; i != 0; --i) - { - newStops[i] = fminf(newStops[i], newStops[i + 1]); - } - } - assert(validate_gradient_stops(newColors.get(), newStops.get(), count)); - } - - float2 v = end - start; - v *= 1.f / simd::dot(v, v); // dot(v, end - start) == 1 - return rcp(new Gradient(PaintType::linearGradient, - std::move(newColors), - std::move(newStops), - count, - v.x, - v.y, - -simd::dot(v, start))); -} - -rcp Gradient::MakeRadial(float cx, - float cy, - float radius, - const ColorInt colors[], // [count] - const float stops[], // [count] - size_t count) -{ - if (!validate_gradient_stops(colors, stops, count)) - { - return nullptr; - } - - GradDataArray newColors(colors, count); - GradDataArray newStops(stops, count); - - // If the stops don't end on 1, scale the gradient so they do. This allows us to take better - // advantage of the gradient's full range of pixels in the texture. - // - // TODO: If we want to take full advantage of the gradient texture pixels, we could add an inner - // radius that specifies where t=0 begins (instead of assuming it begins at the center). - float lastStop = stops[count - 1]; - if (lastStop != 1 && lastStop > math::EPSILON) - { - // Update the gradient to finish on 1. - newStops[count - 1] = 1; - - // Scale the radius to align with the final stop. - radius *= lastStop; - - // Scale the stops into the range defined by the new radius. - float inverseLastStop = 1.f / lastStop; - for (size_t i = 0; i < count - 1; ++i) - { - newStops[i] = stops[i] * inverseLastStop; - } - - if (count > 1) - { - // Clamp the stops so they remain monotonically increasing. newStops[count - 1] is - // already 1, so this also ensures they stay within 0..1. - newStops[0] = fmaxf(0, newStops[0]); - for (size_t i = 1; i < count - 1; ++i) - { - newStops[i] = fmaxf(newStops[i - 1], newStops[i]); - } - for (size_t i = count - 2; i != -1; --i) - { - newStops[i] = fminf(newStops[i], newStops[i + 1]); - } - } - - assert(validate_gradient_stops(newColors.get(), newStops.get(), count)); - } - - return rcp(new Gradient(PaintType::radialGradient, - std::move(newColors), - std::move(newStops), - count, - cx, - cy, - radius)); -} - -bool Gradient::isOpaque() const -{ - if (m_isOpaque == gpu::TriState::unknown) - { - ColorInt allColors = ~0; - for (int i = 0; i < m_count; ++i) - { - allColors &= m_colors[i]; - } - m_isOpaque = colorAlpha(allColors) == 0xff ? gpu::TriState::yes : gpu::TriState::no; - } - return m_isOpaque == gpu::TriState::yes; -} - void RiveRenderPaint::color(ColorInt color) { - m_paintType = PaintType::solidColor; + m_paintType = gpu::PaintType::solidColor; m_simpleValue.color = color; m_gradient.reset(); m_imageTexture.reset(); @@ -195,17 +22,17 @@ void RiveRenderPaint::color(ColorInt color) void RiveRenderPaint::shader(rcp shader) { - m_gradient = static_rcp_cast(std::move(shader)); - m_paintType = m_gradient ? m_gradient->paintType() : PaintType::solidColor; + m_gradient = static_rcp_cast(std::move(shader)); + m_paintType = m_gradient ? m_gradient->paintType() : gpu::PaintType::solidColor; // m_simpleValue.colorRampLocation is unused at this level. A new location for a this gradient's // color ramp will decided by the render context every frame. m_simpleValue.color = 0xff000000; m_imageTexture.reset(); } -void RiveRenderPaint::image(rcp imageTexture, float opacity) +void RiveRenderPaint::image(rcp imageTexture, float opacity) { - m_paintType = PaintType::image; + m_paintType = gpu::PaintType::image; m_simpleValue.imageOpacity = opacity; m_gradient.reset(); m_imageTexture = std::move(imageTexture); @@ -213,7 +40,7 @@ void RiveRenderPaint::image(rcp imageTexture, float opacity) void RiveRenderPaint::clipUpdate(uint32_t outerClipID) { - m_paintType = PaintType::clipUpdate; + m_paintType = gpu::PaintType::clipUpdate; m_simpleValue.outerClipID = outerClipID; m_gradient.reset(); m_imageTexture.reset(); @@ -234,4 +61,4 @@ bool RiveRenderPaint::getIsOpaque() const } RIVE_UNREACHABLE(); } -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/src/rive_render_paint.hpp b/renderer/src/rive_render_paint.hpp index d11d6c63..be847983 100644 --- a/renderer/src/rive_render_paint.hpp +++ b/renderer/src/rive_render_paint.hpp @@ -6,106 +6,14 @@ #include "rive/renderer/gpu.hpp" #include "rive/renderer.hpp" -#include namespace rive::gpu { -// Copies an array of colors or stops for a gradient. -// Stores the data locally if there are 4 values or fewer. -// Spills onto the heap if there are >4 values. -template class GradDataArray -{ -public: - static_assert(std::is_pod_v); - - GradDataArray(const T data[], size_t count) - { - m_data = count <= m_localData.size() ? m_localData.data() : new T[count]; - memcpy(m_data, data, count * sizeof(T)); - } - - GradDataArray(GradDataArray&& other) - { - if (other.m_data == other.m_localData.data()) - { - m_localData = other.m_localData; - m_data = m_localData.data(); - } - else - { - m_data = other.m_data; - other.m_data = other.m_localData.data(); // Don't delete[] other.m_data. - } - } - - ~GradDataArray() - { - if (m_data != m_localData.data()) - { - delete[] m_data; - } - } - - const T* get() const { return m_data; } - const T operator[](size_t i) const { return m_data[i]; } - T& operator[](size_t i) { return m_data[i]; } - -private: - std::array m_localData; - T* m_data; -}; +class Gradient; +} -// RenderShader implementation for Rive's pixel local storage renderer. -class Gradient : public lite_rtti_override +namespace rive { -public: - static rcp MakeLinear(float sx, - float sy, - float ex, - float ey, - const ColorInt colors[], // [count] - const float stops[], // [count] - size_t count); - - static rcp MakeRadial(float cx, - float cy, - float radius, - const ColorInt colors[], // [count] - const float stops[], // [count] - size_t count); - - PaintType paintType() const { return m_paintType; } - const float* coeffs() const { return m_coeffs.data(); } - const ColorInt* colors() const { return m_colors.get(); } - const float* stops() const { return m_stops.get(); } - size_t count() const { return m_count; } - bool isOpaque() const; - -private: - Gradient(PaintType paintType, - GradDataArray&& colors, // [count] - GradDataArray&& stops, // [count] - size_t count, - float coeffX, - float coeffY, - float coeffZ) : - m_paintType(paintType), - m_colors(std::move(colors)), - m_stops(std::move(stops)), - m_count(count), - m_coeffs{coeffX, coeffY, coeffZ} - { - assert(paintType == PaintType::linearGradient || paintType == PaintType::radialGradient); - } - - PaintType m_paintType; // Specifically, linearGradient or radialGradient. - GradDataArray m_colors; - GradDataArray m_stops; - size_t m_count; - std::array m_coeffs; - mutable gpu::TriState m_isOpaque = gpu::TriState::unknown; -}; - // RenderPaint implementation for Rive's pixel local storage renderer. class RiveRenderPaint : public lite_rtti_override { @@ -120,16 +28,16 @@ class RiveRenderPaint : public lite_rtti_override void cap(StrokeCap cap) override { m_cap = cap; } void blendMode(BlendMode mode) override { m_blendMode = mode; } void shader(rcp shader) override; - void image(rcp, float opacity); + void image(rcp, float opacity); void clipUpdate(uint32_t outerClipID); void invalidateStroke() override {} - PaintType getType() const { return m_paintType; } + gpu::PaintType getType() const { return m_paintType; } bool getIsStroked() const { return m_stroked; } ColorInt getColor() const { return m_simpleValue.color; } float getThickness() const { return m_thickness; } - const Gradient* getGradient() const { return m_gradient.get(); } - const Texture* getImageTexture() const { return m_imageTexture.get(); } + const gpu::Gradient* getGradient() const { return m_gradient.get(); } + const gpu::Texture* getImageTexture() const { return m_imageTexture.get(); } float getImageOpacity() const { return m_simpleValue.imageOpacity; } float getOuterClipID() const { return m_simpleValue.outerClipID; } StrokeJoin getJoin() const { return m_join; } @@ -139,14 +47,14 @@ class RiveRenderPaint : public lite_rtti_override bool getIsOpaque() const; private: - PaintType m_paintType = PaintType::solidColor; + gpu::PaintType m_paintType = gpu::PaintType::solidColor; gpu::SimplePaintValue m_simpleValue; - rcp m_gradient; - rcp m_imageTexture; + rcp m_gradient; + rcp m_imageTexture; float m_thickness = 1; StrokeJoin m_join = StrokeJoin::miter; StrokeCap m_cap = StrokeCap::butt; BlendMode m_blendMode = BlendMode::srcOver; bool m_stroked = false; }; -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/src/rive_render_path.cpp b/renderer/src/rive_render_path.cpp index f37d6f9d..38ec2382 100644 --- a/renderer/src/rive_render_path.cpp +++ b/renderer/src/rive_render_path.cpp @@ -8,7 +8,7 @@ #include "rive/math/simd.hpp" #include "rive/math/wangs_formula.hpp" -namespace rive::gpu +namespace rive { RiveRenderPath::RiveRenderPath(FillRule fillRule, RawPath& rawPath) { @@ -125,7 +125,7 @@ float RiveRenderPath::getCoarseArea() const n = std::min(n, 64.f); float4 t = float4{1, 1, 2, 2} * (1 / n); float4 dt = t.w; - EvalCubic evalCubic(pts); + gpu::EvalCubic evalCubic(pts); for (; t.x < 1; t += dt) { float4 p = evalCubic.at(t); @@ -163,4 +163,4 @@ uint64_t RiveRenderPath::getRawPathMutationID() const } return m_rawPathMutationID; } -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/src/rive_render_path.hpp b/renderer/src/rive_render_path.hpp index 5bcd8edf..58d21e72 100644 --- a/renderer/src/rive_render_path.hpp +++ b/renderer/src/rive_render_path.hpp @@ -7,7 +7,7 @@ #include "rive/math/raw_path.hpp" #include "rive/renderer.hpp" -namespace rive::gpu +namespace rive { // RenderPath implementation for Rive's pixel local storage renderer. class RiveRenderPath : public lite_rtti_override @@ -65,4 +65,4 @@ class RiveRenderPath : public lite_rtti_override mutable uint32_t m_dirt = kAllDirt; RIVE_DEBUG_CODE(mutable int m_rawPathMutationLockCount = 0;) }; -} // namespace rive::gpu +} // namespace rive diff --git a/renderer/src/rive_renderer.cpp b/renderer/src/rive_renderer.cpp index 66ba0dc5..7156a0cc 100644 --- a/renderer/src/rive_renderer.cpp +++ b/renderer/src/rive_renderer.cpp @@ -11,7 +11,7 @@ #include "rive/renderer/rive_render_image.hpp" #include "shaders/constants.glsl" -namespace rive::gpu +namespace rive { bool RiveRenderer::IsAABB(const RawPath& path, AABB* result) { @@ -77,7 +77,7 @@ bool RiveRenderer::ClipElement::isEquivalent(const Mat2D& matrix_, path_->getFillRule() == fillRule; } -RiveRenderer::RiveRenderer(RenderContext* context) : m_context(context) {} +RiveRenderer::RiveRenderer(gpu::RenderContext* context) : m_context(context) {} RiveRenderer::~RiveRenderer() {} @@ -125,12 +125,12 @@ void RiveRenderer::drawPath(RenderPath* renderPath, RenderPaint* renderPaint) return; } - clipAndPushDraw(RiveRenderPathDraw::Make(m_context, - m_stack.back().matrix, - ref_rcp(path), - path->getFillRule(), - paint, - &m_scratchPath)); + clipAndPushDraw(gpu::RiveRenderPathDraw::Make(m_context, + m_stack.back().matrix, + ref_rcp(path), + path->getFillRule(), + paint, + &m_scratchPath)); } void RiveRenderer::clipPath(RenderPath* renderPath) @@ -271,13 +271,13 @@ void RiveRenderer::drawImage(const RenderImage* renderImage, BlendMode blendMode // paints. const Mat2D& m = m_stack.back().matrix; auto riveRenderImage = static_cast(renderImage); - clipAndPushDraw(DrawUniquePtr( - m_context->make(m_context, - m.mapBoundingBox(AABB{0, 0, 1, 1}).roundOut(), - m, - blendMode, - riveRenderImage->refTexture(), - opacity))); + clipAndPushDraw(gpu::DrawUniquePtr( + m_context->make(m_context, + m.mapBoundingBox(AABB{0, 0, 1, 1}).roundOut(), + m, + blendMode, + riveRenderImage->refTexture(), + opacity))); } else { @@ -309,24 +309,25 @@ void RiveRenderer::drawImageMesh(const RenderImage* renderImage, float opacity) { LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage); - const Texture* texture = image->getTexture(); + const gpu::Texture* texture = image->getTexture(); assert(vertices_f32); assert(uvCoords_f32); assert(indices_u16); - clipAndPushDraw(DrawUniquePtr(m_context->make(Draw::kFullscreenPixelBounds, - m_stack.back().matrix, - blendMode, - ref_rcp(texture), - std::move(vertices_f32), - std::move(uvCoords_f32), - std::move(indices_u16), - indexCount, - opacity))); + clipAndPushDraw( + gpu::DrawUniquePtr(m_context->make(gpu::Draw::kFullscreenPixelBounds, + m_stack.back().matrix, + blendMode, + ref_rcp(texture), + std::move(vertices_f32), + std::move(uvCoords_f32), + std::move(indices_u16), + indexCount, + opacity))); } -void RiveRenderer::clipAndPushDraw(DrawUniquePtr draw) +void RiveRenderer::clipAndPushDraw(gpu::DrawUniquePtr draw) { if (m_stack.back().clipIsEmpty) { @@ -385,7 +386,7 @@ void RiveRenderer::clipAndPushDraw(DrawUniquePtr draw) "RiveRenderer::clipAndPushDraw failed. The draw and/or clip stack are too complex.\n"); } -bool RiveRenderer::applyClip(Draw* draw) +bool RiveRenderer::applyClip(gpu::Draw* draw) { draw->setClipRect(m_stack.back().clipRectInverseMatrix); @@ -421,10 +422,10 @@ bool RiveRenderer::applyClip(Draw* draw) { // Time for a new stencil clip! Erase the clip currently in the stencil buffer before we // draw the new one. - auto stencilClipClear = DrawUniquePtr(m_context->make( + auto stencilClipClear = gpu::DrawUniquePtr(m_context->make( m_context, m_context->getClipContentID(), - StencilClipReset::ResetAction::clearPreviousClip)); + gpu::StencilClipReset::ResetAction::clearPreviousClip)); if (!m_context->isOutsideCurrentFrame(stencilClipClear->pixelBounds())) { m_internalDrawBatch.push_back(std::move(stencilClipClear)); @@ -441,12 +442,12 @@ bool RiveRenderer::applyClip(Draw* draw) { RiveRenderPaint clipUpdatePaint; clipUpdatePaint.clipUpdate(/*clip THIS clipDraw against:*/ lastClipID); - auto clipDraw = RiveRenderPathDraw::Make(m_context, - clip.matrix, - clip.path, - clip.fillRule, - &clipUpdatePaint, - &m_scratchPath); + auto clipDraw = gpu::RiveRenderPathDraw::Make(m_context, + clip.matrix, + clip.path, + clip.fillRule, + &clipUpdatePaint, + &m_scratchPath); clipDrawBounds = clipDraw->pixelBounds(); // Generate a new clipID every time we (re-)render an element to the clip buffer. // (Each embodiment of the element needs its own separate readBounds.) @@ -471,10 +472,11 @@ bool RiveRenderer::applyClip(Draw* draw) // When drawing nested stencil clips, we need to intersect them, which involves // erasing the region of the current clip in the stencil buffer that is outside the // the one we just drew. - auto stencilClipIntersect = DrawUniquePtr(m_context->make( - m_context, - lastClipID, - StencilClipReset::ResetAction::intersectPreviousClip)); + auto stencilClipIntersect = + gpu::DrawUniquePtr(m_context->make( + m_context, + lastClipID, + gpu::StencilClipReset::ResetAction::intersectPreviousClip)); if (!m_context->isOutsideCurrentFrame(stencilClipIntersect->pixelBounds())) { m_internalDrawBatch.push_back(std::move(stencilClipIntersect)); @@ -490,4 +492,4 @@ bool RiveRenderer::applyClip(Draw* draw) m_context->setClipContentID(lastClipID); return true; } -} // namespace rive::gpu +} // namespace rive