-
Notifications
You must be signed in to change notification settings - Fork 3.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
Add Hi DPI Support for GLFW #20584
Add Hi DPI Support for GLFW #20584
Conversation
- added Browser.isHiDPIAware flag that gets initialized from Module.isHiDPIAware - from the webgpu samples (https://webgpu.github.io/webgpu-samples/samples/helloTriangle), the gist of the logic is to scale canvas.width (resp. canvas.height) by the devicePixelRatio and set canvas.clientWidth to the width - coordinates are then scaled down to reflect what the client is expecting
- calling Browser.requestFullscreen raises "Failed to execute 'requestFullscreen' on 'Element': API can only be initiated by a user gesture"
- handle case where the canvas size is fixed (default shell) - handle case where request full screen is issued by the user (default shell)
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.
Thanks for details writeup and great looking first PR!
I'm not too familiar with this part of the codebase but the general direction looks good.
- created issue emscripten-core#20600 to implement in a separate PR
- the rationale is that the client can simply call Module.setHiDPIAware based on the needs
I just did a push that addresses the issues:
|
- ironically, although the call was wrong, it ended up doing the right thing...
@sbc100 Reverting the changes related to issue #20600 makes fullscreen/exit fullscreen no longer work in my test scenarios. Since I reverted the changes I had made, I assume it works like it used to. But since I don't have a good way to verify it, I don't feel very comfortable with the state of the PR at this moment. I will let you know my findings after I spend more time with it. |
Well good news. I did some more local testing and by using the default shell that comes with emscripten, the "Fullscreen" button works as expected with the changes in this PR. I can also see that all the tests have passed. So I am now confident with the state of this PR. Of course, the other use case we discussed in issue #20600 still remain a problem, but it is the same issue before this PR. So I am going to spend some time now and try to see if I can address it. But we have decoupled it from this PR which I think was the right call. |
@juj WDYT? |
I can see that github says that there is a conflict that must be resolved. When I click "Resolve conflicts", it doesn't look like I can do anything about it. Am I supposed to fix it on my fork and push again? |
Yes, I would fix locally then then push again. You can use either |
# Conflicts: # src/library_glfw.js
@sbc100 I believe it is fixed now as the PR only shows the 2 modified files (I used github "Sync" branch on my fork this time). I also checked that the changes to the 2 files are what I was expecting and double checked that the expected behavior is the same on my local test playground. |
# Conflicts: # src/library_browser.js
Fixed the merge conflict introduced by the latest check ins and pushed the branch. It looks like this time I did it right the first time... |
As far as I can tell the failing tests have nothing to do with my changes:
Do I need to do anything about this? |
What I mean here is that user JS libraries no longer have limitations that they used to, and users can author JS libraries that have all the capabilities that system JS libraries have. The mechanism I was referring to landed in this PR: https://github.com/emscripten-core/emscripten/pull/18849/files , although there was no documentation added (so follow the syntax that exists in the current JS libraries) |
src/library_glfw.js
Outdated
@@ -105,6 +107,7 @@ var LibraryGLFW = { | |||
versionString: null, | |||
initialTime: null, | |||
extensions: null, | |||
devicePixelRatioMQS: null, |
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.
What is MQS short for?
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.
It was supposed to be MediaQuerySearch but I realized that window.matchMedia
returns a MediaQueryList
not MediaQuerySearch
... so I just renamed it devicePixelRatioMQL
and added a comment for clarity
Looks good except for that one double-checking question. Nice to see the existing GLFW attribute |
# Conflicts: # src/library_glfw.js
Yay! Thank you @juj I fixed the merge conflict and hopefully the tests will pass! Let me know if you want me to update release notes/documentation, etc... when you are ready for the merge. |
The dreaded random tests failures are back:
But the primary test for this PR is passing:
|
@juj as a side note regarding your comment:
I have started looking into this... and toying around with implementation (c++ like your webgpu library)... :) |
After merging with latest branch as of this morning, all tests are now passing. Yay! |
Great! Landing this now. |
@sbc100 Thank you! Let me know if you want me to update any release notes or documentation! (I can do a PR just for that purpose) |
We don't really have any specific docs about our GLFW implementations (at least not that I know of). If you like you could add a ChangeLog entry. |
@juj I must admit I have been enjoying working on a glfw3 port... although I am far from finished, I already do support multiple canvases each with their own hi dpi aware flag! I had no idea if I could make it work, but it does (as can be seen in the screenshot). So exciting!!! // from main.cpp
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHintString(GLFW_EMSCRIPTEN_CANVAS_SELECTOR, "#canvas1");
auto window1 = glfwCreateWindow(300, 200, "4k", nullptr, nullptr);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
glfwWindowHintString(GLFW_EMSCRIPTEN_CANVAS_SELECTOR, "#canvas2");
auto window2 = glfwCreateWindow(300, 200, "2k", nullptr, nullptr); // from shell.html
<canvas class=emscripten id=canvas1 oncontextmenu=event.preventDefault() tabindex=-1></canvas>
<canvas class=emscripten id=canvas2 oncontextmenu=event.preventDefault() tabindex=-1></canvas> ![]() |
This is the PR following the discussion Support for 4k/retina displays
This is also my first PR and I tried to be as conservative as possible, read the contributing notes, ran as many tests I could on my local machine... I have also tried to minimize the amount of changes.
In the end I have implemented support for Hi DPI environment with webgpu/glfw. I can work in adding other frameworks (SDL, glut, etc...) in the future if this PR is successful and you think it would be worthwhile.
As described in the discussion, I ended up adding a property to the
Browser
object calledisHiDPIAware
which isfalse
by default and can be set by callingsetHiDPIAware
(which the demos use). It is also set automatically by glfw depending on the value ofModule.isHiDPIAware
(inglfwInit()
).I have created 2 public examples demonstrating the changes (which ends up using webgpu/glfw under the cover).
This demos work with Chrome (119+), Firefox (119+), Safari (16.6+). If you are on a 4k monitor then you will see a difference when checking the
isHiDPIAware
checkbox (it's 100% dynamic). Note that if you move the window from a 4k screen to a 2k screen, the change happens automatically which is pretty cool.The reason of these 2 demos is because, when there is a shell, the canvas is non-resizable in its own but you can make it fullscreen by clicking the Fullscreen button. The other demo, shows an example where the canvas size is dynamic and take up the full window (completely different code paths, as
onCanvasResize
gets called on every change). In this demo, you can select the Google Chrome menu to go Fullscreen. Note that this use-case was triggering an error in the codelibrary_glfw.js
line 986 because callingsetSize
with the exact size of the monitor would end up callingBrowser.requestFullscreen
which triggers an error when it is not triggered by the user explicitly (I added a comment in the code with the error).I did not add any tests because I do not know how to test it since it depends on the tests running on Google Chrome (no other browser to my knowledge supports webgpu) on a 4k monitor. I have no idea if the environment is that way. I will be more than happy to add test(s) if you give me some hints on what to do.
I will also gladly change anything you want me to change to abide by any rules I might have overlooked.
Thank you