Improve canvas text#831
Open
eXecutable wants to merge 4 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the canvas text rendering path to avoid getImageData pixel readback by using GPU-friendly sources (ImageBitmap via transferToImageBitmap on OffscreenCanvas, or passing an HTMLCanvasElement directly) as texture inputs.
Changes:
- Extend texture source typing to allow
HTMLCanvasElement(and broaden internal image sources inImageTexture). - Update the canvas text renderer to capture output as
ImageBitmap/HTMLCanvasElementinstead ofImageData. - Update WebGL and Canvas texture upload paths to accept
HTMLCanvasElementas a valid source type.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/core/textures/Texture.ts | Adds HTMLCanvasElement to the core TextureData union. |
| src/core/textures/ImageTexture.ts | Broadens src typing to include ImageBitmap/HTMLCanvasElement and unifies non-string load handling. |
| src/core/text-rendering/TextRenderer.ts | Updates CanvasRenderInfo.imageData to `ImageBitmap |
| src/core/text-rendering/CanvasTextRenderer.ts | Switches capture from getImageData to transferToImageBitmap/direct-canvas source. |
| src/core/renderers/webgl/WebGlCtxTexture.ts | Allows uploading textures from HTMLCanvasElement in the WebGL path. |
| src/core/renderers/webgl/WebGlCtxSubTexture.ts | Extends subtexture data union to include HTMLCanvasElement. |
| src/core/renderers/canvas/CanvasTexture.ts | Allows HTMLCanvasElement as a direct image source in the Canvas renderer path. |
| src/core/CoreTextNode.ts | Passes through the new canvas text image source type to ImageTexture. |
Comments suppressed due to low confidence (1)
src/core/renderers/webgl/WebGlCtxTexture.ts:209
- HTMLCanvasElement support was added to the WebGL upload path, but there’s no unit test to ensure this new branch is exercised (and that upload + UNPACK_PREMULTIPLY_ALPHA_WEBGL behavior matches the ImageData/HTMLImageElement path). Consider extending WebGlCtxTexture.test.ts with a stubbed
HTMLCanvasElementand asserting it goes through the same upload branch.
const memoryPadding = 1.1; // Add padding to account for GPU Padding
const isImageBitmap =
typeof ImageBitmap !== 'undefined' && tdata instanceof ImageBitmap;
const isHTMLCanvas =
typeof HTMLCanvasElement !== 'undefined' &&
tdata instanceof HTMLCanvasElement;
// If textureData is null, the texture is empty (0, 0) and we don't need to
// upload any data to the GPU.
if (
isImageBitmap ||
isHTMLCanvas ||
tdata instanceof ImageData ||
// not using typeof HTMLI mageElement due to web worker
isHTMLImageElement(tdata) === true
) {
Comment on lines
+180
to
+186
| if (isOffscreen) { | ||
| drawCanvas = canvas; | ||
| } else { | ||
| // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
| drawCanvas = stage!.platform.createCanvas(); | ||
| context = drawCanvas.getContext('2d') as CanvasRenderingContext2D; | ||
| } |
Comment on lines
+385
to
+389
| let imageData: ImageBitmap | HTMLCanvasElement | null = null; | ||
| if (drawCanvas.width > 0 && drawCanvas.height > 0) { | ||
| if (isOffscreen) { | ||
| imageData = (drawCanvas as OffscreenCanvas).transferToImageBitmap(); | ||
| } else { |
Comment on lines
+175
to
+179
| // For OffscreenCanvas we reuse the shared canvas and snapshot via | ||
| // transferToImageBitmap at the end. For HTMLCanvasElement we allocate a | ||
| // fresh canvas per text node so it can be passed directly as the texture | ||
| // source — no pixel readback or intermediate copy needed. | ||
| let drawCanvas: HTMLCanvasElement | OffscreenCanvas; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
getImageDataforces the browser to copy the pixels drawn by the canvas to JS world. By using ImageBitmap instead the pixels can be drawn on the GPU and stay there.