-
-
Notifications
You must be signed in to change notification settings - Fork 312
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
Scale windows and resolution for HiDPI displays #2544
Conversation
Very cool effort! I have no idea if the approach you took (modifying every shader with a scale factor) is the "right" one (I had hoped there could be a simpler solution) but we'll sort that out with the others who are more knowledgeable about that code than me. However, I could test with a Mac and it's not working correctly there, yet.
|
I've made some additions which fix window size and mouse behavior on my mac. The I still find the nomenclature quite confusing and am not sure if everything is correct. My problem is that window size and framebuffer size are not clearly separated (I made one attempt at separation by renaming |
Also for discussion, check out what happens if the Then 3: Then 4: The way that @ffreyer 's PR worked, the resolution of the buffer that was drawn into did not change the real estate in the plot, but here it does. If the frame buffer size is changed with the same factor as the |
Right — I ended up at the place I did because GLFW handles resizing the window/frame buffer (when using the As far as I can tell on Linux, there's no way to have a frame buffer with different size than the window, so arbitrarily large scaling factors will cause/require the window to be potentially larger than the entire monitor. That also doesn't seem ideal, though. |
I think that's true — on Linux and Windows, frame buffer and window sizes are the same. I've been interpreting the scene resolution to be the logical window size — if you switch backends, you should get the same result, so that motivated my approach at not manipulating any of the stored window sizes and instead doing all of the scaling during interactions with GLFW/the rendering pipeline. To help with cross-compatibility between OSX and others, though, it probably would make sense to better delineate between window and buffer sizes, and then there'd be different implementations based on OS to scale up/down sizes accordingly. |
I think we need to separate between windows that are displayed on screens, and images that are saved directly from frame buffers. As far as I understand (and this was also visible in the other PR by ffreyer), the frame buffer we draw everything into doesn't have to have the same resolution as the window it's being displayed on. At least, in my tests I could vary the same layout (shown in the same window size) from blurry to sharp by decreasing or increasing the frame buffer size. This would be the basis for saving out images with arbitrary resolution, we'd just increase the frame buffer size as high as we like (and the hardware allows). Maybe I can incorporate that part of @ffreyer's PR into this one. On the other hand, we have the scaling aspect that has to do with monitor pixel densities and OS scaling settings. Here we have the slightly problematic difference between OSes in how window and frame buffer size differ. But I think we were already agreeing about the fact that Let's say we have the same screen on Windows/Linux and Mac which is 3456 × 2234 pixels in size (like my macbook).
The pixel buffer underlying that window (not the frame buffer) would be the same size for both, 1600x1200. If we move the window to a different screen, the scale factor reported by GLFW might change and we should update to a new pixel buffer size. Therefore, I'd argue that the pixel buffer size should be fixed given the However, this is different than the size of the frame buffer which we draw into, and which is then shown as a bitmap scaled to the size of the pixel buffer. (At least that's my current understanding, please correct me if I'm wrong). There are two scenarios:
So it seems to me that the scaling factor
The pixel buffer size of a window should always be set by multiplying the
The frame buffer size in which we draw should however be set by multiplying the
My main assumption in this text was that we're not directly drawing into the buffer that is underlying the window, and that there's a separation there which decouples |
I've pushed a new change which separates the concept of the window scaling factor from the (rendering) frame buffer "px_per_unit". For instance, by default I now get the simple scatter plot: but if I manually change the scene's |
Lovely! This seems to work really well for me on Mac as well when displaying the figure. (Minus the slider and menu bugs already noticed before). The behavior when saving is a bit peculiar, I managed to write out a high-resolution image by setting both Also the px_per_unit value in the f, ax, l = lines(cumsum(randn(100)))
surface(f[1, 2], 0:0.1:10, 0:0.1:10, (x, y) -> sqrt(x) * sqrt(y), color = :red, axis = (type = Axis3,))
Label(f[0, :], "Super title", font = :bold)
# m = Menu(f[end+1, :], options = ["A", "B", "C"])
gl = GridLayout(f[end+1, :], tellwidth = false)
Button(gl[1, 1], label = "Click me")
Textbox(gl[1, 2], width = 200)
Slider(f[end+1, :], range = 1:100)
f
screen = display(f)
ppu = 4.0f0
screen.px_per_unit[] = ppu
save("test.png", f, px_per_unit = ppu)
run(`file test.png`) # check pixel size of output With these settings I get a nice and sharp 3200 x 2400 png file: |
Some more observations. The effective window size is the same, no matter if I have Also, with |
GLMakie/src/screen.jl
Outdated
@@ -68,7 +68,7 @@ mutable struct ScreenConfig | |||
vsync::Bool, | |||
render_on_demand::Bool, | |||
framerate::Number, | |||
px_per_unit::Union{Makie.Automatic, Float32}, |
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.
can we type this concretely to just Float64/Float32?
We can also use Float64 if it helps ;) The conversion from automatic/number should happen in the constructor!
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.
Sorry if I'm misunderstanding something — isn't this the appropriate place to deal with automatic
? This line is specifically in the function arguments to the constructor, which is converted within the function to nothing
or a Float32
. (I'm using nothing
as a sentinel to indicate that automatic decisions should be made, with the idea that being overridden by the user will disable automatic updates.)
With the latest two commits:
That was an easy fix by just allowing all
In the second commit, I explicitly changed/ignored a comment saying not to change the framebuffer size, but that seems to be necessary to not crop/pad the output image when the julia> f, ax, l = lines(cumsum(randn(100)))
julia> surface(f[1, 2], 0:0.1:10, 0:0.1:10, (x, y) -> sqrt(x) * sqrt(y), color = :red, axis = (type = Axis3,))
Makie.AxisPlot(Axis3(), Surface{Tuple{Vector{Float32}, Vector{Float32}, Matrix{Float32}}})
julia> Label(f[0, :], "Super title", font = :bold)
Label()
julia> # m = Menu(f[end+1, :], options = ["A", "B", "C"])
gl = GridLayout(f[end+1, :], tellwidth = false)
GridLayout[1:1, 1:1] with 0 children
julia> Button(gl[1, 1], label = "Click me")
Button()
julia> Textbox(gl[1, 2], width = 200)
Textbox()
julia> Slider(f[end+1, :], range = 1:100)
Slider()
julia> f
julia> screen = display(f)
GLMakie.Screen(...)
julia> ppu = 4
4
julia> save("test.png", f, px_per_unit = ppu)
julia> run(`file test.png`) # check pixel size of output
test.png: PNG image data, 3200 x 2400, 8-bit/color RGB, non-interlaced
Process(`file test.png`, ProcessExited(0))
Yeah, I've noticed that but haven't yet gone through the work of hooking up the right observable action to resize the window. I think that should be possible, though. (I just have to think through how to manage both manually setting the scale factor and receiving callbacks from GL when moving across differently-scaled monitors.) |
4f3e68c
to
91e5509
Compare
|
Good observation. I was wondering about that since I never saw any kind of push-pop state save, but I hadn't actually noticed an effect — I probably just didn't interact with the window, though. I've also found another issue with high-res rendering and saving animations, so there are still some fundamental problems with conveying the size of the buffer that I need to sort out. |
2358a63
to
04bdd91
Compare
Has your testing of this included something like my setup? It consists of a hidpi (Mac Retina) main display, and external lower-res monitors, and I've noticed some odd stuff: On the external monitor, sometimes a 3D axis will respond to mouse drags to rotate the scene, sometimes it won't at all, and sometimes it will do so but only when dragging in very specific locations in the 3D scene. I see this in a figure with a 1-column, 2 row layout where the 3D axis is the upper one. It seems to happen only if I include The axis in the 2nd row (a 2D This is GLMakie 0.8.1, Julia 1.8.4, MacOS Ventura, Intel. If this isn't a known issue I can try to make a minimal example, but I wonder if it sounds like something that's already been seen. Edit: I just noticed that it's possible to get similar behavior on the hidpi screen too, so I think that may be a red herring, and also without the Edit again: I just restarted my Julia session and can no longer reproduce the issue, so it must be something stateful. |
No, I don't have access to OSX, so I assume things may be (probably are) broken until someone else figures out what needs to be changed. It seems Windows and Linux are relatively consistent in how screens/framebuffers are dealt with, and OSX is the oddball. (My computers are all Linux, so that's where I'm developing/testing everything.) |
Just reporting that Menu and Slider work for me now on Mac with the recent fixes. |
0cb0f51
to
aa11a87
Compare
aa11a87
to
ef1c698
Compare
ebcac6d
to
d3a2b7f
Compare
From my perspective, this is ready to go and be reviewed. I haven't figured out how to write a reference image test that propagates a different I've been using this branch on my main Linux desktop, and I even tested briefly on a Windows machine at work and didn't see any problems. An OSX user should confirm. |
Good to hear on the moving across monitors, but no, I must have broken something with the scaling now. What I'm expecting to see is that the window changes sizes to accommodate different native resolution — i.e. on a 100% monitor, an 800×600 window uses 800×600 pixels, but you move it across to a 200% monitor and then the window resizes to be 1600×1200 (so that it's roughly the same apparent size).
Hmmm, that failure in the test suite is less obvious. Not sure what to think about that one yet. |
I think I've tracked down the problem with the window not resizing when The fundamental problem is that there's a race condition between the I can reliably reproduce the behavior by adding a "long" callback in the julia> fig, _, _ = scatter([1, 2], [3, 4]);
julia> screen = display(fig, resolution = (800, 600), scalefactor = 2, framerate = 30)
GLMakie.Screen(...)
julia> size(screen.root_scene)
(800, 600)
julia> on(screen.scalefactor, priority=typemax(Int)) do _
sleep(0.1)
end
ObserverFunction defined at REPL[404]:2 operating on Observable(2.0)
julia> screen.scalefactor[] = 1
1
julia> size(screen.root_scene)
(1600, 1200) Note that the figure size has been doubled after switching to half the scale factor, and the window did not change size on my screen (but the plot contents were shrunk as expected). Now if we reduce the frame rate of the render loop, we can still have the long callback run before the area updater recalculates the scene size based on the actual window size and the declared scale factor. julia> fig, _, _ = scatter([1, 2], [3, 4]);
julia> screen = display(fig, resolution = (800, 600), framerate = 1)
GLMakie.Screen(...)
julia> size(screen.root_scene)
(800, 600)
julia> on(screen.scalefactor, priority=typemax(Int)) do _
sleep(0.1)
end
ObserverFunction defined at REPL[412]:2 operating on Observable(2.0)
julia> screen.scalefactor[] = 1
1
julia> size(screen.root_scene)
(800, 600) Now the window changes size as expected, and the scene size is not modified. (It of course does take a full second to redraw the contents to match the new size.) |
The latest commit is my solution to the race described in #2544 (comment). Instead of constantly polling for the window size at every render tick, we can instead just use another GLFW callback to be notified when the size of the window is changed (so that the scene size can be updated to match). (Is this also theoretically better for overall performance since there should be less work done on each render tick? The same kind of change should be possible for the mouse position polling as well...) |
On my mac (MBP M1), line widths and text sizes look substantially thinner at Also, the default scalefactor seems to be doubling the size of the window - setting I believe that you can dictate size using physical units in matplotlib; perhaps that is a solution we could explore for the display-based backends. I uploaded a Youtube video of what I found here. Otherwise, I really love this PR! The (Sidenote: the "stresstest multiple displays" issue crops up again in tests, as mentioned in @pbouffard's comment). Test Summary: | Pass Total Time
destroying singleton screen | 1 1 3.0s
stresstest multi displays: Test Failed at /Users/anshul/Documents/Business/India/XKDR/dev/Makie.jl/GLMakie/test/unit_tests.jl:229
Expression: all((x->begin
x ≈ first(images)
end), images)
Stacktrace:
[1] macro expansion
@ /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Test/src/Test.jl:464 [inlined]
[2] macro expansion
@ ~/Documents/Business/India/XKDR/dev/Makie.jl/GLMakie/test/unit_tests.jl:229 [inlined]
[3] macro expansion
@ /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Test/src/Test.jl:1363 [inlined]
[4] top-level scope
@ ~/Documents/Business/India/XKDR/dev/Makie.jl/GLMakie/test/unit_tests.jl:211
Test Summary: | Pass Fail Total Time
stresstest multi displays | 133 1 134 17.3s
ERROR: LoadError: Some tests did not pass: 133 passed, 1 failed, 0 errored, 0 broken.
in expression starting at /Users/anshul/Documents/Business/India/XKDR/dev/Makie.jl/GLMakie/test/unit_tests.jl:210
in expression starting at /Users/anshul/Documents/Business/India/XKDR/dev/Makie.jl/GLMakie/test/runtests.jl:30
ERROR: Package GLMakie errored during testing |
I thought this was a change I made but I guess not JuliaPlots/GLMakie.jl#122. I made the same kind of change for mouse position before, because mouse position updates happen per pixel moved. I thought we changed window area for the same reason, but size updates seem to be batched. Moving the window triggers per pixel moved though, so we should try batching them to reduce the number of updates we trigger. (Or skip them entirely I guess) |
(Given my 200% scaled screen where
On at least Windows and Linux, yes, the doubling is expected and part of the goal. On my screen, old figures are far too small because they're sized for a low-DPI screen rather than a HiDPI one. There was Apple-specific code prior to this PR that has now been completely replaced. I thought the change I've been making are mostly just generalizing that, but since I can't actually test anything I do on OSX, it's all kind of just guessing on my part based on feedback I'm getting here. For example, if you repeat the test I did in the very first comment — saving a figure to SVG, opening in a browser, opening the same figure in GLMakie, and then comparing the two for relative size — are they roughly the same? (My experience is that Firefox has figured out the whole HiDPI mess on Linux, so I use it as a reference to say 800x600 logical pixels should be this size on a HiDPI screen.) Alternatively, some simple math checks also confirm I'm getting the apparent size I expect.
As for the overall size, I too think the defaults end up a bit too big, but that's just part of the theme. The default 16 (pt? px?) font size is just bigger than I'd normally use, but that's relatively easy to fix with the theme: set_theme!(fontsize = 12, resolution = (600, 450))
fig, _, _ = scatter([1, 2], [3, 4]) |
I can't reproduce that error on my system, so it's hard for me to debug.
Oh, that PR link is interesting, since I'm essentially reverting that completely. I should probably add a test for the race bug I was seeing to help justify why the change to the callback is necessary, but it'd also be good to fully understand the "async rendering" which was being fixed. For instance, if I rapidly resize the window back and forth, I do see the contents "lag" behind the actual size, and I can sometimes get a "wobbling" effect as the queued renders catch up. |
In case it's helpful (I'd really like to see this PR merged), I ran the tests on this branch rebased on master (and with Julia 1.9.0-beta4). This are mostly passing but this one in the GLMakie tests errors for me:
Full output
Similar error for CairoMakie tests:
Most WGLMakie tests pass but there were some failures: ]test WGLMakie output
MakieCore passes 100%. I'm not able to test RPRMakie, of course :) |
.. and finally, on Julia 1.8.5, I get the same error during the Hope these data points from a Mac M-series user are helpful. |
This is accomplished by making the window and rendered framebuffer sizes independent of one another. By separating the two concepts, we can create rasterized graphics at higher (or lower) resolution than what is shown on screen. The window scale factor is used to scale the sizes of elements within the window (and on Linux and Windows, the window size itself from the requested logical sizes), and the px-per-unit scale factor dictates the size of the rasterized render. The default scaling factors are initialized by requesting the content scale factor from GLFW (and dynamically responding to changes in the content scale factor on platforms where GLFW provides support). Testing is added on Linux where xvfb-run can be used to force a HiDPI context.
- Clear the `scalefactor` and `px_per_unit` observables when the figure is closed. It's possible both may be used during a figure's lifetime, but that should not persist past a close. - In the system scale factor callback, do not unconditionally resize the native window. Instead, leverage the fact that the observable callback will invoke a resize event, and that correctly will check that the root scene is not `nothing`. - Do not completely ignore the scale factor on OSX. The difference is that there is a native scaling factor applied by the OS, but if/when the desired scale factor differs from the native scaling, we must still make adjustments.
Instead of polling for window size changes on every render tick, use the size-changed callback from GLFW to only make changes when it is known that there's been a change in the size of the window. This solves a concurrency problem that can happen when the scale factor is changed. The sequence of events looks like: 1. The `screen.scalefactor[]` value is changed 2. The listeners to `scalefactor` start to be notified. 3. Asynchronously, the `WindowAreaUpdater` listener attached to the `render_tick` observable runs. 4. The window area listener notices that the window size given the _new_ value of the scale factor doesn't match the scene size, so it updates the scene size. 5. The `scalefactor` listener responsible for resizing the window gets its slice of time to run, and it now sees that everything is already the "correct" size. Therefore, the window is not resized, and instead the scene size is rescaled in the opposite direction of the scale factor change.
3f47986
to
5ba035c
Compare
I've squashed a bunch of the (relatively) sure commits into a single commit, and then I've kept some of the OSX-specific fixes and the potentially-more-controversial change to the window size callback as separate commits (to ease reverting if necessary). As for the failures on OSX, can anyone inspect/share the reference and test images to see what is the failing feature? In my latest local test run with julia-master, I'm also seeing some errors to do with finalizers/closing windows on Linux — I haven't investigated if that's new to this PR or a more general Julia v1.10-DEV problem, though... |
Unfortunately, I see the same error on Julia 1.8 so it's not just a DEV incompatibility. The assertion makes me wonder if it's related to #2553, though, since it's the assertion added there that's being violated. Rebasing has brought that PR into the history here, so the fact that I didn't used to see these errors would suggest a change on master either interacts poorly with changes here or these changes make a now existing error more obvious. Backtrace and error messageerror in running finalizer: GLFW.GLFWError(code=GLFW.ErrorCode(0x00010001), description="The GLFW library is not initialized") jl_f_throw at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/builtins.c:531 _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 _ErrorCallbackWrapper at /home/justin/.julia/packages/GLFW/BWxfF/src/callback.jl:43 unknown function (ip: 0x7ffa68b0efc3) _glfwInputError at /home/justin/.julia/artifacts/5aa80c7b8e919cbfee41019069d9b25269befe10/lib/libglfw.so (unknown line) HideWindow at /home/justin/.julia/packages/GLFW/BWxfF/src/glfw3.jl:604 [inlined] set_visibility! at /home/justin/.julia/packages/GLFW/BWxfF/src/glfw3.jl:376 [inlined] set_screen_visibility! at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:383 [inlined] set_screen_visibility! at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:380 [inlined] #close#54 at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:590 close at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:589 [inlined] #1021 at /home/justin/.julia/dev/Makie/src/display.jl:45 unknown function (ip: 0x7ffa3698f554) _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 jl_apply at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/julia.h:1843 [inlined] jl_f__call_latest at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/builtins.c:774 #invokelatest#2 at ./essentials.jl:729 [inlined] invokelatest at ./essentials.jl:726 [inlined] notify at /home/justin/.julia/packages/Observables/PHGQ8/src/Observables.jl:169 [inlined] setindex! at /home/justin/.julia/packages/Observables/PHGQ8/src/Observables.jl:86 [inlined] empty! at /home/justin/.julia/dev/Makie/src/scenes.jl:393 unknown function (ip: 0x7ffa369a7c22) _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 jl_apply at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/julia.h:1843 [inlined] run_finalizer at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:280 jl_gc_run_finalizers_in_list at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:367 run_finalizers at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:410 ijl_atexit_hook at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/init.c:236 jl_repl_entrypoint at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/jlapi.c:720 main at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/cli/loader_exe.c:59 unknown function (ip: 0x7ffa6a26d78f) __libc_start_main at /usr/lib/libc.so.6 (unknown line) unknown function (ip: 0x401098) error in running finalizer: GLFW.GLFWError(code=GLFW.ErrorCode(0x00010001), description="The GLFW library is not initialized") jl_f_throw at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/builtins.c:531 _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 _ErrorCallbackWrapper at /home/justin/.julia/packages/GLFW/BWxfF/src/callback.jl:43 unknown function (ip: 0x7ffa68b0efc3) _glfwInputError at /home/justin/.julia/artifacts/5aa80c7b8e919cbfee41019069d9b25269befe10/lib/libglfw.so (unknown line) HideWindow at /home/justin/.julia/packages/GLFW/BWxfF/src/glfw3.jl:604 [inlined] set_visibility! at /home/justin/.julia/packages/GLFW/BWxfF/src/glfw3.jl:376 [inlined] set_screen_visibility! at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:383 [inlined] set_screen_visibility! at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:380 [inlined] #close#54 at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:590 close at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:589 [inlined] #1021 at /home/justin/.julia/dev/Makie/src/display.jl:45 unknown function (ip: 0x7ffa3698f554) _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 jl_apply at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/julia.h:1843 [inlined] jl_f__call_latest at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/builtins.c:774 #invokelatest#2 at ./essentials.jl:729 [inlined] invokelatest at ./essentials.jl:726 [inlined] notify at /home/justin/.julia/packages/Observables/PHGQ8/src/Observables.jl:169 [inlined] setindex! at /home/justin/.julia/packages/Observables/PHGQ8/src/Observables.jl:86 [inlined] empty! at /home/justin/.julia/dev/Makie/src/scenes.jl:393 unknown function (ip: 0x7ffa369a7c22) _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 jl_apply at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/julia.h:1843 [inlined] run_finalizer at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:280 jl_gc_run_finalizers_in_list at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:367 run_finalizers at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:410 ijl_atexit_hook at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/init.c:236 jl_repl_entrypoint at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/jlapi.c:720 main at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/cli/loader_exe.c:59 unknown function (ip: 0x7ffa6a26d78f) __libc_start_main at /usr/lib/libc.so.6 (unknown line) unknown function (ip: 0x401098) error in running finalizer: GLFW.GLFWError(code=GLFW.ErrorCode(0x00010001), description="The GLFW library is not initialized") jl_f_throw at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/builtins.c:531 _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 _ErrorCallbackWrapper at /home/justin/.julia/packages/GLFW/BWxfF/src/callback.jl:43 unknown function (ip: 0x7ffa68b0efc3) _glfwInputError at /home/justin/.julia/artifacts/5aa80c7b8e919cbfee41019069d9b25269befe10/lib/libglfw.so (unknown line) HideWindow at /home/justin/.julia/packages/GLFW/BWxfF/src/glfw3.jl:604 [inlined] set_visibility! at /home/justin/.julia/packages/GLFW/BWxfF/src/glfw3.jl:376 [inlined] set_screen_visibility! at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:383 [inlined] set_screen_visibility! at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:380 [inlined] #close#54 at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:590 close at /home/justin/.julia/dev/Makie/GLMakie/src/screen.jl:589 [inlined] #1021 at /home/justin/.julia/dev/Makie/src/display.jl:45 unknown function (ip: 0x7ffa3698f554) _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 jl_apply at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/julia.h:1843 [inlined] jl_f__call_latest at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/builtins.c:774 #invokelatest#2 at ./essentials.jl:729 [inlined] invokelatest at ./essentials.jl:726 [inlined] notify at /home/justin/.julia/packages/Observables/PHGQ8/src/Observables.jl:169 [inlined] setindex! at /home/justin/.julia/packages/Observables/PHGQ8/src/Observables.jl:86 [inlined] empty! at /home/justin/.julia/dev/Makie/src/scenes.jl:393 unknown function (ip: 0x7ffa369a7c22) _jl_invoke at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2377 [inlined] ijl_apply_generic at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gf.c:2559 jl_apply at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/julia.h:1843 [inlined] run_finalizer at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:280 jl_gc_run_finalizers_in_list at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:367 run_finalizers at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/gc.c:410 ijl_atexit_hook at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/init.c:236 jl_repl_entrypoint at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/src/jlapi.c:720 main at /cache/build/default-aws-shared0-3/julialang/julia-release-1-dot-8/cli/loader_exe.c:59 unknown function (ip: 0x7ffa6a26d78f) __libc_start_main at /usr/lib/libc.so.6 (unknown line) unknown function (ip: 0x401098) ┌ Warning: error closing screen │ exception = │ AssertionError: nw.handle !== C_NULL │ Stacktrace: │ [1] set_screen_visibility! │ @ ~/.julia/dev/Makie/GLMakie/src/screen.jl:382 [inlined] │ [2] set_screen_visibility! │ @ ~/.julia/dev/Makie/GLMakie/src/screen.jl:380 [inlined] │ [3] close(screen::GLMakie.Screen{GLFW.Window}; reuse::Bool) │ @ GLMakie ~/.julia/dev/Makie/GLMakie/src/screen.jl:590 │ [4] close │ @ ~/.julia/dev/Makie/GLMakie/src/screen.jl:589 [inlined] │ [5] (::Makie.var"#1021#1022"{Scene, GLMakie.Screen{GLFW.Window}})(is_open::Bool) │ @ Makie ~/.julia/dev/Makie/src/display.jl:45 │ [6] #invokelatest#2 │ @ ./essentials.jl:729 [inlined] │ [7] invokelatest │ @ ./essentials.jl:726 [inlined] │ [8] (::Makie.var"#1021#1022"{Scene, GLMakie.Screen{GLFW.Window}})(is_open::Bool) │ @ Makie ~/.julia/dev/Makie/src/display.jl:55 │ [9] #invokelatest#2 │ @ ./essentials.jl:729 [inlined] │ [10] invokelatest │ @ ./essentials.jl:726 [inlined] │ [11] notify │ @ ~/.julia/packages/Observables/PHGQ8/src/Observables.jl:169 [inlined] │ [12] setindex! │ @ ~/.julia/packages/Observables/PHGQ8/src/Observables.jl:86 [inlined] │ [13] (::Makie.var"#953#954"{Scene})(open::Bool) │ @ Makie ~/.julia/dev/Makie/src/interaction/events.jl:17 │ [14] #invokelatest#2 │ @ ./essentials.jl:729 [inlined] │ [15] invokelatest │ @ ./essentials.jl:726 [inlined] │ [16] notify │ @ ~/.julia/packages/Observables/PHGQ8/src/Observables.jl:169 [inlined] │ [17] setindex! │ @ ~/.julia/packages/Observables/PHGQ8/src/Observables.jl:86 [inlined] │ [18] close(screen::GLMakie.Screen{GLFW.Window}; reuse::Bool) │ @ GLMakie ~/.julia/dev/Makie/GLMakie/src/screen.jl:593 │ [19] close │ @ ~/.julia/dev/Makie/GLMakie/src/screen.jl:589 [inlined] │ [20] renderloop(screen::GLMakie.Screen{GLFW.Window}) │ @ GLMakie ~/.julia/dev/Makie/GLMakie/src/screen.jl:927 │ [21] (::GLMakie.var"#61#62"{GLMakie.Screen{GLFW.Window}})() │ @ GLMakie ./task.jl:484 └ @ GLMakie ~/.julia/dev/Makie/GLMakie/src/screen.jl:929 |
That would mean glfwInit didn't run, failed or glfwTerminate ran. You should be getting a Julia error on The assertion is basically just "Window must exist" which is reasonable. Something would have to destroy (or fail to create) the window for it to trigger. Maybe it's trying to close the screen a second time from here, and failing? |
FWIW, I also happened on this error when trying to use a sysimage, see my post: https://discourse.julialang.org/t/errors-when-using-sysimage-with-makie-master/95132. |
merged into #2831 |
Continues #2831 ! Still needs to check, if I rebased correctly and didn't incorrectly apply some of the changes! ## Merged PRs - #2598 - #2746 - #2346 - #2544 - #3082 - #2868 - #3062 - #3106 - #3281 - #3246 ## TODOS - [x] fix flaky test `@test GLMakie.window_size(screen.glscreen) == scaled(screen, (W, H))` - [x] Merge axis type inferences from #2220 - [x] Test on different resolution screens, IJulia, Pluto, VSCode, Windowed - [x] rebase to only have merge commits from the PRs - [x] investigate unexpected speed ups - [x] reset camera settings from tests - [ ] check doc image generation - [x] rethink default near/far in Camera3D (compatability with OIT) - [x] merge #3246 - [x] fix WGLMakie issues/tests: - [x] fix line depth issues (see tests: ~~hexbin colorrange~~ (not new), LaTeXStrings in Axis3, Axis3 axis reversal) - [x] fix lighting of surface with nan points (fixed in #3246) - ~~volume/3D contour artifacts (see 3D Contour with 2D contour slices)~~ not new - ~~artifacting in "colorscale (lines)"~~ not new - [x] GLMakie: - [x] slight outline in "scatter image markers" test - ~~clipping/z-fighting in "volume translated"~~ not new - [x] CairoMakie: - ~~Artfiacting in `colorscale (lines)"~~ not new - ~~markersize in "scatter rotations" changed?~~ not new - ~~color change in "colorscale (poly)"~~ not new - ~~transparency/render order of "OldAxis + Surface"~~ not new - ~~render order in "Merged color mesh"~~ not new - ~~render order of "Surface + wireframe + contour"~~ not new - [x] Check "SpecApi in convert_arguments" (colors swapped?) ## Fixes the following errors - fixes #2721 via #2746 - fixes #1600 via #2746 - fixes #1236 via #2746 - fixes MakieOrg/GeoMakie.jl#133 via #2598 - closes #2522 - closes #3239 via #3246 - fixes #3238 via #3246 - fixes #2985 via #3246 - fixes #3307 via #3281
Description
On my HiDPI monitors [*], GLMakie's windows appear with a small default size and very small font size compared to other UI elements. Overriding themes to enlarge font sizes, default window size, default line thicknesses, etc is possible, but that makes sharing plotting scripts across machines difficult.
The approach I've taken here is to distinguish between a logical pixel and physical pixel, based on the fact that GLFW can report the device scaling factor in use. Therefore, the default window size, font sizes, marker/line sizes, etc can all be left alone (i.e. 800x600 window with 16pt fonts), and all lengths are dynamically rescaled by the device scaling factor during rendering.
With what I've hacked together, I can view images in GLMakie that have similar scale to those I'd get from saving an image to disk and loading in Firefox (which does similar HiDPI scaling from nominal "1x" CSS pixels to actual screen pixels):
Important caveats
I've also discovered that #2529 now exists, which must have been created just after I'd starting working on this independently. I've borrowed the
px_per_unit
nomenclature and including that in the theme from that PR, but otherwise I think this has taken a different approach. That might be a clue as to differences between Linux and OSX...[*] Machine details:
Type of change
Delete options that do not apply:
Checklist