Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy canvas data into intermediary ImageData buffer #5155

Merged
merged 4 commits into from
Aug 29, 2017
Merged

Copy canvas data into intermediary ImageData buffer #5155

merged 4 commits into from
Aug 29, 2017

Conversation

lbud
Copy link
Contributor

@lbud lbud commented Aug 16, 2017

I believe this fixes #4262: I've confirmed with a few colleagues who have affected GPUs that multiple test cases were fixed with this build.

I suspect affected GPUs have a bug in using an HTMLCanvasElement as the pixels argument in texImage2D/texSubImage2D. I haven't been able to corroborate this theory anywhere on the internet, unfortunately.

This PR circumvents that by copying canvas data into an intermediary ImageData object.
⚠️ BREAKING ⚠️ : It does necessitate the addition of a CanvasSource#contextType parameter.

Launch Checklist

  • briefly describe the changes in this PR
  • document any changes to public APIs
  • manually test the debug page

@lbud lbud requested a review from jfirebaugh August 16, 2017 23:37
const gl = this.context;
const data = new Uint8Array(this.width * this.height * 4);
gl.readPixels(0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, data);
return new window.ImageData(new Uint8ClampedArray(data), this.width, this.height);
Copy link
Contributor

Choose a reason for hiding this comment

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

According to MDN, the ImageData constructor is not available on IE (and Safari support is unknown).

One possible way around this would be to return {width: number, height: number, data: Uint8ClampedArray} (which ImageData will also satisfy), and have _prepareImage accept that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I started going down this path but ran into complications with different texImage2D/texSubImage2D signatures and with flow 😕 instead I went with using CanvasRenderingContext2D.createImageData, which is much cleaner but requires creating an extra canvas context for webgl-based canvas sources…

@@ -22,7 +22,8 @@ import type Evented from '../util/evented';
* [-76.52, 39.18],
* [-76.52, 39.17],
* [-76.54, 39.17]
* ]
* ],
* contextType: '2d'
Copy link
Contributor

Choose a reason for hiding this comment

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

If we have to make a breaking change here, maybe it's better to replace the canvas property with a context property of type CanvasRenderingContext2D | WebGLRenderingContext. On the other hand, that would be a property that's not JSON-serializable...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Intuitively I think I prefer the JSON-serializable string, and feel okay with the string enum options since it must match the string that was used to access the drawing context in the first place 🤔 though I'm happy to defer to stronger opinions…

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.

Canvas source errors when larger than some environment-specific size
2 participants