-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Fix GLUT window resizing when CSS scaling #24699
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
Conversation
@ypujante will certainly have some thoughts in this area. |
In general I think moving away from |
I couldn't find a path using |
Fair enough. It looks like the use of |
I don't have any knowledge of GLUT so I am not sure what I can contribute. I will say that there was a PR that I authored to restore CSS scaling that I had accidentally removed when working on Hi DPI support for |
Thanks - I did look at GLFW CSS scaling test which was helpful in writing the automated tests and also to confirm that no DPI ratio work is addressed by this fix. GLUT doesn't handle Hi DPI but this fix doesn't make it any better or worse. |
ac4945c
to
97ecaee
Compare
Looking into CI failures now. |
97ecaee
to
d212829
Compare
Added potential fix for CI tests. |
d212829
to
1e23887
Compare
All of the CI errors related to this PR appear to be fixed. The remaining CI errors look unrelated to the fix, test-windows test-other test-mac-arm64 test-browser-chrome-wasm64-4gb
|
I forgot to mention my motivation for seeing this fix in GLUT: I'm interested in preserving old OpenGL graphics demos. Emscripten is the perfect vehicle for this, as I can compile C and C++ to the web, and then the demos can be run forever more, on any device with a web browser. Without Emscripten, a lot of this code is lost to time. |
b5a508c
to
8cdbd15
Compare
Head branch was pushed to by a user without write access
8cdbd15
to
12865c3
Compare
Hmm.. I recently added test_codesize_hello_dylink_all and I think it might be too sensitive. I think I will revert that. |
Can you rebase (or merge) one more time. |
Looks like you need to do a |
Okay, updated to emsdk tot and latest emscripten, ran Ran 60 tests in 170.629s OK (skipped=1) Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (9) test expectation files were updated by
Anything else I can do? |
That doesn't looks quite right... can you make sure you are up-to-date with the emscripten main branch. And also try |
1) Add reshapeHandler() to set canvas size to clientWidth, clientHeight, and pass these along to glutReshapeFunc. 2) Register reshapeHandler as 'resize' event listener with addEventListener. 3) Call reshapeHandler on glutMainLoop instead of glutReshapeWindow, which unnecessarily exits fullscreen.
…h modify CSS and manually trigger a resize event). Also removed unnecessary whitespace change from libglut.js. Callback sequence for synchronous test cases 1-2: case 1: glutMainLoop -> GLUT.onSize -> Browser.setCanvasSize -> updateResizeListeners -> GLUT.reshapeFunc case 2: glutResizeWindow -> Browser.setCanvasSize -> updateResizeListeners -> GLUT.reshapeFunc Callback sequence for asynchronous test cases 3-5: window resize -> async update -> GLUT.onSize -> Browser.setCanvasSize -> updateResizeListeners -> GLUT.reshapeFunc Because window resize does not immediately call GLUT.onSize, we wait to run verification of a test until we get confirmation in GLUT.reshapeFunc. And after verification is done, we move on to the next test.
This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (9) test expectation files were updated by running the tests with `--rebaseline`: ``` code_size/test_codesize_cxx_ctors1.json: 149256 => 149232 [-24 bytes / -0.02%] code_size/test_codesize_cxx_ctors2.json: 148662 => 148638 [-24 bytes / -0.02%] code_size/test_codesize_cxx_except.json: 194695 => 194671 [-24 bytes / -0.01%] code_size/test_codesize_cxx_mangle.json: 258786 => 258762 [-24 bytes / -0.01%] code_size/test_codesize_cxx_noexcept.json: 151674 => 151650 [-24 bytes / -0.02%] code_size/test_codesize_cxx_wasmfs.json: 176935 => 176911 [-24 bytes / -0.01%] code_size/test_codesize_hello_O0.json: 37467 => 37453 [-14 bytes / -0.04%] code_size/test_codesize_hello_dylink_all.json: 844590 => 844684 [+94 bytes / +0.01%] code_size/test_unoptimized_code_size.json: 175109 => 175067 [-42 bytes / -0.02%] Average change: -0.01% (-0.04% - +0.01%) ```
3c0caba
to
75bbf01
Compare
Ok. Ran Ran 60 tests in 187.014s OK (skipped=1) Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (9) test expectation files were updated by
|
I don't think this change should include changes to most of those test files. Something odd must be going on there. |
Yeah I don't see how a change to libglut.js would cause changes elsewhere like this. Maybe something with my environment? Tried on an intel iMac on Sonoma 14.7.6 and a Macbook with latest Sequoia - same diffs. |
Curious that the diffs of the second run exactly cancels out the first run? I'm not familiar with rebaseline_tests.py, would one run affect the next? |
If you are having trouble rebaselining I can update the PR for you with the correct expectations. |
Yes, please. This is my first PR, and I'm happy to learn how to rebaseline if you can point me to documentation, otherwise please have at it. |
When using GLUT and the window is resized with the canvas dependent upon it due to CSS scaling, the result is a stretched canvas with blocky pixel scaling. Here's a CSS scaling example:
While position fixed isn't strictly necessary, it more readily shows the problem as it makes the canvas size directly dependent upon the browser window. For comparison, SDL behaves properly in this same scenario.
Fix
Three issues were found:
On window resize, glutReshapeFunc is never called.
Even with glutReshapeFunc working, the dimensions passed to it do not include CSS scaling. Specifically, the canvas width and height are never updated with the canvas clientWidth and clientHeight, which does include scaling.
On GLUT program startup, glutMainLoop calls glutReshapeWindow, which is slightly problematic for the case of loading the page while already in fullscreen. This is a problem because, while an initial resize is needed on startup, glutReshapeWindow also forces an exit from fullscreen mode.
Here are the proposed fixes:
Register a new resize callback
GLUT.reshapeHandler
usingwindow.addEventListener
, replacingBrowser.resizeListeners.push
. Previous work in this area (see below) utilizedresizeListeners
, however this fix takes a different route that is self-contained and I think simpler:window.addEventListener
keeps the fix entirely withinlibglut.js
, avoiding anylibbrowser.js
changes as in previous attempts. As well,updateResizeListeners
doesn't pass CSS-scaled canvas dimensions, so changingupdateResizeListeners
implementation might be necessary and this could impact other non-GLUT clients, going beyond this GLUT-only fix.glutInit
already utilizeswindow.addEventListener
for all other event handling, doing the same for the resize event seems consistent and simpler, as it avoids mixing event handling methods for GLUT.Create a new resize callback function,
GLUT.reshapeHandler
, which does the following:canvas
dimensions (viaBrowser.setCanvasSize
) tocanvas.clientWidth
andclientHeight
, so that CSS scaling is accounted for. If no CSS scaling is present,clientWidth
andclientHeight
matchcanvas.width
andheight
, so these values are safe to use in all cases, scaling or not.clientWidth
andclientHeight
toglutReshapeFunc
. This is needed so that GLUT reshape callbacks can properly update their viewport transform by callingglViewport
with the actual canvas dimensions.At GLUT startup in
glutMainLoop
, callGLUT.reshapeHandler
instead ofglutReshapeWindow
.glutReshapeWindow
has an unwanted side effect of always forcing an exit from fullscreen (and this is by design, according to the GLUT API).Testing
Manual testing:
Automated tests:
Related work
All the previous work in this area worked toward enabling GLUT resize callbacks via Emscripten’s built-in event handling (specifically
Browser.resizeListeners
andupdateResizeListeners
). As mentioned above, this fix takes a different approach that is entirely self-contained withinlibglut.js
.This 2013 commit added
GLUT.reshapeFunc
toBrowser.resizeListeners
, presumably to handle window resizing. However there is no test code with that commit, and as of current Emscripten,updateResizeListeners()
is never called on window resizing with GLUT programs, so this code is currently a no-op.Issue 7133 (that I logged in 2018, hi again!) got part of the way on a fix, but used
glutReshapeWindow
which has the previously mentioned side effect of exiting fullscreen. This was closed unresolved.PR 9835 proposed a fix for 7133. Also closed unresolved, this fix involved modifying
libbrowser.js
in order to get resize callbacks to GLUT viaresizeListeners
. While this got resize callbacks working, in my testing it didn’t pass CSS-scaled canvas size in the callback (the all-important clientWidth and clientHeight).I also looked at how SDL handles resizing, which uses
resizeEventListeners
, but decided the more straightforward fix was to useaddEventListener
. Last, I looked at GLFW CSS scaling test which was helpful in writing the automated tests and also to confirm that no DPI ratio work is addressed by this fix.Fixes: #7133