Skip to content

Commit b085e00

Browse files
authored
Allow reading back from canvases after present (#2905)
* Allow reading back from canvases after present This allows drawImage/toDataURL/etc. to see the canvas contents presented in the previous frame, as long as getCurrentTexture (or configure/unconfigure) hasn't been called yet this frame. alphaMode (née compositingAlphaMode) now affects using the canvas as an image source (drawImage/etc.) as well as compositing, so that the observed contents don't change on a frame boundary. As a weird aside (necessary to fully define the image source behavior), defines super-luminant values as being in the extended color space (i.e. once un-premultiplied). This definition emerges naturally, but it's also weird. Fixes #2743 Fixes #1847 Fixes a leftover bit from #2373 (placeholder canvases) * nit * Remove the "cancel present" behavior of destroy() This fixes several problems: - Unnecessary complexity in how currentTexture logic works. - Errors in the previous commit, where this was just not fully handled. - Using the "destroyed" state on the content process (minor issue). * nits * nit
1 parent 52ec46c commit b085e00

2 files changed

Lines changed: 183 additions & 102 deletions

File tree

explainer/index.bs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,15 +1040,17 @@ even though context state does not persist across loss/restoration.)
10401040
In order to access a canvas, an app gets a `GPUTexture` from the `GPUCanvasContext`
10411041
and then writes to it, as it would with a normal `GPUTexture`.
10421042

1043-
### Swap Chains ### {#canvas-output-swap-chains}
1043+
### Canvas Configuration ### {#canvas-output-swap-chains}
10441044

10451045
Canvas `GPUTexture`s are vended in a very structured way:
10461046

1047-
- `canvas.getContext('gpupresent')` provides a `GPUCanvasContext`.
1048-
- `GPUCanvasContext.configureSwapChain({ device, format, usage })` provides a `GPUSwapChain`,
1049-
invalidating any previous swapchains, attaching the canvas to the provided device, and
1050-
setting the `GPUTextureFormat` and `GPUTextureUsage` for vended textures.
1051-
- `GPUSwapChain.getCurrentTexture()` provides a `GPUTexture`.
1047+
- `canvas.getContext('webgpu')` provides a `GPUCanvasContext`.
1048+
- `GPUCanvasContext.configure({ device, format, usage })` modifies the current configuration
1049+
invalidating any previous texture object, attaching the canvas to the provided device,
1050+
and setting options for vended textures and canvas behavior.
1051+
- Resizing the canvas also invalidates previous texture objects.
1052+
- `GPUCanvasContext.getCurrentTexture()` provides a `GPUTexture`.
1053+
- `GPUCanvasContext.unconfigure()` returns the context to its initial, unconfigured state.
10521054

10531055
This structure provides maximal compatibility with optimized paths in native graphics APIs.
10541056
In these, typically, a platform-specific "surface" object can produce an API object called a
@@ -1057,14 +1059,16 @@ into.
10571059

10581060
### Current Texture ### {#canvas-output-current-texture}
10591061

1060-
A `GPUSwapChain` provides a "current texture" via `getCurrentTexture()`.
1062+
A `GPUCanvasContext` provides a "current texture" via `getCurrentTexture()`.
10611063
For <{canvas}> elements, this returns a texture for the *current frame*:
10621064

1063-
- On `getCurrentTexture()`, `[[currentTexture]]` is created if it doesn't exist, then returned.
1064-
- During the "[=Update the rendering=]" step, the browser compositor takes ownership of the
1065-
`[[currentTexture]]` for display, and that internal slot is cleared for the next frame.
1065+
- On `getCurrentTexture()`, a new `[[drawingBuffer]]` is created if one doesn't exist for the
1066+
current frame, wrapped in a `GPUTexture`, and returned.
1067+
- During the "[=Update the rendering=]" step, the `[[drawingBuffer]]` becomes readonly. Then, it is
1068+
shared by the browser compositor (for display) and the page's canvas (readable using
1069+
drawImage/toDataURL/etc.)
10661070

1067-
### `getSwapChainPreferredFormat()` ### {#canvas-output-preferred-format}
1071+
### `getPreferredCanvasFormat()` ### {#canvas-output-preferred-format}
10681072

10691073
Due to framebuffer hardware differences, different devices have different preferred byte layouts
10701074
for display surfaces.
@@ -1089,8 +1093,8 @@ As today with WebGL, user agents can make their own decisions about how to expos
10891093
capabilities, e.g. choosing the capabilities of the initial, primary, or most-capable display.
10901094

10911095
In the future, an event might be provided that allows applications to detect when a canvas moves
1092-
to a display with different properties so they can call `getSwapChainPreferredFormat()` and
1093-
`configureSwapChain()` again.
1096+
to a display with different properties so they can call `getPreferredCanvasFormat()` and
1097+
`configure()` again.
10941098

10951099
#### Multiple Adapters #### {#canvas-output-multiple-adapters}
10961100

0 commit comments

Comments
 (0)