Skip to main content
RiveRenderer and rive::gpu::RenderContext are one possible backend. The core runtime is renderer-agnostic — anything you pass to StateMachineInstance::draw only has to implement two interfaces:
  • rive::Renderer — receives draw / clip / save / restore commands.
  • rive::Factory — creates RenderPath, RenderPaint, RenderImage, RenderShader, RenderBuffer, Font, AudioSource from raw bytes or parameters during file import.
Implement both and Rive will route everything through them.

Use Cases

  • You already have a 2D vector engine (Skia, Direct2D, custom) and want Rive to render through it.
  • You’re targeting a platform Rive doesn’t ship a backend for.
  • You want CPU-side hit-testing or analytics — render into a no-op Renderer that records command counts.
If you only need Rive on Windows / macOS / iOS / Linux / Web / Android, prefer the built-in renderers — they’re faster and feature-complete.

The Renderer Interface

A few constraints worth knowing up front:
  • save / restore form a stack and must capture: the current transform, clip stack, and the modulated opacity.
  • clipPath adds to the current clip — never replaces it.
  • modulateOpacity is multiplicative; 0.5 then 0.20.1 effective opacity until the next restore.
  • drawImageMesh indices are 16-bit; vertex / UV buffers are tightly-packed float pairs.

The Factory Interface

Things to keep in mind:
  • Gradient colors[] are packed ARGB ints; stops[] are normalized 0..1.
  • makeRenderPath(RawPath&, FillRule) may steal the path’s storage — treat the input as moved-from after the call.
  • decodeImage is called with raw PNG / JPEG / WebP bytes, etc. Decode in whatever pixel format your renderer prefers and wrap the result in a subclass of RenderImage.
  • decodeFont / decodeAudio are non-virtual helpers that fan out to Rive’s built-in HarfBuzz / miniaudio paths. They are not subclass override points; use the actual virtual Factory extension points for custom font shaping or audio integration.

RenderPath / RenderPaint Subclasses

Each holds the state your backend reads during drawing:
(Method signatures match rive/command_path.hpp (for CommandPath) and rive/renderer.hpp (for RenderPath and RenderPaint) — read those for the full set.)

Wiring It Up

There’s no RenderContext in this path — your Renderer is responsible for making the GPU calls (or buffering them, or counting them, or whatever you want).

Reference Implementations

All paths below are in the rive-runtime repo. The Skia and CoreGraphics implementations are the most direct templates for a “forward to an existing 2D engine” Renderer.