blob: 239e218d8748e7d5fb102e7d95c8c20f8fbcd79e [file] [log] [blame]
/*
* Copyright 2022 Rive
*/
#include "bench.hpp"
#include "common/render_context_null.hpp"
#include "rive/file.hpp"
#include "rive/scene.hpp"
#include "assets/paper.riv.hpp"
#include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive_render_paint.hpp"
#include "rive_render_path.hpp"
using namespace rive;
using namespace rive::gpu;
using PathDraw = std::tuple<rcp<RiveRenderPath>, rcp<RiveRenderPaint>>;
// Measure the speed of RiveRenderer::drawPath(), with a null render context.
class DrawRiveRenderPath : public Bench
{
protected:
int run() const final
{
for (int i = 0; i < 10; ++i)
{
m_nullContext->beginFrame({
.renderTargetWidth = m_renderTarget->width(),
.renderTargetHeight = m_renderTarget->height(),
});
for (const auto& [path, paint] : m_pathDraws)
{
m_renderer.drawPath(path.get(), paint.get());
}
m_nullContext->flush({.renderTarget = m_renderTarget.get()});
}
return 0;
}
std::vector<PathDraw> m_pathDraws;
std::unique_ptr<RenderContext> m_nullContext =
RenderContextNULL::MakeContext();
mutable RiveRenderer m_renderer{m_nullContext.get()};
rive::rcp<RenderTarget> m_renderTarget =
m_nullContext->static_impl_cast<RenderContextNULL>()->makeRenderTarget(
1600,
1600);
};
class SniffPathsRenderer : public Renderer
{
public:
SniffPathsRenderer(std::vector<PathDraw>* pathDraws,
bool allStrokes,
bool allRoundJoin) :
m_pathDraws(pathDraws),
m_allStrokes(allStrokes),
m_allRoundJoin(allRoundJoin)
{}
void save() override {}
void restore() override {}
void transform(const Mat2D& matrix) override {}
void drawPath(RenderPath* path, RenderPaint* paint) override
{
auto renderPath = static_cast<RiveRenderPath*>(path);
auto renderPaint = static_cast<RiveRenderPaint*>(paint);
if (m_allStrokes)
{
renderPaint->style(RenderPaintStyle::stroke);
renderPaint->join(StrokeJoin::bevel);
renderPaint->thickness(2);
}
if (m_allRoundJoin)
{
renderPaint->join(StrokeJoin::round);
}
m_pathDraws->push_back({ref_rcp(renderPath), ref_rcp(renderPaint)});
}
void clipPath(RenderPath* path) override {}
void drawImage(const RenderImage*, BlendMode, float) override {}
void drawImageMesh(const RenderImage*,
rcp<RenderBuffer>,
rcp<RenderBuffer>,
rcp<RenderBuffer>,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode,
float) override
{}
private:
std::vector<PathDraw>* m_pathDraws;
bool m_allStrokes;
bool m_allRoundJoin;
};
// Measure the speed of RiveRenderer::drawPath() from the contents of a .riv
// file.
class DrawRiveRenderPaths : public DrawRiveRenderPath
{
public:
DrawRiveRenderPaths(bool allStrokes = false, bool allRoundJoin = false)
{
// Sniff paths out of a .riv file.
SniffPathsRenderer sniffer(&m_pathDraws, allStrokes, allRoundJoin);
std::unique_ptr<File> rivFile =
File::import(assets::paper_riv(), m_nullContext.get());
std::unique_ptr<ArtboardInstance> artboard = rivFile->artboardDefault();
std::unique_ptr<Scene> scene = artboard->defaultScene();
scene->advanceAndApply(0);
scene->draw(&sniffer);
}
};
REGISTER_BENCH(DrawRiveRenderPaths);
// Measure the speed of RiveRenderer::drawPath() from the contents of a .riv
// file, all paths converted to strokes.
class DrawRiveRenderPathsAsStrokes : public DrawRiveRenderPaths
{
public:
DrawRiveRenderPathsAsStrokes() : DrawRiveRenderPaths(true) {}
};
REGISTER_BENCH(DrawRiveRenderPathsAsStrokes);
class DrawRiveRenderPathsAsRoundJoinStrokes : public DrawRiveRenderPaths
{
public:
DrawRiveRenderPathsAsRoundJoinStrokes() : DrawRiveRenderPaths(true, true) {}
};
REGISTER_BENCH(DrawRiveRenderPathsAsRoundJoinStrokes);
class DrawCustomRiveRenderPaths : public DrawRiveRenderPath
{
public:
void setup() final
{
for (int i = 0; i < 1000; ++i)
{
RawPath rawPath;
buildPath(rawPath);
auto renderPath = static_rcp_cast<RiveRenderPath>(
m_nullContext->makeRenderPath(rawPath, FillRule::nonZero));
auto renderPaint = static_rcp_cast<RiveRenderPaint>(
m_nullContext->makeRenderPaint());
renderPaint->style(RenderPaintStyle::stroke);
renderPaint->thickness(2);
m_pathDraws.emplace_back(std::move(renderPath),
std::move(renderPaint));
}
}
protected:
virtual void buildPath(RawPath& rawPath) = 0;
};
class DrawZeroChopStrokes : public DrawCustomRiveRenderPaths
{
protected:
void buildPath(RawPath& rawPath) final
{
rawPath.moveTo(199, 1225);
for (int j = 0; j < 50; ++j)
{
rawPath.cubicTo(197, 943, 349, 607, 549, 427);
rawPath.cubicTo(349, 607, 197, 943, 199, 1225);
}
}
};
REGISTER_BENCH(DrawZeroChopStrokes);
class DrawOneChopStrokes : public DrawCustomRiveRenderPaths
{
protected:
void buildPath(RawPath& rawPath) final
{
for (int j = 0; j < 50; ++j)
{
rawPath.cubicTo(100, 0, 50, 100, 100, 100);
rawPath.cubicTo(0, -100, 200, 100, 0, 0);
}
}
};
REGISTER_BENCH(DrawOneChopStrokes);
class DrawTwoChopStrokes : public DrawCustomRiveRenderPaths
{
protected:
void buildPath(RawPath& rawPath) final
{
rawPath.moveTo(460, 1060);
for (int j = 0; j < 50; ++j)
{
rawPath.cubicTo(403, -320, 60, 660, 1181, 634);
rawPath.cubicTo(60, 660, 403, -320, 460, 1060);
}
}
};
REGISTER_BENCH(DrawTwoChopStrokes);
class DrawOneCuspStrokes : public DrawCustomRiveRenderPaths
{
protected:
void buildPath(RawPath& rawPath) final
{
for (int j = 0; j < 50; ++j)
{
rawPath.cubicTo(100, 100, 100, 0, 0, 100);
rawPath.cubicTo(100, 0, 100, 100, 0, 0);
}
}
};
REGISTER_BENCH(DrawOneCuspStrokes);
class DrawTwoCuspStrokes : public DrawCustomRiveRenderPaths
{
protected:
void buildPath(RawPath& rawPath) final
{
for (int j = 0; j < 50; ++j)
{
rawPath.cubicTo(100, 0, 50, 0, 150, 0);
rawPath.cubicTo(50, 0, 100, 0, 0, 0);
}
}
};
REGISTER_BENCH(DrawTwoCuspStrokes);