Skip to content

Commit

Permalink
Merge branch 'master' into jw/gl_linux_hidpi
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonDanisch committed Feb 17, 2023
2 parents a0cbf85 + 406b48d commit 3f47986
Show file tree
Hide file tree
Showing 35 changed files with 561 additions and 95 deletions.
34 changes: 34 additions & 0 deletions CairoMakie/src/primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ function draw_atomic(scene::Scene, screen::Screen, @nospecialize(primitive::Unio
if !isnothing(linestyle) && !(linewidth isa AbstractArray)
Cairo.set_dash(ctx, diff(Float64.(linestyle)) .* linewidth)
end

if primitive isa Lines && primitive.input_args[1][] isa BezierPath
return draw_bezierpath_lines(ctx, primitive.input_args[1][], scene, color, space, model, linewidth)
end

if color isa AbstractArray || linewidth isa AbstractArray
# stroke each segment separately, this means disjointed segments with probably
# wonky dash patterns if segments are short
Expand All @@ -70,6 +75,35 @@ function draw_atomic(scene::Scene, screen::Screen, @nospecialize(primitive::Unio
nothing
end

function draw_bezierpath_lines(ctx, bezierpath::BezierPath, scene, color, space, model, linewidth)
for c in bezierpath.commands
proj_comm = project_command(c, scene, space, model)
path_command(ctx, proj_comm)
end
Cairo.set_source_rgba(ctx, rgbatuple(color)...)
Cairo.set_line_width(ctx, linewidth)
Cairo.stroke(ctx)
return
end

function project_command(m::MoveTo, scene, space, model)
MoveTo(project_position(scene, space, m.p, model))
end

function project_command(l::LineTo, scene, space, model)
LineTo(project_position(scene, space, l.p, model))
end

function project_command(c::CurveTo, scene, space, model)
CurveTo(
project_position(scene, space, c.c1, model),
project_position(scene, space, c.c2, model),
project_position(scene, space, c.p, model),
)
end

project_command(c::ClosePath, scene, space, model) = c

function draw_single(primitive::Lines, ctx, positions)
n = length(positions)
@inbounds for i in 1:n
Expand Down
2 changes: 1 addition & 1 deletion GLMakie/assets/shader/postprocessing/SSAO_blur.frag
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ void main(void)
{
// occlusion blur
uvec2 id0 = texture(ids, frag_uv).xy;
if (id0.x == 0){
if (id0.x == uint(0)){
fragment_color = texture(color_texture, frag_uv);
// fragment_color = vec4(1,0,1,1); // show discarded
return;
Expand Down
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# News

## master
- Added the `stephist` plotting function [#2408](https://github.com/JuliaPlots/Makie.jl/pull/2408).

- Added the `stephist` plotting function [#2408](https://github.com/JuliaPlots/Makie.jl/pull/2408).
- Fixed an issue where `poly` plots with `Vector{<: MultiPolygon}` inputs with per-polygon color were mistakenly rendered as meshes using CairoMakie. [#2590](https://github.com/MakieOrg/Makie.jl/pulls/2478)
- Fixed a small typo which caused an error in the `Stepper` constructor. [#2600](https://github.com/MakieOrg/Makie.jl/pulls/2478)
- GLMakie has gained support for HiDPI (aka Retina) screens.
This also enables saving images with higher resolution than screen pixel dimensions.
[#2544](https://github.com/MakieOrg/Makie.jl/pull/2544)
- Fixed rectangle zoom for nonlinear axes [#2674](https://github.com/MakieOrg/Makie.jl/pull/2674)

## v0.19.1

Expand Down
56 changes: 56 additions & 0 deletions ReferenceTests/src/tests/examples2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,63 @@ end
f
end

@reference_test "bracket scalar" begin
f, ax, l = lines(0..9, sin; axis = (; xgridvisible = false, ygridvisible = false))
ylims!(ax, -1.5, 1.5)

bracket!(pi/2, 1, 5pi/2, 1, offset = 5, text = "Period length", style = :square)

bracket!(pi/2, 1, pi/2, -1, text = "Amplitude", orientation = :down,
linestyle = :dash, rotation = 0, align = (:right, :center), textoffset = 4, linewidth = 2, color = :red, textcolor = :red)

bracket!(2.3, sin(2.3), 4.0, sin(4.0),
text = "Falling", offset = 10, orientation = :up, color = :purple, textcolor = :purple)

bracket!(Point(5.5, sin(5.5)), Point(7.0, sin(7.0)),
text = "Rising", offset = 10, orientation = :down, color = :orange, textcolor = :orange,
fontsize = 30, textoffset = 30, width = 50)
f
end

@reference_test "bracket vector" begin
f = Figure()
ax = Axis(f[1, 1])

bracket!(ax,
1:5,
2:6,
3:7,
2:6,
text = ["A", "B", "C", "D", "E"],
orientation = :down,
)

bracket!(ax,
[(Point2f(i, i-0.7), Point2f(i+2, i-0.7)) for i in 1:5],
text = ["F", "G", "H", "I", "J"],
color = [:red, :blue, :green, :orange, :brown],
linestyle = [:dash, :dot, :dash, :dot, :dash],
orientation = [:up, :down, :up, :down, :up],
textcolor = [:red, :blue, :green, :orange, :brown],
fontsize = range(12, 24, length = 5),
)

f
end

@reference_test "Stephist" begin
stephist(RNG.rand(10000))
current_figure()
end

@reference_test "LaTeXStrings linesegment offsets" begin
s = Scene(camera = campixel!, resolution = (600, 600))
for (i, (offx, offy)) in enumerate(zip([0, 20, 50], [0, 10, 30]))
for (j, rot) in enumerate([0, pi/4, pi/2])
scatter!(s, 150i, 150j)
text!(s, 150i, 150j, text = L"\sqrt{x+y}", offset = (offx, offy),
rotation = rot, fontsize = 30)
end
end
s
end
10 changes: 10 additions & 0 deletions ReferenceTests/src/tests/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,13 @@ end
ylims!(ax, -0.8, 0.6)
fig
end

@reference_test "label type change" begin
fig = Figure()
ax = Axis3(fig[1, 1])
ax.xlabel[] = L"1 + \alpha^2"
ax.ylabel[] = L"\lim_{x\to\infty} f(x)"
ax.zlabel[] = L"\sum_{n=1}^{\infty} 2^{-n} = 1"
fig
end

2 changes: 1 addition & 1 deletion ReferenceTests/src/tests/updating.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function load_frames(video, dir)
mkdir(framedir)
Makie.extract_frames(video, framedir)
return map(readdir(framedir; join=true)) do path
return convert(Matrix{RGB{N0f8}}, load(path))
return convert(Matrix{RGB{N0f8}}, FileIO.load(path))
end
end

Expand Down
21 changes: 20 additions & 1 deletion WGLMakie/src/Serialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ export function deserialize_scene(data, screen) {
scene.screen = screen;
const { canvas } = screen;
add_scene(data.uuid, scene);
scene.scene_uuid = data.uuid;
scene.frustumCulled = false;
scene.pixelarea = data.pixelarea;
scene.backgroundcolor = data.backgroundcolor;
Expand Down Expand Up @@ -515,4 +516,22 @@ export function deserialize_scene(data, screen) {
return scene;
}

export { TEXTURE_ATLAS, scene_cache };
export function delete_plot(plot) {
delete plot_cache[plot.plot_uuid];
const {parent} = plot
if (parent) {
parent.remove(plot)
}
plot.geometry.dispose();
plot.material.dispose();
}

export function delete_three_scene(scene) {
delete scene_cache[scene.scene_uuid];
scene.scene_children.forEach(delete_three_scene);
while(scene.children.length > 0) {
delete_plot(scene.children[0])
}
}

export { TEXTURE_ATLAS, scene_cache, plot_cache };
2 changes: 1 addition & 1 deletion WGLMakie/src/WGLMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function activate!(; screen_config...)
return
end

const TEXTURE_ATLAS = Observable{Vector{Float32}}()
const TEXTURE_ATLAS = Observable(Float32[])

wgl_texture_atlas() = Makie.get_texture_atlas(1024, 32)

Expand Down
17 changes: 15 additions & 2 deletions WGLMakie/src/display.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function JSServe.jsrender(session::Session, scene::Scene)
c = Channel{ThreeDisplay}(1)
put!(c, three)
screen = Screen(c, true, scene)
screen.session = session
Makie.push_screen!(scene, screen)
on(on_init) do i
mark_as_displayed!(screen, scene)
Expand Down Expand Up @@ -60,14 +61,15 @@ $(Base.doc(MakieScreen))
"""
mutable struct Screen <: Makie.MakieScreen
three::Channel{ThreeDisplay}
session::Union{Nothing, Session}
display::Any
scene::Union{Nothing, Scene}
displayed_scenes::Set{String}
function Screen(
three::Channel{ThreeDisplay},
display::Any,
scene::Union{Nothing, Scene})
return new(three, display, scene, Set{String}())
return new(three, nothing, display, scene, Set{String}())
end
end

Expand All @@ -88,6 +90,7 @@ for M in WEB_MIMES
@eval begin
function Makie.backend_show(screen::Screen, io::IO, m::$M, scene::Scene)
inline_display = App() do session::Session
screen.session = session
three, canvas, init_obs = three_display(session, scene)
Makie.push_screen!(scene, screen)
on(init_obs) do _
Expand Down Expand Up @@ -115,6 +118,10 @@ function Base.size(screen::Screen)
end

function get_three(screen::Screen; timeout = 100, error::Union{Nothing, String}=nothing)::Union{Nothing, ThreeDisplay}
if screen.display !== true
error("Screen hasn't displayed anything, so can't get three context")
end
isnothing(screen.session) && return nothing
tstart = time()
result = nothing
while true
Expand Down Expand Up @@ -159,6 +166,7 @@ function Base.display(screen::Screen, scene::Scene; kw...)
Makie.push_screen!(scene, screen)
# Reference to three object which gets set once we serve this to a browser
app = App() do session, request
screen.session = session
three, canvas, done_init = three_display(session, scene)
on(done_init) do _
put!(screen.three, three)
Expand Down Expand Up @@ -241,8 +249,13 @@ function Base.insert!(screen::Screen, scene::Scene, plot::Combined)
end

function Base.delete!(td::Screen, scene::Scene, plot::Combined)
isopen(scene) || return
three = get_three(td)
isnothing(three) && return # if no session we haven't displayed and dont need to delete
isready(three.session) || return

uuids = js_uuid.(Makie.flatten_plots(plot))
JSServe.evaljs(td.session, js"""
JSServe.evaljs(three.session, js"""
$(WGL).then(WGL=> {
WGL.delete_plots($(js_uuid(scene)), $uuids);
})""")
Expand Down
43 changes: 34 additions & 9 deletions WGLMakie/src/imagelike.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,40 @@ xy_convert(x::AbstractArray{Float32}, n) = copy(x)
xy_convert(x::AbstractArray, n) = el32convert(x)
xy_convert(x, n) = Float32[LinRange(extrema(x)..., n + 1);]

# TODO, speed up GeometryBasics
function fast_faces(nvertices)
w, h = nvertices
idx = LinearIndices(nvertices)
nfaces = 2 * (w - 1) * (h - 1)
faces = Vector{GLTriangleFace}(undef, nfaces)
face_idx = 1
@inbounds for i in 1:(w - 1)
for j in 1:(h - 1)
a, b, c, d = idx[i, j], idx[i + 1, j], idx[i + 1, j + 1], idx[i, j + 1]
faces[face_idx] = GLTriangleFace(a, b, c)
face_idx += 1
faces[face_idx] = GLTriangleFace(a, c, d)
face_idx += 1
end
end
return faces
end
# TODO, speed up GeometryBasics
function fast_uv(nvertices)
xrange, yrange = LinRange.((0, 1), (1, 0), nvertices)
return [Vec2f(x, y) for y in yrange for x in xrange]
end

function limits_to_uvmesh(plot)
px, py, pz = plot[1], plot[2], plot[3]
px = map((x, z)-> xy_convert(x, size(z, 1)), px, pz)
py = map((y, z)-> xy_convert(y, size(z, 2)), py, pz)
px = map((x, z)-> xy_convert(x, size(z, 1)), px, pz; ignore_equal_values=true)
py = map((y, z) -> xy_convert(y, size(z, 2)), py, pz; ignore_equal_values=true)
# Special path for ranges of length 2 which
# can be displayed as a rectangle
t = Makie.transform_func_obs(plot)[]

# TODO, this branch is only hit by Image, but not for Heatmap with stepranges
# because convert_arguments converts x/y to Vector{Float32}
if px[] isa StepRangeLen && py[] isa StepRangeLen && Makie.is_identity_transform(t)
rect = lift(px, py) do x, y
xmin, xmax = extrema(x)
Expand All @@ -68,14 +95,12 @@ function limits_to_uvmesh(plot)
uv = Buffer(lift(decompose_uv, rect))
else
grid(x, y, trans, space) = Makie.matrix_grid(p-> apply_transform(trans, p, space), x, y, zeros(length(x), length(y)))
rect = lift((x, y) -> Tesselation(Rect2(0f0, 0f0, 1f0, 1f0), (length(x), length(y))), px, py)
resolution = lift((x, y) -> (length(x), length(y)), px, py; ignore_equal_values=true)
positions = Buffer(lift(grid, px, py, t, get(plot, :space, :data)))
faces = Buffer(lift(r -> decompose(GLTriangleFace, r), rect))
uv = Buffer(lift(decompose_uv, rect))
faces = Buffer(lift(fast_faces, resolution))
uv = Buffer(lift(fast_uv, resolution))
end

vertices = GeometryBasics.meta(positions; uv=uv)

return GeometryBasics.Mesh(vertices, faces)
end

Expand Down Expand Up @@ -172,8 +197,8 @@ function create_shader(mscene::Scene, plot::Volume)
:isorange => lift(Float32, plot.isorange),
:absorption => lift(Float32, get(plot, :absorption, Observable(1.0f0))),
:algorithm => algorithm,
:diffuse => diffuse,
:specular => specular,
:diffuse => diffuse,
:specular => specular,
:shininess => shininess,
:model => model2,
:depth_shift => get(plot, :depth_shift, Observable(0.0f0)),
Expand Down
1 change: 1 addition & 0 deletions WGLMakie/src/picking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function Makie.pick_sorted(scene::Scene, screen::Screen, xy, range)
selection = JSServe.evaljs_value(session, js"""
Promise.all([$(WGL), $(scene)]).then(([WGL, scene]) => WGL.pick_sorted(scene, $(xy_vec), $(range)))
""")
isnothing(selection) && return Tuple{Union{Nothing,AbstractPlot},Int}[]
lookup = plot_lookup(scene)
return map(selection) do (plot_id, index)
return (lookup[plot_id], index + 1)
Expand Down
26 changes: 15 additions & 11 deletions WGLMakie/src/precompiles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ using SnoopPrecompile

macro compile(block)
return quote
figlike = $(esc(block))
# We don't do something like colorbuffer(fig)
# since we can't guarantee that the user has a browser setup
# while precompiling
# So we just do all parts of the stack we can do without browser
scene = Makie.get_scene(figlike)
session = Session(JSServe.NoConnection(); asset_server=JSServe.NoServer())
three_display(session, scene)
JSServe.jsrender(session, figlike)
s = serialize_scene(scene)
JSServe.serialize_binary(session, Dict(:data => s))
let
figlike = $(esc(block))
# We don't do something like colorbuffer(fig)
# since we can't guarantee that the user has a browser setup
# while precompiling
# So we just do all parts of the stack we can do without browser
scene = Makie.get_scene(figlike)
session = Session(JSServe.NoConnection(); asset_server=JSServe.NoServer())
three_display(session, scene)
JSServe.jsrender(session, figlike)
s = serialize_scene(scene)
JSServe.SerializedMessage(session, Dict(:data => s))
close(session)
nothing
end
end
end

Expand Down
Loading

0 comments on commit 3f47986

Please sign in to comment.