-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
core(full-page-screenshot): get the MAX_TEXTURE_SIZE from the browser #11847
Conversation
lgtm but my concerns: what's the overhead for making a webgl context? Could this be more noticeable in LR given we are software rendering based there? |
/* istanbul ignore next */ // todo, c8 ignore? | ||
function getMaxTextureSize() { | ||
const canvas = document.createElement('canvas'); | ||
const webGL = canvas.getContext('webgl'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is destroying necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, but i added it anyway.
Related: are there any environments where webGL might be disabled entirely? How does this fail when it is and should we have a fallback? AFAIK you'd have to go manually disable WebGL in Chrome flags, so probably not a big deal, but pretty costless to have a fallback too. |
it used to be disabled quite a bit due to driver/OS bugs possibly being security issues (e.g. being able to read rasterized pixels from visible windows other than the browser). Now that swiftshader is cross platform...does Chrome always fall back to it? Since webgl isn't actually used for taking the screenshot, this is just a query about machine capabilities, maybe it doesn't matter and we should just have a reasonable fallback number no matter what. |
/* istanbul ignore next */ // todo, c8 ignore? | ||
function getMaxTextureSize() { | ||
const canvas = document.createElement('canvas'); | ||
const webGL = canvas.getContext('webgl'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tsc would correctly call out webGL
as WebGLRenderingContext | null
here if the file wasn't // @ts-nocheck
, so need to handle that case (e.g. webgl is disabled on that machine, as discussed in the other comments :)
Co-authored-by: Brendan Kenny <bckenny@gmail.com>
~10ms on LR. ~20ms on my oldass MBP.
overhead nah, but the M_T_S there is 8192, so our 16k number will give us a problem in LR. either crashes or image repeating. (not sure which)
yes good call. added one. all comments addressed afaik. |
} | ||
if (code.includes('document.documentElement.clientWidth')) { | ||
evaluate: async function(fn) { | ||
if (fn.name === 'resolveNodes') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this so much nicer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn.name is pretty tight. :) good call.
* @see https://bugs.chromium.org/p/chromium/issues/detail?id=770769 | ||
*/ | ||
async getMaxScreenshotHeight(driver) { | ||
return await driver.evaluate(pageFunctions.getMaxTextureSize, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious why a page function and not local to this module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly because theres a lot of ways in which PFs are very diff than node code and so i'd like to ideally have all PFs live in separate files.
- code coverage exemption (istanbul ignore/c8 ignore) is easier since they're colocated
- can apply a
eslint-env browser
instead of our current handcrafted/* global window document Node ShadowRoot */
list. - maybe use some browserish config for typescript on these files
--
but until all are migrated there i'll just place new ones in pf.js. thats my thinking.
i don't care a lot about this particular case tho.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but until all are migrated there i'll just place new ones in pf.js. thats my thinking.
Funny, I have the exact opposite thinking. Not speaking to the idea at all, but if we are currently doing "all page functions local if possible", we should keep doing that until we change how we structure things, instead of starting a transitionary thing w/o any discussion.
fwiw i like your bullet points
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
word.
well... looking at the fn's in pf.js, there already are plenty that are one-offs used by gatherrunner & driver. oh and a singleuse for iframe-elements! :)
let canvas = document.createElement('canvas'); | ||
let gl = canvas.getContext('webgl'); | ||
const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); | ||
canvas = gl = undefined; // Cleanup for GC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought there might have been a more explicit "destroy" method for a context, but there isn't. As long as the element is not on the DOM, we're good. Can remove the "cleanup" line.
sorry for confusion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe i'm overly cautious but memory mgmt with webgl feels like it has some gotchas.. as such, i'm prone to keep the explicit cleanup and not just wait for auto-GC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mathiasbynens we're just two developers who don't know how GC works. wdyt? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither canvas
nor the gl
context escapes from this block, so it should in theory be fine even without the explicit cleanup. (In case anyone‘s interested, I wrote a high-level explanation of escape analysis when I learned about it.)
That said, I’m not familiar with Chromium’s WebGL context lifecycle, and if perhaps there are weird side effects to creating such contexts that I don’t know about.
Connor called this out before and I confirmed and documented it: https://bugs.chromium.org/p/chromium/issues/detail?id=770769#c13
(the 16384 number is the max_texture_size for swiftshader, used by headless (most of the time), but other devices have other ones)
This changes our impl to pull it from the browser rather than use a hardcoded value that might cause problems.