Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions runtimes/flutter/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ Future<void> main() async {
}
```

## "Too many active WebGL contexts" warnings on web

Every `Factory.rive` widget that owns its texture holds a live WebGL context, and browsers cap those. Exhausting the cap can also cause blank or frozen Rive widgets and CanvasKit context-loss errors. See [WebGL contexts (web)](/runtimes/flutter/flutter#webgl-contexts-web) for how contexts are released and reused.

To stay under the cap:

- Draw multiple widgets into one shared texture with a [RivePanel](/runtimes/flutter/flutter#rivepanel) — one context in total.
- Dispose Rive widgets you no longer show — that releases their WebGL contexts.

Set `RiveNative.debugRenderTextureLogging = true` to confirm you're hitting the cap: it logs texture create, reuse, and release with live WebGL context counts.

## How to enable 16KB page support on Android?

Rive Flutter `0.14.x` includes 16KB page support by default.
Expand Down
31 changes: 30 additions & 1 deletion runtimes/flutter/flutter.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ Follow the steps below to integrate Rive into your Flutter apps.
- `useSharedTexture`: Whether to use the nearest inherited shared texture from a [RivePanel](#rivepanel). Defaults to false. Ignored when `sharedTexture` is provided.
- `sharedTexture`: An explicit `SharedRenderTexture` to draw into, bypassing the ancestor-based `RivePanel` lookup. Use this with [`SharedRenderTexture` and `RiveSurface`](#sharedrendertexture-and-rivesurface) to share a texture across arbitrary parts of the widget tree.
- `drawOrder`: Stacking order when drawing to a shared texture with `Factory.rive` (default: `1`). Higher values draw on top. See [Draw Order](#draw-order).
- `renderResolution`: How the widget's backing texture is sized with `Factory.rive` (default: `RenderResolution.display()`). Not valid with `useSharedTexture`/`sharedTexture`. See [Render Resolution](#render-resolution).

### `RiveWidgetBuilder`

Expand All @@ -406,7 +407,7 @@ Follow the steps below to integrate Rive into your Flutter apps.
- When you want to programmatically composite a scene that includes multiple Rive graphics (from multiple Rive files/artboards)
- When using `Factory.rive` (will report errors with `Factory.flutter`) and want to improve performance
- When you want to reduce the number of textures being drawn to
- When targeting web platforms to avoid WebGL context limitations through `Factory.rive`
- When targeting web platforms to avoid [WebGL context limits](#webgl-contexts-web) through `Factory.rive`

**Performance considerations:**

Expand All @@ -429,6 +430,7 @@ RivePanel(
- Only works with `Factory.rive` - has no effect with `Factory.flutter`
- Set `useSharedTexture: true` in your `RiveWidget`s to enable shared texture rendering
- Set `drawOrder` in your `RiveWidget`s to control stacking (see [Draw Order](#draw-order))
- Set `renderResolution` on the panel to control how its shared texture is sized (see [Render Resolution](#render-resolution))
- If you need to interleave Rive content with Flutter content, consider using separate `RivePanel`s or `Factory.flutter`
- For complex scenarios, benchmark both approaches to determine the best performance strategy

Expand Down Expand Up @@ -471,6 +473,7 @@ Widget build(BuildContext context) {
- `RiveWidget.sharedTexture` takes precedence over `useSharedTexture` when both are set.
- You must call `dispose()` on textures created with `SharedRenderTexture.create()` to release the native texture.
- `RiveSurface` is wrapped in `IgnorePointer` by default so pointer events are handled by the individual `RiveWidget`s. Set `ignorePointer: false` if pointer events should reach the native texture widget directly.
- Set `renderResolution` on the `RiveSurface` to control how the shared texture is sized (see [Render Resolution](#render-resolution)).

### Draw Order

Expand All @@ -484,6 +487,20 @@ When multiple `RiveWidget`s draw to the same shared texture - through a [RivePan
`drawOrder` only applies when drawing to a shared texture with `Factory.rive`. When a widget owns its own texture, Flutter's normal paint order applies.
</Note>

### Render Resolution

`Factory.rive` draws content into a backing texture. `RiveWidget.renderResolution` (default: `RenderResolution.display()`) controls how that texture is sized - the same way on every platform, including web. It changes backing resolution only; layout, fit, alignment, and hit testing are unaffected.

- `RenderResolution.display()` (default): layout size * device pixel ratio * any scale ancestors apply at paint time (for example a `FittedBox` or `Transform.scale`). Content stays sharp at its final on-screen size, and allocates for it.
- `RenderResolution.layout(scale: 1.0)`: layout size * device pixel ratio * `scale`. Ancestor transforms apply at composite time, so scaling the widget up stretches the texture (softer output) instead of reallocating it - render small and let a `FittedBox` upscale cheaply.
- `RenderResolution.fixed(width, height)`: an explicit size in physical pixels, independent of layout, device pixel ratio, and transforms. Never reallocated on resize.

For shared textures the surface owns the allocation: set `renderResolution` on the [RivePanel](#rivepanel) or [RiveSurface](#sharedrendertexture-and-rivesurface). Setting it on a `RiveWidget` alongside `useSharedTexture` or `sharedTexture` throws an assertion error.

<Note>
`renderResolution` only applies with `Factory.rive`. `Factory.flutter` paints directly into Flutter's canvas at composite resolution.
</Note>

### `RiveWidgetController`

`RiveWidgetController` manages the graphic.
Expand Down Expand Up @@ -605,6 +622,18 @@ The exception to this is the `FileLoader`, which you control. This loader can be

</Note>

### WebGL contexts (web)

On the web, every `Factory.rive` widget that owns its texture renders into its own WebGL context, and browsers cap live contexts (around 16, shared with Flutter's own CanvasKit surfaces).

Disposing a Rive widget releases its context. A small reuse pool keeps a few canvases alive, so churn like route transitions stays cheap. Contexts the browser has evicted are detected and destroyed, never reused.

Set `RiveNative.debugRenderTextureLogging = true` to log texture create, reuse, and release with live WebGL context counts.

<Tip>
When showing many Rive widgets at once on web, draw them into a single shared texture with a [RivePanel](#rivepanel) - one WebGL context in total instead of one per widget.
</Tip>

## Specifying a renderer

When creating a Rive `File` or `FileLoader`, you need to specify a factory to use:
Expand Down