Add color option to visual bell
This adds the option to specify the color of the visual bell using the `visual_bell.color` configuration setting. This is done by rendering a big quad over the entire screen, which also opens up options to draw other arbitrary rectangles on the screen in the future.
This commit is contained in:
parent
0c3e28617a
commit
cf9d94eb12
|
@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- New configuration field `visual_bell.color` allows changing the visual bell color
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix color issue in ncurses programs by updating terminfo pairs from 0x10000 to 0x7FFF
|
- Fix color issue in ncurses programs by updating terminfo pairs from 0x10000 to 0x7FFF
|
||||||
|
|
|
@ -122,7 +122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.4.8"
|
version = "0.4.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -152,7 +152,7 @@ dependencies = [
|
||||||
"backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
"backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ name = "blake2-rfc"
|
||||||
version = "0.2.18"
|
version = "0.2.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -519,10 +519,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -531,7 +531,7 @@ name = "crossbeam-epoch"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -542,10 +542,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.6.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1535,12 +1535,12 @@ dependencies = [
|
||||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.2.0 (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.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
"openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.39"
|
version = "0.9.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1938,7 +1938,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1954,7 +1954,7 @@ name = "rusttype"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"stb_truetype 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"stb_truetype 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -1965,7 +1965,7 @@ version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"stb_truetype 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"stb_truetype 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -2440,7 +2440,7 @@ name = "tokio-threadpool"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2886,7 +2886,7 @@ dependencies = [
|
||||||
"checksum approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c57ff1a5b00753647aebbbcf4ea67fa1e711a65ea7a30eb90dbf07de2485aee"
|
"checksum approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c57ff1a5b00753647aebbbcf4ea67fa1e711a65ea7a30eb90dbf07de2485aee"
|
||||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||||
"checksum arraydeque 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e300327073b806ffc81fccb228b2d4131ac7ef1b1a015f7b0c399c7f886cacc6"
|
"checksum arraydeque 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e300327073b806ffc81fccb228b2d4131ac7ef1b1a015f7b0c399c7f886cacc6"
|
||||||
"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc"
|
"checksum arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d18513977c2d8261c448511c5c53dc66b26dfccbc3d4446672dea1e71a7d8a26"
|
||||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
"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 autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727"
|
||||||
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
|
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
|
||||||
|
@ -2931,9 +2931,9 @@ dependencies = [
|
||||||
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||||
"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
|
"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
|
||||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||||
"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3"
|
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
|
||||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||||
"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8"
|
"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c"
|
||||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||||
"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a"
|
"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a"
|
||||||
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
|
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
|
||||||
|
@ -3042,7 +3042,7 @@ dependencies = [
|
||||||
"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||||
"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||||
"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985"
|
"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985"
|
||||||
"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106"
|
"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6"
|
||||||
"checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
|
"checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
|
||||||
"checksum ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0015e9e8e28ee20c581cfbfe47c650cedeb9ed0721090e0b7ebb10b9cdbcc2"
|
"checksum ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0015e9e8e28ee20c581cfbfe47c650cedeb9ed0721090e0b7ebb10b9cdbcc2"
|
||||||
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
||||||
|
@ -3086,7 +3086,7 @@ dependencies = [
|
||||||
"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
|
"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
|
||||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||||
"checksum reqwest 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "738769ec83daf6c1929dc9dae7d69ed3779b55ae5c356e989dcd3aa677d8486e"
|
"checksum reqwest 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "738769ec83daf6c1929dc9dae7d69ed3779b55ae5c356e989dcd3aa677d8486e"
|
||||||
"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
|
"checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7"
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
"checksum rusttype 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "11ff03da02f6d340bbee5ec55eed03ff9abd6ea013b93bc7c35973cc28f65999"
|
"checksum rusttype 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "11ff03da02f6d340bbee5ec55eed03ff9abd6ea013b93bc7c35973cc28f65999"
|
||||||
"checksum rusttype 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "436c67ae0d0d24f14e1177c3ed96780ee16db82b405f0fba1bb80b46c9a30625"
|
"checksum rusttype 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "436c67ae0d0d24f14e1177c3ed96780ee16db82b405f0fba1bb80b46c9a30625"
|
||||||
|
|
|
@ -223,6 +223,7 @@ colors:
|
||||||
visual_bell:
|
visual_bell:
|
||||||
animation: EaseOutExpo
|
animation: EaseOutExpo
|
||||||
duration: 0
|
duration: 0
|
||||||
|
color: '0xffffff'
|
||||||
|
|
||||||
# Background opacity
|
# Background opacity
|
||||||
#
|
#
|
||||||
|
|
|
@ -234,6 +234,7 @@ colors:
|
||||||
visual_bell:
|
visual_bell:
|
||||||
animation: EaseOutExpo
|
animation: EaseOutExpo
|
||||||
duration: 0
|
duration: 0
|
||||||
|
color: '0xffffff'
|
||||||
|
|
||||||
# Background opacity
|
# Background opacity
|
||||||
#
|
#
|
||||||
|
@ -244,15 +245,15 @@ background_opacity: 1.0
|
||||||
# Mouse bindings
|
# Mouse bindings
|
||||||
#
|
#
|
||||||
# Available fields:
|
# Available fields:
|
||||||
# - mouse
|
# - mouse
|
||||||
# - action
|
# - action
|
||||||
# - mods (optional)
|
# - mods (optional)
|
||||||
#
|
#
|
||||||
# Values for `mouse`:
|
# Values for `mouse`:
|
||||||
# - Middle
|
# - Middle
|
||||||
# - Left
|
# - Left
|
||||||
# - Right
|
# - Right
|
||||||
# - Numeric identifier such as `5`
|
# - Numeric identifier such as `5`
|
||||||
#
|
#
|
||||||
# All available `mods` and `action` values are documented in the key binding
|
# All available `mods` and `action` values are documented in the key binding
|
||||||
# section.
|
# section.
|
||||||
|
|
|
@ -204,6 +204,7 @@ colors:
|
||||||
visual_bell:
|
visual_bell:
|
||||||
animation: EaseOutExpo
|
animation: EaseOutExpo
|
||||||
duration: 0
|
duration: 0
|
||||||
|
color: '0xffffff'
|
||||||
|
|
||||||
# Background opacity
|
# Background opacity
|
||||||
#
|
#
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#version 330 core
|
||||||
|
in vec4 color;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = color;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
uniform vec4 col;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
|
||||||
|
color = col;
|
||||||
|
}
|
|
@ -15,7 +15,6 @@
|
||||||
in vec2 TexCoords;
|
in vec2 TexCoords;
|
||||||
in vec3 fg;
|
in vec3 fg;
|
||||||
in vec4 bg;
|
in vec4 bg;
|
||||||
flat in float vb;
|
|
||||||
flat in int background;
|
flat in int background;
|
||||||
|
|
||||||
layout(location = 0, index = 0) out vec4 color;
|
layout(location = 0, index = 0) out vec4 color;
|
||||||
|
@ -31,7 +30,7 @@ void main()
|
||||||
discard;
|
discard;
|
||||||
|
|
||||||
alphaMask = vec4(1.0);
|
alphaMask = vec4(1.0);
|
||||||
color = vec4(bg.rgb + vb, 1.0);
|
color = vec4(bg.rgb, 1.0);
|
||||||
} else {
|
} else {
|
||||||
vec3 textColor = texture(mask, TexCoords).rgb;
|
vec3 textColor = texture(mask, TexCoords).rgb;
|
||||||
alphaMask = vec4(textColor, textColor.r);
|
alphaMask = vec4(textColor, textColor.r);
|
||||||
|
|
|
@ -25,6 +25,7 @@ layout (location = 3) in vec4 uv;
|
||||||
|
|
||||||
// text fg color
|
// text fg color
|
||||||
layout (location = 4) in vec3 textColor;
|
layout (location = 4) in vec3 textColor;
|
||||||
|
|
||||||
// Background color
|
// Background color
|
||||||
layout (location = 5) in vec4 backgroundColor;
|
layout (location = 5) in vec4 backgroundColor;
|
||||||
|
|
||||||
|
@ -36,12 +37,10 @@ out vec4 bg;
|
||||||
uniform vec2 termDim;
|
uniform vec2 termDim;
|
||||||
uniform vec2 cellDim;
|
uniform vec2 cellDim;
|
||||||
|
|
||||||
uniform float visualBell;
|
|
||||||
uniform int backgroundPass;
|
uniform int backgroundPass;
|
||||||
|
|
||||||
// Orthographic projection
|
// Orthographic projection
|
||||||
uniform mat4 projection;
|
uniform mat4 projection;
|
||||||
flat out float vb;
|
|
||||||
flat out int background;
|
flat out int background;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
@ -73,7 +72,6 @@ void main()
|
||||||
TexCoords = uvOffset + vec2(position.x, 1 - position.y) * uvSize;
|
TexCoords = uvOffset + vec2(position.x, 1 - position.y) * uvSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
vb = visualBell;
|
|
||||||
background = backgroundPass;
|
background = backgroundPass;
|
||||||
bg = vec4(backgroundColor.rgb / 255.0, backgroundColor.a);
|
bg = vec4(backgroundColor.rgb / 255.0, backgroundColor.a);
|
||||||
fg = textColor / vec3(255.0, 255.0, 255.0);
|
fg = textColor / vec3(255.0, 255.0, 255.0);
|
||||||
|
|
|
@ -157,13 +157,12 @@ pub struct VisualBellConfig {
|
||||||
animation: VisualBellAnimation,
|
animation: VisualBellAnimation,
|
||||||
|
|
||||||
/// Visual bell duration in milliseconds
|
/// Visual bell duration in milliseconds
|
||||||
#[serde(deserialize_with = "deserialize_visual_bell_duration")]
|
#[serde(default, deserialize_with = "deserialize_visual_bell_duration")]
|
||||||
#[serde(default="default_visual_bell_duration")]
|
|
||||||
duration: u16,
|
duration: u16,
|
||||||
}
|
|
||||||
|
|
||||||
fn default_visual_bell_duration() -> u16 {
|
/// Visual bell flash color
|
||||||
150
|
#[serde(default="default_visual_bell_color", deserialize_with = "rgb_from_hex")]
|
||||||
|
color: Rgb,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_visual_bell_duration<'a, D>(deserializer: D) -> ::std::result::Result<u16, D::Error>
|
fn deserialize_visual_bell_duration<'a, D>(deserializer: D) -> ::std::result::Result<u16, D::Error>
|
||||||
|
@ -173,11 +172,15 @@ fn deserialize_visual_bell_duration<'a, D>(deserializer: D) -> ::std::result::Re
|
||||||
Ok(duration) => Ok(duration),
|
Ok(duration) => Ok(duration),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("problem with config: {}; Using default value", err);
|
error!("problem with config: {}; Using default value", err);
|
||||||
Ok(default_visual_bell_duration())
|
Ok(0)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_visual_bell_color() -> Rgb {
|
||||||
|
Rgb { r: 255, g: 255, b: 255 }
|
||||||
|
}
|
||||||
|
|
||||||
impl VisualBellConfig {
|
impl VisualBellConfig {
|
||||||
/// Visual bell animation
|
/// Visual bell animation
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -190,13 +193,20 @@ impl VisualBellConfig {
|
||||||
pub fn duration(&self) -> Duration {
|
pub fn duration(&self) -> Duration {
|
||||||
Duration::from_millis(u64::from(self.duration))
|
Duration::from_millis(u64::from(self.duration))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Visual bell flash color
|
||||||
|
#[inline]
|
||||||
|
pub fn color(&self) -> Rgb {
|
||||||
|
self.color
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for VisualBellConfig {
|
impl Default for VisualBellConfig {
|
||||||
fn default() -> VisualBellConfig {
|
fn default() -> VisualBellConfig {
|
||||||
VisualBellConfig {
|
VisualBellConfig {
|
||||||
animation: VisualBellAnimation::default(),
|
animation: VisualBellAnimation::default(),
|
||||||
duration: default_visual_bell_duration(),
|
color: default_visual_bell_color(),
|
||||||
|
duration: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,8 +158,8 @@ impl Display {
|
||||||
let dimensions = options.dimensions()
|
let dimensions = options.dimensions()
|
||||||
.unwrap_or_else(|| config.dimensions());
|
.unwrap_or_else(|| config.dimensions());
|
||||||
|
|
||||||
let mut padding_x = (f64::from(config.padding().x) * dpr).floor();
|
let mut padding_x = f64::from(config.padding().x) * dpr;
|
||||||
let mut padding_y = (f64::from(config.padding().y) * dpr).floor();
|
let mut padding_y = f64::from(config.padding().y) * dpr;
|
||||||
|
|
||||||
if dimensions.columns_u32() > 0
|
if dimensions.columns_u32() > 0
|
||||||
&& dimensions.lines_u32() > 0
|
&& dimensions.lines_u32() > 0
|
||||||
|
@ -168,6 +168,8 @@ impl Display {
|
||||||
// Calculate new size based on cols/lines specified in config
|
// Calculate new size based on cols/lines specified in config
|
||||||
let width = cell_width as u32 * dimensions.columns_u32();
|
let width = cell_width as u32 * dimensions.columns_u32();
|
||||||
let height = cell_height as u32 * dimensions.lines_u32();
|
let height = cell_height as u32 * dimensions.lines_u32();
|
||||||
|
padding_x = padding_x.floor();
|
||||||
|
padding_y = padding_y.floor();
|
||||||
|
|
||||||
viewport_size = PhysicalSize::new(
|
viewport_size = PhysicalSize::new(
|
||||||
f64::from(width) + 2. * padding_x,
|
f64::from(width) + 2. * padding_x,
|
||||||
|
@ -211,7 +213,6 @@ impl Display {
|
||||||
renderer.with_api(
|
renderer.with_api(
|
||||||
config,
|
config,
|
||||||
&size_info,
|
&size_info,
|
||||||
0., /* visual bell intensity */
|
|
||||||
|api| {
|
|api| {
|
||||||
api.clear(background_color);
|
api.clear(background_color);
|
||||||
},
|
},
|
||||||
|
@ -325,8 +326,6 @@ impl Display {
|
||||||
self.update_glyph_cache(config);
|
self.update_glyph_cache(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive any resize events; only call gl::Viewport on last
|
|
||||||
// available
|
|
||||||
if let Some(psize) = new_size.take() {
|
if let Some(psize) = new_size.take() {
|
||||||
let width = psize.width as f32;
|
let width = psize.width as f32;
|
||||||
let height = psize.height as f32;
|
let height = psize.height as f32;
|
||||||
|
@ -405,7 +404,7 @@ impl Display {
|
||||||
// handling and rendering.
|
// handling and rendering.
|
||||||
drop(terminal);
|
drop(terminal);
|
||||||
|
|
||||||
self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| {
|
self.renderer.with_api(config, &size_info, |api| {
|
||||||
api.clear(background_color);
|
api.clear(background_color);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -416,12 +415,15 @@ impl Display {
|
||||||
{
|
{
|
||||||
let _sampler = self.meter.sampler();
|
let _sampler = self.meter.sampler();
|
||||||
|
|
||||||
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
|
self.renderer.with_api(config, &size_info, |mut api| {
|
||||||
// Draw the grid
|
// Draw the grid
|
||||||
api.render_cells(grid_cells.iter(), glyph_cache);
|
api.render_cells(grid_cells.iter(), glyph_cache);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw rectangles
|
||||||
|
self.renderer.draw_rects(config, &size_info, visual_bell_intensity);
|
||||||
|
|
||||||
// Draw render timer
|
// Draw render timer
|
||||||
if self.render_timer {
|
if self.render_timer {
|
||||||
let timing = format!("{:.3} usec", self.meter.average());
|
let timing = format!("{:.3} usec", self.meter.average());
|
||||||
|
@ -430,7 +432,7 @@ impl Display {
|
||||||
g: 0x4e,
|
g: 0x4e,
|
||||||
b: 0x53,
|
b: 0x53,
|
||||||
};
|
};
|
||||||
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
|
self.renderer.with_api(config, &size_info, |mut api| {
|
||||||
api.render_string(&timing[..], size_info.lines() - 2, glyph_cache, color);
|
api.render_string(&timing[..], size_info.lines() - 2, glyph_cache, color);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -446,7 +448,7 @@ impl Display {
|
||||||
g: 0x00,
|
g: 0x00,
|
||||||
b: 0x00,
|
b: 0x00,
|
||||||
};
|
};
|
||||||
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
|
self.renderer.with_api(config, &size_info, |mut api| {
|
||||||
api.render_string(&msg, size_info.lines() - 1, glyph_cache, color);
|
api.render_string(&msg, size_info.lines() - 1, glyph_cache, color);
|
||||||
});
|
});
|
||||||
} else if self.logger_proxy.warnings() {
|
} else if self.logger_proxy.warnings() {
|
||||||
|
@ -459,7 +461,7 @@ impl Display {
|
||||||
g: 0xff,
|
g: 0xff,
|
||||||
b: 0x00,
|
b: 0x00,
|
||||||
};
|
};
|
||||||
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
|
self.renderer.with_api(config, &size_info, |mut api| {
|
||||||
api.render_string(&msg, size_info.lines() - 1, glyph_cache, color);
|
api.render_string(&msg, size_info.lines() - 1, glyph_cache, color);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,18 @@ use glutin::dpi::PhysicalSize;
|
||||||
// Shader paths for live reload
|
// Shader paths for live reload
|
||||||
static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");
|
static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");
|
||||||
static TEXT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl");
|
static TEXT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl");
|
||||||
|
static RECT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/rect.f.glsl");
|
||||||
|
static RECT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/rect.v.glsl");
|
||||||
|
|
||||||
// Shader source which is used when live-shader-reload feature is disable
|
// Shader source which is used when live-shader-reload feature is disable
|
||||||
static TEXT_SHADER_F: &'static str =
|
static TEXT_SHADER_F: &'static str =
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl"));
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl"));
|
||||||
static TEXT_SHADER_V: &'static str =
|
static TEXT_SHADER_V: &'static str =
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl"));
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl"));
|
||||||
|
static RECT_SHADER_F: &'static str =
|
||||||
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/rect.f.glsl"));
|
||||||
|
static RECT_SHADER_V: &'static str =
|
||||||
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/rect.v.glsl"));
|
||||||
|
|
||||||
/// `LoadGlyph` allows for copying a rasterized glyph into graphics memory
|
/// `LoadGlyph` allows for copying a rasterized glyph into graphics memory
|
||||||
pub trait LoadGlyph {
|
pub trait LoadGlyph {
|
||||||
|
@ -98,7 +104,7 @@ impl From<ShaderCreationError> for Error {
|
||||||
///
|
///
|
||||||
/// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".
|
/// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ShaderProgram {
|
pub struct TextShaderProgram {
|
||||||
// Program id
|
// Program id
|
||||||
id: GLuint,
|
id: GLuint,
|
||||||
|
|
||||||
|
@ -111,15 +117,23 @@ pub struct ShaderProgram {
|
||||||
/// Cell dimensions (pixels)
|
/// Cell dimensions (pixels)
|
||||||
u_cell_dim: GLint,
|
u_cell_dim: GLint,
|
||||||
|
|
||||||
/// Visual bell
|
|
||||||
u_visual_bell: GLint,
|
|
||||||
|
|
||||||
/// Background pass flag
|
/// Background pass flag
|
||||||
///
|
///
|
||||||
/// Rendering is split into two passes; 1 for backgrounds, and one for text
|
/// Rendering is split into two passes; 1 for backgrounds, and one for text
|
||||||
u_background: GLint,
|
u_background: GLint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rectangle drawing program
|
||||||
|
///
|
||||||
|
/// Uniforms are prefixed with "u"
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RectShaderProgram {
|
||||||
|
// Program id
|
||||||
|
id: GLuint,
|
||||||
|
/// Rectangle color
|
||||||
|
u_col: GLint,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Debug, Clone)]
|
#[derive(Copy, Debug, Clone)]
|
||||||
pub struct Glyph {
|
pub struct Glyph {
|
||||||
tex_id: GLuint,
|
tex_id: GLuint,
|
||||||
|
@ -351,11 +365,13 @@ struct InstanceData {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QuadRenderer {
|
pub struct QuadRenderer {
|
||||||
program: ShaderProgram,
|
program: TextShaderProgram,
|
||||||
|
rect_program: RectShaderProgram,
|
||||||
vao: GLuint,
|
vao: GLuint,
|
||||||
vbo: GLuint,
|
|
||||||
ebo: GLuint,
|
ebo: GLuint,
|
||||||
vbo_instance: GLuint,
|
vbo_instance: GLuint,
|
||||||
|
rect_vao: GLuint,
|
||||||
|
rect_vbo: GLuint,
|
||||||
atlas: Vec<Atlas>,
|
atlas: Vec<Atlas>,
|
||||||
current_atlas: usize,
|
current_atlas: usize,
|
||||||
active_tex: GLuint,
|
active_tex: GLuint,
|
||||||
|
@ -369,9 +385,8 @@ pub struct RenderApi<'a> {
|
||||||
batch: &'a mut Batch,
|
batch: &'a mut Batch,
|
||||||
atlas: &'a mut Vec<Atlas>,
|
atlas: &'a mut Vec<Atlas>,
|
||||||
current_atlas: &'a mut usize,
|
current_atlas: &'a mut usize,
|
||||||
program: &'a mut ShaderProgram,
|
program: &'a mut TextShaderProgram,
|
||||||
config: &'a Config,
|
config: &'a Config,
|
||||||
visual_bell_intensity: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -470,7 +485,8 @@ const ATLAS_SIZE: i32 = 1024;
|
||||||
impl QuadRenderer {
|
impl QuadRenderer {
|
||||||
// TODO should probably hand this a transform instead of width/height
|
// TODO should probably hand this a transform instead of width/height
|
||||||
pub fn new(size: PhysicalSize) -> Result<QuadRenderer, Error> {
|
pub fn new(size: PhysicalSize) -> Result<QuadRenderer, Error> {
|
||||||
let program = ShaderProgram::new(size)?;
|
let program = TextShaderProgram::new(size)?;
|
||||||
|
let rect_program = RectShaderProgram::new()?;
|
||||||
|
|
||||||
let mut vao: GLuint = 0;
|
let mut vao: GLuint = 0;
|
||||||
let mut vbo: GLuint = 0;
|
let mut vbo: GLuint = 0;
|
||||||
|
@ -478,6 +494,10 @@ impl QuadRenderer {
|
||||||
|
|
||||||
let mut vbo_instance: GLuint = 0;
|
let mut vbo_instance: GLuint = 0;
|
||||||
|
|
||||||
|
let mut rect_vao: GLuint = 0;
|
||||||
|
let mut rect_vbo: GLuint = 0;
|
||||||
|
let mut rect_ebo: GLuint = 0;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::Enable(gl::BLEND);
|
gl::Enable(gl::BLEND);
|
||||||
gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
|
gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
|
||||||
|
@ -598,8 +618,27 @@ impl QuadRenderer {
|
||||||
gl::EnableVertexAttribArray(5);
|
gl::EnableVertexAttribArray(5);
|
||||||
gl::VertexAttribDivisor(5, 1);
|
gl::VertexAttribDivisor(5, 1);
|
||||||
|
|
||||||
|
// Rectangle setup
|
||||||
|
gl::GenVertexArrays(1, &mut rect_vao);
|
||||||
|
gl::GenBuffers(1, &mut rect_vbo);
|
||||||
|
gl::GenBuffers(1, &mut rect_ebo);
|
||||||
|
gl::BindVertexArray(rect_vao);
|
||||||
|
let indices: [i32; 6] = [
|
||||||
|
0, 1, 3,
|
||||||
|
1, 2, 3,
|
||||||
|
];
|
||||||
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, rect_ebo);
|
||||||
|
gl::BufferData(
|
||||||
|
gl::ELEMENT_ARRAY_BUFFER,
|
||||||
|
(size_of::<i32>() * indices.len()) as _,
|
||||||
|
indices.as_ptr() as *const _,
|
||||||
|
gl::STATIC_DRAW
|
||||||
|
);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
gl::BindVertexArray(0);
|
gl::BindVertexArray(0);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (msg_tx, msg_rx) = mpsc::channel();
|
let (msg_tx, msg_rx) = mpsc::channel();
|
||||||
|
@ -635,10 +674,12 @@ impl QuadRenderer {
|
||||||
|
|
||||||
let mut renderer = QuadRenderer {
|
let mut renderer = QuadRenderer {
|
||||||
program,
|
program,
|
||||||
|
rect_program,
|
||||||
vao,
|
vao,
|
||||||
vbo,
|
|
||||||
ebo,
|
ebo,
|
||||||
vbo_instance,
|
vbo_instance,
|
||||||
|
rect_vao,
|
||||||
|
rect_vbo,
|
||||||
atlas: Vec::new(),
|
atlas: Vec::new(),
|
||||||
current_atlas: 0,
|
current_atlas: 0,
|
||||||
active_tex: 0,
|
active_tex: 0,
|
||||||
|
@ -652,28 +693,77 @@ impl QuadRenderer {
|
||||||
Ok(renderer)
|
Ok(renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_api<F, T>(
|
// Draw all rectangles simultaneously to prevent excessive program swaps
|
||||||
|
pub fn draw_rects(
|
||||||
&mut self,
|
&mut self,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
props: &term::SizeInfo,
|
props: &term::SizeInfo,
|
||||||
visual_bell_intensity: f64,
|
visual_bell_intensity: f64,
|
||||||
|
) {
|
||||||
|
// Swap to rectangle rendering program
|
||||||
|
unsafe {
|
||||||
|
// Swap program
|
||||||
|
gl::UseProgram(self.rect_program.id);
|
||||||
|
|
||||||
|
// Remove padding from viewport
|
||||||
|
gl::Viewport(0, 0, props.width as i32, props.height as i32);
|
||||||
|
|
||||||
|
// Change blending strategy
|
||||||
|
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// Setup data and buffers
|
||||||
|
gl::BindVertexArray(self.rect_vao);
|
||||||
|
gl::BindBuffer(gl::ARRAY_BUFFER, self.rect_vbo);
|
||||||
|
|
||||||
|
// Position
|
||||||
|
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, (size_of::<f32>() * 3) as _, ptr::null());
|
||||||
|
gl::EnableVertexAttribArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw visual bell
|
||||||
|
let color = config.visual_bell().color();
|
||||||
|
let rect = Rect::new(0., 0., props.width, props.height);
|
||||||
|
self.render_rect(&rect, color, visual_bell_intensity as f32, props);
|
||||||
|
|
||||||
|
// Deactivate rectangle program again
|
||||||
|
unsafe {
|
||||||
|
// Reset blending strategy
|
||||||
|
gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
|
||||||
|
|
||||||
|
// Reset data and buffers
|
||||||
|
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
|
gl::BindVertexArray(0);
|
||||||
|
|
||||||
|
let padding_x = props.padding_x as i32;
|
||||||
|
let padding_y = props.padding_y as i32;
|
||||||
|
let width = props.width as i32;
|
||||||
|
let height = props.height as i32;
|
||||||
|
gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y);
|
||||||
|
|
||||||
|
// Disable program
|
||||||
|
gl::UseProgram(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_api<F, T>(
|
||||||
|
&mut self,
|
||||||
|
config: &Config,
|
||||||
|
props: &term::SizeInfo,
|
||||||
func: F,
|
func: F,
|
||||||
) -> T
|
) -> T
|
||||||
where
|
where
|
||||||
F: FnOnce(RenderApi<'_>) -> T,
|
F: FnOnce(RenderApi<'_>) -> T,
|
||||||
{
|
{
|
||||||
while let Ok(msg) = self.rx.try_recv() {
|
// Flush message queue
|
||||||
match msg {
|
if let Ok(Msg::ShaderReload) = self.rx.try_recv() {
|
||||||
Msg::ShaderReload => {
|
let size = PhysicalSize::new(f64::from(props.width), f64::from(props.height));
|
||||||
self.reload_shaders(PhysicalSize::new(f64::from(props.width), f64::from(props.height)));
|
self.reload_shaders(size);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
while let Ok(_) = self.rx.try_recv() {}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.program.activate();
|
gl::UseProgram(self.program.id);
|
||||||
self.program.set_term_uniforms(props);
|
self.program.set_term_uniforms(props);
|
||||||
self.program.set_visual_bell(visual_bell_intensity as _);
|
|
||||||
|
|
||||||
gl::BindVertexArray(self.vao);
|
gl::BindVertexArray(self.vao);
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
|
||||||
|
@ -687,7 +777,6 @@ impl QuadRenderer {
|
||||||
atlas: &mut self.atlas,
|
atlas: &mut self.atlas,
|
||||||
current_atlas: &mut self.current_atlas,
|
current_atlas: &mut self.current_atlas,
|
||||||
program: &mut self.program,
|
program: &mut self.program,
|
||||||
visual_bell_intensity: visual_bell_intensity as _,
|
|
||||||
config,
|
config,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -696,7 +785,7 @@ impl QuadRenderer {
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
gl::BindVertexArray(0);
|
gl::BindVertexArray(0);
|
||||||
|
|
||||||
self.program.deactivate();
|
gl::UseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -719,12 +808,13 @@ impl QuadRenderer {
|
||||||
|
|
||||||
pub fn reload_shaders(&mut self, size: PhysicalSize) {
|
pub fn reload_shaders(&mut self, size: PhysicalSize) {
|
||||||
warn!("Reloading shaders ...");
|
warn!("Reloading shaders ...");
|
||||||
let program = match ShaderProgram::new(size) {
|
let result = (TextShaderProgram::new(size), RectShaderProgram::new());
|
||||||
Ok(program) => {
|
let (program, rect_program) = match result {
|
||||||
|
(Ok(program), Ok(rect_program)) => {
|
||||||
warn!(" ... OK");
|
warn!(" ... OK");
|
||||||
program
|
(program, rect_program)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
(Err(err), _) | (_, Err(err)) => {
|
||||||
match err {
|
match err {
|
||||||
ShaderCreationError::Io(err) => {
|
ShaderCreationError::Io(err) => {
|
||||||
error!("Error reading shader file: {}", err);
|
error!("Error reading shader file: {}", err);
|
||||||
|
@ -743,6 +833,7 @@ impl QuadRenderer {
|
||||||
|
|
||||||
self.active_tex = 0;
|
self.active_tex = 0;
|
||||||
self.program = program;
|
self.program = program;
|
||||||
|
self.rect_program = rect_program;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, size: PhysicalSize, padding_x: f32, padding_y: f32) {
|
pub fn resize(&mut self, size: PhysicalSize, padding_x: f32, padding_y: f32) {
|
||||||
|
@ -755,12 +846,72 @@ impl QuadRenderer {
|
||||||
let padding_x = padding_x as i32;
|
let padding_x = padding_x as i32;
|
||||||
let padding_y = padding_y as i32;
|
let padding_y = padding_y as i32;
|
||||||
gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y);
|
gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y);
|
||||||
|
|
||||||
|
// update projection
|
||||||
|
gl::UseProgram(self.program.id);
|
||||||
|
self.program.update_projection(
|
||||||
|
width as f32,
|
||||||
|
height as f32,
|
||||||
|
padding_x as f32,
|
||||||
|
padding_y as f32,
|
||||||
|
);
|
||||||
|
gl::UseProgram(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render a rectangle
|
||||||
|
//
|
||||||
|
// This requires the rectangle program to be activated
|
||||||
|
fn render_rect(&mut self, rect: &Rect<f32>, color: Rgb, alpha: f32, size: &term::SizeInfo) {
|
||||||
|
// Do nothing when alpha is fully transparent
|
||||||
|
if alpha == 0. {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update projection
|
// Calculate rectangle position
|
||||||
self.program.activate();
|
let center_x = size.width / 2.;
|
||||||
self.program.update_projection(width as f32, height as f32, padding_x, padding_y);
|
let center_y = size.height / 2.;
|
||||||
self.program.deactivate();
|
let x = (rect.x - center_x) / center_x;
|
||||||
|
let y = -(rect.y - center_y) / center_y;
|
||||||
|
let width = rect.width / center_x;
|
||||||
|
let height = rect.height / center_y;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// Setup vertices
|
||||||
|
let vertices: [f32; 12] = [
|
||||||
|
x + width, y , 0.0,
|
||||||
|
x + width, y - height, 0.0,
|
||||||
|
x , y - height, 0.0,
|
||||||
|
x , y , 0.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load vertex data into array buffer
|
||||||
|
gl::BufferData(
|
||||||
|
gl::ARRAY_BUFFER,
|
||||||
|
(size_of::<f32>() * vertices.len()) as _,
|
||||||
|
vertices.as_ptr() as *const _,
|
||||||
|
gl::STATIC_DRAW
|
||||||
|
);
|
||||||
|
|
||||||
|
// Color
|
||||||
|
self.rect_program.set_color(color, alpha);
|
||||||
|
|
||||||
|
// Draw the rectangle
|
||||||
|
gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Rect<T> {
|
||||||
|
x: T,
|
||||||
|
y: T,
|
||||||
|
width: T,
|
||||||
|
height: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Rect<T> {
|
||||||
|
fn new(x: T, y: T, width: T, height: T) -> Self {
|
||||||
|
Rect { x, y, width, height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,11 +920,11 @@ impl<'a> RenderApi<'a> {
|
||||||
let alpha = self.config.background_opacity().get();
|
let alpha = self.config.background_opacity().get();
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::ClearColor(
|
gl::ClearColor(
|
||||||
(self.visual_bell_intensity + f32::from(color.r) / 255.0).min(1.0) * alpha,
|
(f32::from(color.r) / 255.0).min(1.0) * alpha,
|
||||||
(self.visual_bell_intensity + f32::from(color.g) / 255.0).min(1.0) * alpha,
|
(f32::from(color.g) / 255.0).min(1.0) * alpha,
|
||||||
(self.visual_bell_intensity + f32::from(color.b) / 255.0).min(1.0) * alpha,
|
(f32::from(color.b) / 255.0).min(1.0) * alpha,
|
||||||
alpha
|
alpha,
|
||||||
);
|
);
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1012,39 +1163,20 @@ impl<'a> Drop for RenderApi<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShaderProgram {
|
impl TextShaderProgram {
|
||||||
pub fn activate(&self) {
|
pub fn new(size: PhysicalSize) -> Result<TextShaderProgram, ShaderCreationError> {
|
||||||
unsafe {
|
let (vertex_src, fragment_src) = if cfg!(feature = "live-shader-reload") {
|
||||||
gl::UseProgram(self.id);
|
(None, None)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deactivate(&self) {
|
|
||||||
unsafe {
|
|
||||||
gl::UseProgram(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(size: PhysicalSize) -> Result<ShaderProgram, ShaderCreationError> {
|
|
||||||
let vertex_source = if cfg!(feature = "live-shader-reload") {
|
|
||||||
None
|
|
||||||
} else {
|
} else {
|
||||||
Some(TEXT_SHADER_V)
|
(Some(TEXT_SHADER_V), Some(TEXT_SHADER_F))
|
||||||
};
|
};
|
||||||
let vertex_shader =
|
let vertex_shader = create_shader(TEXT_SHADER_V_PATH, gl::VERTEX_SHADER, vertex_src)?;
|
||||||
ShaderProgram::create_shader(TEXT_SHADER_V_PATH, gl::VERTEX_SHADER, vertex_source)?;
|
let fragment_shader = create_shader(TEXT_SHADER_F_PATH, gl::FRAGMENT_SHADER, fragment_src)?;
|
||||||
let frag_source = if cfg!(feature = "live-shader-reload") {
|
let program = create_program(vertex_shader, fragment_shader)?;
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(TEXT_SHADER_F)
|
|
||||||
};
|
|
||||||
let fragment_shader =
|
|
||||||
ShaderProgram::create_shader(TEXT_SHADER_F_PATH, gl::FRAGMENT_SHADER, frag_source)?;
|
|
||||||
let program = ShaderProgram::create_program(vertex_shader, fragment_shader)?;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::DeleteShader(vertex_shader);
|
|
||||||
gl::DeleteShader(fragment_shader);
|
gl::DeleteShader(fragment_shader);
|
||||||
|
gl::DeleteShader(vertex_shader);
|
||||||
gl::UseProgram(program);
|
gl::UseProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,30 +1195,28 @@ impl ShaderProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get uniform locations
|
// get uniform locations
|
||||||
let (projection, term_dim, cell_dim, visual_bell, background) = unsafe {
|
let (projection, term_dim, cell_dim, background) = unsafe {
|
||||||
(
|
(
|
||||||
gl::GetUniformLocation(program, cptr!(b"projection\0")),
|
gl::GetUniformLocation(program, cptr!(b"projection\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"termDim\0")),
|
gl::GetUniformLocation(program, cptr!(b"termDim\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"cellDim\0")),
|
gl::GetUniformLocation(program, cptr!(b"cellDim\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"visualBell\0")),
|
|
||||||
gl::GetUniformLocation(program, cptr!(b"backgroundPass\0")),
|
gl::GetUniformLocation(program, cptr!(b"backgroundPass\0")),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_uniform_valid!(projection, term_dim, cell_dim);
|
assert_uniform_valid!(projection, term_dim, cell_dim);
|
||||||
|
|
||||||
let shader = ShaderProgram {
|
let shader = TextShaderProgram {
|
||||||
id: program,
|
id: program,
|
||||||
u_projection: projection,
|
u_projection: projection,
|
||||||
u_term_dim: term_dim,
|
u_term_dim: term_dim,
|
||||||
u_cell_dim: cell_dim,
|
u_cell_dim: cell_dim,
|
||||||
u_visual_bell: visual_bell,
|
|
||||||
u_background: background,
|
u_background: background,
|
||||||
};
|
};
|
||||||
|
|
||||||
shader.update_projection(size.width as f32, size.height as f32, 0., 0.);
|
shader.update_projection(size.width as f32, size.height as f32, 0., 0.);
|
||||||
|
|
||||||
shader.deactivate();
|
unsafe { gl::UseProgram(0); }
|
||||||
|
|
||||||
Ok(shader)
|
Ok(shader)
|
||||||
}
|
}
|
||||||
|
@ -1133,12 +1263,6 @@ impl ShaderProgram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_visual_bell(&self, visual_bell: f32) {
|
|
||||||
unsafe {
|
|
||||||
gl::Uniform1f(self.u_visual_bell, visual_bell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_background_pass(&self, background_pass: bool) {
|
fn set_background_pass(&self, background_pass: bool) {
|
||||||
let value = if background_pass { 1 } else { 0 };
|
let value = if background_pass { 1 } else { 0 };
|
||||||
|
|
||||||
|
@ -1146,69 +1270,9 @@ impl ShaderProgram {
|
||||||
gl::Uniform1i(self.u_background, value);
|
gl::Uniform1i(self.u_background, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_program(vertex: GLuint, fragment: GLuint) -> Result<GLuint, ShaderCreationError> {
|
|
||||||
unsafe {
|
|
||||||
let program = gl::CreateProgram();
|
|
||||||
gl::AttachShader(program, vertex);
|
|
||||||
gl::AttachShader(program, fragment);
|
|
||||||
gl::LinkProgram(program);
|
|
||||||
|
|
||||||
let mut success: GLint = 0;
|
|
||||||
gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);
|
|
||||||
|
|
||||||
if success == i32::from(gl::TRUE) {
|
|
||||||
Ok(program)
|
|
||||||
} else {
|
|
||||||
Err(ShaderCreationError::Link(get_program_info_log(program)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_shader(
|
|
||||||
path: &str,
|
|
||||||
kind: GLenum,
|
|
||||||
source: Option<&'static str>,
|
|
||||||
) -> Result<GLuint, ShaderCreationError> {
|
|
||||||
let from_disk;
|
|
||||||
let source = if let Some(src) = source {
|
|
||||||
src
|
|
||||||
} else {
|
|
||||||
from_disk = read_file(path)?;
|
|
||||||
&from_disk[..]
|
|
||||||
};
|
|
||||||
|
|
||||||
let len: [GLint; 1] = [source.len() as GLint];
|
|
||||||
|
|
||||||
let shader = unsafe {
|
|
||||||
let shader = gl::CreateShader(kind);
|
|
||||||
gl::ShaderSource(shader, 1, &(source.as_ptr() as *const _), len.as_ptr());
|
|
||||||
gl::CompileShader(shader);
|
|
||||||
shader
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut success: GLint = 0;
|
|
||||||
unsafe {
|
|
||||||
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success);
|
|
||||||
}
|
|
||||||
|
|
||||||
if success == GLint::from(gl::TRUE) {
|
|
||||||
Ok(shader)
|
|
||||||
} else {
|
|
||||||
// Read log
|
|
||||||
let log = get_shader_info_log(shader);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
unsafe {
|
|
||||||
gl::DeleteShader(shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(ShaderCreationError::Compile(PathBuf::from(path), log))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ShaderProgram {
|
impl Drop for TextShaderProgram {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::DeleteProgram(self.id);
|
gl::DeleteProgram(self.id);
|
||||||
|
@ -1216,6 +1280,123 @@ impl Drop for ShaderProgram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RectShaderProgram {
|
||||||
|
pub fn new() -> Result<Self, ShaderCreationError> {
|
||||||
|
let (vertex_src, fragment_src) = if cfg!(feature = "live-shader-reload") {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
(Some(RECT_SHADER_V), Some(RECT_SHADER_F))
|
||||||
|
};
|
||||||
|
let vertex_shader = create_shader(
|
||||||
|
RECT_SHADER_V_PATH,
|
||||||
|
gl::VERTEX_SHADER,
|
||||||
|
vertex_src
|
||||||
|
)?;
|
||||||
|
let fragment_shader = create_shader(
|
||||||
|
RECT_SHADER_F_PATH,
|
||||||
|
gl::FRAGMENT_SHADER,
|
||||||
|
fragment_src
|
||||||
|
)?;
|
||||||
|
let program = create_program(vertex_shader, fragment_shader)?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::DeleteShader(fragment_shader);
|
||||||
|
gl::DeleteShader(vertex_shader);
|
||||||
|
gl::UseProgram(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get uniform locations
|
||||||
|
let u_col = unsafe {
|
||||||
|
gl::GetUniformLocation(program, b"col\0".as_ptr() as *const _)
|
||||||
|
};
|
||||||
|
|
||||||
|
let shader = RectShaderProgram {
|
||||||
|
id: program,
|
||||||
|
u_col,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe { gl::UseProgram(0) }
|
||||||
|
|
||||||
|
Ok(shader)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_color(&self, color: Rgb, alpha: f32) {
|
||||||
|
unsafe {
|
||||||
|
gl::Uniform4f(
|
||||||
|
self.u_col,
|
||||||
|
f32::from(color.r) / 255.,
|
||||||
|
f32::from(color.g) / 255.,
|
||||||
|
f32::from(color.b) / 255.,
|
||||||
|
alpha,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for RectShaderProgram {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
gl::DeleteProgram(self.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_program(vertex: GLuint, fragment: GLuint) -> Result<GLuint, ShaderCreationError> {
|
||||||
|
unsafe {
|
||||||
|
let program = gl::CreateProgram();
|
||||||
|
gl::AttachShader(program, vertex);
|
||||||
|
gl::AttachShader(program, fragment);
|
||||||
|
gl::LinkProgram(program);
|
||||||
|
|
||||||
|
let mut success: GLint = 0;
|
||||||
|
gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);
|
||||||
|
|
||||||
|
if success == i32::from(gl::TRUE) {
|
||||||
|
Ok(program)
|
||||||
|
} else {
|
||||||
|
Err(ShaderCreationError::Link(get_program_info_log(program)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_shader(path: &str, kind: GLenum, source: Option<&'static str>)
|
||||||
|
-> Result<GLuint, ShaderCreationError>
|
||||||
|
{
|
||||||
|
let from_disk;
|
||||||
|
let source = if let Some(src) = source {
|
||||||
|
src
|
||||||
|
} else {
|
||||||
|
from_disk = read_file(path)?;
|
||||||
|
&from_disk[..]
|
||||||
|
};
|
||||||
|
|
||||||
|
let len: [GLint; 1] = [source.len() as GLint];
|
||||||
|
|
||||||
|
let shader = unsafe {
|
||||||
|
let shader = gl::CreateShader(kind);
|
||||||
|
gl::ShaderSource(shader, 1, &(source.as_ptr() as *const _), len.as_ptr());
|
||||||
|
gl::CompileShader(shader);
|
||||||
|
shader
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut success: GLint = 0;
|
||||||
|
unsafe {
|
||||||
|
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success);
|
||||||
|
}
|
||||||
|
|
||||||
|
if success == GLint::from(gl::TRUE) {
|
||||||
|
Ok(shader)
|
||||||
|
} else {
|
||||||
|
// Read log
|
||||||
|
let log = get_shader_info_log(shader);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
unsafe { gl::DeleteShader(shader); }
|
||||||
|
|
||||||
|
Err(ShaderCreationError::Compile(PathBuf::from(path), log))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_program_info_log(program: GLuint) -> String {
|
fn get_program_info_log(program: GLuint) -> String {
|
||||||
// Get expected log length
|
// Get expected log length
|
||||||
let mut max_length: GLint = 0;
|
let mut max_length: GLint = 0;
|
||||||
|
|
Loading…
Reference in New Issue