Skip to content
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

Reviving CairoMakie/GLMakie integration #3652

Draft
wants to merge 37 commits into
base: master
Choose a base branch
from

Conversation

asinghvi17
Copy link
Member

This is a draft PR from my old GLMakie rasterization pipeline into CairoMakie.

As I recall, the issue was that displaying a child of the main Scene would cause that main Scene to resize to the size of the child's window, creating a loop of sorts. This was because scenes in a tree share the same events struct.

What I want to do here is figure out how to isolate or unlink the newly constructed screen from all events, so that subscenes can be displayed without resizing the main scene.

jmert and others added 30 commits January 29, 2023 20:20
By separating the two concepts, we can create rasterized graphics at
higher 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.
This works around a crash that otherwise occurs when creating a
screen directly with something like
```julia
screen = GLMakie.Screen(resolution = (100, 100), visible = false)
```

I'm not sure why this is necessary, though, so that probably points
at some subtle logic error in handling scaling factors and/or dimensions
of windows and buffers.
so force the scale and px-per-unit factors to unity for the test.
This was causing problems with setting up the stream size for video
outputs. Instead, just grab the scene size where necessary explicitly.
After identifying failing tests, closer reading suggests the line
rendering shaders all work in normalized units that arise naturally
from comparing the framebuffer size to resolution factor. This means
adding additional scaling is unnecessary since the framebuffer size
is already scaled.
- More explicit `range` to support older versions of Julia
- Force a render of the figure before testing picking operations, since
  that doesn't happen implicitly when the sequence is not done
  with a visible plot interactively.
- Use a less exact test for running within an Xvfb instance to support
  older versions of `xrdb` without the -get option.
- 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`.

  At the same time, clean up other callbacks a little bit by
  making use of `Base.Fix1` to pass the associated screen through via
  a closure.

- 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.
technically, the `render_scene` hack is no longer used
Basically data space, without applying `apply_transform`.  Works pretty well.

MWE:
```julia
fig, ax, plt = lines(1:10, 1:10; axis = (; xscale = log10))
lines!(ax, LinRange(0, 10, 10), 1:10; space = :transformed)
```

This is useful if you want to control when the plot's transform_func is applied, especially in a recipe!
@asinghvi17 asinghvi17 marked this pull request as draft February 23, 2024 15:05
@asinghvi17 asinghvi17 changed the title As/cairo glmakie hidpi Reviving CairoGLMakie Feb 26, 2024
@asinghvi17 asinghvi17 changed the title Reviving CairoGLMakie Reviving CairoMakie/GLMakie integration Feb 26, 2024
Base automatically changed from breaking-0.21 to master May 8, 2024 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants