Viewport scaling disabled in fullscreen mode breaks WebGL canvas matching device pixel ratio
Reported by
carolina...@gmail.com,
Jun 23 2017
|
||||||||
Issue descriptionSteps to reproduce the problem: 1. Go to a web page with viewport scaling set to a value other than 1.0. 2. View the web page from an Android mobile device whose window.devicePixelRatio value is greater than 1.0 (e.g., most late model phones with a high-res screen). 3. Enter full screen mode via window.webkitRequestFullscreen while on the page (presumably via a page element provided for that purpose). What is the expected behavior? When you enter full screen mode the page should continue to scale the page using the scaling value specified in the page's meta viewport element. What went wrong? When entering full screen mode Chrome will stop scaling the page's viewport (i.e., it will start using a viewport scaling value of 1.0 regardless of the value specified in the page's meta viewport element). When full screen mode is exited then proper viewport scaling is reinstated. Did this work before? N/A Chrome version: 58 Channel: stable OS Version: 5.0 Flash Version: The following web page demonstrates the bug on high-res Android mobile devices: http://www.carolinaroad.com/viewport-bug-demo.html (page source code is attached to this report). Go to https://mydevice.io/devices/ to see a list of phones and tablets with a window.devicePixelRatio greater than 1.0. If you view the demo page using Firefox on the same device you will see Firefox continues to apply proper viewport scaling regardless of whether the browser is in full screen mode. Note that this bug is a duplicate of 515427, which is closed. However, that bug was never actually fixed! 515427 was mistakenly marked as a duplicate of 499721 (fixed) even though it is actually a different viewport/full screen mode bug.
,
Jun 26 2017
,
Jun 26 2017
Yeah, bug 515427 was mistakenly dup'd into bug 499721 , they are not the same issue. This is intentional behavior and not a bug. When we enter fullscreen we lock pinch-zoom and reset the scale to 1.0. Firefox too locks pinch-zoom but leaves the scale at whatever the value was when we entered fullscreen. From my POV this seems like worse behavior as the scale locks to essentially an arbitrary value - this has potential to confuse users. Pinch-zoom is generally meant for making legacy desktop pages usable on a mobile. Could you describe your use case in more detail? You mentioned in issue 515427 that this is needed for games. I have a hard time seeing how that's the case - a game especially should want to fill the whole screen. Pinch-zooming would allow part of the game view to be offscreen.
,
Jun 27 2017
Thank you for your response, Bokan. Actually, the pinch-zoom behavior is a non-issue. Game devs (and potentially other web app devs) are more concerned about being able to maintain the specified viewport scale when entering full screen mode. Typical full page games (i.e., width: 100%; height: 100%) will set viewport scaling to 1.0 as an easy way to ensure the game UI is appropriately sized on all devices without having to do much extra work. However, the resulting browser scaling applied to that page means the game will be displayed at a lower DPI on mobile devices than the device's native screen DPI. That means the game elements will appear a bit fuzzy/blocky compared to what the screen is actually capable of. Some game devs will instead want to provide a nicer game experience. This can be accomplished by using JavaScript to set the meta element's viewport scaling value to the reciprocal of the value of window.devicePixelRatio. That effectively disables scaling of the page because the viewport's DPI now matches the device's native screen DPI. The dev can now display the game with far more visual appeal on mobile devices with high DPI screens. Of course, it also means the dev has more work to do because he is now responsible for ensuring the game's UI elements are appropriately sized on all devices. But for some us, that extra effort is well worth the beautiful result. Unfortunately, if the game also provides a full screen mode button, and the user taps it, Android Chrome reverts back to a viewport scale of 1.0. So now the mobile user sees a low resolution display of the game, which is a pretty bad experience after having just seen the game displayed at high resolution. In my case, I will choose to avoid the problem by not providing full screen mode on Android Chrome unless the situation changes. However, that's a tough choice because users really like full screen mode for games, especially on phones where the browser chrome uses a significant percentage of the available real estate. I hope I was able to explain the use case clearly. However, I can provide an example of the use case if needed. I have a game that is not released yet, but it demonstrates a high DPI game display on mobile devices achieved via setting the viewport scale. If it would be helpful to see it then let me know and I will set it up for you.
,
Jun 29 2017
Bokan, I wanted to add a couple of additional comments because it occurred to me that the use case description I provided may not have directly or succinctly addressed the points you made... - The purpose of viewport scaling in the context of the issue being considered is not to facilitate zooming in or out of a page, but rather to make full use of the available pixels on a mobile device in order to provide the user with a high-resolution view of the page. - It is certainly fine for Chrome to lock down pinch zooming and to reset viewport scaling when entering full screen mode. However, it would be well for the viewport scaling value to be reset to the value specified by the meta viewport "initial-scale" value, rather than forced to a value of 1.0, since the developer has already determined the page will look best at the "initial-scale" value.
,
Jun 29 2017
Got it, thanks for the thorough explanation. To me this seems like an abuse of the viewport meta tag. In general, the viewport meta tag is used for compatibility with legacy desktop pages. We don't like to fix / encourage these kinds of uses because it's known to be highly quirky and has lots of interop issues. Because you mention your use case is games, I'm assuming we're talking about a Canvas here? Basically, you can achieve thing but with a CSS transform rather than pinch-zoom. i.e. Make your canvas size 100% * devicePixelRatio (actually, devicePixelRatio / canvas.webkitBackingStorePixelRatio, see https://www.html5rocks.com/en/tutorials/canvas/hidpi/) and then scale transform it by the inverse. This should be much more interoperable and you don't have to deal with these pinch-zoom quirks.
,
Jun 29 2017
Oh, and while locking it to the inital-scale/minimum-scale sounds ok in this case, I expect it would break those "legacy" cases I mentioned. e.g. if you load a desktop page that has to zoom out significantly, fullscreening a video on that page, for e.g., would likely result in the video being really tiny.
,
Jul 1 2017
Thank you for the "High DPI Canvas" article. I read it with interest, but that technique is only available to 2D canvases, not WebGL canvases. Even if it did work for WebGL the technique is egregiously inefficient and therefore unsuitable for many games. The game use case is simply using the meta viewport tag to specify a desired viewport scale for the page. As such, setting the viewport scale for a game page should work exactly the same as it does for any legacy use case page without any quirks or interoperability issues. In fact, in my own testing across the major browsers and devices, the only interop issue I found is that Firefox maintains viewport scaling in full screen mode and Chrome does not. I am concerned the game use case has become a distraction to that interop issue which is the focus of the bug report. I certainly understand your desire not to break legacy cases. However, webmasters already see that Firefox enters full screen mode and maintains the viewport "initial-scale" setting (assuming the user has not pinch-zoomed), so this behavior is not new to them and is almost certainly the preferred behavior. I even tried the video example you mentioned and the video looked fine in Firefox when full screened on a page whose viewport is scaled out. I'm still having difficulty understanding the rationale for hardcoding the full screen viewport scale to 1.0 if the webmaster himself has specified a different scale as more appropriate for his page. The purpose behind his choice of viewport scale should be irrelevant. Surely, it would be worthwhile to alleviate the existing Chrome/Firefox interop issue so webmasters/devs won't continue to encounter it going forward?
,
Jul 5 2017
Why is this not available to WebGL Canvases? WebGL rendering goes into a regular <canvas>, no? And what about it is inefficient? CSS transforms work on the same machinery that pinch-zoom does so there should be no performance difference. Admittedly, I'm not well versed on this problem, but a quick search shows that there are well-accepted ways of dealing with DPI issues that don't involve the viewport tag (e.g. https://www.khronos.org/webgl/wiki/HandlingHighDPI). In fact, they can't rely on the viewport tag as only mobile devices support that and the mobile/desktop line is blurry these days. Re: interop issues, there are plenty. How browsers handle the case where there's an extra wide element somewhere on the page (i.e. wider than the viewport `width=` attribute, this often surprises authors as it causes the page to zoom out further than the author expects), or various less common keywords on the viewport meta tag (how `height=` interacts with `width=`). > I certainly understand your desire not to break legacy cases. However, webmasters already see that Firefox > enters full screen mode and maintains the viewport "initial-scale" setting (assuming the user has not > pinch-zoomed), so this behavior is not new to them and is almost certainly the preferred behavior. Unfortunately, Firefox on mobile isn't very popular so I don't believe authors are testing against it. AFAICT, Safari doesn't support fullscreen at all. For better or worse, I'd guess authors are coding fullscreen against Chrome's implementation. > I'm still having difficulty understanding the rationale for hardcoding the full screen viewport scale to > 1.0 if the webmaster himself has specified a different scale as more appropriate for his page. The rationale is that the webmaster specified the viewport for what makes their page look good. But they rarely fullscreen their whole page, it's often a picture or video. Additionally, if the author didn't specify a viewport we use a default one so we'd be changing the behaviour in those cases unexpectedly. Not to mention, many pages just blindly cargo-culted a viewport meta from stackoverflow or elsewhere without understanding it's implications. I'm not saying that the change you proposed wouldn't work (I think the right thing to do might be to reset the zoom level to the minimum). However, for writing new apps, if there exist alternatives (as I believe there do here) that are better specified, more interoperable, and work across all manner of devices then it's difficult to justify a change to what is really a legacy feature for this. It might not seem like a lot of work but small changes like this require detailed testing, developer outreach, followed by potentially dozens of bug reports/fixes and complaints by authors that we broke their sites. IMHO, the compat-interop tradoff here is weighted towards maintaining compatibility for existing pages. I haven't seen evidence that this is a serious impediment to authors building new (interoperable) apps today.
,
Jul 7 2017
> Why is this not available to WebGL Canvases? WebGL rendering goes into a > regular <canvas>, no? 2D and WebGL canvases both use the <canvas> tag, but they are very different canvas types, each with its own API. This is a somewhat similar situation to the <object> tag which is used by Flash, Silverlight, and other things. The technique discussed in the first article you referenced uses an API that does not exist in the WebGL canvas context's API. > And what about it is inefficient? CSS transforms work on the same machinery > that pinch-zoom does so there should be no performance difference. The technique referenced in both articles involves using CSS scaling to counteract the mobile viewport scaling, both of which consume machine cycles. The viewport technique I described effectively disables viewport scaling and therefore no CSS scaling is needed to counteract it (i.e., the canvas, viewport, and screen DPIs are all the same). Just to be sure, I benchmarked the two methods using different browsers and devices and the CSS scaling technique is definitely slower (the magnitude of the difference varies widely depending on the level of stress applied by the app and the hardware being run on). > a quick search shows that there are well-accepted ways of > dealing with DPI issues that don't involve the viewport tag (e.g. > https://www.khronos.org/webgl/wiki/HandlingHighDPI). That article describes the same technique as the first article, but without the benefit of the special API 2D canvases have. As a result, knowing the exact relationship between canvas pixels and CSS pixels is difficult due to implementation differences among the browsers. This is touched on by the author in the article. That is not to say the technique is unusable, but the reliability of achieving a good result with it is questionable. > In fact, they can't rely on the viewport tag as only mobile devices > support that and the mobile/desktop line is blurry these days. That's fine, the use case I'm concerned with is only relevant to mobile. > Safari doesn't support fullscreen at all. For better or worse That's true, but I would not want to deny Android users the benefit of a fullscreen mode feature just because iOS users can't have it. > I'd guess authors are coding fullscreen against Chrome's implementation. That's true, but that does not imply Chrome's implementation is necessarily correct, it is simply the implementation devs have available to them. > The rationale is that the webmaster specified the viewport for what makes > their page look good. But they rarely fullscreen their whole page, it's > often a picture or video. That's understandable. Out of curiosity, I quickly tested that scenario in Firefox and saw no issues. Going fullscreen for videos on mobile devices is done so commonly I can't imagine Firefox would not have had to change their implementation if it did not work well for that scenario. Also, my guess would be webmasters using fullscreen for the whole page is becoming more common as web apps continue to proliferate. > Additionally, if the author didn't specify a viewport we use a default one > so we'd be changing the behaviour in those cases unexpectedly. I didn't understand this point, unless you're saying the fullscreen code has no way of knowing whether the meta viewport tag was specified. Otherwise, I would think any code changes should ensure the scenario where no meta viewport tag is specified behaves exactly as it does today. > I'm not saying that the change you proposed wouldn't work (I think the right > thing to do might be to reset the zoom level to the minimum). Resetting the viewport scale to "minimum-scale", rather than "initial-scale", would be completely fine! Is that a possibility? For that matter, there could be a new "fullscreen-scale" value which would only apply to fullscreen mode. That would completely eliminate any concerns with backwards compatibility. Is that a possible alternative?
,
Jul 11 2017
> The technique referenced in both articles involves using CSS scaling to counteract > the mobile viewport scaling, both of which consume machine cycles. The viewport > technique I described effectively disables viewport scaling and therefore no CSS > scaling is needed to counteract it (i.e., the canvas, viewport, and screen DPIs are > all the same). That's not how DPI scaling works in Chrome, the viewport and DPI scale are applied in separate places so applying a scale in the viewport tag is also counteracting the DPI scale. Viewport scaling is effectively identical to a CSS scale on the entire page. Additionally, this all happens with GPU operations so I'm surprised it's noticeable at all. > Just to be sure, I benchmarked the two methods using different browsers and devices > and the CSS scaling technique is definitely slower (the magnitude of the difference > varies widely depending on the level of stress applied by the app and the hardware > being run on). This is surprising to me. Could you share your results (on which browsers/devices) and methodology so I can investigate? I'd be surprised to see this in Chrome but I guess I have little understanding of how other the other engines handle this. > That article describes the same technique as the first article, but without the > benefit of the special API 2D canvases have. As a result, knowing the exact > relationship between canvas pixels and CSS pixels is difficult due to implementation > differences among the browsers. Doesn't your viewport scale technique suffer from the same issue? i.e. how do you know how much scaling to apply? My assumption would be that a GL canvas is missing that extra API because the GL canvas backing always sized to the devicePixelRatio (but that's just my guess). > That's fine, the use case I'm concerned with is only relevant to mobile. Right, but that's the problem. IMHO, having a mobile/desktop divide is hurting the web platform so we'd like to get away from it. > I didn't understand this point, unless you're saying the fullscreen code has no way of > knowing whether the meta viewport tag was specified. Right, in general, we treat no viewport meta tag as <meta name="viewport" content="width=980">. While it's possible for us to have different behavior based on whether it's specified or not, it feels like it would be surprising and irrational as an API to treat them differently. > Resetting the viewport scale to "minimum-scale", rather than "initial-scale", would > be completely fine! Is that a possibility? If we were to go down this road, I guess I could see the argument for either - I'd have to think about it a little more which would be preferable. > For that matter, there could be a new "fullscreen-scale" value which would only apply to > fullscreen mode. That would completely eliminate any concerns with backwards compatibility. > Is that a possible alternative? I'd like to avoid this if at all possible. As I mentioned, the viewport meta tag is already notoriously under-specified and quirky. This would only make that situation worse. I think the most compelling argument here is the performance one. IMHO, from an API and platform rationality perspective, CSS scaling is superior in every way but I'm sympathetic to the performance concerns. If we could fix perf issues with CSS scaling, would there be any reason to prefer the viewport method from your perspective?
,
Jul 15 2017
> That's not how DPI scaling works in Chrome, the viewport and DPI scale are > applied in separate places so applying a scale in the viewport tag is also > counteracting the DPI scale. If by "DPI scale" you mean CSS scale then yes that's what I was trying to say. Viewport scaling and CSS scaling are separate and if one is set up simply to counteract the other then that wastes machine cycles. When "initial-scale" is set to 1.0 the page is scaled by devicePixelRatio (e.g., devicePixelRatio=2 means two screen pixels for every CSS pixel). So, if you set "initial-scale" to 1/devicePixelRatio the page scale goes to unity (i.e., one screen pixel for every CSS pixel) and therefore no page scaling should occur. Since no page scaling occurs, no CSS scaling is needed to counteract it, which saves machine cycles. > Additionally, this all happens with GPU operations so I'm surprised it's > noticeable at all. Normally, that would be true. But WebGL code targets the GPU, so WebGL games (especially 3D games) can put a lot more pressure on the GPU than other web pages. Once the GPU begins to max out the performance losses due to unnecessary scaling become noticeable. > Could you share your results (on which browsers/devices) and methodology so > I can investigate? I'd be surprised to see this in Chrome but I guess I > have little understanding of how other the other engines handle this. Actually, I meant that I ran my benchmarks only on different devices, NOT "on different browsers and devices" as I stated earlier. I apologize for the confusion. As best I remember I ran my benchmarks only on Chrome, but I ran the benchmarks on both iOS and Android devices. Methodology: I took my own existing game and modified it in a way that put extra pressure on the CPU and GPU. I measured the frame rate of the game while using viewport scaling. The measurements were taken on an iPad, an Android tablet, and an Android phone. I then recoded the game to use CSS scaling. The frame rate was then measured again under the same conditions used for the viewport scaling test and on the same devices. The modifications I made to increase the game's activity were not enough to max out the GPU, but it was enough to see a performance difference between viewport scaling and CSS scaling. I suspect your Chromium WebGL co-workers have better benchmarking setups you could use for this purpose. > Doesn't your viewport scale technique suffer from the same issue? Theoretically, it could. The author did not provide enough information about the issue for me to know. I only know I haven't seen any evidence of the problem when using viewport scaling. For that matter, it didn't see evidence for the problem while testing CSS scaling either, so it's possible the issue doesn't exist anymore, or else the devices I tested on are not affected. Again, this might be something your WebGL co-workers could shed some light on. > I think the most compelling argument here is the performance one. IMHO, > from an API and platform rationality perspective, CSS scaling is superior in > every way but I'm sympathetic to the performance concerns. If we could fix > perf issues with CSS scaling, would there be any reason to prefer the > viewport method from your perspective? Assuming the CSS scaling quirks described by the article authors are no longer an issue (I haven't seen those quirks, and most game devs won't be too concerned if they only occur in ancient browser versions) then the performance gap would be the only reason I can see for preferring viewport scaling. It would be great news if the performance gap can be closed in Chrome! Note: I suspect Safari also has a performance gap between viewport and CSS scaling, but since iOS devices generally have much more performant GPUs than Android devices any performance gap in Safari would be significantly less noticeable than the performance gap of Chrome on Android. So, I doubt many game devs would continue to prefer viewport scaling over CSS scaling if the only advantage is that it makes games on Safari a bit faster on iOS devices.
,
Jul 17 2017
Thanks. I'll take a look and try to reproduce the performance issue you mentioned. If I can do that I might be able to get an idea if that's inherent and how easily we might be able to fix that. +junov@, kbr@ who work on Canvas and WebGL in case they have any thoughts.
,
Jul 18 2017
I'm not an expert in this area so please take this with a grain of salt. Why not take only the canvas element fullscreen? This will be the fastest path and the one which is expected to perform well. https://github.com/toji/webgl2-particles-2 does this and trivially achieves high-res rendering of the WebGL demo. One way or another, it should definitely be possible to render a WebGL-rendered canvas at full resolution where one pixel matches one device pixel.
,
Jul 19 2017
> Why not take only the canvas element fullscreen? AFAIK, Chrome's fullscreen feature switches the viewport scale to 1.0 regardless of what DOM element is being fullscreened. > One way or another, it should definitely be possible to render a WebGL- > rendered canvas at full resolution where one pixel matches one device pixel. Yes, there are actually two methods that accomplish that goal, but they each have a disadvantage: 1) Viewport scaling does not maintain the desired scale if the user enters fullscreen mode, which is a big problem for games. 2) CSS scaling is slower than viewport scaling, and game devs are often concerned with conserving machine cycles because games can push the limits of the machine.
,
Jul 19 2017
+foolip who maintains fullscreen API. I definitely agree browsers need to provide a way to have pixel-exact fullscreen canvases at no performance cost. The question is just how. Maybe if the element being fullscreened is a fixed-size nonrelayoutable thing, we could spec that browsers should scale-to-fit instead of today's behavior of (attempt-to-)relayout-to-fit. Then the web developer would just need to size the canvas to the screen size.
,
Aug 4 2017
Using the Fullscreen API it is possible to make a canvas element occupy exactly the whole screen, in fact that is the default per spec and will be in Chromium if issue 240576 can land without too many regressions. So, assuming the element already exactly fills the screen, does it not work to set the size of the canvas (in pixels) to match the screen? I've never done this, but https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html says something about it. Is the problem that there's no way to set up the canvas in such a way that it doesn't need to be recreated when entering/exiting fullscreen?
,
Aug 5 2017
@foolip, the Apple page you referenced describes what is called "CSS scaling" in this thread. Yes, it works but there is a performance hit when using it. The "viewport scaling" method described in this thread accomplishes the same goal, but without the performance hit. However, Chrome effectively disables the viewport scaling method when entering fullscreen mode, which makes that scaling method unsuitable. So, the discussion is about how to remove the performance hit from the CSS scaling method.
,
Aug 7 2017
OK, so the problem isn't merely that the canvas doesn't match the device pixel ratio, it can be made to match but it's not performant. I'm afraid I don't have any insight into why that's the case. If it's something fundamental that would apply to more engines than just Chromium, then one could of course consider adding options to the Fullscreen API to affect this behavior.
,
Jul 25
|
||||||||
►
Sign in to add a comment |
||||||||
Comment 1 by carolina...@gmail.com
, Jun 24 2017