Add a compute shader path, optimize GPU memory management, and switch from SDL

to `surfman`.

This is a large commit; explanations of each change follow.

This adds an optional compute shader path, off by default, for rendering fills
to alpha masks. It usually does not improve performance at present, but it
provides a good baseline for further optimizations. Later improvements will
likely aim to avoid writes to the mask texture entirely. Supporting
infrastructure for compute shader has been added to `pathfinder_gpu` for the
OpenGL and Metal backends.

The Metal backend has been optimized to avoid unneccessary buffer allocations
and reflection. As part of this, argument buffers have been removed, as the
current SPIRV-Cross compiler no longer requires them.

The GPU renderer has been improved to avoid stalls. Now, separate buffers are
allocated for each fill batch and for each frame. This can be extended in the
future to allow for separate buffers for tile draw operations as well.

SDL usage has been removed in favor of the native Rust `surfman` and `winit`.
Because `surfman` allows for selection of the integrated GPU on multi-GPU
system, it is chosen by default. The demo supports a new
`--high-performance-gpu` option to opt into the discrete GPU.
This commit is contained in:
Patrick Walton 2020-04-23 18:00:52 -07:00
parent 84bf4341c2
commit ac83f79d94
53 changed files with 2975 additions and 1184 deletions

376
Cargo.lock generated
View File

@ -233,6 +233,7 @@ dependencies = [
name = "canvas_minimal"
version = "0.1.0"
dependencies = [
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_canvas 0.5.0",
"pathfinder_color 0.5.0",
@ -242,14 +243,15 @@ dependencies = [
"pathfinder_gpu 0.5.0",
"pathfinder_renderer 0.5.0",
"pathfinder_resources 0.5.0",
"sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"surfman 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "canvas_moire"
version = "0.1.0"
dependencies = [
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_canvas 0.5.0",
"pathfinder_color 0.5.0",
@ -259,8 +261,8 @@ dependencies = [
"pathfinder_gpu 0.5.0",
"pathfinder_renderer 0.5.0",
"pathfinder_resources 0.5.0",
"sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"surfman 0.2.0",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -268,6 +270,7 @@ name = "canvas_nanovg"
version = "0.1.0"
dependencies = [
"arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"font-kit 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.23.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -282,8 +285,8 @@ dependencies = [
"pathfinder_renderer 0.5.0",
"pathfinder_resources 0.5.0",
"pathfinder_simd 0.5.0",
"sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"surfman 0.2.0 (git+https://github.com/pcwalton/surfman?rev=bc29e7ae88ca7dd64d3b1c7e185604693290207f)",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -373,6 +376,20 @@ dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cocoa"
version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cocoa"
version = "0.19.1"
@ -620,11 +637,15 @@ name = "demo"
version = "0.1.0"
dependencies = [
"color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_demo 0.1.0",
"pathfinder_geometry 0.5.1",
"pathfinder_gl 0.5.0",
@ -633,8 +654,8 @@ dependencies = [
"pathfinder_resources 0.5.0",
"pathfinder_simd 0.5.0",
"pretty_env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"surfman 0.2.0",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -662,6 +683,17 @@ name = "dispatch"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "display-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time-point 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dlib"
version = "0.4.1"
@ -899,6 +931,16 @@ dependencies = [
"gl_generator 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gl_generator"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gl_generator"
version = "0.13.1"
@ -919,6 +961,14 @@ dependencies = [
"xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gleam"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gl_generator 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glutin"
version = "0.23.0"
@ -1094,6 +1144,18 @@ dependencies = [
"web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "io-surface"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cgl 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -1201,6 +1263,19 @@ name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "leak"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "leaky-cow"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lexical-core"
version = "0.6.2"
@ -1278,6 +1353,14 @@ name = "lzw"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
@ -1488,6 +1571,16 @@ dependencies = [
"objc_exception 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "objc_exception"
version = "0.1.2"
@ -1496,6 +1589,14 @@ dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "objc_id"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ordered-float"
version = "1.0.2"
@ -1512,6 +1613,16 @@ dependencies = [
"shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.10.2"
@ -1521,6 +1632,20 @@ dependencies = [
"parking_lot_core 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.7.1"
@ -1612,6 +1737,7 @@ dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.23.3 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_color 0.5.0",
@ -1715,9 +1841,11 @@ dependencies = [
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_geometry 0.5.1",
@ -2258,11 +2386,35 @@ name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smallvec"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smithay-client-toolkit"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-commons 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-protocols 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smithay-client-toolkit"
version = "0.6.6"
@ -2301,6 +2453,87 @@ name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "surfman"
version = "0.2.0"
source = "git+https://github.com/pcwalton/surfman?rev=bc29e7ae88ca7dd64d3b1c7e185604693290207f#bc29e7ae88ca7dd64d3b1c7e185604693290207f"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cgl 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"display-link 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wio 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.18.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "surfman"
version = "0.2.0"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cgl 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"display-link 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wio 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.18.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "surfman"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cgl 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"display-link 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wio 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.18.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "svg-to-skia"
version = "0.1.0"
@ -2423,6 +2656,11 @@ dependencies = [
"miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time-point"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "toml"
version = "0.5.6"
@ -2588,6 +2826,20 @@ name = "wasm-bindgen-shared"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wayland-client"
version = "0.21.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-commons 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-scanner 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-client"
version = "0.23.6"
@ -2604,6 +2856,15 @@ dependencies = [
"wayland-sys 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-commons"
version = "0.21.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-commons"
version = "0.23.6"
@ -2613,6 +2874,18 @@ dependencies = [
"wayland-sys 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-protocols"
version = "0.21.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-commons 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-scanner 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-protocols"
version = "0.23.6"
@ -2624,6 +2897,16 @@ dependencies = [
"wayland-scanner 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-scanner"
version = "0.21.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-scanner"
version = "0.23.6"
@ -2634,6 +2917,15 @@ dependencies = [
"xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-sys"
version = "0.21.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-sys"
version = "0.23.6"
@ -2643,6 +2935,15 @@ dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-sys"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "web-sys"
version = "0.3.37"
@ -2689,6 +2990,29 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winit"
version = "0.19.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11-dl 2.18.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winit"
version = "0.21.0"
@ -2734,6 +3058,15 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x11"
version = "2.18.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x11-dl"
version = "2.18.5"
@ -2799,6 +3132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
"checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
"checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400"
"checksum color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65d13f1078cc63c791d0deba0dd43db37c9ec02b311f10bed10b577016f3a957"
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
@ -2827,6 +3161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
"checksum dispatch 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
"checksum display-link 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "303de632386f9c82eb7823456f5932bd40b4de9521078901767bf16a9f331491"
"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
"checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"
"checksum dwrote 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcdf488e3a52a7aa30a05732a3e58420e22acb4b2b75635a561fc6ffbcab59ef"
@ -2854,8 +3189,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum gif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af"
"checksum gimli 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81dd6190aad0f05ddbbf3245c54ed14ca4aa6dd32f22312b70d8f168c3e3e633"
"checksum gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404"
"checksum gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39a23d5e872a275135d66895d954269cf5e8661d234eb1c2480f4ce0d586acbd"
"checksum gl_generator 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ca98bbde17256e02d17336a6bdb5a50f7d0ccacee502e191d3e3d0ec2f96f84a"
"checksum gl_generator 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
"checksum gleam 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ea4f9ba7411ae3f00516401fb811b4f4f37f5c926357f2a033d27f96b74c849"
"checksum glutin 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf22d4e90c55d9be9f2ad52410e7a2c0d7e9c99d93a13df73a672e7ef4e8c7f7"
"checksum glutin_egl_sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772edef3b28b8ad41e4ea202748e65eefe8e5ffd1f4535f1219793dbb20b3d4c"
"checksum glutin_emscripten_sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1"
@ -2874,6 +3211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum image 0.23.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc5483f8d5afd3653b38a196c52294dcb239c3e1a5bade1990353ea13bcf387"
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
"checksum instant 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c346c299e3fe8ef94dc10c2c0253d858a69aac1245157a3bf4125915d528caf"
"checksum io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2279a6faecd06034f88218f77f7a767693e0957bce0323a96d92747e2760b445"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
"checksum jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
@ -2888,6 +3226,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum kurbo 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bf50e17a1697110c694d47c5b1a6b64faf5eb3ffe5a286df23fb8cd516e33be6"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73"
"checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc"
"checksum lexical-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
@ -2897,6 +3237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lzma-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0606857a51b9088eb75b52d8431b7b7c8656849cc6cb96dde9f3d18a1a4b58"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
@ -2920,10 +3261,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
"checksum objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
"checksum objc_exception 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
"checksum parking_lot_core 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
@ -2978,12 +3323,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum skribo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6e9e713ecb4b6d3047428d060aa46cf4abd1109a961da245359e8f88a529d16"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
"checksum smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
"checksum smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa"
"checksum smithay-client-toolkit 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "421c8dc7acf5cb205b88160f8b4cc2c5cfabe210e43b2f80f009f4c1ef910f1d"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
"checksum stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum surfman 0.2.0 (git+https://github.com/pcwalton/surfman?rev=bc29e7ae88ca7dd64d3b1c7e185604693290207f)" = "<none>"
"checksum surfman 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d28b4931b29b2c65fcce61898d6b4dbae2337a60308176c2d5cbff0913740d4a"
"checksum svgtypes 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff"
"checksum swf-fixed 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6b212c20df50b382c442a4098d7d9f1c94f0b040f0f0a5d120fa3a82fa51e302"
"checksum swf-parser 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "847c41c7add3a5a64524fa5883ba4f2ecaccb2e429df9a3d4ed17ad8e379c15f"
@ -2994,6 +3343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum tiff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "002351e428db1eb1d8656d4ca61947c3519ac3191e1c804d4600cd32093b77ad"
"checksum time-point 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06535c958d6abe68dc4b4ef9e6845f758fc42fe463d0093d0aca40254f03fb14"
"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
"checksum ttf-parser 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a67a691cd15aae8f55fcc6e68efec96ec9e6e3ad967ac16f18681e2268c92037"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@ -3015,11 +3365,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum wasm-bindgen-macro 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4"
"checksum wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931"
"checksum wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
"checksum wayland-client 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)" = "49963e5f9eeaf637bfcd1b9f0701c99fd5cd05225eb51035550d4272806f2713"
"checksum wayland-client 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)" = "af1080ebe0efabcf12aef2132152f616038f2d7dcbbccf7b2d8c5270fe14bcda"
"checksum wayland-commons 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)" = "40c08896768b667e1df195d88a62a53a2d1351a1ed96188be79c196b35bb32ec"
"checksum wayland-commons 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bb66b0d1a27c39bbce712b6372131c6e25149f03ffb0cd017cf8f7de8d66dbdb"
"checksum wayland-protocols 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4afde2ea2a428eee6d7d2c8584fdbe8b82eee8b6c353e129a434cd6e07f42145"
"checksum wayland-protocols 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc286643656742777d55dc8e70d144fa4699e426ca8e9d4ef454f4bf15ffcf9"
"checksum wayland-scanner 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3828c568714507315ee425a9529edc4a4aa9901409e373e9e0027e7622b79e"
"checksum wayland-scanner 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93b02247366f395b9258054f964fe293ddd019c3237afba9be2ccbe9e1651c3d"
"checksum wayland-sys 0.21.13 (registry+https://github.com/rust-lang/crates.io-index)" = "520ab0fd578017a0ee2206623ba9ef4afe5e8f23ca7b42f6acfba2f4e66b1628"
"checksum wayland-sys 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d94e89a86e6d6d7c7c9b19ebf48a03afaac4af6bc22ae570e9a24124b75358f4"
"checksum wayland-sys 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "537500923d50be11d95a63c4cb538145e4c82edf61296b7debc1f94a1a6514ed"
"checksum web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
@ -3027,9 +3383,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winit 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7d0da905e61ae52d55c5ca6f8bea1e09daf5e325b6c77b0947c65a5179b49f5f"
"checksum winit 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65a5c1a5ef76ac31cc97ad29489acdbed2178f3fc12ca00ee6cb11d60adb5a3a"
"checksum wio 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum x11 2.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773"
"checksum x11-dl 2.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
"checksum xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb76e5c421bbbeb8924c60c030331b345555024d56261dae8f3e786ed817c23"

View File

@ -39,7 +39,7 @@ use std::slice;
use std::str;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use metal::{CAMetalLayer, CoreAnimationLayerRef};
use metal::{CAMetalLayer, CoreAnimationLayerRef, Device};
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use pathfinder_metal::MetalDevice;
@ -617,7 +617,9 @@ pub unsafe extern "C" fn PFSceneProxyBuildAndRenderMetal(scene_proxy: PFScenePro
#[no_mangle]
pub unsafe extern "C" fn PFMetalDeviceCreate(layer: *mut CAMetalLayer)
-> PFMetalDeviceRef {
Box::into_raw(Box::new(MetalDevice::new(CoreAnimationLayerRef::from_ptr(layer))))
let device = Device::system_default().expect("Failed to get Metal system default device!");
let layer = CoreAnimationLayerRef::from_ptr(layer);
Box::into_raw(Box::new(MetalDevice::new(device, layer.next_drawable().unwrap())))
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
@ -626,12 +628,6 @@ pub unsafe extern "C" fn PFMetalDeviceDestroy(device: PFMetalDeviceRef) {
drop(Box::from_raw(device))
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
#[no_mangle]
pub unsafe extern "C" fn PFMetalDevicePresentDrawable(device: PFMetalDeviceRef) {
(*device).present_drawable()
}
// `renderer`
#[no_mangle]
@ -806,6 +802,8 @@ impl PFRendererOptions {
} else {
None
},
// TODO(pcwalton): Expose this in the C API.
use_compute: false,
}
}
}

View File

@ -57,5 +57,8 @@ path = "../../ui"
[target.'cfg(target_os = "macos")'.dependencies]
metal = "0.17"
[target.'cfg(target_os = "macos")'.dependencies.io-surface]
version = "0.12"
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
path = "../../metal"

View File

@ -29,7 +29,7 @@ where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> GroundProgram<D> {
let program = device.create_program(resources, "demo_ground");
let program = device.create_raster_program(resources, "demo_ground");
let transform_uniform = device.get_uniform(&program, "Transform");
let gridline_count_uniform = device.get_uniform(&program, "GridlineCount");
let ground_color_uniform = device.get_uniform(&program, "GroundColor");

View File

@ -116,13 +116,13 @@ pub struct DemoApp<W> where W: Window {
}
impl<W> DemoApp<W> where W: Window {
pub fn new(window: W, window_size: WindowSize, mut options: Options) -> DemoApp<W> {
pub fn new(window: W, window_size: WindowSize, options: Options) -> DemoApp<W> {
let expire_message_event_id = window.create_user_event_id();
let device;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
{
device = DeviceImpl::new(window.metal_layer());
unsafe {
device = DeviceImpl::new(window.metal_device(), window.metal_io_surface());
}
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
{
@ -131,14 +131,14 @@ impl<W> DemoApp<W> where W: Window {
let resources = window.resource_loader();
// Read command line options.
options.command_line_overrides();
// Set up the executor.
let executor = DemoExecutor::new(options.jobs);
let mut ui_model = DemoUIModel::new(&options);
let render_options = RendererOptions { background_color: None };
let render_options = RendererOptions {
background_color: None,
use_compute: options.compute,
};
let filter = build_filter(&ui_model);
@ -624,6 +624,8 @@ pub struct Options {
pub input_path: SVGPath,
pub ui: UIVisibility,
pub background_color: BackgroundColor,
pub high_performance_gpu: bool,
pub compute: bool,
hidden_field_for_future_proofing: (),
}
@ -635,13 +637,15 @@ impl Default for Options {
input_path: SVGPath::Default,
ui: UIVisibility::All,
background_color: BackgroundColor::Light,
high_performance_gpu: false,
compute: false,
hidden_field_for_future_proofing: (),
}
}
}
impl Options {
fn command_line_overrides(&mut self) {
pub fn command_line_overrides(&mut self) {
let matches = App::new("tile-svg")
.arg(
Arg::with_name("jobs")
@ -681,6 +685,18 @@ impl Options {
.possible_values(&["light", "dark", "transparent"])
.help("The background color to use"),
)
.arg(
Arg::with_name("high-performance-gpu")
.short("g")
.long("high-performance-gpu")
.help("Use the high-performance (discrete) GPU, if available")
)
.arg(
Arg::with_name("compute")
.short("c")
.long("compute")
.help("Use compute shaders for certain tasks, if available")
)
.arg(
Arg::with_name("INPUT")
.help("Path to the SVG file to render")
@ -714,6 +730,14 @@ impl Options {
};
}
if matches.is_present("high-performance-gpu") {
self.high_performance_gpu = true;
}
if matches.is_present("compute") {
self.compute = true;
}
if let Some(path) = matches.value_of("INPUT") {
self.input_path = SVGPath::Path(PathBuf::from(path));
};

View File

@ -89,7 +89,10 @@ impl<W> DemoApp<W> where W: Window {
Mode::ThreeD => None,
Mode::VR => Some(ColorF::transparent_black()),
};
self.renderer.set_options(RendererOptions { background_color: clear_color });
self.renderer.set_options(RendererOptions {
background_color: clear_color,
use_compute: self.options.compute,
});
scene_count
}
@ -229,6 +232,7 @@ impl<W> DemoApp<W> where W: Window {
vertex_array: &self.ground_vertex_array.vertex_array,
primitive: Primitive::Triangles,
textures: &[],
images: &[],
uniforms: &[
(&self.ground_program.transform_uniform,
UniformData::from_transform_3d(&transform)),

View File

@ -18,9 +18,11 @@ use rayon::ThreadPoolBuilder;
use std::path::PathBuf;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use metal::CoreAnimationLayerRef;
use io_surface::IOSurfaceRef;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use pathfinder_metal::MetalDevice;
use metal::Device as MetalDevice;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use pathfinder_metal::MetalDevice as PathfinderMetalDevice;
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use gl::types::GLuint;
@ -36,9 +38,11 @@ pub trait Window {
fn present(&mut self, device: &mut GLDevice);
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn metal_layer(&self) -> &CoreAnimationLayerRef;
fn metal_device(&self) -> MetalDevice;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn present(&mut self, device: &mut MetalDevice);
fn metal_io_surface(&self) -> IOSurfaceRef;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn present(&mut self, device: &mut PathfinderMetalDevice);
fn make_current(&mut self, view: View);
fn viewport(&self, view: View) -> RectI;

View File

@ -11,10 +11,13 @@ pf-no-simd = ["pathfinder_simd/pf-no-simd"]
[dependencies]
color-backtrace = "0.3"
gl = "0.14"
lazy_static = "1"
nfd = "0.0.4"
pretty_env_logger = "0.4"
sdl2 = "0.33"
sdl2-sys = "0.33"
[dependencies.euclid]
version = "0.20"
features = []
[dependencies.pathfinder_demo]
path = "../common"
@ -34,9 +37,19 @@ path = "../../resources"
[dependencies.pathfinder_simd]
path = "../../simd"
[dependencies.surfman]
# version = "0.2"
path = "/Users/pcwalton/Source/surfman/surfman"
features = ["sm-winit"]
[dependencies.winit]
version = "<0.19.4" # 0.19.4 causes build errors https://github.com/rust-windowing/winit/pull/1105
[target.'cfg(target_os = "macos")'.dependencies]
foreign-types = "0.3"
io-surface = "0.12"
metal = "0.17"
objc = "0.2"
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
path = "../../metal"

View File

@ -10,38 +10,48 @@
//! A demo app for Pathfinder using SDL 2.
#[macro_use]
extern crate lazy_static;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
extern crate objc;
use euclid::default::Size2D;
use nfd::Response;
use pathfinder_demo::window::{Event, Keycode, SVGPath, View, Window, WindowSize};
use pathfinder_demo::{DemoApp, Options};
use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::vec2i;
use pathfinder_geometry::vector::{Vector2I, vec2i};
use pathfinder_resources::ResourceLoader;
use pathfinder_resources::fs::FilesystemResourceLoader;
use sdl2::event::{Event as SDLEvent, WindowEvent};
use sdl2::keyboard::Keycode as SDLKeycode;
use sdl2::video::Window as SDLWindow;
use sdl2::{EventPump, EventSubsystem, Sdl, VideoSubsystem};
use sdl2_sys::{SDL_Event, SDL_UserEvent};
use std::cell::Cell;
use std::collections::VecDeque;
use std::path::PathBuf;
use std::ptr;
use std::sync::Mutex;
use surfman::{SurfaceAccess, SurfaceType, declare_surfman};
use winit::{ControlFlow, ElementState, Event as WinitEvent, EventsLoop, EventsLoopProxy};
use winit::{MouseButton, VirtualKeyCode, Window as WinitWindow, WindowBuilder, WindowEvent};
use winit::dpi::LogicalSize;
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use gl::types::GLuint;
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use gl;
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use surfman::{Connection, Context, ContextAttributeFlags, ContextAttributes};
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use surfman::{Device, GLVersion as SurfmanGLVersion};
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use foreign_types::ForeignTypeRef;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use metal::{CAMetalLayer, CoreAnimationLayerRef};
use io_surface::IOSurfaceRef;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use pathfinder_metal::MetalDevice;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use sdl2::hint;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use sdl2::render::Canvas;
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use sdl2_sys::SDL_RenderGetMetalLayer;
use surfman::{NativeDevice, SystemConnection, SystemDevice, SystemSurface};
declare_surfman!();
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use pathfinder_gl::{GLDevice, GLVersion};
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use sdl2::video::{GLContext, GLProfile};
#[cfg(not(windows))]
use jemallocator;
@ -53,13 +63,21 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
const DEFAULT_WINDOW_WIDTH: u32 = 1067;
const DEFAULT_WINDOW_HEIGHT: u32 = 800;
lazy_static! {
static ref EVENT_QUEUE: Mutex<Option<EventQueue>> = Mutex::new(None);
}
fn main() {
color_backtrace::install();
pretty_env_logger::init();
let window = WindowImpl::new();
// Read command line options.
let mut options = Options::default();
options.command_line_overrides();
let window = WindowImpl::new(&options);
let window_size = window.size();
let options = Options::default();
let mut app = DemoApp::new(window, window_size, options);
while !app.should_exit {
@ -72,6 +90,7 @@ fn main() {
}
let scene_count = app.prepare_frame(events);
app.draw_scene();
app.begin_compositing();
for scene_index in 0..scene_count {
@ -81,28 +100,46 @@ fn main() {
}
}
thread_local! {
static SDL_CONTEXT: Sdl = sdl2::init().unwrap();
static SDL_VIDEO: VideoSubsystem = SDL_CONTEXT.with(|context| context.video().unwrap());
static SDL_EVENT: EventSubsystem = SDL_CONTEXT.with(|context| context.event().unwrap());
}
struct WindowImpl {
window: WinitWindow,
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
window: SDLWindow,
context: Context,
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
gl_context: GLContext,
#[allow(dead_code)]
connection: Connection,
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
device: Device,
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
canvas: Canvas<SDLWindow>,
#[allow(dead_code)]
connection: SystemConnection,
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
metal_layer: *mut CAMetalLayer,
device: SystemDevice,
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
metal_device: NativeDevice,
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
surface: SystemSurface,
event_loop: EventsLoop,
pending_events: VecDeque<Event>,
mouse_position: Vector2I,
mouse_down: bool,
next_user_event_id: Cell<u32>,
event_pump: EventPump,
#[allow(dead_code)]
resource_loader: FilesystemResourceLoader,
selected_file: Option<PathBuf>,
open_svg_message_type: u32,
}
struct EventQueue {
event_loop_proxy: EventsLoopProxy,
pending_custom_events: VecDeque<CustomEvent>,
}
#[derive(Clone)]
enum CustomEvent {
User { message_type: u32, message_data: u32 },
OpenSVG(PathBuf),
}
impl Window for WindowImpl {
@ -111,26 +148,35 @@ impl Window for WindowImpl {
GLVersion::GL3
}
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
fn gl_default_framebuffer(&self) -> GLuint {
self.device.context_surface_info(&self.context).unwrap().unwrap().framebuffer_object
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn metal_layer(&self) -> &CoreAnimationLayerRef {
unsafe { CoreAnimationLayerRef::from_ptr(self.metal_layer) }
fn metal_device(&self) -> metal::Device {
self.metal_device.0.clone()
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn metal_io_surface(&self) -> IOSurfaceRef {
self.device.native_surface(&self.surface).0
}
fn viewport(&self, view: View) -> RectI {
let (width, height) = self.window().drawable_size();
let mut width = width as i32;
let height = height as i32;
let WindowSize { logical_size, backing_scale_factor } = self.size();
let mut size = (logical_size.to_f32() * backing_scale_factor).to_i32();
let mut x_offset = 0;
if let View::Stereo(index) = view {
width = width / 2;
x_offset = width * (index as i32);
size.set_x(size.x() / 2);
x_offset = size.x() * (index as i32);
}
RectI::new(vec2i(x_offset, 0), vec2i(width, height))
RectI::new(vec2i(x_offset, 0), size)
}
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
fn make_current(&mut self, _view: View) {
self.window().gl_make_current(&self.gl_context).unwrap();
self.device.make_context_current(&self.context).unwrap();
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
@ -138,40 +184,30 @@ impl Window for WindowImpl {
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
fn present(&mut self, _: &mut GLDevice) {
self.window().gl_swap_window();
let mut surface = self.device
.unbind_surface_from_context(&mut self.context)
.unwrap()
.unwrap();
self.device.present_surface(&mut self.context, &mut surface).unwrap();
self.device.bind_surface_to_context(&mut self.context, surface).unwrap();
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn present(&mut self, device: &mut MetalDevice) {
device.present_drawable();
fn present(&mut self, metal_device: &mut MetalDevice) {
self.device.present_surface(&mut self.surface).expect("Failed to present surface!");
metal_device.swap_texture(self.device.native_surface(&self.surface).0);
}
fn resource_loader(&self) -> &dyn ResourceLoader {
&self.resource_loader
}
fn create_user_event_id(&self) -> u32 {
SDL_EVENT.with(|sdl_event| unsafe { sdl_event.register_event().unwrap() })
}
fn push_user_event(message_type: u32, message_data: u32) {
unsafe {
let mut user_event = SDL_UserEvent {
timestamp: 0,
windowID: 0,
type_: message_type,
code: message_data as i32,
data1: ptr::null_mut(),
data2: ptr::null_mut(),
};
sdl2_sys::SDL_PushEvent(&mut user_event as *mut SDL_UserEvent as *mut SDL_Event);
}
}
fn present_open_svg_dialog(&mut self) {
if let Ok(Response::Okay(path)) = nfd::open_file_dialog(Some("svg"), None) {
self.selected_file = Some(PathBuf::from(path));
WindowImpl::push_user_event(self.open_svg_message_type, 0);
let mut event_queue = EVENT_QUEUE.lock().unwrap();
let event_queue = event_queue.as_mut().unwrap();
event_queue.pending_custom_events.push_back(CustomEvent::OpenSVG(PathBuf::from(path)));
drop(event_queue.event_loop_proxy.wakeup());
}
}
@ -181,181 +217,272 @@ impl Window for WindowImpl {
_ => Err(()),
}
}
fn create_user_event_id(&self) -> u32 {
let id = self.next_user_event_id.get();
self.next_user_event_id.set(id + 1);
id
}
fn push_user_event(message_type: u32, message_data: u32) {
let mut event_queue = EVENT_QUEUE.lock().unwrap();
let event_queue = event_queue.as_mut().unwrap();
event_queue.pending_custom_events.push_back(CustomEvent::User {
message_type,
message_data,
});
drop(event_queue.event_loop_proxy.wakeup());
}
}
impl WindowImpl {
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
fn new() -> WindowImpl {
SDL_VIDEO.with(|sdl_video| {
SDL_EVENT.with(|sdl_event| {
let (window, gl_context, event_pump);
let gl_attributes = sdl_video.gl_attr();
gl_attributes.set_context_profile(GLProfile::Core);
gl_attributes.set_context_version(3, 3);
gl_attributes.set_depth_size(24);
gl_attributes.set_stencil_size(8);
window = sdl_video
.window(
"Pathfinder Demo",
DEFAULT_WINDOW_WIDTH,
DEFAULT_WINDOW_HEIGHT,
)
.opengl()
.resizable()
.allow_highdpi()
.build()
fn new(options: &Options) -> WindowImpl {
let event_loop = EventsLoop::new();
let window_size = Size2D::new(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
let logical_size = LogicalSize::new(window_size.width as f64, window_size.height as f64);
let window = WindowBuilder::new().with_title("Pathfinder Demo")
.with_dimensions(logical_size)
.build(&event_loop)
.unwrap();
window.show();
gl_context = window.gl_create_context().unwrap();
gl::load_with(|name| sdl_video.gl_get_proc_address(name) as *const _);
let connection = Connection::from_winit_window(&window).unwrap();
let native_widget = connection.create_native_widget_from_winit_window(&window).unwrap();
event_pump = SDL_CONTEXT.with(|sdl_context| sdl_context.event_pump().unwrap());
let adapter = if options.high_performance_gpu {
connection.create_hardware_adapter().unwrap()
} else {
connection.create_low_power_adapter().unwrap()
};
let mut device = connection.create_device(&adapter).unwrap();
let context_attributes = ContextAttributes {
version: SurfmanGLVersion::new(3, 0),
flags: ContextAttributeFlags::ALPHA,
};
let context_descriptor = device.create_context_descriptor(&context_attributes).unwrap();
let surface_type = SurfaceType::Widget { native_widget };
let mut context = device.create_context(&context_descriptor).unwrap();
let surface = device.create_surface(&context, SurfaceAccess::GPUOnly, surface_type)
.unwrap();
device.bind_surface_to_context(&mut context, surface).unwrap();
device.make_context_current(&context).unwrap();
gl::load_with(|symbol_name| device.get_proc_address(&context, symbol_name));
let resource_loader = FilesystemResourceLoader::locate();
let open_svg_message_type = unsafe { sdl_event.register_event().unwrap() };
*EVENT_QUEUE.lock().unwrap() = Some(EventQueue {
event_loop_proxy: event_loop.create_proxy(),
pending_custom_events: VecDeque::new(),
});
WindowImpl {
window,
event_pump,
gl_context,
event_loop,
connection,
context,
device,
next_user_event_id: Cell::new(0),
pending_events: VecDeque::new(),
mouse_position: vec2i(0, 0),
mouse_down: false,
resource_loader,
open_svg_message_type,
selected_file: None,
}
})
})
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn new() -> WindowImpl {
assert!(hint::set("SDL_RENDER_DRIVER", "metal"));
SDL_VIDEO.with(|sdl_video| {
SDL_EVENT.with(|sdl_event| {
let window = sdl_video
.window(
"Pathfinder Demo",
DEFAULT_WINDOW_WIDTH,
DEFAULT_WINDOW_HEIGHT,
)
.opengl()
.resizable()
.allow_highdpi()
.build()
fn new(options: &Options) -> WindowImpl {
let event_loop = EventsLoop::new();
let window_size = Size2D::new(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
let logical_size = LogicalSize::new(window_size.width as f64, window_size.height as f64);
let window = WindowBuilder::new().with_title("Pathfinder Demo")
.with_dimensions(logical_size)
.build(&event_loop)
.unwrap();
window.show();
let canvas = window.into_canvas().present_vsync().build().unwrap();
let metal_layer = unsafe {
SDL_RenderGetMetalLayer(canvas.raw()) as *mut CAMetalLayer
let connection = SystemConnection::from_winit_window(&window).unwrap();
let native_widget = connection.create_native_widget_from_winit_window(&window).unwrap();
let adapter = if options.high_performance_gpu {
connection.create_hardware_adapter().unwrap()
} else {
connection.create_low_power_adapter().unwrap()
};
let event_pump = SDL_CONTEXT.with(|sdl_context| sdl_context.event_pump().unwrap());
let mut device = connection.create_device(&adapter).unwrap();
let native_device = device.native_device();
let surface_type = SurfaceType::Widget { native_widget };
let surface = device.create_surface(SurfaceAccess::GPUOnly, surface_type).unwrap();
let resource_loader = FilesystemResourceLoader::locate();
let open_svg_message_type = unsafe { sdl_event.register_event().unwrap() };
*EVENT_QUEUE.lock().unwrap() = Some(EventQueue {
event_loop_proxy: event_loop.create_proxy(),
pending_custom_events: VecDeque::new(),
});
WindowImpl {
event_pump,
canvas,
metal_layer,
window,
event_loop,
connection,
device,
metal_device: native_device,
surface,
next_user_event_id: Cell::new(0),
pending_events: VecDeque::new(),
mouse_position: vec2i(0, 0),
mouse_down: false,
resource_loader,
open_svg_message_type,
selected_file: None,
}
})
})
}
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
fn window(&self) -> &SDLWindow { &self.window }
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
fn window(&self) -> &SDLWindow { self.canvas.window() }
fn window(&self) -> &WinitWindow { &self.window }
fn size(&self) -> WindowSize {
let (logical_width, logical_height) = self.window().size();
let (drawable_width, _) = self.window().drawable_size();
let window = self.window();
let (monitor, size) = (window.get_current_monitor(), window.get_inner_size().unwrap());
WindowSize {
logical_size: vec2i(logical_width as i32, logical_height as i32),
backing_scale_factor: drawable_width as f32 / logical_width as f32,
logical_size: vec2i(size.width as i32, size.height as i32),
backing_scale_factor: monitor.get_hidpi_factor() as f32,
}
}
fn get_event(&mut self) -> Event {
loop {
let sdl_event = self.event_pump.wait_event();
if let Some(event) = self.convert_sdl_event(sdl_event) {
return event;
if self.pending_events.is_empty() {
let window = &self.window;
let mouse_position = &mut self.mouse_position;
let mouse_down = &mut self.mouse_down;
let pending_events = &mut self.pending_events;
self.event_loop.run_forever(|winit_event| {
//println!("blocking {:?}", winit_event);
match convert_winit_event(winit_event,
window,
mouse_position,
mouse_down) {
Some(event) => {
//println!("handled");
pending_events.push_back(event);
ControlFlow::Break
}
None => {
ControlFlow::Continue
}
}
});
}
self.pending_events.pop_front().expect("Where's the event?")
}
fn try_get_event(&mut self) -> Option<Event> {
loop {
let sdl_event = self.event_pump.poll_event()?;
if let Some(event) = self.convert_sdl_event(sdl_event) {
return Some(event);
if self.pending_events.is_empty() {
let window = &self.window;
let mouse_position = &mut self.mouse_position;
let mouse_down = &mut self.mouse_down;
let pending_events = &mut self.pending_events;
self.event_loop.poll_events(|winit_event| {
//println!("nonblocking {:?}", winit_event);
if let Some(event) = convert_winit_event(winit_event,
window,
mouse_position,
mouse_down) {
//println!("handled");
pending_events.push_back(event);
}
});
}
}
fn convert_sdl_event(&self, sdl_event: SDLEvent) -> Option<Event> {
match sdl_event {
SDLEvent::User { type_, .. } if type_ == self.open_svg_message_type => Some(
Event::OpenSVG(SVGPath::Path(self.selected_file.clone().unwrap())),
),
SDLEvent::User { type_, code, .. } => Some(Event::User {
message_type: type_,
message_data: code as u32,
}),
SDLEvent::MouseButtonDown { x, y, .. } => Some(Event::MouseDown(vec2i(x, y))),
SDLEvent::MouseMotion {
x, y, mousestate, ..
} => {
let position = vec2i(x, y);
if mousestate.left() {
Some(Event::MouseDragged(position))
} else {
Some(Event::MouseMoved(position))
}
}
SDLEvent::Quit { .. } => Some(Event::Quit),
SDLEvent::Window {
win_event: WindowEvent::SizeChanged(..),
..
} => Some(Event::WindowResized(self.size())),
SDLEvent::KeyDown {
keycode: Some(sdl_keycode),
..
} => self.convert_sdl_keycode(sdl_keycode).map(Event::KeyDown),
SDLEvent::KeyUp {
keycode: Some(sdl_keycode),
..
} => self.convert_sdl_keycode(sdl_keycode).map(Event::KeyUp),
SDLEvent::MultiGesture { d_dist, .. } => {
let mouse_state = self.event_pump.mouse_state();
let center = vec2i(mouse_state.x(), mouse_state.y());
Some(Event::Zoom(d_dist, center))
}
_ => None,
}
}
fn convert_sdl_keycode(&self, sdl_keycode: SDLKeycode) -> Option<Keycode> {
match sdl_keycode {
SDLKeycode::Escape => Some(Keycode::Escape),
SDLKeycode::Tab => Some(Keycode::Tab),
sdl_keycode
if sdl_keycode as i32 >= SDLKeycode::A as i32
&& sdl_keycode as i32 <= SDLKeycode::Z as i32 =>
{
let offset = (sdl_keycode as i32 - SDLKeycode::A as i32) as u8;
Some(Keycode::Alphanumeric(offset + b'a'))
}
_ => None,
}
self.pending_events.pop_front()
}
}
fn convert_winit_event(winit_event: WinitEvent,
window: &WinitWindow,
mouse_position: &mut Vector2I,
mouse_down: &mut bool)
-> Option<Event> {
match winit_event {
WinitEvent::Awakened => {
let mut event_queue = EVENT_QUEUE.lock().unwrap();
let event_queue = event_queue.as_mut().unwrap();
match event_queue.pending_custom_events
.pop_front()
.expect("`Awakened` with no pending custom event!") {
CustomEvent::OpenSVG(svg_path) => Some(Event::OpenSVG(SVGPath::Path(svg_path))),
CustomEvent::User { message_data, message_type } => {
Some(Event::User { message_data, message_type })
}
}
}
WinitEvent::WindowEvent { event: window_event, .. } => {
match window_event {
WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
..
} => {
*mouse_down = true;
Some(Event::MouseDown(*mouse_position))
}
WindowEvent::MouseInput {
state: ElementState::Released,
button: MouseButton::Left,
..
} => {
*mouse_down = false;
None
}
WindowEvent::CursorMoved { position, .. } => {
*mouse_position = vec2i(position.x as i32, position.y as i32);
if *mouse_down {
Some(Event::MouseDragged(*mouse_position))
} else {
Some(Event::MouseMoved(*mouse_position))
}
}
WindowEvent::KeyboardInput { input, .. } => {
input.virtual_keycode.and_then(|virtual_keycode| {
match virtual_keycode {
VirtualKeyCode::Escape => Some(Keycode::Escape),
VirtualKeyCode::Tab => Some(Keycode::Tab),
virtual_keycode => {
let vk = virtual_keycode as u32;
let vk_a = VirtualKeyCode::A as u32;
let vk_z = VirtualKeyCode::Z as u32;
if vk >= vk_a && vk <= vk_z {
let character = ((vk - vk_a) + 'A' as u32) as u8;
Some(Keycode::Alphanumeric(character))
} else {
None
}
}
}
}).map(|keycode| {
match input.state {
ElementState::Pressed => Event::KeyDown(keycode),
ElementState::Released => Event::KeyUp(keycode),
}
})
}
WindowEvent::CloseRequested => Some(Event::Quit),
WindowEvent::Resized(new_size) => {
let logical_size = vec2i(new_size.width as i32, new_size.height as i32);
let backing_scale_factor =
window.get_current_monitor().get_hidpi_factor() as f32;
Some(Event::WindowResized(WindowSize {
logical_size,
backing_scale_factor,
}))
}
_ => None,
}
}
_ => None,
}
}

View File

@ -51,7 +51,10 @@ fn main() {
let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0),
&FilesystemResourceLoader::locate(),
DestFramebuffer::full_window(window_size),
RendererOptions { background_color: Some(ColorF::white()) });
RendererOptions {
background_color: Some(ColorF::white()),
..RendererOptions::default()
});
// Make a canvas. We're going to draw a house.
let font_context = CanvasFontContext::from_system_source();

View File

@ -6,8 +6,10 @@ edition = "2018"
[dependencies]
gl = "0.14"
sdl2 = "0.33"
sdl2-sys = "0.33"
[dependencies.euclid]
version = "0.20"
features = []
[dependencies.pathfinder_canvas]
path = "../../canvas"
@ -32,3 +34,10 @@ path = "../../renderer"
[dependencies.pathfinder_resources]
path = "../../resources"
[dependencies.surfman]
version = "0.2"
features = ["sm-winit"]
[dependencies.winit]
version = "<0.19.4" # 0.19.4 causes build errors https://github.com/rust-windowing/winit/pull/1105

View File

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use euclid::default::Size2D;
use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D};
use pathfinder_color::ColorF;
use pathfinder_geometry::rect::RectF;
@ -19,41 +20,69 @@ use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions};
use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_renderer::options::BuildOptions;
use pathfinder_resources::embedded::EmbeddedResourceLoader;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::video::GLProfile;
use surfman::{Connection, ContextAttributeFlags, ContextAttributes, GLVersion as SurfmanGLVersion};
use surfman::{SurfaceAccess, SurfaceType};
use winit::dpi::LogicalSize;
use winit::{ControlFlow, Event, EventsLoop, WindowBuilder, WindowEvent};
fn main() {
// Set up SDL2.
let sdl_context = sdl2::init().unwrap();
let video = sdl_context.video().unwrap();
// Make sure we have at least a GL 3.0 context. Pathfinder requires this.
let gl_attributes = video.gl_attr();
gl_attributes.set_context_profile(GLProfile::Core);
gl_attributes.set_context_version(3, 3);
// Open a window.
let window_size = vec2i(640, 480);
let window = video.window("Minimal example", window_size.x() as u32, window_size.y() as u32)
.opengl()
.build()
let mut event_loop = EventsLoop::new();
let window_size = Size2D::new(640, 480);
let logical_size = LogicalSize::new(window_size.width as f64, window_size.height as f64);
let window = WindowBuilder::new().with_title("Minimal example")
.with_dimensions(logical_size)
.build(&event_loop)
.unwrap();
window.show();
// Create the GL context, and make it current.
let gl_context = window.gl_create_context().unwrap();
gl::load_with(|name| video.gl_get_proc_address(name) as *const _);
window.gl_make_current(&gl_context).unwrap();
// Create a `surfman` device. On a multi-GPU system, we'll request the low-power integrated
// GPU.
let connection = Connection::from_winit_window(&window).unwrap();
let native_widget = connection.create_native_widget_from_winit_window(&window).unwrap();
let adapter = connection.create_low_power_adapter().unwrap();
let mut device = connection.create_device(&adapter).unwrap();
// Request an OpenGL 3.x context. Pathfinder requires this.
let context_attributes = ContextAttributes {
version: SurfmanGLVersion::new(3, 0),
flags: ContextAttributeFlags::ALPHA,
};
let context_descriptor = device.create_context_descriptor(&context_attributes).unwrap();
// Make the OpenGL context via `surfman`, and load OpenGL functions.
let surface_type = SurfaceType::Widget { native_widget };
let mut context = device.create_context(&context_descriptor).unwrap();
let surface = device.create_surface(&context, SurfaceAccess::GPUOnly, surface_type)
.unwrap();
device.bind_surface_to_context(&mut context, surface).unwrap();
device.make_context_current(&context).unwrap();
gl::load_with(|symbol_name| device.get_proc_address(&context, symbol_name));
// Get the real size of the window, taking HiDPI into account.
let hidpi_factor = window.get_current_monitor().get_hidpi_factor();
let physical_size = logical_size.to_physical(hidpi_factor);
let framebuffer_size = vec2i(physical_size.width as i32, physical_size.height as i32);
// Create a Pathfinder GL device.
let default_framebuffer = device.context_surface_info(&context)
.unwrap()
.unwrap()
.framebuffer_object;
let pathfinder_device = GLDevice::new(GLVersion::GL3, default_framebuffer);
// Create a Pathfinder renderer.
let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0),
let mut renderer = Renderer::new(pathfinder_device,
&EmbeddedResourceLoader::new(),
DestFramebuffer::full_window(window_size),
RendererOptions { background_color: Some(ColorF::white()) });
DestFramebuffer::full_window(framebuffer_size),
RendererOptions {
background_color: Some(ColorF::white()),
..RendererOptions::default()
});
// Make a canvas. We're going to draw a house.
let font_context = CanvasFontContext::from_system_source();
let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context);
let mut canvas = Canvas::new(framebuffer_size.to_f32()).get_context_2d(font_context);
// Set line width.
canvas.set_line_width(10.0);
@ -75,14 +104,23 @@ fn main() {
// Render the canvas to screen.
let scene = SceneProxy::from_scene(canvas.into_canvas().into_scene(), RayonExecutor);
scene.build_and_render(&mut renderer, BuildOptions::default());
window.gl_swap_window();
// Present the surface.
let mut surface = device.unbind_surface_from_context(&mut context).unwrap().unwrap();
device.present_surface(&mut context, &mut surface).unwrap();
device.bind_surface_to_context(&mut context, surface).unwrap();
// Wait for a keypress.
let mut event_pump = sdl_context.event_pump().unwrap();
loop {
match event_pump.wait_event() {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return,
_ => {}
event_loop.run_forever(|event| {
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } |
Event::WindowEvent { event: WindowEvent::KeyboardInput { .. }, .. } => {
ControlFlow::Break
}
_ => ControlFlow::Continue,
}
});
// Clean up.
drop(device.destroy_context(&mut context));
}

View File

@ -6,8 +6,10 @@ edition = "2018"
[dependencies]
gl = "0.14"
sdl2 = "0.33"
sdl2-sys = "0.33"
[dependencies.euclid]
version = "0.20"
features = []
[dependencies.pathfinder_canvas]
features = ["pf-text"]
@ -33,3 +35,11 @@ path = "../../renderer"
[dependencies.pathfinder_resources]
path = "../../resources"
[dependencies.surfman]
# version = "0.2"
path = "/Users/pcwalton/Source/surfman/surfman"
features = ["sm-winit"]
[dependencies.winit]
version = "<0.19.4" # 0.19.4 causes build errors https://github.com/rust-windowing/winit/pull/1105

View File

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use euclid::default::Size2D;
use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillStyle, Path2D};
use pathfinder_color::{ColorF, ColorU};
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i};
@ -18,11 +19,12 @@ use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions};
use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_renderer::options::BuildOptions;
use pathfinder_resources::fs::FilesystemResourceLoader;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::video::GLProfile;
use std::f32::consts::PI;
use std::f32;
use surfman::{Connection, ContextAttributeFlags, ContextAttributes, GLVersion as SurfmanGLVersion};
use surfman::{SurfaceAccess, SurfaceType};
use winit::dpi::LogicalSize;
use winit::{Event, EventsLoop, WindowBuilder, WindowEvent};
const VELOCITY: f32 = 0.02;
const OUTER_RADIUS: f32 = 64.0;
@ -37,50 +39,79 @@ const CIRCLE_THICKNESS: f32 = 16.0;
const COLOR_CYCLE_SPEED: f32 = 0.0025;
fn main() {
// Set up SDL2.
let sdl_context = sdl2::init().unwrap();
let video = sdl_context.video().unwrap();
// Make sure we have at least a GL 3.0 context. Pathfinder requires this.
let gl_attributes = video.gl_attr();
gl_attributes.set_context_profile(GLProfile::Core);
gl_attributes.set_context_version(3, 3);
// Open a window.
let window_size = vec2i(1067, 800);
let window = video.window("Moire example", window_size.x() as u32, window_size.y() as u32)
.opengl()
.allow_highdpi()
.build()
let mut event_loop = EventsLoop::new();
let window_size = Size2D::new(1067, 800);
let logical_size = LogicalSize::new(window_size.width as f64, window_size.height as f64);
let window = WindowBuilder::new().with_title("Moire example")
.with_dimensions(logical_size)
.build(&event_loop)
.unwrap();
let mut event_pump = sdl_context.event_pump().unwrap();
window.show();
// Get the real window size (for HiDPI).
let (drawable_width, drawable_height) = window.drawable_size();
let drawable_size = vec2i(drawable_width as i32, drawable_height as i32);
// Create a `surfman` device. On a multi-GPU system, we'll request the low-power integrated
// GPU.
let connection = Connection::from_winit_window(&window).unwrap();
let native_widget = connection.create_native_widget_from_winit_window(&window).unwrap();
let adapter = connection.create_low_power_adapter().unwrap();
let mut device = connection.create_device(&adapter).unwrap();
// Create the GL context, and make it current.
let gl_context = window.gl_create_context().unwrap();
gl::load_with(|name| video.gl_get_proc_address(name) as *const _);
window.gl_make_current(&gl_context).unwrap();
// Request an OpenGL 3.x context. Pathfinder requires this.
let context_attributes = ContextAttributes {
version: SurfmanGLVersion::new(3, 0),
flags: ContextAttributeFlags::ALPHA,
};
let context_descriptor = device.create_context_descriptor(&context_attributes).unwrap();
// Make the OpenGL context via `surfman`, and load OpenGL functions.
let surface_type = SurfaceType::Widget { native_widget };
let mut gl_context = device.create_context(&context_descriptor).unwrap();
let surface = device.create_surface(&gl_context, SurfaceAccess::GPUOnly, surface_type)
.unwrap();
device.bind_surface_to_context(&mut gl_context, surface).unwrap();
device.make_context_current(&gl_context).unwrap();
gl::load_with(|symbol_name| device.get_proc_address(&gl_context, symbol_name));
// Get the real size of the window, taking HiDPI into account.
let hidpi_factor = window.get_current_monitor().get_hidpi_factor();
let physical_size = logical_size.to_physical(hidpi_factor);
let framebuffer_size = vec2i(physical_size.width as i32, physical_size.height as i32);
// Create a Pathfinder GL device.
let default_framebuffer = device.context_surface_info(&gl_context)
.unwrap()
.unwrap()
.framebuffer_object;
let pathfinder_device = GLDevice::new(GLVersion::GL3, default_framebuffer);
// Create our renderers.
let renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0),
let renderer = Renderer::new(pathfinder_device,
&FilesystemResourceLoader::locate(),
DestFramebuffer::full_window(drawable_size),
RendererOptions { background_color: Some(ColorF::white()) });
let mut moire_renderer = MoireRenderer::new(renderer, window_size, drawable_size);
DestFramebuffer::full_window(framebuffer_size),
RendererOptions {
background_color: Some(ColorF::white()),
..RendererOptions::default()
});
let window_size = vec2i(window_size.width, window_size.height);
let mut moire_renderer = MoireRenderer::new(renderer, window_size, framebuffer_size);
// Enter main render loop.
loop {
let mut exit = false;
while !exit {
moire_renderer.render();
window.gl_swap_window();
match event_pump.poll_event() {
Some(Event::Quit {..}) |
Some(Event::KeyDown { keycode: Some(Keycode::Escape), .. }) => return,
// Present the rendered canvas via `surfman`.
let mut surface = device.unbind_surface_from_context(&mut gl_context).unwrap().unwrap();
device.present_surface(&mut gl_context, &mut surface).unwrap();
device.bind_surface_to_context(&mut gl_context, surface).unwrap();
event_loop.poll_events(|event| {
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } |
Event::WindowEvent { event: WindowEvent::KeyboardInput { .. }, .. } => exit = true,
_ => {}
}
});
}
}
@ -124,7 +155,10 @@ impl MoireRenderer {
let inner_center = window_center + vec2f(1.0, sin_time) * (cos_time * INNER_RADIUS);
// Clear to background color.
self.renderer.set_options(RendererOptions { background_color: Some(background_color) });
self.renderer.set_options(RendererOptions {
background_color: Some(background_color),
..RendererOptions::default()
});
// Make a canvas.
let mut canvas =

View File

@ -8,8 +8,10 @@ edition = "2018"
arrayvec = "0.5"
font-kit = "0.6"
gl = "0.14"
sdl2 = "0.33"
sdl2-sys = "0.33"
[dependencies.euclid]
version = "0.20"
features = []
[dependencies.image]
version = "0.23"
@ -48,5 +50,13 @@ path = "../../resources"
[dependencies.pathfinder_simd]
path = "../../simd"
[dependencies.surfman]
git = "https://github.com/pcwalton/surfman"
rev = "bc29e7ae88ca7dd64d3b1c7e185604693290207f"
features = ["sm-winit"]
[dependencies.winit]
version = "<0.19.4" # 0.19.4 causes build errors https://github.com/rust-windowing/winit/pull/1105
[target.'cfg(not(windows))'.dependencies]
jemallocator = "0.3"

View File

@ -9,6 +9,7 @@
// except according to those terms.
use arrayvec::ArrayVec;
use euclid::default::Size2D;
use font_kit::handle::Handle;
use font_kit::sources::mem::MemSource;
use image;
@ -35,14 +36,15 @@ use pathfinder_renderer::options::BuildOptions;
use pathfinder_resources::ResourceLoader;
use pathfinder_resources::fs::FilesystemResourceLoader;
use pathfinder_simd::default::F32x2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::video::GLProfile;
use std::collections::VecDeque;
use std::f32::consts::PI;
use std::iter;
use std::sync::Arc;
use std::time::Instant;
use surfman::{Connection, ContextAttributeFlags, ContextAttributes, GLVersion as SurfmanGLVersion};
use surfman::{SurfaceAccess, SurfaceType};
use winit::dpi::LogicalSize;
use winit::{Event, EventsLoop, WindowBuilder, WindowEvent};
#[cfg(not(windows))]
use jemallocator;
@ -1460,33 +1462,43 @@ impl DemoData {
}
fn main() {
// Set up SDL2.
let sdl_context = sdl2::init().unwrap();
let video = sdl_context.video().unwrap();
// Make sure we have at least a GL 3.0 context. Pathfinder requires this.
let gl_attributes = video.gl_attr();
gl_attributes.set_context_profile(GLProfile::Core);
gl_attributes.set_context_version(3, 3);
// Open a window.
let window_size = vec2i(WINDOW_WIDTH, WINDOW_HEIGHT);
let window =
video.window("NanoVG example port", window_size.x() as u32, window_size.y() as u32)
.opengl()
.allow_highdpi()
.build()
let mut event_loop = EventsLoop::new();
let window_size = Size2D::new(WINDOW_WIDTH, WINDOW_HEIGHT);
let logical_size = LogicalSize::new(window_size.width as f64, window_size.height as f64);
let window = WindowBuilder::new().with_title("NanoVG example port")
.with_dimensions(logical_size)
.build(&event_loop)
.unwrap();
window.show();
// Create the GL context, and make it current.
let gl_context = window.gl_create_context().unwrap();
gl::load_with(|name| video.gl_get_proc_address(name) as *const _);
window.gl_make_current(&gl_context).unwrap();
// Create a `surfman` device. On a multi-GPU system, we'll request the low-power integrated
// GPU.
let connection = Connection::from_winit_window(&window).unwrap();
let native_widget = connection.create_native_widget_from_winit_window(&window).unwrap();
let adapter = connection.create_low_power_adapter().unwrap();
let mut device = connection.create_device(&adapter).unwrap();
// Get the real window size (for HiDPI).
let (drawable_width, drawable_height) = window.drawable_size();
let drawable_size = vec2i(drawable_width as i32, drawable_height as i32);
let hidpi_factor = drawable_size.x() as f32 / window_size.x() as f32;
// Request an OpenGL 3.x context. Pathfinder requires this.
let context_attributes = ContextAttributes {
version: SurfmanGLVersion::new(3, 0),
flags: ContextAttributeFlags::ALPHA,
};
let context_descriptor = device.create_context_descriptor(&context_attributes).unwrap();
// Make the OpenGL context via `surfman`, and load OpenGL functions.
let surface_type = SurfaceType::Widget { native_widget };
let mut gl_context = device.create_context(&context_descriptor).unwrap();
let surface = device.create_surface(&gl_context, SurfaceAccess::GPUOnly, surface_type)
.unwrap();
device.bind_surface_to_context(&mut gl_context, surface).unwrap();
device.make_context_current(&gl_context).unwrap();
gl::load_with(|symbol_name| device.get_proc_address(&gl_context, symbol_name));
// Get the real size of the window, taking HiDPI into account.
let hidpi_factor = window.get_current_monitor().get_hidpi_factor();
let physical_size = logical_size.to_physical(hidpi_factor);
let framebuffer_size = vec2i(physical_size.width as i32, physical_size.height as i32);
// Load demo data.
let resources = FilesystemResourceLoader::locate();
@ -1497,12 +1509,20 @@ fn main() {
];
let demo_data = DemoData::load(&resources);
// Create a Pathfinder GL device.
let default_framebuffer = device.context_surface_info(&gl_context)
.unwrap()
.unwrap()
.framebuffer_object;
let pathfinder_device = GLDevice::new(GLVersion::GL3, default_framebuffer);
// Create a Pathfinder renderer.
let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0),
let mut renderer = Renderer::new(pathfinder_device,
&resources,
DestFramebuffer::full_window(drawable_size),
DestFramebuffer::full_window(framebuffer_size),
RendererOptions {
background_color: Some(rgbf(0.3, 0.3, 0.32)),
..RendererOptions::default()
});
// Initialize font state.
@ -1510,7 +1530,6 @@ fn main() {
let font_context = CanvasFontContext::new(font_source.clone());
// Initialize general state.
let mut event_pump = sdl_context.event_pump().unwrap();
let mut mouse_position = Vector2F::zero();
let start_time = Instant::now();
@ -1520,21 +1539,23 @@ fn main() {
let mut gpu_graph = PerfGraph::new(GraphStyle::MS, "GPU Time");
// Enter the main loop.
loop {
let mut exit = false;
while !exit {
// Make a canvas.
let mut context = Canvas::new(drawable_size.to_f32()).get_context_2d(font_context.clone());
let mut context =
Canvas::new(framebuffer_size.to_f32()).get_context_2d(font_context.clone());
// Start performance timing.
let frame_start_time = Instant::now();
let frame_start_elapsed_time = (frame_start_time - start_time).as_secs_f32();
// Render the demo.
context.scale(hidpi_factor);
context.scale(hidpi_factor as f32);
render_demo(&mut context,
mouse_position,
window_size.to_f32(),
vec2f(WINDOW_WIDTH as f32, WINDOW_HEIGHT as f32),
frame_start_elapsed_time,
hidpi_factor,
hidpi_factor as f32,
&demo_data);
// Render performance graphs.
@ -1547,7 +1568,11 @@ fn main() {
let canvas = context.into_canvas();
let scene = SceneProxy::from_scene(canvas.into_scene(), RayonExecutor);
scene.build_and_render(&mut renderer, BuildOptions::default());
window.gl_swap_window();
// Present the rendered canvas via `surfman`.
let mut surface = device.unbind_surface_from_context(&mut gl_context).unwrap().unwrap();
device.present_surface(&mut gl_context, &mut surface).unwrap();
device.bind_surface_to_context(&mut gl_context, surface).unwrap();
// Add stats to performance graphs.
if let Some(gpu_time) = renderer.shift_rendering_time() {
@ -1558,12 +1583,18 @@ fn main() {
gpu_graph.push(gpu_time);
}
for event in event_pump.poll_iter() {
event_loop.poll_events(|event| {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return,
Event::MouseMotion { x, y, .. } => mouse_position = vec2i(x, y).to_f32(),
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } |
Event::WindowEvent { event: WindowEvent::KeyboardInput { .. }, .. } => exit = true,
Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => {
mouse_position = vec2f(position.x as f32, position.y as f32);
}
_ => {}
}
});
}
}
// Clean up.
drop(device.destroy_context(&mut gl_context));
}

View File

@ -53,7 +53,10 @@ fn main() {
let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0),
&resource_loader,
DestFramebuffer::full_window(window_size),
RendererOptions { background_color: Some(ColorF::white()) });
RendererOptions {
background_color: Some(ColorF::white()),
..RendererOptions::default()
});
// Load a font.
let font_data = Arc::new(resource_loader.slurp("fonts/Overpass-Regular.otf").unwrap());

View File

@ -102,7 +102,10 @@ fn main() {
GLDevice::new(GLVersion::GL3, 0),
&resource_loader,
DestFramebuffer::full_window(pixel_size),
RendererOptions { background_color: Some(stage.background_color()) }
RendererOptions {
background_color: Some(stage.background_color()),
..RendererOptions::default()
}
);
// Clear to swf stage background color.
let mut scene = Scene::new();

View File

@ -13,13 +13,13 @@
#[macro_use]
extern crate log;
use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr, GLsync};
use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLintptr, GLsizei, GLsizeiptr, GLsync};
use gl::types::{GLuint, GLvoid};
use half::f16;
use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::Vector2I;
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
use pathfinder_gpu::{DepthFunc, Device, Primitive, RenderOptions, RenderState, RenderTarget};
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps, ComputeDimensions, ComputeState};
use pathfinder_gpu::{DepthFunc, Device, ImageAccess, ImageBinding, Primitive, ProgramKind, RenderOptions, RenderState, RenderTarget};
use pathfinder_gpu::{ShaderKind, StencilFunc, TextureData, TextureDataRef, TextureFormat};
use pathfinder_gpu::{TextureSamplingFlags, UniformData, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
@ -71,6 +71,18 @@ impl GLDevice {
self.set_render_options(&render_state.options);
}
fn set_compute_state(&self, compute_state: &ComputeState<GLDevice>) {
self.use_program(compute_state.program);
for (texture_unit, texture) in compute_state.textures.iter().enumerate() {
self.bind_texture(texture, texture_unit as u32);
}
for (image_unit, image) in compute_state.images.iter().enumerate() {
self.bind_image(image, image_unit as u32);
}
compute_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
}
fn set_render_options(&self, render_options: &RenderOptions) {
unsafe {
// Set blend.
@ -165,7 +177,7 @@ impl GLDevice {
UniformData::Vec4(data) => {
gl::Uniform4f(uniform.location, data.x(), data.y(), data.z(), data.w()); ck();
}
UniformData::TextureUnit(unit) => {
UniformData::TextureUnit(unit) | UniformData::ImageUnit(unit) => {
gl::Uniform1i(uniform.location, unit as GLint); ck();
}
}
@ -194,6 +206,19 @@ impl GLDevice {
self.unbind_vertex_array();
}
fn reset_compute_state(&self, compute_state: &ComputeState<GLDevice>) {
for image_unit in 0..(compute_state.images.len() as u32) {
self.unbind_image(image_unit);
}
for texture_unit in 0..(compute_state.textures.len() as u32) {
self.unbind_texture(texture_unit);
}
for (uniform, data) in compute_state.uniforms {
self.unset_uniform(uniform, data);
}
self.unuse_program();
}
fn reset_render_options(&self, render_options: &RenderOptions) {
unsafe {
if render_options.blend.is_some() {
@ -216,9 +241,11 @@ impl GLDevice {
impl Device for GLDevice {
type Buffer = GLBuffer;
type Fence = GLFence;
type Framebuffer = GLFramebuffer;
type Program = GLProgram;
type Shader = GLShader;
type StorageBuffer = GLStorageBuffer;
type Texture = GLTexture;
type TextureDataReceiver = GLTextureDataReceiver;
type TimerQuery = GLTimerQuery;
@ -279,6 +306,7 @@ impl Device for GLDevice {
let gl_shader_kind = match kind {
ShaderKind::Vertex => gl::VERTEX_SHADER,
ShaderKind::Fragment => gl::FRAGMENT_SHADER,
ShaderKind::Compute => gl::COMPUTE_SHADER,
};
unsafe {
@ -310,14 +338,23 @@ impl Device for GLDevice {
fn create_program_from_shaders(&self,
_resources: &dyn ResourceLoader,
name: &str,
vertex_shader: GLShader,
fragment_shader: GLShader)
shaders: ProgramKind<GLShader>)
-> GLProgram {
let gl_program;
unsafe {
gl_program = gl::CreateProgram(); ck();
match shaders {
ProgramKind::Raster {
vertex: ref vertex_shader,
fragment: ref fragment_shader,
} => {
gl::AttachShader(gl_program, vertex_shader.gl_shader); ck();
gl::AttachShader(gl_program, fragment_shader.gl_shader); ck();
}
ProgramKind::Compute(ref compute_shader) => {
gl::AttachShader(gl_program, compute_shader.gl_shader); ck();
}
}
gl::LinkProgram(gl_program); ck();
let mut link_status = 0;
@ -335,8 +372,18 @@ impl Device for GLDevice {
}
}
match shaders {
ProgramKind::Raster { vertex: vertex_shader, fragment: fragment_shader } => {
GLProgram { gl_program, vertex_shader, fragment_shader }
}
ProgramKind::Compute(_) => unimplemented!(),
}
}
#[inline]
fn set_compute_program_local_size(&self, _: &mut Self::Program, _: ComputeDimensions) {
// This does nothing on OpenGL, since the local size is set in the shader.
}
#[inline]
fn create_vertex_array(&self) -> GLVertexArray {
@ -367,6 +414,10 @@ impl Device for GLDevice {
GLUniform { location }
}
fn get_storage_buffer(&self, _: &Self::Program, _: &str, binding: u32) -> GLStorageBuffer {
GLStorageBuffer { location: binding as GLint }
}
fn configure_vertex_attr(&self,
vertex_array: &GLVertexArray,
attr: &GLVertexAttr,
@ -424,35 +475,47 @@ impl Device for GLDevice {
GLFramebuffer { gl_framebuffer, texture }
}
fn create_buffer(&self) -> GLBuffer {
fn create_buffer(&self, mode: BufferUploadMode) -> GLBuffer {
unsafe {
let mut gl_buffer = 0;
gl::GenBuffers(1, &mut gl_buffer); ck();
GLBuffer { gl_buffer }
GLBuffer { gl_buffer, mode }
}
}
fn allocate_buffer<T>(&self,
buffer: &GLBuffer,
data: BufferData<T>,
target: BufferTarget,
mode: BufferUploadMode) {
let target = match target {
BufferTarget::Vertex => gl::ARRAY_BUFFER,
BufferTarget::Index => gl::ELEMENT_ARRAY_BUFFER,
};
target: BufferTarget) {
let target = target.to_gl_target();
let (ptr, len) = match data {
BufferData::Uninitialized(len) => (ptr::null(), len),
BufferData::Memory(buffer) => (buffer.as_ptr() as *const GLvoid, buffer.len()),
};
let len = (len * mem::size_of::<T>()) as GLsizeiptr;
let usage = mode.to_gl_usage();
let usage = buffer.mode.to_gl_usage();
unsafe {
gl::BindBuffer(target, buffer.gl_buffer); ck();
gl::BufferData(target, len, ptr, usage); ck();
}
}
fn upload_to_buffer<T>(&self,
buffer: &Self::Buffer,
position: usize,
data: &[T],
target: BufferTarget) {
let target = target.to_gl_target();
let len = (data.len() * mem::size_of::<T>()) as GLsizeiptr;
unsafe {
gl::BindBuffer(target, buffer.gl_buffer); ck();
gl::BufferSubData(target,
position as GLintptr,
len,
data.as_ptr() as *const GLvoid); ck();
}
}
#[inline]
fn framebuffer_texture<'f>(&self, framebuffer: &'f Self::Framebuffer) -> &'f Self::Texture {
&framebuffer.texture
@ -627,6 +690,14 @@ impl Device for GLDevice {
self.reset_render_state(render_state);
}
fn dispatch_compute(&self, dimensions: ComputeDimensions, compute_state: &ComputeState<Self>) {
self.set_compute_state(compute_state);
unsafe {
gl::DispatchCompute(dimensions.x, dimensions.y, dimensions.z); ck();
}
self.reset_compute_state(compute_state);
}
#[inline]
fn create_timer_query(&self) -> GLTimerQuery {
let mut query = GLTimerQuery { gl_query: 0 };
@ -712,10 +783,24 @@ impl Device for GLDevice {
let suffix = match kind {
ShaderKind::Vertex => 'v',
ShaderKind::Fragment => 'f',
ShaderKind::Compute => 'c',
};
let path = format!("shaders/gl3/{}.{}s.glsl", name, suffix);
self.create_shader_from_source(name, &resources.slurp(&path).unwrap(), kind)
}
fn add_fence(&self) -> Self::Fence {
unsafe {
let gl_sync = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0); ck();
GLFence { gl_sync }
}
}
fn wait_for_fence(&self, fence: &Self::Fence) {
unsafe {
gl::ClientWaitSync(fence.gl_sync, gl::SYNC_FLUSH_COMMANDS_BIT, 0); ck();
}
}
}
impl GLDevice {
@ -752,6 +837,24 @@ impl GLDevice {
}
}
fn bind_image(&self, binding: &ImageBinding<GLDevice>, unit: u32) {
unsafe {
gl::BindImageTexture(unit,
binding.texture.gl_texture,
0,
gl::FALSE,
0,
binding.access.to_gl_access(),
binding.texture.format.gl_internal_format() as GLenum); ck();
}
}
fn unbind_image(&self, unit: u32) {
unsafe {
gl::BindImageTexture(unit, 0, 0, gl::FALSE, 0, 0, 0); ck();
}
}
fn use_program(&self, program: &GLProgram) {
unsafe {
gl::UseProgram(program.gl_program); ck();
@ -933,6 +1036,18 @@ impl GLVertexAttr {
}
}
pub struct GLFence {
pub gl_sync: GLsync,
}
impl Drop for GLFence {
fn drop(&mut self) {
unsafe {
gl::DeleteSync(self.gl_sync); ck();
}
}
}
pub struct GLFramebuffer {
pub gl_framebuffer: GLuint,
pub texture: GLTexture,
@ -948,6 +1063,7 @@ impl Drop for GLFramebuffer {
pub struct GLBuffer {
pub gl_buffer: GLuint,
pub mode: BufferUploadMode,
}
impl Drop for GLBuffer {
@ -963,6 +1079,11 @@ pub struct GLUniform {
location: GLint,
}
#[derive(Debug)]
pub struct GLStorageBuffer {
location: GLint,
}
pub struct GLProgram {
pub gl_program: GLuint,
#[allow(dead_code)]
@ -1063,6 +1184,7 @@ impl BufferTargetExt for BufferTarget {
match self {
BufferTarget::Vertex => gl::ARRAY_BUFFER,
BufferTarget::Index => gl::ELEMENT_ARRAY_BUFFER,
BufferTarget::Storage => gl::SHADER_STORAGE_BUFFER,
}
}
}
@ -1093,6 +1215,20 @@ impl DepthFuncExt for DepthFunc {
}
}
trait ImageAccessExt {
fn to_gl_access(self) -> GLenum;
}
impl ImageAccessExt for ImageAccess {
fn to_gl_access(self) -> GLenum {
match self {
ImageAccess::Read => gl::READ_ONLY,
ImageAccess::Write => gl::WRITE_ONLY,
ImageAccess::ReadWrite => gl::READ_WRITE,
}
}
}
trait PrimitiveExt {
fn to_gl_primitive(self) -> GLuint;
}
@ -1192,6 +1328,8 @@ pub enum GLVersion {
GL3 = 0,
/// OpenGL ES 3.0+.
GLES3 = 1,
/// OpenGL 4.3+, core profile.
GL4_3 = 2,
}
impl GLVersion {
@ -1199,6 +1337,7 @@ impl GLVersion {
match *self {
GLVersion::GL3 => "330",
GLVersion::GLES3 => "300 es",
GLVersion::GL4_3 => "430",
}
}
}

View File

@ -26,9 +26,11 @@ use std::time::Duration;
pub trait Device: Sized {
type Buffer;
type Fence;
type Framebuffer;
type Program;
type Shader;
type StorageBuffer;
type Texture;
type TextureDataReceiver;
type TimerQuery;
@ -44,15 +46,18 @@ pub trait Device: Sized {
fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind)
-> Self::Shader;
fn create_vertex_array(&self) -> Self::VertexArray;
fn create_program_from_shaders(
&self,
fn create_program_from_shaders(&self,
resources: &dyn ResourceLoader,
name: &str,
vertex_shader: Self::Shader,
fragment_shader: Self::Shader,
) -> Self::Program;
shaders: ProgramKind<Self::Shader>)
-> Self::Program;
fn set_compute_program_local_size(&self,
program: &mut Self::Program,
local_size: ComputeDimensions);
fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Option<Self::VertexAttr>;
fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform;
fn get_storage_buffer(&self, program: &Self::Program, name: &str, binding: u32)
-> Self::StorageBuffer;
fn bind_buffer(&self,
vertex_array: &Self::VertexArray,
buffer: &Self::Buffer,
@ -62,14 +67,16 @@ pub trait Device: Sized {
attr: &Self::VertexAttr,
descriptor: &VertexAttrDescriptor);
fn create_framebuffer(&self, texture: Self::Texture) -> Self::Framebuffer;
fn create_buffer(&self) -> Self::Buffer;
fn allocate_buffer<T>(
&self,
fn create_buffer(&self, mode: BufferUploadMode) -> Self::Buffer;
fn allocate_buffer<T>(&self,
buffer: &Self::Buffer,
data: BufferData<T>,
target: BufferTarget,
mode: BufferUploadMode,
);
target: BufferTarget);
fn upload_to_buffer<T>(&self,
buffer: &Self::Buffer,
position: usize,
data: &[T],
target: BufferTarget);
fn framebuffer_texture<'f>(&self, framebuffer: &'f Self::Framebuffer) -> &'f Self::Texture;
fn destroy_framebuffer(&self, framebuffer: Self::Framebuffer) -> Self::Texture;
fn texture_format(&self, texture: &Self::Texture) -> TextureFormat;
@ -86,6 +93,9 @@ pub trait Device: Sized {
index_count: u32,
instance_count: u32,
render_state: &RenderState<Self>);
fn dispatch_compute(&self, dimensions: ComputeDimensions, state: &ComputeState<Self>);
fn add_fence(&self) -> Self::Fence;
fn wait_for_fence(&self, fence: &Self::Fence);
fn create_timer_query(&self) -> Self::TimerQuery;
fn begin_timer_query(&self, query: &Self::TimerQuery);
fn end_timer_query(&self, query: &Self::TimerQuery);
@ -107,17 +117,30 @@ pub trait Device: Sized {
&self,
resources: &dyn ResourceLoader,
program_name: &str,
vertex_shader_name: &str,
fragment_shader_name: &str,
shader_names: ProgramKind<&str>,
) -> Self::Program {
let vertex_shader = self.create_shader(resources, vertex_shader_name, ShaderKind::Vertex);
let fragment_shader =
self.create_shader(resources, fragment_shader_name, ShaderKind::Fragment);
self.create_program_from_shaders(resources, program_name, vertex_shader, fragment_shader)
let shaders = match shader_names {
ProgramKind::Raster { vertex, fragment } => {
ProgramKind::Raster {
vertex: self.create_shader(resources, vertex, ShaderKind::Vertex),
fragment: self.create_shader(resources, fragment, ShaderKind::Fragment),
}
}
ProgramKind::Compute(compute) => {
ProgramKind::Compute(self.create_shader(resources, compute, ShaderKind::Compute))
}
};
self.create_program_from_shaders(resources, program_name, shaders)
}
fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program {
self.create_program_from_shader_names(resources, name, name, name)
fn create_raster_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program {
let shaders = ProgramKind::Raster { vertex: name, fragment: name };
self.create_program_from_shader_names(resources, name, shaders)
}
fn create_compute_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program {
let shaders = ProgramKind::Compute(name);
self.create_program_from_shader_names(resources, name, shaders)
}
}
@ -149,6 +172,7 @@ pub enum BufferData<'a, T> {
pub enum BufferTarget {
Vertex,
Index,
Storage,
}
#[derive(Clone, Copy, Debug)]
@ -161,6 +185,23 @@ pub enum BufferUploadMode {
pub enum ShaderKind {
Vertex,
Fragment,
Compute,
}
#[derive(Clone, Copy, Debug)]
pub enum ProgramKind<T> {
Raster {
vertex: T,
fragment: T,
},
Compute(T),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ComputeDimensions {
pub x: u32,
pub y: u32,
pub z: u32,
}
#[derive(Clone, Copy)]
@ -175,6 +216,7 @@ pub enum UniformData {
Vec3([f32; 3]),
Vec4(F32x4),
TextureUnit(u32),
ImageUnit(u32),
}
#[derive(Clone, Copy)]
@ -191,10 +233,26 @@ pub struct RenderState<'a, D> where D: Device {
pub primitive: Primitive,
pub uniforms: &'a [(&'a D::Uniform, UniformData)],
pub textures: &'a [&'a D::Texture],
pub images: &'a [ImageBinding<'a, D>],
pub viewport: RectI,
pub options: RenderOptions,
}
#[derive(Clone)]
pub struct ComputeState<'a, D> where D: Device {
pub program: &'a D::Program,
pub uniforms: &'a [(&'a D::Uniform, UniformData)],
pub textures: &'a [&'a D::Texture],
pub images: &'a [ImageBinding<'a, D>],
pub storage_buffers: &'a [(&'a D::StorageBuffer, &'a D::Buffer)],
}
#[derive(Clone, Debug)]
pub struct ImageBinding<'a, D> where D: Device {
pub texture: &'a D::Texture,
pub access: ImageAccess,
}
#[derive(Clone, Debug)]
pub struct RenderOptions {
pub blend: Option<BlendState>,
@ -408,6 +466,13 @@ bitflags! {
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ImageAccess {
Read,
Write,
ReadWrite,
}
impl<'a> TextureDataRef<'a> {
#[doc(hidden)]
pub fn check_and_extract_data_ptr(self, minimum_size: Vector2I, format: TextureFormat)

View File

@ -13,9 +13,11 @@ bitflags = "1.0"
byteorder = "1.3"
block = "0.1"
cocoa = "0.19"
core-foundation = "0.7"
core-foundation = "0.6"
foreign-types = "0.3"
half = "1.5"
io-surface = "0.12"
libc = "0.2"
metal = "0.17"
objc = "0.2"

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,7 @@ enum TreeNode {
}
#[derive(Clone, Copy, PartialEq, Debug)]
#[allow(dead_code)]
pub enum AllocationMode {
Atlas,
OwnPage,

View File

@ -29,7 +29,6 @@ use pathfinder_content::render_target::RenderTargetId;
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
use pathfinder_geometry::rect::{RectF, RectI};
use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::util;
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i};
use pathfinder_gpu::TextureSamplingFlags;
use pathfinder_simd::default::{F32x4, I32x4};
@ -464,30 +463,6 @@ impl<'a, 'b> SceneBuilder<'a, 'b> {
display_item_index: usize,
tile_page: u16,
}
/*
// Create a new `DrawTiles` display item if we don't have one or if we have to break a
// batch due to blend mode or paint page. Note that every path with a blend mode that
// requires a readable framebuffer needs its own batch.
//
// TODO(pcwalton): If we really wanted to, we could use tile maps to avoid
// batch breaks in some cases…
// Fetch the destination alpha tiles buffer.
let culled_alpha_tiles = match *culled_tiles.display_list.last_mut().unwrap() {
CulledDisplayItem::DrawTiles(TileBatch { tiles: ref mut culled_alpha_tiles, .. }) => {
culled_alpha_tiles
}
_ => unreachable!(),
};
for alpha_tile in alpha_tiles {
let alpha_tile_coords = alpha_tile.tile_position();
if layer_z_buffer.test(alpha_tile_coords, current_depth) {
culled_alpha_tiles.push(*alpha_tile);
}
}
*/
}
fn pack_tiles(&mut self, culled_tiles: CulledTiles) {

View File

@ -17,13 +17,11 @@ use pathfinder_gpu::Device;
#[derive(Default)]
pub struct RendererOptions {
pub background_color: Option<ColorF>,
pub use_compute: bool,
}
#[derive(Clone)]
pub enum DestFramebuffer<D>
where
D: Device,
{
pub enum DestFramebuffer<D> where D: Device {
Default {
viewport: RectI,
window_size: Vector2I,

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::gpu_data::Fill;
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass};
use crate::gpu::options::RendererOptions;
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
use pathfinder_gpu::{BufferTarget, BufferUploadMode, ComputeDimensions, Device, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_resources::ResourceLoader;
@ -49,12 +50,8 @@ impl<D> BlitVertexArray<D> where D: Device {
}
}
pub struct FillVertexArray<D>
where
D: Device,
{
pub struct FillVertexArray<D> where D: Device {
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
}
impl<D> FillVertexArray<D>
@ -63,21 +60,13 @@ where
{
pub fn new(
device: &D,
fill_program: &FillProgram<D>,
fill_program: &FillRasterProgram<D>,
vertex_buffer: &D::Buffer,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> FillVertexArray<D> {
let vertex_array = device.create_vertex_array();
let vertex_buffer = device.create_buffer();
let vertex_buffer_data: BufferData<Fill> = BufferData::Uninitialized(MAX_FILLS_PER_BATCH);
device.allocate_buffer(
&vertex_buffer,
vertex_buffer_data,
BufferTarget::Vertex,
BufferUploadMode::Dynamic,
);
let tess_coord_attr = device.get_vertex_attr(&fill_program.program, "TessCoord").unwrap();
let from_px_attr = device.get_vertex_attr(&fill_program.program, "FromPx").unwrap();
let to_px_attr = device.get_vertex_attr(&fill_program.program, "ToPx").unwrap();
@ -96,30 +85,12 @@ where
buffer_index: 0,
});
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &from_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 0,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &to_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 1,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &from_subpx_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 2,
offset: 0,
divisor: 1,
buffer_index: 1,
});
@ -128,10 +99,28 @@ where
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 2,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &from_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 4,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &to_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 5,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &tile_index_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
@ -143,7 +132,7 @@ where
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
FillVertexArray { vertex_array, vertex_buffer }
FillVertexArray { vertex_array }
}
}
@ -277,7 +266,7 @@ impl<D> ClipTileVertexArray<D> where D: Device {
quad_vertex_indices_buffer: &D::Buffer)
-> ClipTileVertexArray<D> {
let vertex_array = device.create_vertex_array();
let vertex_buffer = device.create_buffer();
let vertex_buffer = device.create_buffer(BufferUploadMode::Dynamic);
let tile_offset_attr =
device.get_vertex_attr(&clip_tile_program.program, "TileOffset").unwrap();
@ -340,32 +329,42 @@ pub struct BlitProgram<D> where D: Device {
impl<D> BlitProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram<D> {
let program = device.create_program(resources, "blit");
let program = device.create_raster_program(resources, "blit");
let src_uniform = device.get_uniform(&program, "Src");
BlitProgram { program, src_uniform }
}
}
pub struct FillProgram<D>
where
D: Device,
{
pub enum FillProgram<D> where D: Device {
Raster(FillRasterProgram<D>),
Compute(FillComputeProgram<D>),
}
impl<D> FillProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader, options: &RendererOptions)
-> FillProgram<D> {
if options.use_compute {
FillProgram::Compute(FillComputeProgram::new(device, resources))
} else {
FillProgram::Raster(FillRasterProgram::new(device, resources))
}
}
}
pub struct FillRasterProgram<D> where D: Device {
pub program: D::Program,
pub framebuffer_size_uniform: D::Uniform,
pub tile_size_uniform: D::Uniform,
pub area_lut_uniform: D::Uniform,
}
impl<D> FillProgram<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgram<D> {
let program = device.create_program(resources, "fill");
impl<D> FillRasterProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillRasterProgram<D> {
let program = device.create_raster_program(resources, "fill");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let area_lut_uniform = device.get_uniform(&program, "AreaLUT");
FillProgram {
FillRasterProgram {
program,
framebuffer_size_uniform,
tile_size_uniform,
@ -374,6 +373,41 @@ where
}
}
pub struct FillComputeProgram<D> where D: Device {
pub program: D::Program,
pub dest_uniform: D::Uniform,
pub area_lut_uniform: D::Uniform,
pub first_tile_index_uniform: D::Uniform,
pub fills_storage_buffer: D::StorageBuffer,
pub next_fills_storage_buffer: D::StorageBuffer,
pub fill_tile_map_storage_buffer: D::StorageBuffer,
}
impl<D> FillComputeProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillComputeProgram<D> {
let mut program = device.create_compute_program(resources, "fill");
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT, z: 1 };
device.set_compute_program_local_size(&mut program, local_size);
let dest_uniform = device.get_uniform(&program, "Dest");
let area_lut_uniform = device.get_uniform(&program, "AreaLUT");
let first_tile_index_uniform = device.get_uniform(&program, "FirstTileIndex");
let fills_storage_buffer = device.get_storage_buffer(&program, "Fills", 0);
let next_fills_storage_buffer = device.get_storage_buffer(&program, "NextFills", 1);
let fill_tile_map_storage_buffer = device.get_storage_buffer(&program, "FillTileMap", 2);
FillComputeProgram {
program,
dest_uniform,
area_lut_uniform,
first_tile_index_uniform,
fills_storage_buffer,
next_fills_storage_buffer,
fill_tile_map_storage_buffer,
}
}
}
pub struct TileProgram<D> where D: Device {
pub program: D::Program,
pub transform_uniform: D::Uniform,
@ -395,7 +429,7 @@ pub struct TileProgram<D> where D: Device {
impl<D> TileProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileProgram<D> {
let program = device.create_program(resources, "tile");
let program = device.create_raster_program(resources, "tile");
let transform_uniform = device.get_uniform(&program, "Transform");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let texture_metadata_uniform = device.get_uniform(&program, "TextureMetadata");
@ -442,7 +476,7 @@ pub struct CopyTileProgram<D> where D: Device {
impl<D> CopyTileProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> CopyTileProgram<D> {
let program = device.create_program(resources, "tile_copy");
let program = device.create_raster_program(resources, "tile_copy");
let transform_uniform = device.get_uniform(&program, "Transform");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
@ -464,7 +498,7 @@ pub struct ClipTileProgram<D> where D: Device {
impl<D> ClipTileProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileProgram<D> {
let program = device.create_program(resources, "tile_clip");
let program = device.create_raster_program(resources, "tile_clip");
let src_uniform = device.get_uniform(&program, "Src");
ClipTileProgram { program, src_uniform }
}
@ -482,7 +516,7 @@ where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram<D> {
let program = device.create_program(resources, "stencil");
let program = device.create_raster_program(resources, "stencil");
StencilProgram { program }
}
}
@ -502,7 +536,8 @@ where
{
pub fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> {
let vertex_array = device.create_vertex_array();
let (vertex_buffer, index_buffer) = (device.create_buffer(), device.create_buffer());
let vertex_buffer = device.create_buffer(BufferUploadMode::Static);
let index_buffer = device.create_buffer(BufferUploadMode::Static);
let position_attr = device.get_vertex_attr(&stencil_program.program, "Position").unwrap();
@ -537,7 +572,7 @@ where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
let program = device.create_program(resources, "reproject");
let program = device.create_raster_program(resources, "reproject");
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
let texture_uniform = device.get_uniform(&program, "Texture");

View File

@ -147,12 +147,11 @@ pub struct FillBatchEntry {
pub page: u16,
}
// FIXME(pcwalton): Move `subpx` before `px` and remove `repr(packed)`.
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
#[repr(C)]
pub struct Fill {
pub px: LineSegmentU4,
pub subpx: LineSegmentU8,
pub px: LineSegmentU4,
pub alpha_tile_index: u16,
}

View File

@ -12,21 +12,24 @@
#extension GL_GOOGLE_include_directive : enable
precision highp float;
precision highp sampler2D;
uniform sampler2D uAreaLUT;
in vec2 vFrom;
in vec2 vTo;
out vec4 oFragColor;
void main(){
vec2 from = vFrom, to = vTo;
float computeCoverage(vec2 from, vec2 to, sampler2D areaLUT){
vec2 left = from . x < to . x ? from : to, right = from . x < to . x ? to : from;
@ -40,6 +43,18 @@ void main(){
float dX = window . x - window . y;
oFragColor = vec4(texture(uAreaLUT, vec2(y + 8.0, abs(d * dX))/ 16.0). r * dX);
return texture(areaLUT, vec2(y + 8.0, abs(d * dX))/ 16.0). r * dX;
}
uniform sampler2D uAreaLUT;
in vec2 vFrom;
in vec2 vTo;
out vec4 oFragColor;
void main(){
oFragColor = vec4(computeCoverage(vFrom, vTo, uAreaLUT));
}

View File

@ -4,12 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
texture2d<float> uSrc [[id(0)]];
sampler uSrcSmplr [[id(1)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
@ -20,10 +14,10 @@ struct main0_in
float2 vTexCoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uSrc [[texture(0)]], sampler uSrcSmplr [[sampler(0)]])
{
main0_out out = {};
float4 color = spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, in.vTexCoord);
float4 color = uSrc.sample(uSrcSmplr, in.vTexCoord);
out.oFragColor = float4(color.xyz * color.w, color.w);
return out;
}

View File

@ -4,20 +4,15 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float4* uColor [[id(0)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
};
fragment main0_out main0(constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
fragment main0_out main0(constant float4& uColor [[buffer(0)]])
{
main0_out out = {};
out.oFragColor = float4((*spvDescriptorSet0.uColor).xyz, 1.0) * (*spvDescriptorSet0.uColor).w;
out.oFragColor = float4(uColor.xyz, 1.0) * uColor.w;
return out;
}

View File

@ -4,11 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float2* uFramebufferSize [[id(0)]];
};
struct main0_out
{
float4 gl_Position [[position]];
@ -19,10 +14,10 @@ struct main0_in
int2 aPosition [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant float2& uFramebufferSize [[buffer(0)]])
{
main0_out out = {};
float2 position = ((float2(in.aPosition) / (*spvDescriptorSet0.uFramebufferSize)) * 2.0) - float2(1.0);
float2 position = ((float2(in.aPosition) / uFramebufferSize) * 2.0) - float2(1.0);
out.gl_Position = float4(position.x, -position.y, 0.0, 1.0);
return out;
}

View File

@ -4,13 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
texture2d<float> uTexture [[id(0)]];
sampler uTextureSmplr [[id(1)]];
constant float4* uColor [[id(2)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
@ -21,11 +14,11 @@ struct main0_in
float2 vTexCoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
fragment main0_out main0(main0_in in [[stage_in]], constant float4& uColor [[buffer(0)]], texture2d<float> uTexture [[texture(0)]], sampler uTextureSmplr [[sampler(0)]])
{
main0_out out = {};
float alpha = spvDescriptorSet0.uTexture.sample(spvDescriptorSet0.uTextureSmplr, in.vTexCoord).x * (*spvDescriptorSet0.uColor).w;
out.oFragColor = float4((*spvDescriptorSet0.uColor).xyz, 1.0) * alpha;
float alpha = uTexture.sample(uTextureSmplr, in.vTexCoord).x * uColor.w;
out.oFragColor = float4(uColor.xyz, 1.0) * alpha;
return out;
}

View File

@ -4,12 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float2* uTextureSize [[id(0)]];
constant float2* uFramebufferSize [[id(1)]];
};
struct main0_out
{
float2 vTexCoord [[user(locn0)]];
@ -22,11 +16,11 @@ struct main0_in
int2 aTexCoord [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant float2& uTextureSize [[buffer(0)]], constant float2& uFramebufferSize [[buffer(1)]])
{
main0_out out = {};
out.vTexCoord = float2(in.aTexCoord) / (*spvDescriptorSet0.uTextureSize);
float2 position = ((float2(in.aPosition) / (*spvDescriptorSet0.uFramebufferSize)) * 2.0) - float2(1.0);
out.vTexCoord = float2(in.aTexCoord) / uTextureSize;
float2 position = ((float2(in.aPosition) / uFramebufferSize) * 2.0) - float2(1.0);
out.gl_Position = float4(position.x, -position.y, 0.0, 1.0);
return out;
}

View File

@ -4,12 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float4* uGridlineColor [[id(0)]];
constant float4* uGroundColor [[id(1)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
@ -20,11 +14,11 @@ struct main0_in
float2 vTexCoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
fragment main0_out main0(main0_in in [[stage_in]], constant float4& uGridlineColor [[buffer(0)]], constant float4& uGroundColor [[buffer(1)]])
{
main0_out out = {};
float2 texCoordPx = fract(in.vTexCoord) / fwidth(in.vTexCoord);
out.oFragColor = select((*spvDescriptorSet0.uGroundColor), (*spvDescriptorSet0.uGridlineColor), bool4(any(texCoordPx <= float2(1.0))));
out.oFragColor = select(uGroundColor, uGridlineColor, bool4(any(texCoordPx <= float2(1.0))));
return out;
}

View File

@ -4,12 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant int* uGridlineCount [[id(0)]];
constant float4x4* uTransform [[id(1)]];
};
struct main0_out
{
float2 vTexCoord [[user(locn0)]];
@ -21,11 +15,11 @@ struct main0_in
int2 aPosition [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant int& uGridlineCount [[buffer(0)]], constant float4x4& uTransform [[buffer(1)]])
{
main0_out out = {};
out.vTexCoord = float2(in.aPosition * int2((*spvDescriptorSet0.uGridlineCount)));
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(int4(in.aPosition.x, 0, in.aPosition.y, 1));
out.vTexCoord = float2(in.aPosition * int2(uGridlineCount));
out.gl_Position = uTransform * float4(int4(in.aPosition.x, 0, in.aPosition.y, 1));
return out;
}

View File

@ -0,0 +1,67 @@
// Automatically generated from files in pathfinder/shaders/. Do not edit!
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct bFillTileMap
{
int iFillTileMap[1];
};
struct bFills
{
uint2 iFills[1];
};
struct bNextFills
{
int iNextFills[1];
};
constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(16u, 16u, 1u);
static inline __attribute__((always_inline))
float computeCoverage(thread const float2& from, thread const float2& to, thread const texture2d<float> areaLUT, thread const sampler areaLUTSmplr)
{
float2 left = select(to, from, bool2(from.x < to.x));
float2 right = select(from, to, bool2(from.x < to.x));
float2 window = fast::clamp(float2(from.x, to.x), float2(-0.5), float2(0.5));
float offset = mix(window.x, window.y, 0.5) - left.x;
float t = offset / (right.x - left.x);
float y = mix(left.y, right.y, t);
float d = (right.y - left.y) / (right.x - left.x);
float dX = window.x - window.y;
return areaLUT.sample(areaLUTSmplr, (float2(y + 8.0, abs(d * dX)) / float2(16.0)), level(0.0)).x * dX;
}
kernel void main0(constant int& uFirstTileIndex [[buffer(0)]], const device bFillTileMap& _165 [[buffer(1)]], const device bFills& _186 [[buffer(2)]], const device bNextFills& _269 [[buffer(3)]], texture2d<float> uAreaLUT [[texture(0)]], texture2d<float, access::write> uDest [[texture(1)]], sampler uAreaLUTSmplr [[sampler(0)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
{
int2 tileSubCoord = int2(gl_LocalInvocationID.xy);
uint tileIndexOffset = gl_WorkGroupID.z;
uint tileIndex = tileIndexOffset + uint(uFirstTileIndex);
int2 tileOrigin = int2(int(tileIndex & 255u), int((tileIndex >> 8u) & 255u)) * int2(16);
int2 destCoord = tileOrigin + tileSubCoord;
int fillIndex = _165.iFillTileMap[tileIndex];
if (fillIndex < 0)
{
return;
}
float coverage = 0.0;
do
{
uint2 fill = _186.iFills[fillIndex];
float2 from = float2(float(fill.y & 15u), float((fill.y >> 4u) & 15u)) + (float2(float(fill.x & 255u), float((fill.x >> 8u) & 255u)) / float2(256.0));
float2 to = float2(float((fill.y >> 8u) & 15u), float((fill.y >> 12u) & 15u)) + (float2(float((fill.x >> 16u) & 255u), float((fill.x >> 24u) & 255u)) / float2(256.0));
from -= (float2(tileSubCoord) + float2(0.5));
to -= (float2(tileSubCoord) + float2(0.5));
float2 param = from;
float2 param_1 = to;
coverage += computeCoverage(param, param_1, uAreaLUT, uAreaLUTSmplr);
fillIndex = _269.iNextFills[fillIndex];
} while (fillIndex >= 0);
uDest.write(float4(coverage), uint2(destCoord));
}

View File

@ -1,15 +1,11 @@
// Automatically generated from files in pathfinder/shaders/. Do not edit!
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvDescriptorSetBuffer0
{
texture2d<float> uAreaLUT [[id(0)]];
sampler uAreaLUTSmplr [[id(1)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
@ -21,11 +17,9 @@ struct main0_in
float2 vTo [[user(locn1)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
static inline __attribute__((always_inline))
float computeCoverage(thread const float2& from, thread const float2& to, thread const texture2d<float> areaLUT, thread const sampler areaLUTSmplr)
{
main0_out out = {};
float2 from = in.vFrom;
float2 to = in.vTo;
float2 left = select(to, from, bool2(from.x < to.x));
float2 right = select(from, to, bool2(from.x < to.x));
float2 window = fast::clamp(float2(from.x, to.x), float2(-0.5), float2(0.5));
@ -34,7 +28,15 @@ fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuff
float y = mix(left.y, right.y, t);
float d = (right.y - left.y) / (right.x - left.x);
float dX = window.x - window.y;
out.oFragColor = float4(spvDescriptorSet0.uAreaLUT.sample(spvDescriptorSet0.uAreaLUTSmplr, (float2(y + 8.0, abs(d * dX)) / float2(16.0))).x * dX);
return areaLUT.sample(areaLUTSmplr, (float2(y + 8.0, abs(d * dX)) / float2(16.0))).x * dX;
}
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uAreaLUT [[texture(0)]], sampler uAreaLUTSmplr [[sampler(0)]])
{
main0_out out = {};
float2 param = in.vFrom;
float2 param_1 = in.vTo;
out.oFragColor = float4(computeCoverage(param, param_1, uAreaLUT, uAreaLUTSmplr));
return out;
}

View File

@ -6,12 +6,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float2* uTileSize [[id(0)]];
constant float2* uFramebufferSize [[id(1)]];
};
struct main0_out
{
float2 vFrom [[user(locn0)]];
@ -29,6 +23,7 @@ struct main0_in
uint aTileIndex [[attribute(5)]];
};
static inline __attribute__((always_inline))
float2 computeTileOffset(thread const uint& tileIndex, thread const float& stencilTextureWidth, thread float2 uTileSize)
{
uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x);
@ -36,12 +31,12 @@ float2 computeTileOffset(thread const uint& tileIndex, thread const float& stenc
return float2(tileOffset) * uTileSize;
}
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant float2& uTileSize [[buffer(0)]], constant float2& uFramebufferSize [[buffer(1)]])
{
main0_out out = {};
uint param = in.aTileIndex;
float param_1 = (*spvDescriptorSet0.uFramebufferSize).x;
float2 tileOrigin = computeTileOffset(param, param_1, (*spvDescriptorSet0.uTileSize));
float param_1 = uFramebufferSize.x;
float2 tileOrigin = computeTileOffset(param, param_1, uTileSize);
float2 from = float2(float(in.aFromPx & 15u), float(in.aFromPx >> 4u)) + in.aFromSubpx;
float2 to = float2(float(in.aToPx & 15u), float(in.aToPx >> 4u)) + in.aToSubpx;
float2 position;
@ -59,11 +54,11 @@ vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer
}
else
{
position.y = (*spvDescriptorSet0.uTileSize).y;
position.y = uTileSize.y;
}
out.vFrom = from - position;
out.vTo = to - position;
float2 globalPosition = (((tileOrigin + position) / (*spvDescriptorSet0.uFramebufferSize)) * 2.0) - float2(1.0);
float2 globalPosition = (((tileOrigin + position) / uFramebufferSize) * 2.0) - float2(1.0);
globalPosition.y = -globalPosition.y;
out.gl_Position = float4(globalPosition, 0.0, 1.0);
return out;

View File

@ -4,13 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float4x4* uOldTransform [[id(0)]];
texture2d<float> uTexture [[id(1)]];
sampler uTextureSmplr [[id(2)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
@ -21,12 +14,12 @@ struct main0_in
float2 vTexCoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
fragment main0_out main0(main0_in in [[stage_in]], constant float4x4& uOldTransform [[buffer(0)]], texture2d<float> uTexture [[texture(0)]], sampler uTextureSmplr [[sampler(0)]])
{
main0_out out = {};
float4 normTexCoord = (*spvDescriptorSet0.uOldTransform) * float4(in.vTexCoord, 0.0, 1.0);
float4 normTexCoord = uOldTransform * float4(in.vTexCoord, 0.0, 1.0);
float2 texCoord = ((normTexCoord.xy / float2(normTexCoord.w)) + float2(1.0)) * 0.5;
out.oFragColor = spvDescriptorSet0.uTexture.sample(spvDescriptorSet0.uTextureSmplr, texCoord);
out.oFragColor = uTexture.sample(uTextureSmplr, texCoord);
return out;
}

View File

@ -4,11 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float4x4* uNewTransform [[id(0)]];
};
struct main0_out
{
float2 vTexCoord [[user(locn0)]];
@ -20,13 +15,13 @@ struct main0_in
int2 aPosition [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant float4x4& uNewTransform [[buffer(0)]])
{
main0_out out = {};
float2 position = float2(in.aPosition);
out.vTexCoord = position;
position.y = 1.0 - position.y;
out.gl_Position = (*spvDescriptorSet0.uNewTransform) * float4(position, 0.0, 1.0);
out.gl_Position = uNewTransform * float4(position, 0.0, 1.0);
return out;
}

View File

@ -6,24 +6,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
texture2d<float> uMaskTexture0 [[id(0)]];
sampler uMaskTexture0Smplr [[id(1)]];
texture2d<float> uColorTexture0 [[id(2)]];
sampler uColorTexture0Smplr [[id(3)]];
texture2d<float> uGammaLUT [[id(4)]];
sampler uGammaLUTSmplr [[id(5)]];
constant float2* uColorTexture0Size [[id(6)]];
constant float2* uFramebufferSize [[id(7)]];
constant float4* uFilterParams0 [[id(8)]];
constant float4* uFilterParams1 [[id(9)]];
constant float4* uFilterParams2 [[id(10)]];
texture2d<float> uDestTexture [[id(11)]];
sampler uDestTextureSmplr [[id(12)]];
constant int* uCtrl [[id(13)]];
};
constant float3 _1041 = {};
struct main0_out
@ -41,11 +23,12 @@ struct main0_in
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
template<typename Tx, typename Ty>
Tx mod(Tx x, Ty y)
inline Tx mod(Tx x, Ty y)
{
return x - y * floor(x / y);
}
static inline __attribute__((always_inline))
float sampleMask(thread const float& maskAlpha, thread const texture2d<float> maskTexture, thread const sampler maskTextureSmplr, thread const float3& maskTexCoord, thread const int& maskCtrl)
{
if (maskCtrl == 0)
@ -64,6 +47,7 @@ float sampleMask(thread const float& maskAlpha, thread const texture2d<float> ma
return fast::min(maskAlpha, coverage);
}
static inline __attribute__((always_inline))
float4 filterRadialGradient(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTextureSize, thread const float2& fragCoord, thread const float2& framebufferSize, thread const float4& filterParams0, thread const float4& filterParams1)
{
float2 lineFrom = filterParams0.xy;
@ -100,6 +84,7 @@ float4 filterRadialGradient(thread const float2& colorTexCoord, thread const tex
return color;
}
static inline __attribute__((always_inline))
float4 filterBlur(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTextureSize, thread const float4& filterParams0, thread const float4& filterParams1)
{
float2 srcOffsetScale = filterParams0.xy / colorTextureSize;
@ -124,11 +109,13 @@ float4 filterBlur(thread const float2& colorTexCoord, thread const texture2d<flo
return color / float4(gaussSum);
}
static inline __attribute__((always_inline))
float filterTextSample1Tap(thread const float& offset, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTexCoord)
{
return colorTexture.sample(colorTextureSmplr, (colorTexCoord + float2(offset, 0.0))).x;
}
static inline __attribute__((always_inline))
void filterTextSample9Tap(thread float4& outAlphaLeft, thread float& outAlphaCenter, thread float4& outAlphaRight, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTexCoord, thread const float4& kernel0, thread const float& onePixel)
{
bool wide = kernel0.x > 0.0;
@ -173,16 +160,19 @@ void filterTextSample9Tap(thread float4& outAlphaLeft, thread float& outAlphaCen
outAlphaRight = float4(filterTextSample1Tap(param_10, colorTexture, colorTextureSmplr, param_11), filterTextSample1Tap(param_12, colorTexture, colorTextureSmplr, param_13), filterTextSample1Tap(param_14, colorTexture, colorTextureSmplr, param_15), _295);
}
static inline __attribute__((always_inline))
float filterTextConvolve7Tap(thread const float4& alpha0, thread const float3& alpha1, thread const float4& kernel0)
{
return dot(alpha0, kernel0) + dot(alpha1, kernel0.zyx);
}
static inline __attribute__((always_inline))
float filterTextGammaCorrectChannel(thread const float& bgColor, thread const float& fgColor, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr)
{
return gammaLUT.sample(gammaLUTSmplr, float2(fgColor, 1.0 - bgColor)).x;
}
static inline __attribute__((always_inline))
float3 filterTextGammaCorrect(thread const float3& bgColor, thread const float3& fgColor, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr)
{
float param = bgColor.x;
@ -194,6 +184,7 @@ float3 filterTextGammaCorrect(thread const float3& bgColor, thread const float3&
return float3(filterTextGammaCorrectChannel(param, param_1, gammaLUT, gammaLUTSmplr), filterTextGammaCorrectChannel(param_2, param_3, gammaLUT, gammaLUTSmplr), filterTextGammaCorrectChannel(param_4, param_5, gammaLUT, gammaLUTSmplr));
}
static inline __attribute__((always_inline))
float4 filterText(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr, thread const float2& colorTextureSize, thread const float4& filterParams0, thread const float4& filterParams1, thread const float4& filterParams2)
{
float4 kernel0 = filterParams0;
@ -240,17 +231,20 @@ float4 filterText(thread const float2& colorTexCoord, thread const texture2d<flo
return float4(mix(bgColor, fgColor, alpha), 1.0);
}
static inline __attribute__((always_inline))
float4 sampleColor(thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTexCoord)
{
return colorTexture.sample(colorTextureSmplr, colorTexCoord);
}
static inline __attribute__((always_inline))
float4 filterNone(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr)
{
float2 param = colorTexCoord;
return sampleColor(colorTexture, colorTextureSmplr, param);
}
static inline __attribute__((always_inline))
float4 filterColor(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr, thread const float2& colorTextureSize, thread const float2& fragCoord, thread const float2& framebufferSize, thread const float4& filterParams0, thread const float4& filterParams1, thread const float4& filterParams2, thread const int& colorFilter)
{
switch (colorFilter)
@ -287,6 +281,7 @@ float4 filterColor(thread const float2& colorTexCoord, thread const texture2d<fl
return filterNone(param_15, colorTexture, colorTextureSmplr);
}
static inline __attribute__((always_inline))
float4 combineColor0(thread const float4& destColor, thread const float4& srcColor, thread const int& op)
{
switch (op)
@ -303,11 +298,13 @@ float4 combineColor0(thread const float4& destColor, thread const float4& srcCol
return destColor;
}
static inline __attribute__((always_inline))
float3 compositeScreen(thread const float3& destColor, thread const float3& srcColor)
{
return (destColor + srcColor) - (destColor * srcColor);
}
static inline __attribute__((always_inline))
float3 compositeSelect(thread const bool3& cond, thread const float3& ifTrue, thread const float3& ifFalse)
{
float _725;
@ -340,6 +337,7 @@ float3 compositeSelect(thread const bool3& cond, thread const float3& ifTrue, th
return float3(_725, _736, _747);
}
static inline __attribute__((always_inline))
float3 compositeHardLight(thread const float3& destColor, thread const float3& srcColor)
{
float3 param = destColor;
@ -350,6 +348,7 @@ float3 compositeHardLight(thread const float3& destColor, thread const float3& s
return compositeSelect(param_2, param_3, param_4);
}
static inline __attribute__((always_inline))
float3 compositeColorDodge(thread const float3& destColor, thread const float3& srcColor)
{
bool3 destZero = destColor == float3(0.0);
@ -363,6 +362,7 @@ float3 compositeColorDodge(thread const float3& destColor, thread const float3&
return compositeSelect(param_3, param_4, param_5);
}
static inline __attribute__((always_inline))
float3 compositeSoftLight(thread const float3& destColor, thread const float3& srcColor)
{
bool3 param = destColor <= float3(0.25);
@ -376,6 +376,7 @@ float3 compositeSoftLight(thread const float3& destColor, thread const float3& s
return destColor + (((srcColor * 2.0) - float3(1.0)) * factor);
}
static inline __attribute__((always_inline))
float compositeDivide(thread const float& num, thread const float& denom)
{
float _761;
@ -390,6 +391,7 @@ float compositeDivide(thread const float& num, thread const float& denom)
return _761;
}
static inline __attribute__((always_inline))
float3 compositeRGBToHSL(thread const float3& rgb)
{
float v = fast::max(fast::max(rgb.x, rgb.y), rgb.z);
@ -424,6 +426,7 @@ float3 compositeRGBToHSL(thread const float3& rgb)
return float3(h, s, l);
}
static inline __attribute__((always_inline))
float3 compositeHSL(thread const float3& destColor, thread const float3& srcColor, thread const int& op)
{
switch (op)
@ -447,6 +450,7 @@ float3 compositeHSL(thread const float3& destColor, thread const float3& srcColo
}
}
static inline __attribute__((always_inline))
float3 compositeHSLToRGB(thread const float3& hsl)
{
float a = hsl.y * fast::min(hsl.z, 1.0 - hsl.z);
@ -454,6 +458,7 @@ float3 compositeHSLToRGB(thread const float3& hsl)
return hsl.zzz - (fast::clamp(fast::min(ks - float3(3.0), float3(9.0) - ks), float3(-1.0), float3(1.0)) * a);
}
static inline __attribute__((always_inline))
float3 compositeRGB(thread const float3& destColor, thread const float3& srcColor, thread const int& op)
{
switch (op)
@ -531,6 +536,7 @@ float3 compositeRGB(thread const float3& destColor, thread const float3& srcColo
return srcColor;
}
static inline __attribute__((always_inline))
float4 composite(thread const float4& srcColor, thread const texture2d<float> destTexture, thread const sampler destTextureSmplr, thread const float2& destTextureSize, thread const float2& fragCoord, thread const int& op)
{
if (op == 0)
@ -546,6 +552,7 @@ float4 composite(thread const float4& srcColor, thread const texture2d<float> de
return float4(((srcColor.xyz * (srcColor.w * (1.0 - destColor.w))) + (blendedRGB * (srcColor.w * destColor.w))) + (destColor.xyz * (1.0 - srcColor.w)), 1.0);
}
static inline __attribute__((always_inline))
void calculateColor(thread const int& tileCtrl, thread const int& ctrl, thread texture2d<float> uMaskTexture0, thread const sampler uMaskTexture0Smplr, thread float3& vMaskTexCoord0, thread float4& vBaseColor, thread float2& vColorTexCoord0, thread texture2d<float> uColorTexture0, thread const sampler uColorTexture0Smplr, thread texture2d<float> uGammaLUT, thread const sampler uGammaLUTSmplr, thread float2 uColorTexture0Size, thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread float4 uFilterParams0, thread float4 uFilterParams1, thread float4 uFilterParams2, thread texture2d<float> uDestTexture, thread const sampler uDestTextureSmplr, thread float4& oFragColor)
{
int maskCtrl0 = (tileCtrl >> 0) & 3;
@ -585,12 +592,12 @@ void calculateColor(thread const int& tileCtrl, thread const int& ctrl, thread t
oFragColor = color;
}
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
fragment main0_out main0(main0_in in [[stage_in]], constant int& uCtrl [[buffer(5)]], constant float2& uColorTexture0Size [[buffer(0)]], constant float2& uFramebufferSize [[buffer(1)]], constant float4& uFilterParams0 [[buffer(2)]], constant float4& uFilterParams1 [[buffer(3)]], constant float4& uFilterParams2 [[buffer(4)]], texture2d<float> uMaskTexture0 [[texture(0)]], texture2d<float> uColorTexture0 [[texture(1)]], texture2d<float> uGammaLUT [[texture(2)]], texture2d<float> uDestTexture [[texture(3)]], sampler uMaskTexture0Smplr [[sampler(0)]], sampler uColorTexture0Smplr [[sampler(1)]], sampler uGammaLUTSmplr [[sampler(2)]], sampler uDestTextureSmplr [[sampler(3)]], float4 gl_FragCoord [[position]])
{
main0_out out = {};
int param = int(in.vTileCtrl);
int param_1 = (*spvDescriptorSet0.uCtrl);
calculateColor(param, param_1, spvDescriptorSet0.uMaskTexture0, spvDescriptorSet0.uMaskTexture0Smplr, in.vMaskTexCoord0, in.vBaseColor, in.vColorTexCoord0, spvDescriptorSet0.uColorTexture0, spvDescriptorSet0.uColorTexture0Smplr, spvDescriptorSet0.uGammaLUT, spvDescriptorSet0.uGammaLUTSmplr, (*spvDescriptorSet0.uColorTexture0Size), gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), (*spvDescriptorSet0.uFilterParams0), (*spvDescriptorSet0.uFilterParams1), (*spvDescriptorSet0.uFilterParams2), spvDescriptorSet0.uDestTexture, spvDescriptorSet0.uDestTextureSmplr, out.oFragColor);
int param_1 = uCtrl;
calculateColor(param, param_1, uMaskTexture0, uMaskTexture0Smplr, in.vMaskTexCoord0, in.vBaseColor, in.vColorTexCoord0, uColorTexture0, uColorTexture0Smplr, uGammaLUT, uGammaLUTSmplr, uColorTexture0Size, gl_FragCoord, uFramebufferSize, uFilterParams0, uFilterParams1, uFilterParams2, uDestTexture, uDestTextureSmplr, out.oFragColor);
return out;
}

View File

@ -4,15 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float2* uTileSize [[id(0)]];
constant int2* uTextureMetadataSize [[id(1)]];
texture2d<float> uTextureMetadata [[id(2)]];
sampler uTextureMetadataSmplr [[id(3)]];
constant float4x4* uTransform [[id(4)]];
};
struct main0_out
{
float3 vMaskTexCoord0 [[user(locn0)]];
@ -32,26 +23,26 @@ struct main0_in
int aTileCtrl [[attribute(5)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant int2& uTextureMetadataSize [[buffer(1)]], constant float2& uTileSize [[buffer(0)]], constant float4x4& uTransform [[buffer(2)]], texture2d<float> uTextureMetadata [[texture(0)]], sampler uTextureMetadataSmplr [[sampler(0)]])
{
main0_out out = {};
float2 tileOrigin = float2(in.aTileOrigin);
float2 tileOffset = float2(in.aTileOffset);
float2 position = (tileOrigin + tileOffset) * (*spvDescriptorSet0.uTileSize);
float2 position = (tileOrigin + tileOffset) * uTileSize;
float2 maskTexCoord0 = (float2(in.aMaskTexCoord0) + tileOffset) / float2(256.0);
float2 textureMetadataScale = float2(1.0) / float2((*spvDescriptorSet0.uTextureMetadataSize));
float2 textureMetadataScale = float2(1.0) / float2(uTextureMetadataSize);
float2 metadataEntryCoord = float2(float((in.aColor % 128) * 4), float(in.aColor / 128));
float2 colorTexMatrix0Coord = (metadataEntryCoord + float2(0.5)) * textureMetadataScale;
float2 colorTexOffsetsCoord = (metadataEntryCoord + float2(1.5, 0.5)) * textureMetadataScale;
float2 baseColorCoord = (metadataEntryCoord + float2(2.5, 0.5)) * textureMetadataScale;
float4 colorTexMatrix0 = spvDescriptorSet0.uTextureMetadata.sample(spvDescriptorSet0.uTextureMetadataSmplr, colorTexMatrix0Coord, level(0.0));
float4 colorTexOffsets = spvDescriptorSet0.uTextureMetadata.sample(spvDescriptorSet0.uTextureMetadataSmplr, colorTexOffsetsCoord, level(0.0));
float4 baseColor = spvDescriptorSet0.uTextureMetadata.sample(spvDescriptorSet0.uTextureMetadataSmplr, baseColorCoord, level(0.0));
float4 colorTexMatrix0 = uTextureMetadata.sample(uTextureMetadataSmplr, colorTexMatrix0Coord, level(0.0));
float4 colorTexOffsets = uTextureMetadata.sample(uTextureMetadataSmplr, colorTexOffsetsCoord, level(0.0));
float4 baseColor = uTextureMetadata.sample(uTextureMetadataSmplr, baseColorCoord, level(0.0));
out.vColorTexCoord0 = (float2x2(float2(colorTexMatrix0.xy), float2(colorTexMatrix0.zw)) * position) + colorTexOffsets.xy;
out.vMaskTexCoord0 = float3(maskTexCoord0, float(in.aMaskBackdrop.x));
out.vBaseColor = baseColor;
out.vTileCtrl = float(in.aTileCtrl);
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
out.gl_Position = uTransform * float4(position, 0.0, 1.0);
return out;
}

View File

@ -4,12 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
texture2d<float> uSrc [[id(0)]];
sampler uSrcSmplr [[id(1)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
@ -21,10 +15,10 @@ struct main0_in
float vBackdrop [[user(locn1)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uSrc [[texture(0)]], sampler uSrcSmplr [[sampler(0)]])
{
main0_out out = {};
float alpha = fast::clamp(abs(spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, in.vTexCoord).x + in.vBackdrop), 0.0, 1.0);
float alpha = fast::clamp(abs(uSrc.sample(uSrcSmplr, in.vTexCoord).x + in.vBackdrop), 0.0, 1.0);
out.oFragColor = float4(alpha, 0.0, 0.0, 1.0);
return out;
}

View File

@ -4,23 +4,16 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float2* uFramebufferSize [[id(0)]];
texture2d<float> uSrc [[id(1)]];
sampler uSrcSmplr [[id(2)]];
};
struct main0_out
{
float4 oFragColor [[color(0)]];
};
fragment main0_out main0(constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
fragment main0_out main0(constant float2& uFramebufferSize [[buffer(0)]], texture2d<float> uSrc [[texture(0)]], sampler uSrcSmplr [[sampler(0)]], float4 gl_FragCoord [[position]])
{
main0_out out = {};
float2 texCoord = gl_FragCoord.xy / (*spvDescriptorSet0.uFramebufferSize);
out.oFragColor = spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, texCoord);
float2 texCoord = gl_FragCoord.xy / uFramebufferSize;
out.oFragColor = uSrc.sample(uSrcSmplr, texCoord);
return out;
}

View File

@ -4,12 +4,6 @@
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant float2* uTileSize [[id(0)]];
constant float4x4* uTransform [[id(1)]];
};
struct main0_out
{
float4 gl_Position [[position]];
@ -20,11 +14,11 @@ struct main0_in
int2 aTilePosition [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
vertex main0_out main0(main0_in in [[stage_in]], constant float2& uTileSize [[buffer(0)]], constant float4x4& uTransform [[buffer(1)]])
{
main0_out out = {};
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
float2 position = float2(in.aTilePosition) * uTileSize;
out.gl_Position = uTransform * float4(position, 0.0, 1.0);
return out;
}

View File

@ -25,21 +25,29 @@ SHADERS=\
tile_copy.vs.glsl \
$(EMPTY)
COMPUTE_SHADERS=\
fill.cs.glsl \
$(EMPTY)
INCLUDES=\
fill.inc.glsl \
$(EMPTY)
OUT=\
$(SHADERS:%=$(TARGET_DIR)/gl3/%) \
$(SHADERS:%.glsl=$(TARGET_DIR)/metal/%.metal) \
$(SHADERS:%.glsl=build/metal/%.spv) \
$(COMPUTE_SHADERS:%.glsl=$(TARGET_DIR)/metal/%.metal) \
$(COMPUTE_SHADERS:%.glsl=build/metal/%.spv) \
$(EMPTY)
GLSL_VERSION=330
GLSL_COMPUTE_VERSION=430
GLSLANGFLAGS=--auto-map-locations -I.
GLSLANGFLAGS_METAL=$(GLSLANGFLAGS) -DPF_ORIGIN_UPPER_LEFT=1
SPIRVCROSS?=spirv-cross
SPIRVCROSSFLAGS=--msl --msl-version 020100 --msl-argument-buffers
SPIRVCROSSFLAGS=--msl --msl-version 020100
GLSL_VERSION_HEADER="\#version {{version}}"
HEADER="// Automatically generated from files in pathfinder/shaders/. Do not edit!"
@ -65,5 +73,8 @@ build/metal/%.vs.spv: %.vs.glsl $(INCLUDES)
$(TARGET_DIR)/gl3/%.vs.glsl: %.vs.glsl $(INCLUDES)
mkdir -p $(TARGET_DIR)/gl3 && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S vert -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
build/metal/%.cs.spv: %.cs.glsl $(INCLUDES)
mkdir -p build/metal && glslangValidator $(GLSLANGFLAGS_METAL) -G$(GLSL_COMPUTE_VERSION) -S comp -o $@ $<
$(TARGET_DIR)/metal/%.metal: build/metal/%.spv
mkdir -p $(TARGET_DIR)/metal && echo $(HEADER) > $@ && ( $(SPIRVCROSS) $(SPIRVCROSSFLAGS) $< | sed $(METAL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )

67
shaders/fill.cs.glsl Normal file
View File

@ -0,0 +1,67 @@
#version 430
// pathfinder/shaders/fill.cs.glsl
//
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#extension GL_GOOGLE_include_directive : enable
precision highp float;
precision highp sampler2D;
#include "fill.inc.glsl"
layout(local_size_x = 16, local_size_y = 16) in;
uniform writeonly image2D uDest;
uniform sampler2D uAreaLUT;
uniform int uFirstTileIndex;
layout(std430, binding = 0) buffer bFills {
restrict readonly uvec2 iFills[];
};
layout(std430, binding = 1) buffer bNextFills {
restrict readonly int iNextFills[];
};
layout(std430, binding = 2) buffer bFillTileMap {
restrict readonly int iFillTileMap[];
};
void main() {
ivec2 tileSubCoord = ivec2(gl_LocalInvocationID.xy);
uint tileIndexOffset = gl_WorkGroupID.z;
uint tileIndex = tileIndexOffset + uint(uFirstTileIndex);
ivec2 tileOrigin = ivec2(tileIndex & 0xff, (tileIndex >> 8u) & 0xff) * 16;
ivec2 destCoord = tileOrigin + tileSubCoord;
int fillIndex = iFillTileMap[tileIndex];
if (fillIndex < 0)
return;
float coverage = 0.0;
do {
uvec2 fill = iFills[fillIndex];
vec2 from = vec2(fill.y & 0xf, (fill.y >> 4u) & 0xf) +
vec2(fill.x & 0xff, (fill.x >> 8u) & 0xff) / 256.0;
vec2 to = vec2((fill.y >> 8u) & 0xf, (fill.y >> 12u) & 0xf) +
vec2((fill.x >> 16u) & 0xff, (fill.x >> 24u) & 0xff) / 256.0;
from -= vec2(tileSubCoord) + vec2(0.5);
to -= vec2(tileSubCoord) + vec2(0.5);
coverage += computeCoverage(from, to, uAreaLUT);
fillIndex = iNextFills[fillIndex];
} while (fillIndex >= 0);
imageStore(uDest, destCoord, vec4(coverage));
}

View File

@ -1,8 +1,8 @@
#version 330
// pathfinder/shaders/stencil.fs.glsl
// pathfinder/shaders/fill.fs.glsl
//
// Copyright © 2019 The Pathfinder Project Developers.
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@ -10,9 +10,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#extension GL_GOOGLE_include_directive : enable
precision highp float;
precision highp sampler2D;
#include "fill.inc.glsl"
uniform sampler2D uAreaLUT;
in vec2 vFrom;
@ -21,22 +25,5 @@ in vec2 vTo;
out vec4 oFragColor;
void main() {
// Unpack.
vec2 from = vFrom, to = vTo;
// Determine winding, and sort into a consistent order so we only need to find one root below.
vec2 left = from.x < to.x ? from : to, right = from.x < to.x ? to : from;
// Shoot a vertical ray toward the curve.
vec2 window = clamp(vec2(from.x, to.x), -0.5, 0.5);
float offset = mix(window.x, window.y, 0.5) - left.x;
float t = offset / (right.x - left.x);
// Compute position and derivative to form a line approximation.
float y = mix(left.y, right.y, t);
float d = (right.y - left.y) / (right.x - left.x);
// Look up area under that line, and scale horizontally to the window size.
float dX = window.x - window.y;
oFragColor = vec4(texture(uAreaLUT, vec2(y + 8.0, abs(d * dX)) / 16.0).r * dX);
oFragColor = vec4(computeCoverage(vFrom, vTo, uAreaLUT));
}

27
shaders/fill.inc.glsl Normal file
View File

@ -0,0 +1,27 @@
// pathfinder/shaders/fill.inc.glsl
//
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
float computeCoverage(vec2 from, vec2 to, sampler2D areaLUT) {
// Determine winding, and sort into a consistent order so we only need to find one root below.
vec2 left = from.x < to.x ? from : to, right = from.x < to.x ? to : from;
// Shoot a vertical ray toward the curve.
vec2 window = clamp(vec2(from.x, to.x), -0.5, 0.5);
float offset = mix(window.x, window.y, 0.5) - left.x;
float t = offset / (right.x - left.x);
// Compute position and derivative to form a line approximation.
float y = mix(left.y, right.y, t);
float d = (right.y - left.y) / (right.x - left.x);
// Look up area under that line, and scale horizontally to the window size.
float dX = window.x - window.y;
return texture(areaLUT, vec2(y + 8.0, abs(d * dX)) / 16.0).r * dX;
}

View File

@ -2,7 +2,7 @@
// pathfinder/shaders/fill.vs.glsl
//
// Copyright © 2019 The Pathfinder Project Developers.
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license

View File

@ -166,12 +166,10 @@ impl<D> UIPresenter<D> where D: Device {
filled: bool) {
device.allocate_buffer(&self.solid_vertex_array.vertex_buffer,
BufferData::Memory(vertex_data),
BufferTarget::Vertex,
BufferUploadMode::Dynamic);
BufferTarget::Vertex);
device.allocate_buffer(&self.solid_vertex_array.index_buffer,
BufferData::Memory(index_data),
BufferTarget::Index,
BufferUploadMode::Dynamic);
BufferTarget::Index);
let primitive = if filled { Primitive::Triangles } else { Primitive::Lines };
device.draw_elements(index_data.len() as u32, &RenderState {
@ -185,6 +183,7 @@ impl<D> UIPresenter<D> where D: Device {
(&self.solid_program.color_uniform, get_color_uniform(color)),
],
textures: &[],
images: &[],
viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
options: RenderOptions {
blend: Some(alpha_blend_state()),
@ -398,12 +397,10 @@ impl<D> UIPresenter<D> where D: Device {
color: ColorU) {
device.allocate_buffer(&self.texture_vertex_array.vertex_buffer,
BufferData::Memory(vertex_data),
BufferTarget::Vertex,
BufferUploadMode::Dynamic);
BufferTarget::Vertex);
device.allocate_buffer(&self.texture_vertex_array.index_buffer,
BufferData::Memory(index_data),
BufferTarget::Index,
BufferUploadMode::Dynamic);
BufferTarget::Index);
device.draw_elements(index_data.len() as u32, &RenderState {
target: &RenderTarget::Default,
@ -411,6 +408,7 @@ impl<D> UIPresenter<D> where D: Device {
vertex_array: &self.texture_vertex_array.vertex_array,
primitive: Primitive::Triangles,
textures: &[&texture],
images: &[],
uniforms: &[
(&self.texture_program.framebuffer_size_uniform,
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
@ -569,7 +567,7 @@ struct DebugTextureProgram<D> where D: Device {
impl<D> DebugTextureProgram<D> where D: Device {
fn new(device: &D, resources: &dyn ResourceLoader) -> DebugTextureProgram<D> {
let program = device.create_program(resources, "debug_texture");
let program = device.create_raster_program(resources, "debug_texture");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let texture_size_uniform = device.get_uniform(&program, "TextureSize");
let texture_uniform = device.get_uniform(&program, "Texture");
@ -593,7 +591,8 @@ struct DebugTextureVertexArray<D> where D: Device {
impl<D> DebugTextureVertexArray<D> where D: Device {
fn new(device: &D, debug_texture_program: &DebugTextureProgram<D>)
-> DebugTextureVertexArray<D> {
let (vertex_buffer, index_buffer) = (device.create_buffer(), device.create_buffer());
let vertex_buffer = device.create_buffer(BufferUploadMode::Dynamic);
let index_buffer = device.create_buffer(BufferUploadMode::Dynamic);
let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&debug_texture_program.program, "Position")
@ -634,7 +633,8 @@ struct DebugSolidVertexArray<D> where D: Device {
impl<D> DebugSolidVertexArray<D> where D: Device {
fn new(device: &D, debug_solid_program: &DebugSolidProgram<D>) -> DebugSolidVertexArray<D> {
let (vertex_buffer, index_buffer) = (device.create_buffer(), device.create_buffer());
let vertex_buffer = device.create_buffer(BufferUploadMode::Dynamic);
let index_buffer = device.create_buffer(BufferUploadMode::Dynamic);
let vertex_array = device.create_vertex_array();
let position_attr =
@ -663,7 +663,7 @@ struct DebugSolidProgram<D> where D: Device {
impl<D> DebugSolidProgram<D> where D: Device {
fn new(device: &D, resources: &dyn ResourceLoader) -> DebugSolidProgram<D> {
let program = device.create_program(resources, "debug_solid");
let program = device.create_raster_program(resources, "debug_solid");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let color_uniform = device.get_uniform(&program, "Color");
DebugSolidProgram { program, framebuffer_size_uniform, color_uniform }

View File

@ -16,15 +16,15 @@ extern crate log;
use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::Vector2I;
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, RenderTarget};
use pathfinder_gpu::{BufferUploadMode, ClearOps, DepthFunc, Device, Primitive, RenderOptions};
use pathfinder_gpu::{RenderState, ShaderKind, StencilFunc, TextureData, TextureDataRef};
use pathfinder_gpu::{TextureFormat, TextureSamplingFlags, UniformData, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_gpu::{BufferUploadMode, ClearOps, ComputeDimensions, ComputeState, DepthFunc, Device, Primitive, ProgramKind};
use pathfinder_gpu::{RenderOptions, RenderState, ShaderKind, StencilFunc, TextureData};
use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData};
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
use pathfinder_resources::ResourceLoader;
use std::mem;
use std::str;
use std::time::Duration;
use wasm_bindgen::{JsCast, JsValue};
use wasm_bindgen::JsCast;
use web_sys::WebGl2RenderingContext as WebGl;
use js_sys::{Uint8Array, Uint16Array, Float32Array, Object};
@ -169,7 +169,7 @@ impl WebGlDevice {
self.context.uniform3i(location, data[0], data[1], data[2]);
self.ck();
}
UniformData::TextureUnit(unit) => {
UniformData::TextureUnit(unit) | UniformData::ImageUnit(unit) => {
self.context.uniform1i(location, unit as i32);
self.ck();
}
@ -412,9 +412,11 @@ unsafe fn check_and_extract_data(
impl Device for WebGlDevice {
type Buffer = WebGlBuffer;
type Fence = ();
type Framebuffer = WebGlFramebuffer;
type Program = WebGlProgram;
type Shader = WebGlShader;
type StorageBuffer = ();
type Texture = WebGlTexture;
type TextureDataReceiver = ();
type TimerQuery = WebGlTimerQuery;
@ -504,6 +506,7 @@ impl Device for WebGlDevice {
let gl_shader_kind = match kind {
ShaderKind::Vertex => WebGl::VERTEX_SHADER,
ShaderKind::Fragment => WebGl::FRAGMENT_SHADER,
ShaderKind::Compute => panic!("Compute shaders are unsupported in WebGL!"),
};
let gl_shader = self
@ -529,17 +532,21 @@ impl Device for WebGlDevice {
&self,
_resources: &dyn ResourceLoader,
name: &str,
vertex_shader: WebGlShader,
fragment_shader: WebGlShader,
shaders: ProgramKind<WebGlShader>,
) -> WebGlProgram {
let gl_program = self
.context
.create_program()
.expect("unable to create program object");
self.context
.attach_shader(&gl_program, &vertex_shader.gl_shader);
self.context
.attach_shader(&gl_program, &fragment_shader.gl_shader);
match shaders {
ProgramKind::Raster { ref vertex, ref fragment } => {
self.context.attach_shader(&gl_program, &vertex.gl_shader);
self.context.attach_shader(&gl_program, &fragment.gl_shader);
}
ProgramKind::Compute(ref shader) => {
self.context.attach_shader(&gl_program, &shader.gl_shader);
}
}
self.context.link_program(&gl_program);
if !self
.context
@ -559,6 +566,11 @@ impl Device for WebGlDevice {
}
}
#[inline]
fn set_compute_program_local_size(&self, _: &mut Self::Program, _: ComputeDimensions) {
// This does nothing on OpenGL, since the local size is set in the shader.
}
#[inline]
fn create_vertex_array(&self) -> WebGlVertexArray {
WebGlVertexArray {
@ -585,6 +597,10 @@ impl Device for WebGlDevice {
WebGlUniform { location: location }
}
fn get_storage_buffer(&self, _: &Self::Program, _: &str, _: u32) {
// TODO(pcwalton)
}
fn configure_vertex_attr(
&self,
vertex_array: &WebGlVertexArray,
@ -671,11 +687,12 @@ impl Device for WebGlDevice {
framebuffer.texture
}
fn create_buffer(&self) -> WebGlBuffer {
fn create_buffer(&self, mode: BufferUploadMode) -> WebGlBuffer {
let buffer = self.context.create_buffer().unwrap();
WebGlBuffer {
buffer,
context: self.context.clone(),
mode,
}
}
@ -684,15 +701,15 @@ impl Device for WebGlDevice {
buffer: &WebGlBuffer,
data: BufferData<T>,
target: BufferTarget,
mode: BufferUploadMode,
) {
let target = match target {
BufferTarget::Vertex => WebGl::ARRAY_BUFFER,
BufferTarget::Index => WebGl::ELEMENT_ARRAY_BUFFER,
BufferTarget::Storage => panic!("Shader storage buffers are unsupported in WebGL!"),
};
self.context.bind_buffer(target, Some(&buffer.buffer));
self.ck();
let usage = mode.to_gl_usage();
let usage = buffer.mode.to_gl_usage();
match data {
BufferData::Uninitialized(len) => {
self.context
@ -705,6 +722,18 @@ impl Device for WebGlDevice {
}
}
fn upload_to_buffer<T>(&self,
buffer: &Self::Buffer,
position: usize,
data: &[T],
target: BufferTarget) {
let target = target.to_gl_target();
self.context.bind_buffer(target, Some(&buffer.buffer)); self.ck();
self.context.buffer_sub_data_with_i32_and_u8_array(target,
position as i32,
slice_to_u8(data)); self.ck();
}
#[inline]
fn framebuffer_texture<'f>(&self, framebuffer: &'f Self::Framebuffer) -> &'f Self::Texture {
&framebuffer.texture
@ -845,6 +874,10 @@ impl Device for WebGlDevice {
self.reset_render_state(render_state);
}
fn dispatch_compute(&self, _: ComputeDimensions, _: &ComputeState<Self>) {
panic!("Compute shader is unsupported in WebGL!")
}
#[inline]
fn create_timer_query(&self) -> WebGlTimerQuery {
// FIXME use performance timers
@ -900,10 +933,19 @@ impl Device for WebGlDevice {
let suffix = match kind {
ShaderKind::Vertex => 'v',
ShaderKind::Fragment => 'f',
ShaderKind::Compute => 'c',
};
let path = format!("shaders/gl3/{}.{}s.glsl", name, suffix);
self.create_shader_from_source(name, &resources.slurp(&path).unwrap(), kind)
}
fn add_fence(&self) -> Self::Fence {
// TODO(pcwalton)
}
fn wait_for_fence(&self, _: &Self::Fence) {
// TODO(pcwalton)
}
}
pub struct WebGlVertexArray {
@ -931,6 +973,7 @@ pub struct WebGlFramebuffer {
pub struct WebGlBuffer {
context: web_sys::WebGl2RenderingContext,
pub buffer: web_sys::WebGlBuffer,
pub mode: BufferUploadMode,
}
impl Drop for WebGlBuffer {
@ -982,6 +1025,7 @@ impl BufferTargetExt for BufferTarget {
match self {
BufferTarget::Vertex => WebGl::ARRAY_BUFFER,
BufferTarget::Index => WebGl::ELEMENT_ARRAY_BUFFER,
BufferTarget::Storage => panic!("Shader storage buffers are unsupported in WebGL!"),
}
}
}