From a4c279688384a274c0fdcad86506555ebb7a8738 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 14 Jan 2019 19:32:53 -0800 Subject: [PATCH] Implement a third demo with native code, not working yet --- Cargo.lock | 247 ++++++++++ Cargo.toml | 1 + demo3/Cargo.toml | 28 ++ demo3/shaders/fill.fs.glsl | 42 ++ demo3/shaders/fill.vs.glsl | 58 +++ demo3/shaders/mask_tile.fs.glsl | 28 ++ demo3/shaders/mask_tile.vs.glsl | 45 ++ demo3/shaders/solid_tile.fs.glsl | 21 + demo3/shaders/solid_tile.vs.glsl | 31 ++ demo3/src/main.rs | 769 +++++++++++++++++++++++++++++++ demo3/textures/area-lut.png | Bin 0 -> 7096 bytes geometry/src/line_segment.rs | 2 + renderer/src/gpu_data.rs | 4 + 13 files changed, 1276 insertions(+) create mode 100644 demo3/Cargo.toml create mode 100644 demo3/shaders/fill.fs.glsl create mode 100644 demo3/shaders/fill.vs.glsl create mode 100644 demo3/shaders/mask_tile.fs.glsl create mode 100644 demo3/shaders/mask_tile.vs.glsl create mode 100644 demo3/shaders/solid_tile.fs.glsl create mode 100644 demo3/shaders/solid_tile.vs.glsl create mode 100644 demo3/src/main.rs create mode 100644 demo3/textures/area-lut.png diff --git a/Cargo.lock b/Cargo.lock index 93ee88fa..c6a6437d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,6 +46,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base64" version = "0.9.3" @@ -150,6 +155,23 @@ dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "demo3" +version = "0.1.0" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_geometry 0.3.0", + "pathfinder_renderer 0.1.0", + "pathfinder_svg 0.1.0", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", + "usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.0" @@ -225,6 +247,24 @@ dependencies = [ "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gl" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gl_generator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gl_generator" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashbrown" version = "0.1.7" @@ -259,6 +299,20 @@ dependencies = [ "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "image" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "inflate" version = "0.4.4" @@ -295,6 +349,11 @@ dependencies = [ "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "khronos_api" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "1.2.0" @@ -374,6 +433,16 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-derive" version = "0.2.3" @@ -411,6 +480,15 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-rational" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.2.6" @@ -495,6 +573,17 @@ dependencies = [ "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "png" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", + "inflate 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.24" @@ -539,6 +628,32 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.2.2" @@ -552,6 +667,52 @@ name = "rand_core" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (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 = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rayon" version = "1.0.3" @@ -578,6 +739,14 @@ name = "rctree" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.50" @@ -619,6 +788,19 @@ dependencies = [ "xmlparser 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "safe-transmute" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "safemem" version = "0.3.0" @@ -634,6 +816,40 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sdl2" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sdl2-sys" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "1.0.84" @@ -842,6 +1058,14 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xml-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "xmlparser" version = "0.8.1" @@ -853,6 +1077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" @@ -875,13 +1100,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4bca55ac1f213920ce3527ccd62386f1f15fa3f1714aeee1cf93f2c416903f" +"checksum gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1c73b90c285f02059b34a6c66bc645ba5faa18c0e3ab332e0725654fc71db441" +"checksum gl_generator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "75d69f914b49d9ff32fdf394cbd798f8c716d74fd19f9cc29da3e99797b2a78d" "checksum hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "64b7d419d0622ae02fe5da6b9a5e1964b610a65bb37923b976aeebb6dbb8f86e" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" +"checksum image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "52fb0666a1273dac46f9725aa4859bcd5595fc3554cf3495051b4de8db745e7d" "checksum inflate 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "84c683bde2d8413b8f1be3e459c30e4817672b6e7a31d9212b0323154e76eba7" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3" "checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d" +"checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" "checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" @@ -893,33 +1122,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" "checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" +"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b" +"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4537d3e4edf73a15dd059b75bed1c292d17d3ea7517f583cebe716794fcf816" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" +"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rctree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1817e0f0056f95bce0d6ab1a5be62ca24bd756b5547c20637ef47cc9a2065f4b" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum roxmltree 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02660467d0c2da1b6276042501aee6e15ec5b8ff59423243f185b294cd53acf3" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebf85f207d42e4da59fa31fff977be5ff0b224873506c4bd70cc1c94b331593" +"checksum sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e82803e85c2e6178d28886cef25b2c53afc2eecaeff739f2247f23ed3352e6c1" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" "checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" "checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e" @@ -946,4 +1192,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" "checksum xmlparser 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d78a7f29bb57edf63321d545d84f99360df71df36929a090bc067e1bcb65e34d" diff --git a/Cargo.toml b/Cargo.toml index 113054d6..63f517c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "demo3", "geometry", "gfx-utils", "renderer", diff --git a/demo3/Cargo.toml b/demo3/Cargo.toml new file mode 100644 index 00000000..01e27e91 --- /dev/null +++ b/demo3/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "demo3" +version = "0.1.0" +edition = "2018" +authors = ["Patrick Walton "] + +[dependencies] +clap = "2.32" +euclid = "0.19" +gl = "0.6" +jemallocator = "0.1" +rayon = "1.0" +sdl2 = "0.32" +usvg = "0.4" + +[dependencies.image] +version = "0.21" +default-features = false +features = ["png_codec"] + +[dependencies.pathfinder_geometry] +path = "../geometry" + +[dependencies.pathfinder_renderer] +path = "../renderer" + +[dependencies.pathfinder_svg] +path = "../svg" diff --git a/demo3/shaders/fill.fs.glsl b/demo3/shaders/fill.fs.glsl new file mode 100644 index 00000000..51ca70f1 --- /dev/null +++ b/demo3/shaders/fill.fs.glsl @@ -0,0 +1,42 @@ +#version 330 + +// pathfinder/demo2/stencil.fs.glsl +// +// Copyright © 2018 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +uniform sampler2D uAreaLUT; + +in vec2 vFrom; +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. + bool winding = from.x < to.x; + vec2 left = winding ? from : to, right = winding ? 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); +} diff --git a/demo3/shaders/fill.vs.glsl b/demo3/shaders/fill.vs.glsl new file mode 100644 index 00000000..b81bd8ad --- /dev/null +++ b/demo3/shaders/fill.vs.glsl @@ -0,0 +1,58 @@ +#version 330 + +// pathfinder/demo2/stencil.vs.glsl +// +// Copyright © 2018 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +uniform vec2 uFramebufferSize; +uniform vec2 uTileSize; + +in vec2 aTessCoord; +in uint aFromPx; +in uint aToPx; +in vec2 aFromSubpx; +in vec2 aToSubpx; +in uint aTileIndex; + +out vec2 vFrom; +out vec2 vTo; + +vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { + uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); + uvec2 tileOffset = uvec2(aTileIndex % tilesPerRow, aTileIndex / tilesPerRow); + return vec2(tileOffset) * uTileSize; +} + +void main() { + vec2 tileOrigin = computeTileOffset(aTileIndex, uFramebufferSize.x); + + vec2 from = vec2(aFromPx & 15u, aFromPx >> 4u) + aFromSubpx; + vec2 to = vec2(aToPx & 15u, aToPx >> 4u) + aToSubpx; + + vec2 position; + bool zeroArea = !(abs(from.x - to.x) > 0.1) || !(abs(uTileSize.y - min(from.y, to.y)) > 0.1); + if (aTessCoord.x < 0.5) + position.x = floor(min(from.x, to.x)); + else + position.x = ceil(max(from.x, to.x)); + if (aTessCoord.y < 0.5) + position.y = floor(min(from.y, to.y)); + else + position.y = uTileSize.y; + + vFrom = from - position; + vTo = to - position; + + if (zeroArea) + gl_Position = vec4(0.0); + else + gl_Position = vec4((tileOrigin + position) / uFramebufferSize * 2.0 - 1.0, 0.0, 1.0); +} diff --git a/demo3/shaders/mask_tile.fs.glsl b/demo3/shaders/mask_tile.fs.glsl new file mode 100644 index 00000000..a7ef2d81 --- /dev/null +++ b/demo3/shaders/mask_tile.fs.glsl @@ -0,0 +1,28 @@ +#version 330 + +// pathfinder/demo2/cover.fs.glsl +// +// Copyright © 2018 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +uniform sampler2D uStencilTexture; + +in vec2 vTexCoord; +in float vBackdrop; +in vec4 vColor; + +out vec4 oFragColor; + +void main() { + float coverage = abs(texture(uStencilTexture, vTexCoord).r + vBackdrop); + vec4 color = vec4(1.0, 0.0, 0.0, 1.0); + //oFragColor = vec4(vColor.rgb, vColor.a * coverage); + oFragColor = vec4(color.rgb, color.a * coverage); +} diff --git a/demo3/shaders/mask_tile.vs.glsl b/demo3/shaders/mask_tile.vs.glsl new file mode 100644 index 00000000..1c7293b5 --- /dev/null +++ b/demo3/shaders/mask_tile.vs.glsl @@ -0,0 +1,45 @@ +#version 330 + +// pathfinder/demo2/cover.vs.glsl +// +// Copyright © 2018 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +uniform vec2 uFramebufferSize; +uniform vec2 uTileSize; +uniform vec2 uStencilTextureSize; +uniform sampler2D uFillColorsTexture; +uniform vec2 uFillColorsTextureSize; +uniform vec2 uViewBoxOrigin; + +in vec2 aTessCoord; +in vec2 aTileOrigin; +in int aBackdrop; +in uint aObject; + +out vec2 vTexCoord; +out float vBackdrop; +out vec4 vColor; + +vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { + uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); + uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow); + return vec2(tileOffset) * uTileSize; +} + +void main() { + uint tileIndex = uint(gl_InstanceID); + vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; + vec2 texCoord = computeTileOffset(tileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize; + vTexCoord = texCoord / uStencilTextureSize; + vBackdrop = float(aBackdrop); + vColor = texture(uFillColorsTexture, vec2(float(aObject) / uFillColorsTextureSize.x, 0.0)); + gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0); +} diff --git a/demo3/shaders/solid_tile.fs.glsl b/demo3/shaders/solid_tile.fs.glsl new file mode 100644 index 00000000..9db70a17 --- /dev/null +++ b/demo3/shaders/solid_tile.fs.glsl @@ -0,0 +1,21 @@ +#version 330 + +// pathfinder/demo2/opaque.fs.glsl +// +// Copyright © 2018 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +in vec4 vColor; + +out vec4 oFragColor; + +void main() { + oFragColor = vColor; +} diff --git a/demo3/shaders/solid_tile.vs.glsl b/demo3/shaders/solid_tile.vs.glsl new file mode 100644 index 00000000..38743f85 --- /dev/null +++ b/demo3/shaders/solid_tile.vs.glsl @@ -0,0 +1,31 @@ +#version 330 + +// pathfinder/demo2/opaque.vs.glsl +// +// Copyright © 2018 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +uniform vec2 uFramebufferSize; +uniform vec2 uTileSize; +uniform sampler2D uFillColorsTexture; +uniform vec2 uFillColorsTextureSize; +uniform vec2 uViewBoxOrigin; + +in vec2 aTessCoord; +in vec2 aTileOrigin; +in uint aObject; + +out vec4 vColor; + +void main() { + vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; + vColor = texture(uFillColorsTexture, vec2(float(aObject) / uFillColorsTextureSize.x, 0.0)); + gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0); +} diff --git a/demo3/src/main.rs b/demo3/src/main.rs new file mode 100644 index 00000000..0d62c8d0 --- /dev/null +++ b/demo3/src/main.rs @@ -0,0 +1,769 @@ +// pathfinder/demo3/src/main.rs +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use clap::{App, Arg}; +use euclid::Size2D; +use gl::types::{GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid}; +use jemallocator; +use pathfinder_renderer::builder::SceneBuilder; +use pathfinder_renderer::gpu_data::{Batch, BuiltScene, FillBatchPrimitive}; +use pathfinder_renderer::scene::Scene; +use pathfinder_renderer::tiles::{TILE_HEIGHT, TILE_WIDTH}; +use pathfinder_renderer::z_buffer::ZBuffer; +use pathfinder_svg::SceneExt; +use rayon::ThreadPoolBuilder; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use sdl2::video::GLProfile; +use std::ffi::CString; +use std::fs::File; +use std::io::Read; +use std::mem; +use std::path::PathBuf; +use std::ptr; +use std::time::{Duration, Instant}; +use usvg::{Options as UsvgOptions, Tree}; + +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + +static QUAD_VERTEX_POSITIONS: [u8; 8] = [0, 0, 1, 0, 1, 1, 0, 1]; + +// TODO(pcwalton): Replace with `mem::size_of` calls? +const FILL_INSTANCE_SIZE: GLint = 8; +const SOLID_TILE_INSTANCE_SIZE: GLint = 6; +const MASK_TILE_INSTANCE_SIZE: GLint = 8; + +const MASK_FRAMEBUFFER_WIDTH: u32 = TILE_WIDTH * 256; +const MASK_FRAMEBUFFER_HEIGHT: u32 = TILE_HEIGHT * 256; + +// FIXME(pcwalton): Make this dynamic! +const MAIN_FRAMEBUFFER_WIDTH: u32 = 800; +const MAIN_FRAMEBUFFER_HEIGHT: u32 = 800; + +fn main() { + let scene = load_scene(); + + let sdl_context = sdl2::init().unwrap(); + let sdl_video = sdl_context.video().unwrap(); + + let gl_attributes = sdl_video.gl_attr(); + gl_attributes.set_context_profile(GLProfile::Core); + gl_attributes.set_context_version(3, 3); + + let window = + sdl_video.window("Pathfinder Demo", MAIN_FRAMEBUFFER_WIDTH, MAIN_FRAMEBUFFER_HEIGHT) + .opengl() + .build() + .unwrap(); + + let gl_context = window.gl_create_context().unwrap(); + gl::load_with(|name| sdl_video.gl_get_proc_address(name) as *const _); + + let mut sdl_event_pump = sdl_context.event_pump().unwrap(); + let mut exit = false; + while !exit { + let mut renderer = Renderer::new(); + + unsafe { + gl::ClearColor(1.0, 1.0, 1.0, 1.0); + gl::Clear(gl::COLOR_BUFFER_BIT); + renderer.render_scene(&scene); + } + + window.gl_swap_window(); + + for event in sdl_event_pump.poll_iter() { + match event { + Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { + exit = true; + } + _ => {} + } + } + } +} + +fn load_scene() -> BuiltScene { + let matches = App::new("tile-svg") + .arg( + Arg::with_name("jobs") + .short("j") + .long("jobs") + .value_name("THREADS") + .takes_value(true) + .help("Number of threads to use"), + ) + .arg( + Arg::with_name("INPUT") + .help("Path to the SVG file to render") + .required(true) + .index(1), + ) + .get_matches(); + let jobs: Option = matches + .value_of("jobs") + .map(|string| string.parse().unwrap()); + let input_path = PathBuf::from(matches.value_of("INPUT").unwrap()); + + // Set up Rayon. + let mut thread_pool_builder = ThreadPoolBuilder::new(); + if let Some(jobs) = jobs { + thread_pool_builder = thread_pool_builder.num_threads(jobs); + } + thread_pool_builder.build_global().unwrap(); + + // Build scene. + let usvg = Tree::from_file(&input_path, &UsvgOptions::default()).unwrap(); + let scene = Scene::from_tree(usvg); + + println!( + "Scene bounds: {:?} View box: {:?}", + scene.bounds, scene.view_box + ); + println!( + "{} objects, {} paints", + scene.objects.len(), + scene.paints.len() + ); + + let (mut elapsed_object_build_time, mut elapsed_scene_build_time) = (0.0, 0.0); + + let mut built_scene = BuiltScene::new(&scene.view_box); + let z_buffer = ZBuffer::new(&scene.view_box); + + let start_time = Instant::now(); + let built_objects = match jobs { + Some(1) => scene.build_objects_sequentially(&z_buffer), + _ => scene.build_objects(&z_buffer), + }; + elapsed_object_build_time += duration_to_ms(&(Instant::now() - start_time)); + + let start_time = Instant::now(); + built_scene = BuiltScene::new(&scene.view_box); + built_scene.shaders = scene.build_shaders(); + let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, &scene.view_box); + built_scene.solid_tiles = scene_builder.build_solid_tiles(); + while let Some(batch) = scene_builder.build_batch() { + built_scene.batches.push(batch); + } + elapsed_scene_build_time += duration_to_ms(&(Instant::now() - start_time)); + + let total_elapsed_time = elapsed_object_build_time + elapsed_scene_build_time; + + println!( + "{:.3}ms ({:.3}ms objects, {:.3}ms scene) elapsed", + total_elapsed_time, elapsed_object_build_time, elapsed_scene_build_time + ); + + println!("{} solid tiles", built_scene.solid_tiles.len()); + for (batch_index, batch) in built_scene.batches.iter().enumerate() { + println!( + "Batch {}: {} fills, {} mask tiles", + batch_index, + batch.fills.len(), + batch.mask_tiles.len() + ); + } + + built_scene +} + +fn duration_to_ms(duration: &Duration) -> f64 { + duration.as_secs() as f64 * 1000.0 + f64::from(duration.subsec_micros()) / 1000.0 +} + +struct Renderer { + fill_program: FillProgram, + solid_tile_program: SolidTileProgram, + mask_tile_program: MaskTileProgram, + area_lut_texture: Texture, + quad_vertex_positions_buffer: Buffer, + fill_vertex_array: FillVertexArray, + mask_tile_vertex_array: MaskTileVertexArray, + solid_tile_vertex_array: SolidTileVertexArray, + mask_framebuffer: Framebuffer, +} + +impl Renderer { + fn new() -> Renderer { + let fill_program = FillProgram::new(); + let solid_tile_program = SolidTileProgram::new(); + let mask_tile_program = MaskTileProgram::new(); + + let area_lut_texture = Texture::from_png("area-lut"); + + let quad_vertex_positions_buffer = Buffer::new(); + quad_vertex_positions_buffer.upload(&QUAD_VERTEX_POSITIONS, BufferUploadMode::Static); + + let fill_vertex_array = FillVertexArray::new(&fill_program, &quad_vertex_positions_buffer); + let mask_tile_vertex_array = MaskTileVertexArray::new(&mask_tile_program, + &quad_vertex_positions_buffer); + let solid_tile_vertex_array = SolidTileVertexArray::new(&solid_tile_program, + &quad_vertex_positions_buffer); + + let mask_framebuffer = Framebuffer::new(&Size2D::new(MASK_FRAMEBUFFER_WIDTH, + MASK_FRAMEBUFFER_HEIGHT)); + + Renderer { + fill_program, + solid_tile_program, + mask_tile_program, + area_lut_texture, + quad_vertex_positions_buffer, + fill_vertex_array, + mask_tile_vertex_array, + solid_tile_vertex_array, + mask_framebuffer, + } + } + + fn render_scene(&mut self, built_scene: &BuiltScene) { + for batch in &built_scene.batches { + self.upload_batch(batch); + self.draw_batch_fills(batch); + self.draw_batch_mask_tiles(batch); + } + } + + fn upload_batch(&mut self, batch: &Batch) { + self.fill_vertex_array.vertex_buffer.upload(&batch.fills, BufferUploadMode::Dynamic); + self.mask_tile_vertex_array.vertex_buffer.upload(&batch.mask_tiles, + BufferUploadMode::Dynamic); + } + + fn draw_batch_fills(&mut self, batch: &Batch) { + unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, self.mask_framebuffer.gl_framebuffer); + gl::Viewport(0, 0, MASK_FRAMEBUFFER_WIDTH as GLint, MASK_FRAMEBUFFER_HEIGHT as GLint); + // TODO(pcwalton): Only clear the appropriate portion? + gl::ClearColor(0.0, 0.0, 0.0, 0.0); + gl::Clear(gl::COLOR_BUFFER_BIT); + + gl::BindVertexArray(self.fill_vertex_array.gl_vertex_array); + gl::UseProgram(self.fill_program.program.gl_program); + gl::Uniform2f(self.fill_program.framebuffer_size_uniform.location, + MASK_FRAMEBUFFER_WIDTH as GLfloat, + MASK_FRAMEBUFFER_HEIGHT as GLfloat); + gl::Uniform2f(self.fill_program.tile_size_uniform.location, + TILE_WIDTH as GLfloat, + TILE_HEIGHT as GLfloat); + self.area_lut_texture.bind(0); + gl::Uniform1i(self.fill_program.area_lut_uniform.location, 0); + gl::BlendEquation(gl::FUNC_ADD); + gl::BlendFunc(gl::ONE, gl::ONE); + gl::Enable(gl::BLEND); + gl::DrawArraysInstanced(gl::TRIANGLE_FAN, 0, 4, batch.fills.len() as GLint); + gl::Disable(gl::BLEND); + } + } + + fn draw_batch_mask_tiles(&mut self, batch: &Batch) { + unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + gl::Viewport(0, 0, MAIN_FRAMEBUFFER_WIDTH as GLint, MAIN_FRAMEBUFFER_HEIGHT as GLint); + + gl::BindVertexArray(self.mask_tile_vertex_array.gl_vertex_array); + gl::UseProgram(self.mask_tile_program.program.gl_program); + gl::Uniform2f(self.mask_tile_program.framebuffer_size_uniform.location, + MAIN_FRAMEBUFFER_WIDTH as GLfloat, + MAIN_FRAMEBUFFER_HEIGHT as GLfloat); + gl::Uniform2f(self.mask_tile_program.tile_size_uniform.location, + TILE_WIDTH as GLfloat, + TILE_HEIGHT as GLfloat); + self.mask_framebuffer.texture.bind(0); + gl::Uniform1i(self.mask_tile_program.stencil_texture_uniform.location, 0); + gl::Uniform2f(self.mask_tile_program.stencil_texture_size_uniform.location, + MASK_FRAMEBUFFER_WIDTH as GLfloat, + MASK_FRAMEBUFFER_HEIGHT as GLfloat); + // FIXME(pcwalton): Fill this in properly! + gl::Uniform2f(self.mask_tile_program.view_box_origin_uniform.location, 0.0, 0.0); + gl::BlendEquation(gl::FUNC_ADD); + gl::BlendFuncSeparate(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA, gl::ONE, gl::ONE); + gl::Enable(gl::BLEND); + gl::DrawArraysInstanced(gl::TRIANGLE_FAN, 0, 4, batch.mask_tiles.len() as GLint); + gl::Disable(gl::BLEND); + } + } +} + +struct FillVertexArray { + gl_vertex_array: GLuint, + vertex_buffer: Buffer, +} + +impl FillVertexArray { + fn new(fill_program: &FillProgram, quad_vertex_positions_buffer: &Buffer) -> FillVertexArray { + let vertex_buffer = Buffer::new(); + let mut gl_vertex_array = 0; + unsafe { + let tess_coord_attr = VertexAttr::new(&fill_program.program, "TessCoord"); + let from_px_attr = VertexAttr::new(&fill_program.program, "FromPx"); + let to_px_attr = VertexAttr::new(&fill_program.program, "ToPx"); + let from_subpx_attr = VertexAttr::new(&fill_program.program, "FromSubpx"); + let to_subpx_attr = VertexAttr::new(&fill_program.program, "ToSubpx"); + let tile_index_attr = VertexAttr::new(&fill_program.program, "TileIndex"); + + gl::GenVertexArrays(1, &mut gl_vertex_array); + gl::BindVertexArray(gl_vertex_array); + gl::UseProgram(fill_program.program.gl_program); + gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer); + tess_coord_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0); + gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer.gl_buffer); + from_px_attr.configure_int(1, gl::UNSIGNED_BYTE, FILL_INSTANCE_SIZE, 0, 1); + to_px_attr.configure_int(1, gl::UNSIGNED_BYTE, FILL_INSTANCE_SIZE, 1, 1); + from_subpx_attr.configure_float(2, gl::UNSIGNED_BYTE, true, FILL_INSTANCE_SIZE, 2, 1); + to_subpx_attr.configure_float(2, gl::UNSIGNED_BYTE, true, FILL_INSTANCE_SIZE, 4, 1); + tile_index_attr.configure_int(1, gl::UNSIGNED_SHORT, FILL_INSTANCE_SIZE, 6, 1); + } + + FillVertexArray { gl_vertex_array, vertex_buffer } + } +} + +struct MaskTileVertexArray { + gl_vertex_array: GLuint, + vertex_buffer: Buffer, +} + +impl MaskTileVertexArray { + fn new(mask_tile_program: &MaskTileProgram, quad_vertex_positions_buffer: &Buffer) + -> MaskTileVertexArray { + let vertex_buffer = Buffer::new(); + let mut gl_vertex_array = 0; + unsafe { + let tess_coord_attr = VertexAttr::new(&mask_tile_program.program, "TessCoord"); + let tile_origin_attr = VertexAttr::new(&mask_tile_program.program, "TileOrigin"); + let backdrop_attr = VertexAttr::new(&mask_tile_program.program, "Backdrop"); + let object_attr = VertexAttr::new(&mask_tile_program.program, "Object"); + + gl::GenVertexArrays(1, &mut gl_vertex_array); + gl::BindVertexArray(gl_vertex_array); + gl::UseProgram(mask_tile_program.program.gl_program); + gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer); + tess_coord_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0); + gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer.gl_buffer); + tile_origin_attr.configure_float(2, gl::SHORT, false, MASK_TILE_INSTANCE_SIZE, 0, 1); + backdrop_attr.configure_int(1, gl::SHORT, MASK_TILE_INSTANCE_SIZE, 4, 1); + object_attr.configure_int(2, gl::UNSIGNED_SHORT, MASK_TILE_INSTANCE_SIZE, 6, 1); + } + + MaskTileVertexArray { gl_vertex_array, vertex_buffer } + } +} + +struct SolidTileVertexArray { + gl_vertex_array: GLuint, + vertex_buffer: Buffer, +} + +impl SolidTileVertexArray { + fn new(solid_tile_program: &SolidTileProgram, quad_vertex_positions_buffer: &Buffer) + -> SolidTileVertexArray { + let vertex_buffer = Buffer::new(); + let mut gl_vertex_array = 0; + unsafe { + let tess_coord_attr = VertexAttr::new(&solid_tile_program.program, "TessCoord"); + let tile_origin_attr = VertexAttr::new(&solid_tile_program.program, "TileOrigin"); + let object_attr = VertexAttr::new(&solid_tile_program.program, "Object"); + + gl::GenVertexArrays(1, &mut gl_vertex_array); + gl::BindVertexArray(gl_vertex_array); + gl::UseProgram(solid_tile_program.program.gl_program); + gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer); + tess_coord_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0); + gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer.gl_buffer); + tile_origin_attr.configure_float(2, gl::SHORT, false, SOLID_TILE_INSTANCE_SIZE, 0, 1); + object_attr.configure_int(1, gl::UNSIGNED_SHORT, SOLID_TILE_INSTANCE_SIZE, 4, 1); + } + + SolidTileVertexArray { gl_vertex_array, vertex_buffer } + } +} + +struct VertexAttr { + attr: GLuint, +} + +impl VertexAttr { + fn new(program: &Program, name: &str) -> VertexAttr { + let name = CString::new(format!("a{}", name)).unwrap(); + let attr = unsafe { + gl::GetAttribLocation(program.gl_program, name.as_ptr() as *const GLchar) as GLuint + }; + VertexAttr { attr } + } + + fn configure_float(&self, + size: GLint, + gl_type: GLuint, + normalized: bool, + stride: GLsizei, + offset: usize, + divisor: GLuint) { + unsafe { + gl::VertexAttribPointer(self.attr, + size, + gl_type, + if normalized { gl::TRUE } else { gl::FALSE }, + stride, + offset as *const GLvoid); + gl::VertexAttribDivisor(self.attr, divisor); + gl::EnableVertexAttribArray(self.attr); + } + } + + fn configure_int(&self, + size: GLint, + gl_type: GLuint, + stride: GLsizei, + offset: usize, + divisor: GLuint) { + unsafe { + gl::VertexAttribIPointer(self.attr, size, gl_type, stride, offset as *const GLvoid); + gl::VertexAttribDivisor(self.attr, divisor); + gl::EnableVertexAttribArray(self.attr); + } + } +} + +struct Framebuffer { + gl_framebuffer: GLuint, + texture: Texture, +} + +impl Framebuffer { + fn new(size: &Size2D) -> Framebuffer { + let texture = Texture::new_r16f(size); + let mut gl_framebuffer = 0; + unsafe { + gl::GenFramebuffers(1, &mut gl_framebuffer); + assert_eq!(gl::GetError(), gl::NO_ERROR); + gl::BindFramebuffer(gl::FRAMEBUFFER, gl_framebuffer); + texture.bind(0); + gl::FramebufferTexture2D(gl::FRAMEBUFFER, + gl::COLOR_ATTACHMENT0, + gl::TEXTURE_2D, + texture.gl_texture, + 0); + assert_eq!(gl::CheckFramebufferStatus(gl::FRAMEBUFFER), gl::FRAMEBUFFER_COMPLETE); + } + Framebuffer { gl_framebuffer, texture } + } +} + +impl Drop for Framebuffer { + fn drop(&mut self) { + unsafe { + gl::DeleteFramebuffers(1, &mut self.gl_framebuffer) + } + } +} + +struct Buffer { + gl_buffer: GLuint, +} + +impl Buffer { + fn new() -> Buffer { + unsafe { + let mut gl_buffer = 0; + gl::GenBuffers(1, &mut gl_buffer); + Buffer { gl_buffer } + } + } + + fn upload(&self, data: &[T], mode: BufferUploadMode) { + let mode = match mode { + BufferUploadMode::Static => gl::STATIC_DRAW, + BufferUploadMode::Dynamic => gl::DYNAMIC_DRAW, + }; + unsafe { + gl::BindBuffer(gl::ARRAY_BUFFER, self.gl_buffer); + gl::BufferData(gl::ARRAY_BUFFER, + (data.len() * mem::size_of::()) as GLsizeiptr, + data.as_ptr() as *const GLvoid, + mode); + } + } +} + +impl Drop for Buffer { + fn drop(&mut self) { + unsafe { + gl::DeleteBuffers(1, &mut self.gl_buffer) + } + } +} + +enum BufferUploadMode { + Static, + Dynamic, +} + +struct FillProgram { + program: Program, + framebuffer_size_uniform: Uniform, + tile_size_uniform: Uniform, + area_lut_uniform: Uniform, +} + +impl FillProgram { + fn new() -> FillProgram { + let program = Program::new("fill"); + let framebuffer_size_uniform = Uniform::new(&program, "FramebufferSize"); + let tile_size_uniform = Uniform::new(&program, "TileSize"); + let area_lut_uniform = Uniform::new(&program, "AreaLUT"); + FillProgram { program, framebuffer_size_uniform, tile_size_uniform, area_lut_uniform } + } +} + +struct SolidTileProgram { + program: Program, + framebuffer_size_uniform: Uniform, + tile_size_uniform: Uniform, + fill_colors_texture_uniform: Uniform, + fill_colors_texture_size_uniform: Uniform, + view_box_origin_uniform: Uniform, +} + +impl SolidTileProgram { + fn new() -> SolidTileProgram { + let program = Program::new("solid_tile"); + let framebuffer_size_uniform = Uniform::new(&program, "FramebufferSize"); + let tile_size_uniform = Uniform::new(&program, "TileSize"); + let fill_colors_texture_uniform = Uniform::new(&program, "FillColorsTexture"); + let fill_colors_texture_size_uniform = Uniform::new(&program, "FillColorsTextureSize"); + let view_box_origin_uniform = Uniform::new(&program, "ViewBoxOrigin"); + SolidTileProgram { + program, + framebuffer_size_uniform, + tile_size_uniform, + fill_colors_texture_uniform, + fill_colors_texture_size_uniform, + view_box_origin_uniform, + } + } +} + +struct MaskTileProgram { + program: Program, + framebuffer_size_uniform: Uniform, + tile_size_uniform: Uniform, + stencil_texture_uniform: Uniform, + stencil_texture_size_uniform: Uniform, + fill_colors_texture_uniform: Uniform, + fill_colors_texture_size_uniform: Uniform, + view_box_origin_uniform: Uniform, +} + +impl MaskTileProgram { + fn new() -> MaskTileProgram { + let program = Program::new("mask_tile"); + let framebuffer_size_uniform = Uniform::new(&program, "FramebufferSize"); + let tile_size_uniform = Uniform::new(&program, "TileSize"); + let stencil_texture_uniform = Uniform::new(&program, "StencilTexture"); + let stencil_texture_size_uniform = Uniform::new(&program, "StencilTextureSize"); + let fill_colors_texture_uniform = Uniform::new(&program, "FillColorsTexture"); + let fill_colors_texture_size_uniform = Uniform::new(&program, "FillColorsTextureSize"); + let view_box_origin_uniform = Uniform::new(&program, "ViewBoxOrigin"); + MaskTileProgram { + program, + framebuffer_size_uniform, + tile_size_uniform, + stencil_texture_uniform, + stencil_texture_size_uniform, + fill_colors_texture_uniform, + fill_colors_texture_size_uniform, + view_box_origin_uniform, + } + } +} + +struct Uniform { + location: GLint, +} + +impl Uniform { + fn new(program: &Program, name: &str) -> Uniform { + let name = CString::new(format!("u{}", name)).unwrap(); + let location = unsafe { + gl::GetUniformLocation(program.gl_program, name.as_ptr() as *const GLchar) + }; + Uniform { location } + } +} + +struct Program { + gl_program: GLuint, + vertex_shader: Shader, + fragment_shader: Shader, +} + +impl Program { + fn new(name: &'static str) -> Program { + let vertex_shader = Shader::new(name, ShaderKind::Vertex); + let fragment_shader = Shader::new(name, ShaderKind::Fragment); + + let gl_program; + unsafe { + gl_program = gl::CreateProgram(); + gl::AttachShader(gl_program, vertex_shader.gl_shader); + gl::AttachShader(gl_program, fragment_shader.gl_shader); + gl::LinkProgram(gl_program); + + let mut link_status = 0; + gl::GetProgramiv(gl_program, gl::LINK_STATUS, &mut link_status); + if link_status != gl::TRUE as GLint { + let mut info_log_length = 0; + gl::GetProgramiv(gl_program, gl::INFO_LOG_LENGTH, &mut info_log_length); + let mut info_log = vec![0; info_log_length as usize]; + gl::GetProgramInfoLog(gl_program, + info_log.len() as GLint, + ptr::null_mut(), + info_log.as_mut_ptr() as *mut GLchar); + eprintln!("Program info log:\n{}", String::from_utf8_lossy(&info_log)); + panic!("Program '{}' linking failed", name); + } + } + + Program { gl_program, vertex_shader, fragment_shader } + } +} + +impl Drop for Program { + fn drop(&mut self) { + unsafe { + gl::DeleteProgram(self.gl_program) + } + } +} + +struct Shader { + gl_shader: GLuint, +} + +impl Shader { + fn new(name: &str, kind: ShaderKind) -> Shader { + let suffix = match kind { ShaderKind::Vertex => 'v', ShaderKind::Fragment => 'f' }; + // FIXME(pcwalton): Put the shaders somewhere else. Maybe compile them in? + let path = format!("shaders/{}.{}s.glsl", name, suffix); + let mut source = vec![]; + File::open(&path).unwrap().read_to_end(&mut source).unwrap(); + unsafe { + let gl_shader_kind = match kind { + ShaderKind::Vertex => gl::VERTEX_SHADER, + ShaderKind::Fragment => gl::FRAGMENT_SHADER, + }; + let gl_shader = gl::CreateShader(gl_shader_kind); + gl::ShaderSource(gl_shader, + 1, + [source.as_ptr() as *const GLchar].as_ptr(), + [source.len() as GLint].as_ptr()); + gl::CompileShader(gl_shader); + + let mut compile_status = 0; + gl::GetShaderiv(gl_shader, gl::COMPILE_STATUS, &mut compile_status); + if compile_status != gl::TRUE as GLint { + let mut info_log_length = 0; + gl::GetShaderiv(gl_shader, gl::INFO_LOG_LENGTH, &mut info_log_length); + let mut info_log = vec![0; info_log_length as usize]; + gl::GetShaderInfoLog(gl_shader, + info_log.len() as GLint, + ptr::null_mut(), + info_log.as_mut_ptr() as *mut GLchar); + eprintln!("Shader info log:\n{}", String::from_utf8_lossy(&info_log)); + panic!("{:?} shader '{}' compilation failed", kind, name); + } + + Shader { gl_shader } + } + } +} + +impl Drop for Shader { + fn drop(&mut self) { + unsafe { + gl::DeleteShader(self.gl_shader) + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum ShaderKind { + Vertex, + Fragment, +} + +struct Texture { + gl_texture: GLuint, +} + +impl Texture { + fn new_r16f(size: &Size2D) -> Texture { + let mut texture = Texture { gl_texture: 0 }; + unsafe { + gl::GenTextures(1, &mut texture.gl_texture); + texture.bind(0); + gl::TexImage2D(gl::TEXTURE_2D, + 0, + gl::R16F as GLint, + size.width as GLsizei, + size.height as GLsizei, + 0, + gl::RED, + gl::HALF_FLOAT, + ptr::null()); + } + + texture.set_parameters(); + texture + } + + fn from_png(name: &str) -> Texture { + let path = format!("textures/{}.png", name); + let image = image::open(&path).unwrap().to_luma(); + + let mut texture = Texture { gl_texture: 0 }; + unsafe { + gl::GenTextures(1, &mut texture.gl_texture); + texture.bind(0); + gl::TexImage2D(gl::TEXTURE_2D, + 0, + gl::RED as GLint, + image.width() as GLsizei, + image.height() as GLsizei, + 0, + gl::RED, + gl::UNSIGNED_BYTE, + image.as_ptr() as *const GLvoid); + } + + texture.set_parameters(); + texture + } + + fn bind(&self, unit: u32) { + unsafe { + gl::ActiveTexture(gl::TEXTURE0 + unit); + gl::BindTexture(gl::TEXTURE_2D, self.gl_texture); + } + } + + fn set_parameters(&self) { + self.bind(0); + unsafe { + gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint); + gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); + gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint); + gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint); + } + } +} diff --git a/demo3/textures/area-lut.png b/demo3/textures/area-lut.png new file mode 100644 index 0000000000000000000000000000000000000000..b54d669f1a205b4a26aad4172550a927f29a6000 GIT binary patch literal 7096 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 IEwse{1GeKjEC2ui literal 0 HcmV?d00001 diff --git a/geometry/src/line_segment.rs b/geometry/src/line_segment.rs index cf3cd690..2d424240 100644 --- a/geometry/src/line_segment.rs +++ b/geometry/src/line_segment.rs @@ -161,7 +161,9 @@ impl Sub for LineSegmentF32 { } #[derive(Clone, Copy, Debug)] +#[repr(C)] pub struct LineSegmentU4(pub u16); #[derive(Clone, Copy, Debug)] +#[repr(C)] pub struct LineSegmentU8(pub u32); diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 45738023..82aeb538 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -52,6 +52,7 @@ pub struct FillObjectPrimitive { } #[derive(Clone, Copy, Debug)] +#[repr(C)] pub struct TileObjectPrimitive { pub tile_x: i16, pub tile_y: i16, @@ -59,6 +60,7 @@ pub struct TileObjectPrimitive { } #[derive(Clone, Copy, Debug)] +#[repr(C)] pub struct FillBatchPrimitive { pub px: LineSegmentU4, pub subpx: LineSegmentU8, @@ -66,6 +68,7 @@ pub struct FillBatchPrimitive { } #[derive(Clone, Copy, Debug)] +#[repr(C)] pub struct SolidTileScenePrimitive { pub tile_x: i16, pub tile_y: i16, @@ -73,6 +76,7 @@ pub struct SolidTileScenePrimitive { } #[derive(Clone, Copy, Debug)] +#[repr(C)] pub struct MaskTileBatchPrimitive { pub tile: TileObjectPrimitive, pub shader: ShaderId,