close
Skip to content

RFC/POC: Extend View system to support multi-canvas rendering#10229

Open
ibgreen wants to merge 2 commits intomasterfrom
ib/multi-canvas-rfc
Open

RFC/POC: Extend View system to support multi-canvas rendering#10229
ibgreen wants to merge 2 commits intomasterfrom
ib/multi-canvas-rfc

Conversation

@ibgreen
Copy link
Copy Markdown
Collaborator

@ibgreen ibgreen commented Apr 16, 2026

image

RFC: Multi-Canvas Presentation for deck.gl

  • Status: Draft
  • Authors: deck.gl contributors
  • Target release: TBD
  • Related:
    • luma.gl 9.3 PresentationContext
    • @deck.gl/core
    • @deck.gl/react

Summary

Add a multi-canvas presentation mode to deck.gl built on luma.gl 9.3 PresentationContexts.

The proposal adds:

  • DeckProps.canvases?: (string | HTMLCanvasElement)[]
  • View.canvasId?: string

When canvases is defined, deck.gl creates or uses an offscreen-backed default device canvas and presents rendered output into one or more DOM canvases. Views are assigned to canvases by canvasId. Each canvas gets its own PresentationContext, event handling root, and controller binding.

This enables a single Deck instance to render multiple independently interactive views into separate canvases on a normal web page, while keeping React basemaps and other View children bound to the correct view and canvas.

A proof-of-concept app demonstrates four independently navigable city maps on one page, each with its own basemap, controller, and filtered data.

Motivation

deck.gl today assumes a single presentation surface. This makes certain layouts awkward or impossible without creating multiple Deck instances:

  • editorial pages with maps embedded between text
  • small multiples with independent interaction
  • dashboards that mix multiple maps and normal DOM content
  • layouts where each map panel needs its own basemap and DOM subtree

Creating multiple Deck instances works, but it duplicates GPU state, layer setup, animation loops, and application plumbing. luma.gl 9.3 introduces the missing primitive: one device can present to multiple canvases through multiple PresentationContexts.

This RFC proposes a deck.gl integration that:

  • preserves a single Deck and single layer graph
  • allows view-level routing to presentation canvases
  • keeps basemaps view-bound rather than introducing a separate map-to-canvas API

Goals

  • Support multiple presentation canvases from one Deck instance.
  • Assign views to canvases with a small extension to the existing View model.
  • Keep React View children, including basemaps, colocated with the correct canvas.
  • Support dynamic updates to the canvases prop, including add/remove/reorder.
  • Support independent controllers per canvas/view.
  • Keep picking and event routing scoped to the source canvas.
  • Preserve current single-canvas behavior when canvases is not supplied.

Non-Goals

  • Changing non-React overlay integrations in v1:
    • @deck.gl/mapbox
    • @deck.gl/google-maps
    • @deck.gl/arcgis
  • Adding a separate basemap-to-canvas API.
  • Supporting multi-canvas with externally supplied non-offscreen WebGL contexts.
  • Replacing the existing single-canvas API.

Background

luma.gl 9.3 supports multiple PresentationContexts per device. deck.gl can use this by separating:

  1. the device's default rendering surface, which becomes offscreen in multi-canvas mode
  2. the presentation surfaces, one per DOM canvas
  3. the deck.gl view graph, which decides which views render into which presentation target

This RFC treats canvas assignment as a property of a View, not of a layer or basemap. That keeps the model consistent:

  • View.id binds child content to the view
  • View.canvasId binds the view to a presentation canvas

Proposal

Public API

DeckProps.canvases

canvases?: (string | HTMLCanvasElement)[];

@ibgreen ibgreen changed the title Ib/multi canvas rfc feat(core) Extend View system to support multi-canvas rendering Apr 16, 2026
@ibgreen ibgreen changed the title feat(core) Extend View system to support multi-canvas rendering RFC/POC: Extend View system to support multi-canvas rendering Apr 16, 2026
@ibgreen ibgreen requested a review from heshan0131 April 16, 2026 18:05
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72fa41c755

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1181 to +1183
if (!this._isMultiCanvasMode()) {
this._destroyCanvasTargets();
return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep single-canvas event managers alive

In single-canvas mode, _syncCanvasTargets() immediately calls _destroyCanvasTargets(), which nulls this.eventManager/this.eventManagers. Because setProps() invokes _syncCanvasTargets() whenever this.device exists, this runs during normal initialization/update too, so getEventManager() starts returning null and later teardown paths cannot destroy the original EventManager instance (leaking listeners). This affects any app that relies on the standard single-canvas event manager lifecycle.

Useful? React with 👍 / 👎.

Comment on lines +1761 to +1762
if (!canvasViewports.length) {
continue;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear canvases when no views render to them

When running in multi-canvas mode, canvases with zero mapped viewports are skipped via continue, so they are never rendered or presented again. If a view is removed or reassigned to another canvas at runtime, the old frame remains visible indefinitely on the now-unused canvas, producing stale content during dynamic layout/view updates.

Useful? React with 👍 / 👎.

@ibgreen ibgreen mentioned this pull request May 2, 2026
40 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant