Switch back to instanced drawing for tiles.
Improves tile build time by something around 2x in the NanoVG demo.
This commit is contained in:
parent
941abd202e
commit
895f73096e
|
@ -289,6 +289,7 @@ dependencies = [
|
||||||
"font-kit 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"font-kit 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"image 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"image 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pathfinder_canvas 0.1.0",
|
"pathfinder_canvas 0.1.0",
|
||||||
"pathfinder_color 0.1.0",
|
"pathfinder_color 0.1.0",
|
||||||
"pathfinder_content 0.1.0",
|
"pathfinder_content 0.1.0",
|
||||||
|
@ -1009,7 +1010,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1701,7 +1702,7 @@ name = "pathfinder_gl"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pathfinder_geometry 0.4.0",
|
"pathfinder_geometry 0.4.0",
|
||||||
"pathfinder_gpu 0.1.0",
|
"pathfinder_gpu 0.1.0",
|
||||||
|
@ -1714,7 +1715,7 @@ name = "pathfinder_gpu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"image 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"image 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pathfinder_color 0.1.0",
|
"pathfinder_color 0.1.0",
|
||||||
"pathfinder_geometry 0.4.0",
|
"pathfinder_geometry 0.4.0",
|
||||||
|
@ -1764,7 +1765,7 @@ dependencies = [
|
||||||
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pathfinder_geometry 0.4.0",
|
"pathfinder_geometry 0.4.0",
|
||||||
|
@ -1779,6 +1780,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hashbrown 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hashbrown 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"instant 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"instant 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2385,7 +2387,7 @@ name = "swf-parser"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lzma-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lzma-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2944,7 +2946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum glutin_glx_sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "08c243de74d6cf5ea100c788826d2fb9319de315485dd4b310811a663b3809c3"
|
"checksum glutin_glx_sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "08c243de74d6cf5ea100c788826d2fb9319de315485dd4b310811a663b3809c3"
|
||||||
"checksum glutin_wgl_sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a93dba7ee3a0feeac0f437141ff25e71ce2066bcf1a706acab1559ffff94eb6a"
|
"checksum glutin_wgl_sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a93dba7ee3a0feeac0f437141ff25e71ce2066bcf1a706acab1559ffff94eb6a"
|
||||||
"checksum goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da"
|
"checksum goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da"
|
||||||
"checksum half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0"
|
"checksum half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f36b5f248235f45773d4944f555f83ea61fe07b18b561ccf99d7483d7381e54d"
|
||||||
"checksum harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46f7426266a5ece3e49eae6f48e602c0f8c39917354a847eac9c06437dcde8da"
|
"checksum harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46f7426266a5ece3e49eae6f48e602c0f8c39917354a847eac9c06437dcde8da"
|
||||||
"checksum harfbuzz-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d74cab8498b2d15700b694fb38f77562869d05e1f8b602dd05221a1ca2d63"
|
"checksum harfbuzz-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d74cab8498b2d15700b694fb38f77562869d05e1f8b602dd05221a1ca2d63"
|
||||||
"checksum harfbuzz_rs 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cab35982090055087fad29795c465b33e8cf201bda50bfa008311ffe88630f16"
|
"checksum harfbuzz_rs 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cab35982090055087fad29795c465b33e8cf201bda50bfa008311ffe88630f16"
|
||||||
|
|
|
@ -308,7 +308,6 @@ impl CanvasRenderingContext2D {
|
||||||
let transform = self.current_state.transform;
|
let transform = self.current_state.transform;
|
||||||
let clip_path = self.current_state.clip_path;
|
let clip_path = self.current_state.clip_path;
|
||||||
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
||||||
let opacity = (self.current_state.global_alpha * 255.0) as u8;
|
|
||||||
|
|
||||||
outline.transform(&transform);
|
outline.transform(&transform);
|
||||||
|
|
||||||
|
@ -334,7 +333,6 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
path.set_fill_rule(fill_rule);
|
path.set_fill_rule(fill_rule);
|
||||||
path.set_blend_mode(blend_mode);
|
path.set_blend_mode(blend_mode);
|
||||||
path.set_opacity(opacity);
|
|
||||||
self.canvas.scene.push_path(path);
|
self.canvas.scene.push_path(path);
|
||||||
|
|
||||||
self.composite_shadow_blur_render_targets_if_needed(shadow_blur_info, clip_path);
|
self.composite_shadow_blur_render_targets_if_needed(shadow_blur_info, clip_path);
|
||||||
|
@ -344,7 +342,6 @@ impl CanvasRenderingContext2D {
|
||||||
path.set_clip_path(clip_path);
|
path.set_clip_path(clip_path);
|
||||||
path.set_fill_rule(fill_rule);
|
path.set_fill_rule(fill_rule);
|
||||||
path.set_blend_mode(blend_mode);
|
path.set_blend_mode(blend_mode);
|
||||||
path.set_opacity(opacity);
|
|
||||||
self.canvas.scene.push_path(path);
|
self.canvas.scene.push_path(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +584,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_paint<'a>(&self, paint: &'a Paint) -> Cow<'a, Paint> {
|
fn resolve_paint<'a>(&self, paint: &'a Paint) -> Cow<'a, Paint> {
|
||||||
let mut must_copy = !self.transform.is_identity();
|
let mut must_copy = !self.transform.is_identity() || self.global_alpha < 1.0;
|
||||||
if !must_copy {
|
if !must_copy {
|
||||||
if let Paint::Pattern(ref pattern) = *paint {
|
if let Paint::Pattern(ref pattern) = *paint {
|
||||||
must_copy = self.image_smoothing_enabled != pattern.smoothing_enabled()
|
must_copy = self.image_smoothing_enabled != pattern.smoothing_enabled()
|
||||||
|
@ -600,6 +597,7 @@ impl State {
|
||||||
|
|
||||||
let mut paint = (*paint).clone();
|
let mut paint = (*paint).clone();
|
||||||
paint.apply_transform(&self.transform);
|
paint.apply_transform(&self.transform);
|
||||||
|
paint.apply_opacity(self.global_alpha);
|
||||||
if let Paint::Pattern(ref mut pattern) = paint {
|
if let Paint::Pattern(ref mut pattern) = paint {
|
||||||
pattern.set_smoothing_enabled(self.image_smoothing_enabled);
|
pattern.set_smoothing_enabled(self.image_smoothing_enabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
let clip_path = self.current_state.clip_path;
|
let clip_path = self.current_state.clip_path;
|
||||||
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
||||||
let opacity = (self.current_state.global_alpha * 255.0) as u8;
|
|
||||||
|
|
||||||
drop(self.canvas.scene.push_layout(&layout,
|
drop(self.canvas.scene.push_layout(&layout,
|
||||||
&TextStyle { size: self.current_state.font_size },
|
&TextStyle { size: self.current_state.font_size },
|
||||||
|
@ -54,7 +53,6 @@ impl CanvasRenderingContext2D {
|
||||||
HintingOptions::None,
|
HintingOptions::None,
|
||||||
clip_path,
|
clip_path,
|
||||||
blend_mode,
|
blend_mode,
|
||||||
opacity,
|
|
||||||
paint_id));
|
paint_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +65,6 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
let clip_path = self.current_state.clip_path;
|
let clip_path = self.current_state.clip_path;
|
||||||
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
||||||
let opacity = (self.current_state.global_alpha * 255.0) as u8;
|
|
||||||
|
|
||||||
match self.current_state.text_align {
|
match self.current_state.text_align {
|
||||||
TextAlign::Left => {},
|
TextAlign::Left => {},
|
||||||
|
@ -96,7 +93,6 @@ impl CanvasRenderingContext2D {
|
||||||
HintingOptions::None,
|
HintingOptions::None,
|
||||||
clip_path,
|
clip_path,
|
||||||
blend_mode,
|
blend_mode,
|
||||||
opacity,
|
|
||||||
paint_id));
|
paint_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,11 @@ impl Gradient {
|
||||||
&self.stops.array
|
&self.stops.array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn stops_mut(&mut self) -> &mut [ColorStop] {
|
||||||
|
&mut self.stops.array
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sample(&self, mut t: f32) -> ColorU {
|
pub fn sample(&self, mut t: f32) -> ColorU {
|
||||||
if self.stops.is_empty() {
|
if self.stops.is_empty() {
|
||||||
return ColorU::transparent_black();
|
return ColorU::transparent_black();
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub struct Pattern {
|
||||||
transform: Transform2F,
|
transform: Transform2F,
|
||||||
filter: Option<PatternFilter>,
|
filter: Option<PatternFilter>,
|
||||||
flags: PatternFlags,
|
flags: PatternFlags,
|
||||||
|
opacity: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -69,6 +70,7 @@ impl Pattern {
|
||||||
transform: Transform2F::default(),
|
transform: Transform2F::default(),
|
||||||
filter: None,
|
filter: None,
|
||||||
flags: PatternFlags::empty(),
|
flags: PatternFlags::empty(),
|
||||||
|
opacity: !0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +142,16 @@ impl Pattern {
|
||||||
self.flags.set(PatternFlags::NO_SMOOTHING, !enable);
|
self.flags.set(PatternFlags::NO_SMOOTHING, !enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn opacity(&self) -> u8 {
|
||||||
|
self.opacity
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_opacity(&mut self, opacity: u8) {
|
||||||
|
self.opacity = opacity
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_opaque(&self) -> bool {
|
pub fn is_opaque(&self) -> bool {
|
||||||
self.source.is_opaque()
|
self.source.is_opaque()
|
||||||
|
|
|
@ -43,3 +43,6 @@ path = "../../resources"
|
||||||
|
|
||||||
[dependencies.pathfinder_simd]
|
[dependencies.pathfinder_simd]
|
||||||
path = "../../simd"
|
path = "../../simd"
|
||||||
|
|
||||||
|
[target.'cfg(not(windows))'.dependencies]
|
||||||
|
jemallocator = "0.3"
|
||||||
|
|
|
@ -42,13 +42,20 @@ use std::f32::consts::PI;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use jemallocator;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
#[global_allocator]
|
||||||
|
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
||||||
|
|
||||||
// TODO(pcwalton): See if we can reduce the amount of code by using the canvas shadow feature.
|
// TODO(pcwalton): See if we can reduce the amount of code by using the canvas shadow feature.
|
||||||
|
|
||||||
const PI_2: f32 = PI * 2.0;
|
const PI_2: f32 = PI * 2.0;
|
||||||
const FRAC_PI_2_3: f32 = PI * 2.0 / 3.0;
|
const FRAC_PI_2_3: f32 = PI * 2.0 / 3.0;
|
||||||
|
|
||||||
const WINDOW_WIDTH: i32 = 1024;
|
const WINDOW_WIDTH: i32 = 1024;
|
||||||
const WINDOW_HEIGHT: i32 = 768;
|
const WINDOW_HEIGHT: i32 = WINDOW_WIDTH * 3 / 4;
|
||||||
|
|
||||||
static FONT_NAME_REGULAR: &'static str = "Roboto-Regular";
|
static FONT_NAME_REGULAR: &'static str = "Roboto-Regular";
|
||||||
static FONT_NAME_BOLD: &'static str = "Roboto-Bold";
|
static FONT_NAME_BOLD: &'static str = "Roboto-Bold";
|
||||||
|
|
|
@ -228,6 +228,14 @@ impl Transform2F {
|
||||||
pub fn m22(&self) -> f32 {
|
pub fn m22(&self) -> f32 {
|
||||||
self.matrix.m22()
|
self.matrix.m22()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn m31(&self) -> f32 {
|
||||||
|
self.vector.x()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn m32(&self) -> f32 {
|
||||||
|
self.vector.y()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn translate(&self, vector: Vector2F) -> Transform2F {
|
pub fn translate(&self, vector: Vector2F) -> Transform2F {
|
||||||
|
|
|
@ -9,7 +9,7 @@ crate-type = ["rlib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gl = "0.14"
|
gl = "0.14"
|
||||||
half = "1.4"
|
half = "1.5"
|
||||||
|
|
||||||
[dependencies.log]
|
[dependencies.log]
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
|
|
|
@ -132,6 +132,9 @@ impl GLDevice {
|
||||||
UniformData::Float(value) => {
|
UniformData::Float(value) => {
|
||||||
gl::Uniform1f(uniform.location, value); ck();
|
gl::Uniform1f(uniform.location, value); ck();
|
||||||
}
|
}
|
||||||
|
UniformData::IVec2(value) => {
|
||||||
|
gl::Uniform2i(uniform.location, value[0], value[1]); ck();
|
||||||
|
}
|
||||||
UniformData::IVec3(value) => {
|
UniformData::IVec3(value) => {
|
||||||
gl::Uniform3i(uniform.location, value[0], value[1], value[2]); ck();
|
gl::Uniform3i(uniform.location, value[0], value[1], value[2]); ck();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
half = "1.4"
|
half = "1.5"
|
||||||
|
|
||||||
[dependencies.image]
|
[dependencies.image]
|
||||||
version = "0.23"
|
version = "0.23"
|
||||||
|
|
|
@ -20,7 +20,7 @@ use pathfinder_geometry::rect::RectI;
|
||||||
use pathfinder_geometry::transform3d::Transform4F;
|
use pathfinder_geometry::transform3d::Transform4F;
|
||||||
use pathfinder_geometry::vector::{Vector2I, vec2i};
|
use pathfinder_geometry::vector::{Vector2I, vec2i};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_simd::default::{F32x2, F32x4};
|
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -166,6 +166,7 @@ pub enum ShaderKind {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum UniformData {
|
pub enum UniformData {
|
||||||
Float(f32),
|
Float(f32),
|
||||||
|
IVec2(I32x2),
|
||||||
IVec3([i32; 3]),
|
IVec3([i32; 3]),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Mat2(F32x4),
|
Mat2(F32x4),
|
||||||
|
|
|
@ -11,7 +11,7 @@ block = "0.1"
|
||||||
cocoa = "0.19"
|
cocoa = "0.19"
|
||||||
core-foundation = "0.7"
|
core-foundation = "0.7"
|
||||||
foreign-types = "0.3"
|
foreign-types = "0.3"
|
||||||
half = "1.4"
|
half = "1.5"
|
||||||
metal = "0.17"
|
metal = "0.17"
|
||||||
objc = "0.2"
|
objc = "0.2"
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ use pathfinder_gpu::{Device, Primitive, RenderState, RenderTarget, ShaderKind, S
|
||||||
use pathfinder_gpu::{TextureData, TextureDataRef, TextureFormat, TextureSamplingFlags};
|
use pathfinder_gpu::{TextureData, TextureDataRef, TextureFormat, TextureSamplingFlags};
|
||||||
use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_simd::default::{F32x2, F32x4};
|
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -621,19 +621,23 @@ impl Device for MetalDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn begin_timer_query(&self, query: &MetalTimerQuery) {
|
fn begin_timer_query(&self, query: &MetalTimerQuery) {
|
||||||
|
/*
|
||||||
self.command_buffers
|
self.command_buffers
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.encode_signal_event(&self.shared_event, query.0.event_value);
|
.encode_signal_event(&self.shared_event, query.0.event_value);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_timer_query(&self, query: &MetalTimerQuery) {
|
fn end_timer_query(&self, query: &MetalTimerQuery) {
|
||||||
|
/*
|
||||||
self.command_buffers
|
self.command_buffers
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.encode_signal_event(&self.shared_event, query.0.event_value + 1);
|
.encode_signal_event(&self.shared_event, query.0.event_value + 1);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_recv_timer_query(&self, query: &MetalTimerQuery) -> Option<Duration> {
|
fn try_recv_timer_query(&self, query: &MetalTimerQuery) -> Option<Duration> {
|
||||||
|
@ -908,6 +912,10 @@ impl MetalDevice {
|
||||||
UniformData::Float(value) => {
|
UniformData::Float(value) => {
|
||||||
uniform_buffer_data.write_f32::<NativeEndian>(value).unwrap()
|
uniform_buffer_data.write_f32::<NativeEndian>(value).unwrap()
|
||||||
}
|
}
|
||||||
|
UniformData::IVec2(vector) => {
|
||||||
|
uniform_buffer_data.write_i32::<NativeEndian>(vector.x()).unwrap();
|
||||||
|
uniform_buffer_data.write_i32::<NativeEndian>(vector.y()).unwrap();
|
||||||
|
}
|
||||||
UniformData::IVec3(values) => {
|
UniformData::IVec3(values) => {
|
||||||
uniform_buffer_data.write_i32::<NativeEndian>(values[0]).unwrap();
|
uniform_buffer_data.write_i32::<NativeEndian>(values[0]).unwrap();
|
||||||
uniform_buffer_data.write_i32::<NativeEndian>(values[1]).unwrap();
|
uniform_buffer_data.write_i32::<NativeEndian>(values[1]).unwrap();
|
||||||
|
@ -1297,6 +1305,9 @@ impl UniformDataExt for UniformData {
|
||||||
UniformData::Float(ref data) => {
|
UniformData::Float(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const f32 as *const u8, 4 * 1))
|
Some(slice::from_raw_parts(data as *const f32 as *const u8, 4 * 1))
|
||||||
}
|
}
|
||||||
|
UniformData::IVec2(ref data) => {
|
||||||
|
Some(slice::from_raw_parts(data as *const I32x2 as *const u8, 4 * 3))
|
||||||
|
}
|
||||||
UniformData::IVec3(ref data) => {
|
UniformData::IVec3(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const i32 as *const u8, 4 * 3))
|
Some(slice::from_raw_parts(data as *const i32 as *const u8, 4 * 3))
|
||||||
}
|
}
|
||||||
|
@ -1337,6 +1348,8 @@ impl TextureFormatExt for TextureFormat {
|
||||||
// FIXME(pcwalton): This is wrong! But it prevents a crash for now.
|
// FIXME(pcwalton): This is wrong! But it prevents a crash for now.
|
||||||
Some(TextureFormat::RGBA8)
|
Some(TextureFormat::RGBA8)
|
||||||
}
|
}
|
||||||
|
MTLPixelFormat::RGBA16Float => Some(TextureFormat::RGBA16F),
|
||||||
|
MTLPixelFormat::RGBA32Float => Some(TextureFormat::RGBA32F),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
byteorder = "1.2"
|
byteorder = "1.2"
|
||||||
|
half = "1.5"
|
||||||
hashbrown = "0.7"
|
hashbrown = "0.7"
|
||||||
rayon = "1.0"
|
rayon = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
use crate::concurrent::executor::Executor;
|
use crate::concurrent::executor::Executor;
|
||||||
use crate::gpu::renderer::{BlendModeExt, MASK_TILES_ACROSS, MASK_TILES_DOWN};
|
use crate::gpu::renderer::{BlendModeExt, MASK_TILES_ACROSS, MASK_TILES_DOWN};
|
||||||
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TexturePageId, Tile, TileBatch};
|
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TexturePageId, Tile, TileBatch};
|
||||||
use crate::gpu_data::{TileBatchTexture, TileObjectPrimitive, TileVertex};
|
use crate::gpu_data::{TileBatchTexture, TileObjectPrimitive};
|
||||||
use crate::options::{PreparedBuildOptions, PreparedRenderTransform, RenderCommandListener};
|
use crate::options::{PreparedBuildOptions, PreparedRenderTransform, RenderCommandListener};
|
||||||
use crate::paint::{PaintInfo, PaintMetadata};
|
use crate::paint::{PaintInfo, PaintMetadata};
|
||||||
use crate::scene::{DisplayItem, Scene};
|
use crate::scene::{DisplayItem, Scene};
|
||||||
|
@ -125,8 +125,8 @@ impl<'a> SceneBuilder<'a> {
|
||||||
render_commands,
|
render_commands,
|
||||||
paint_metadata,
|
paint_metadata,
|
||||||
opacity_tile_page,
|
opacity_tile_page,
|
||||||
opacity_tile_transform,
|
opacity_tile_transform: _,
|
||||||
render_target_metadata: _
|
render_target_metadata: _,
|
||||||
} = self.scene.build_paint_info(render_transform);
|
} = self.scene.build_paint_info(render_transform);
|
||||||
for render_command in render_commands {
|
for render_command in render_commands {
|
||||||
self.listener.send(render_command);
|
self.listener.send(render_command);
|
||||||
|
@ -153,7 +153,6 @@ impl<'a> SceneBuilder<'a> {
|
||||||
},
|
},
|
||||||
paint_metadata: &paint_metadata,
|
paint_metadata: &paint_metadata,
|
||||||
opacity_tile_page,
|
opacity_tile_page,
|
||||||
opacity_tile_transform,
|
|
||||||
built_clip_paths: &built_clip_paths,
|
built_clip_paths: &built_clip_paths,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -186,7 +185,6 @@ impl<'a> SceneBuilder<'a> {
|
||||||
path_build_params: PathBuildParams { path_index, view_box, built_options, scene },
|
path_build_params: PathBuildParams { path_index, view_box, built_options, scene },
|
||||||
paint_metadata,
|
paint_metadata,
|
||||||
opacity_tile_page,
|
opacity_tile_page,
|
||||||
opacity_tile_transform,
|
|
||||||
built_clip_paths,
|
built_clip_paths,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
|
@ -204,10 +202,9 @@ impl<'a> SceneBuilder<'a> {
|
||||||
path_object.fill_rule(),
|
path_object.fill_rule(),
|
||||||
view_box,
|
view_box,
|
||||||
TilingPathInfo::Draw(DrawTilingPathInfo {
|
TilingPathInfo::Draw(DrawTilingPathInfo {
|
||||||
|
paint_id,
|
||||||
paint_metadata,
|
paint_metadata,
|
||||||
opacity_tile_transform,
|
|
||||||
blend_mode: path_object.blend_mode(),
|
blend_mode: path_object.blend_mode(),
|
||||||
opacity: path_object.opacity(),
|
|
||||||
built_clip_path,
|
built_clip_path,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -444,7 +441,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for alpha_tile in alpha_tiles {
|
for alpha_tile in alpha_tiles {
|
||||||
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
let alpha_tile_coords = alpha_tile.tile_position();
|
||||||
if layer_z_buffer.test(alpha_tile_coords, current_depth) {
|
if layer_z_buffer.test(alpha_tile_coords, current_depth) {
|
||||||
culled_alpha_tiles.push(*alpha_tile);
|
culled_alpha_tiles.push(*alpha_tile);
|
||||||
}
|
}
|
||||||
|
@ -452,6 +449,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pack_tiles(&mut self, culled_tiles: CulledTiles) {
|
fn pack_tiles(&mut self, culled_tiles: CulledTiles) {
|
||||||
|
self.listener.send(RenderCommand::BeginTileDrawing);
|
||||||
for display_item in culled_tiles.display_list {
|
for display_item in culled_tiles.display_list {
|
||||||
match display_item {
|
match display_item {
|
||||||
CulledDisplayItem::DrawTiles(batch) => {
|
CulledDisplayItem::DrawTiles(batch) => {
|
||||||
|
@ -509,7 +507,6 @@ struct DrawPathBuildParams<'a> {
|
||||||
path_build_params: PathBuildParams<'a>,
|
path_build_params: PathBuildParams<'a>,
|
||||||
paint_metadata: &'a [PaintMetadata],
|
paint_metadata: &'a [PaintMetadata],
|
||||||
opacity_tile_page: TexturePageId,
|
opacity_tile_page: TexturePageId,
|
||||||
opacity_tile_transform: Transform2F,
|
|
||||||
built_clip_paths: &'a [BuiltPath],
|
built_clip_paths: &'a [BuiltPath],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,8 +519,7 @@ impl BuiltPath {
|
||||||
let occludes = match *tiling_path_info {
|
let occludes = match *tiling_path_info {
|
||||||
TilingPathInfo::Draw(ref draw_tiling_path_info) => {
|
TilingPathInfo::Draw(ref draw_tiling_path_info) => {
|
||||||
draw_tiling_path_info.paint_metadata.is_opaque &&
|
draw_tiling_path_info.paint_metadata.is_opaque &&
|
||||||
draw_tiling_path_info.blend_mode.occludes_backdrop() &&
|
draw_tiling_path_info.blend_mode.occludes_backdrop()
|
||||||
draw_tiling_path_info.opacity == !0
|
|
||||||
}
|
}
|
||||||
TilingPathInfo::Clip => true,
|
TilingPathInfo::Clip => true,
|
||||||
};
|
};
|
||||||
|
@ -769,74 +765,42 @@ impl<'a> PackedTile<'a> {
|
||||||
tiles: &mut Vec<Tile>,
|
tiles: &mut Vec<Tile>,
|
||||||
draw_tiling_path_info: &DrawTilingPathInfo) {
|
draw_tiling_path_info: &DrawTilingPathInfo) {
|
||||||
let fill_tile_index = self.draw_tile.alpha_tile_index as u16;
|
let fill_tile_index = self.draw_tile.alpha_tile_index as u16;
|
||||||
let fill_tile_backdrop = self.draw_tile.backdrop as i16;
|
let fill_tile_backdrop = self.draw_tile.backdrop as i8;
|
||||||
let (clip_tile_index, clip_tile_backdrop) = match self.clip_tile {
|
let (clip_tile_index, clip_tile_backdrop) = match self.clip_tile {
|
||||||
None => (0, 0),
|
None => (0, 0),
|
||||||
Some(clip_tile) => (clip_tile.alpha_tile_index as u16, clip_tile.backdrop as i16),
|
Some(clip_tile) => (clip_tile.alpha_tile_index as u16, clip_tile.backdrop as i8),
|
||||||
};
|
};
|
||||||
|
|
||||||
tiles.push(Tile {
|
tiles.push(Tile::new_alpha(self.tile_coords,
|
||||||
upper_left: TileVertex::new_alpha(self.tile_coords,
|
|
||||||
fill_tile_index,
|
fill_tile_index,
|
||||||
fill_tile_backdrop,
|
fill_tile_backdrop,
|
||||||
clip_tile_index,
|
clip_tile_index,
|
||||||
clip_tile_backdrop,
|
clip_tile_backdrop,
|
||||||
Vector2I::zero(),
|
draw_tiling_path_info));
|
||||||
draw_tiling_path_info),
|
|
||||||
upper_right: TileVertex::new_alpha(self.tile_coords,
|
|
||||||
fill_tile_index,
|
|
||||||
fill_tile_backdrop,
|
|
||||||
clip_tile_index,
|
|
||||||
clip_tile_backdrop,
|
|
||||||
vec2i(1, 0),
|
|
||||||
draw_tiling_path_info),
|
|
||||||
lower_left: TileVertex::new_alpha(self.tile_coords,
|
|
||||||
fill_tile_index,
|
|
||||||
fill_tile_backdrop,
|
|
||||||
clip_tile_index,
|
|
||||||
clip_tile_backdrop,
|
|
||||||
vec2i(0, 1),
|
|
||||||
draw_tiling_path_info),
|
|
||||||
lower_right: TileVertex::new_alpha(self.tile_coords,
|
|
||||||
fill_tile_index,
|
|
||||||
fill_tile_backdrop,
|
|
||||||
clip_tile_index,
|
|
||||||
clip_tile_backdrop,
|
|
||||||
vec2i(1, 1),
|
|
||||||
draw_tiling_path_info),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TileVertex {
|
impl Tile {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new_alpha(tile_origin: Vector2I,
|
fn new_alpha(tile_origin: Vector2I,
|
||||||
draw_tile_index: u16,
|
draw_tile_index: u16,
|
||||||
draw_tile_backdrop: i16,
|
draw_tile_backdrop: i8,
|
||||||
clip_tile_index: u16,
|
clip_tile_index: u16,
|
||||||
clip_tile_backdrop: i16,
|
clip_tile_backdrop: i8,
|
||||||
tile_offset: Vector2I,
|
|
||||||
draw_tiling_path_info: &DrawTilingPathInfo)
|
draw_tiling_path_info: &DrawTilingPathInfo)
|
||||||
-> TileVertex {
|
-> Tile {
|
||||||
// TODO(pcwalton): Opacity.
|
let mask_0_uv = calculate_mask_uv(draw_tile_index);
|
||||||
let tile_position = tile_origin + tile_offset;
|
let mask_1_uv = calculate_mask_uv(clip_tile_index);
|
||||||
let color_0_uv = draw_tiling_path_info.paint_metadata.calculate_tex_coords(tile_position);
|
Tile {
|
||||||
let color_1_uv = calculate_opacity_uv(draw_tiling_path_info);
|
tile_x: tile_origin.x() as i16,
|
||||||
let mask_0_uv = calculate_mask_uv(draw_tile_index, tile_offset);
|
tile_y: tile_origin.y() as i16,
|
||||||
let mask_1_uv = calculate_mask_uv(clip_tile_index, tile_offset);
|
mask_0_u: mask_0_uv.x() as u8,
|
||||||
TileVertex {
|
mask_0_v: mask_0_uv.y() as u8,
|
||||||
tile_x: tile_position.x() as i16,
|
mask_1_u: mask_1_uv.x() as u8,
|
||||||
tile_y: tile_position.y() as i16,
|
mask_1_v: mask_1_uv.y() as u8,
|
||||||
color_0_u: color_0_uv.x(),
|
|
||||||
color_0_v: color_0_uv.y(),
|
|
||||||
color_1_u: color_1_uv.x(),
|
|
||||||
color_1_v: color_1_uv.y(),
|
|
||||||
mask_0_u: mask_0_uv.x(),
|
|
||||||
mask_0_v: mask_0_uv.y(),
|
|
||||||
mask_1_u: mask_1_uv.x(),
|
|
||||||
mask_1_v: mask_1_uv.y(),
|
|
||||||
mask_0_backdrop: draw_tile_backdrop,
|
mask_0_backdrop: draw_tile_backdrop,
|
||||||
mask_1_backdrop: clip_tile_backdrop,
|
mask_1_backdrop: clip_tile_backdrop,
|
||||||
|
color: draw_tiling_path_info.paint_id.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,16 +810,9 @@ impl TileVertex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_mask_uv(tile_index: u16, tile_offset: Vector2I) -> Vector2F {
|
fn calculate_mask_uv(tile_index: u16) -> Vector2I {
|
||||||
|
debug_assert_eq!(MASK_TILES_ACROSS, MASK_TILES_DOWN);
|
||||||
let mask_u = tile_index as i32 % MASK_TILES_ACROSS as i32;
|
let mask_u = tile_index as i32 % MASK_TILES_ACROSS as i32;
|
||||||
let mask_v = tile_index as i32 / MASK_TILES_ACROSS as i32;
|
let mask_v = tile_index as i32 / MASK_TILES_ACROSS as i32;
|
||||||
let scale = vec2f(1.0 / MASK_TILES_ACROSS as f32, 1.0 / MASK_TILES_DOWN as f32);
|
vec2i(mask_u, mask_v)
|
||||||
(vec2i(mask_u, mask_v) + tile_offset).to_f32() * scale
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_opacity_uv(draw_tiling_path_info: &DrawTilingPathInfo) -> Vector2F {
|
|
||||||
let DrawTilingPathInfo { opacity_tile_transform, opacity, .. } = *draw_tiling_path_info;
|
|
||||||
let texel_coord = (vec2i((opacity % 16) as i32, (opacity / 16) as i32).to_f32() +
|
|
||||||
vec2f(0.5, 0.5)) * (1.0 / 16.0);
|
|
||||||
opacity_tile_transform * texel_coord
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,26 +144,13 @@ where
|
||||||
let mean_gpu_sample = self.gpu_samples.mean();
|
let mean_gpu_sample = self.gpu_samples.mean();
|
||||||
self.ui_presenter.draw_text(
|
self.ui_presenter.draw_text(
|
||||||
device,
|
device,
|
||||||
&format!(
|
&format!("GPU: {:.3} ms", duration_to_ms(mean_gpu_sample.time.time)),
|
||||||
"Stage 0 GPU: {:.3} ms",
|
|
||||||
duration_to_ms(mean_gpu_sample.time.stage_0)
|
|
||||||
),
|
|
||||||
origin + vec2i(0, LINE_HEIGHT * 1),
|
origin + vec2i(0, LINE_HEIGHT * 1),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
self.ui_presenter.draw_text(
|
|
||||||
device,
|
|
||||||
&format!(
|
|
||||||
"Stage 1 GPU: {:.3} ms",
|
|
||||||
duration_to_ms(mean_gpu_sample.time.stage_1)
|
|
||||||
),
|
|
||||||
origin + vec2i(0, LINE_HEIGHT * 2),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let wallclock_time = f64::max(duration_to_ms(mean_gpu_sample.time.stage_0),
|
let wallclock_time = f64::max(duration_to_ms(mean_gpu_sample.time.time),
|
||||||
duration_to_ms(mean_cpu_sample.elapsed)) +
|
duration_to_ms(mean_cpu_sample.elapsed));
|
||||||
duration_to_ms(mean_gpu_sample.time.stage_1);
|
|
||||||
self.ui_presenter.draw_text(
|
self.ui_presenter.draw_text(
|
||||||
device,
|
device,
|
||||||
&format!("Wallclock: {:.3} ms", wallclock_time),
|
&format!("Wallclock: {:.3} ms", wallclock_time),
|
||||||
|
@ -255,12 +242,7 @@ impl Add<GPUSample> for GPUSample {
|
||||||
impl Div<usize> for GPUSample {
|
impl Div<usize> for GPUSample {
|
||||||
type Output = GPUSample;
|
type Output = GPUSample;
|
||||||
fn div(self, divisor: usize) -> GPUSample {
|
fn div(self, divisor: usize) -> GPUSample {
|
||||||
GPUSample {
|
GPUSample { time: RenderTime { time: self.time.time / divisor as u32 } }
|
||||||
time: RenderTime {
|
|
||||||
stage_0: self.time.stage_0 / (divisor as u32),
|
|
||||||
stage_1: self.time.stage_1 / (divisor as u32),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,11 @@ use crate::gpu::shaders::{BlitProgram, BlitVertexArray, CopyTileProgram, CopyTil
|
||||||
use crate::gpu::shaders::{FillProgram, FillVertexArray, MAX_FILLS_PER_BATCH, ReprojectionProgram};
|
use crate::gpu::shaders::{FillProgram, FillVertexArray, MAX_FILLS_PER_BATCH, ReprojectionProgram};
|
||||||
use crate::gpu::shaders::{ReprojectionVertexArray, StencilProgram, StencilVertexArray};
|
use crate::gpu::shaders::{ReprojectionVertexArray, StencilProgram, StencilVertexArray};
|
||||||
use crate::gpu::shaders::{TileProgram, TileVertexArray};
|
use crate::gpu::shaders::{TileProgram, TileVertexArray};
|
||||||
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TextureLocation, TexturePageDescriptor};
|
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TextureLocation, TextureMetadataEntry};
|
||||||
use crate::gpu_data::{TexturePageId, Tile, TileBatchTexture};
|
use crate::gpu_data::{TexturePageDescriptor, TexturePageId, Tile, TileBatchTexture};
|
||||||
use crate::options::BoundingQuad;
|
use crate::options::BoundingQuad;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
|
use half::f16;
|
||||||
use pathfinder_color::{self as color, ColorF, ColorU};
|
use pathfinder_color::{self as color, ColorF, ColorU};
|
||||||
use pathfinder_content::effects::{BlendMode, BlurDirection, DefringingKernel};
|
use pathfinder_content::effects::{BlendMode, BlurDirection, DefringingKernel};
|
||||||
use pathfinder_content::effects::{Filter, PatternFilter};
|
use pathfinder_content::effects::{Filter, PatternFilter};
|
||||||
|
@ -26,13 +27,14 @@ use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
use pathfinder_geometry::rect::RectI;
|
use pathfinder_geometry::rect::RectI;
|
||||||
use pathfinder_geometry::transform3d::Transform4F;
|
use pathfinder_geometry::transform3d::Transform4F;
|
||||||
|
use pathfinder_geometry::util;
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F, vec2f, vec2i};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F, vec2f, vec2i};
|
||||||
use pathfinder_gpu::{BlendFactor, BlendState, BufferData, BufferTarget, BufferUploadMode};
|
use pathfinder_gpu::{BlendFactor, BlendState, BufferData, BufferTarget, BufferUploadMode};
|
||||||
use pathfinder_gpu::{ClearOps, DepthFunc, DepthState, Device, Primitive, RenderOptions};
|
use pathfinder_gpu::{ClearOps, DepthFunc, DepthState, Device, Primitive, RenderOptions};
|
||||||
use pathfinder_gpu::{RenderState, RenderTarget, StencilFunc, StencilState, TextureDataRef};
|
use pathfinder_gpu::{RenderState, RenderTarget, StencilFunc, StencilState, TextureDataRef};
|
||||||
use pathfinder_gpu::{TextureFormat, UniformData};
|
use pathfinder_gpu::{TextureFormat, UniformData};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_simd::default::{F32x2, F32x4};
|
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
|
@ -51,6 +53,11 @@ pub(crate) const MASK_TILES_DOWN: u32 = 256;
|
||||||
const SQRT_2_PI_INV: f32 = 0.3989422804014327;
|
const SQRT_2_PI_INV: f32 = 0.3989422804014327;
|
||||||
|
|
||||||
const TEXTURE_CACHE_SIZE: usize = 8;
|
const TEXTURE_CACHE_SIZE: usize = 8;
|
||||||
|
const TIMER_QUERY_CACHE_SIZE: usize = 8;
|
||||||
|
|
||||||
|
const TEXTURE_METADATA_ENTRIES_PER_ROW: i32 = 256;
|
||||||
|
const TEXTURE_METADATA_TEXTURE_WIDTH: i32 = TEXTURE_METADATA_ENTRIES_PER_ROW * 2;
|
||||||
|
const TEXTURE_METADATA_TEXTURE_HEIGHT: i32 = 65536 / TEXTURE_METADATA_ENTRIES_PER_ROW;
|
||||||
|
|
||||||
// FIXME(pcwalton): Shrink this again!
|
// FIXME(pcwalton): Shrink this again!
|
||||||
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
|
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
|
||||||
|
@ -106,7 +113,6 @@ where
|
||||||
blit_vertex_array: BlitVertexArray<D>,
|
blit_vertex_array: BlitVertexArray<D>,
|
||||||
tile_vertex_array: TileVertexArray<D>,
|
tile_vertex_array: TileVertexArray<D>,
|
||||||
tile_copy_vertex_array: CopyTileVertexArray<D>,
|
tile_copy_vertex_array: CopyTileVertexArray<D>,
|
||||||
area_lut_texture: D::Texture,
|
|
||||||
tile_vertex_buffer: D::Buffer,
|
tile_vertex_buffer: D::Buffer,
|
||||||
quad_vertex_positions_buffer: D::Buffer,
|
quad_vertex_positions_buffer: D::Buffer,
|
||||||
quad_vertex_indices_buffer: D::Buffer,
|
quad_vertex_indices_buffer: D::Buffer,
|
||||||
|
@ -119,7 +125,8 @@ where
|
||||||
texture_pages: Vec<TexturePage<D>>,
|
texture_pages: Vec<TexturePage<D>>,
|
||||||
render_targets: Vec<RenderTargetInfo>,
|
render_targets: Vec<RenderTargetInfo>,
|
||||||
render_target_stack: Vec<RenderTargetId>,
|
render_target_stack: Vec<RenderTargetId>,
|
||||||
|
texture_metadata_texture: D::Texture,
|
||||||
|
area_lut_texture: D::Texture,
|
||||||
gamma_lut_texture: D::Texture,
|
gamma_lut_texture: D::Texture,
|
||||||
|
|
||||||
// Stencil shader
|
// Stencil shader
|
||||||
|
@ -137,8 +144,8 @@ where
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
pub stats: RenderStats,
|
pub stats: RenderStats,
|
||||||
current_timers: RenderTimers<D>,
|
current_timer: Option<D::TimerQuery>,
|
||||||
pending_timers: VecDeque<RenderTimers<D>>,
|
pending_timers: VecDeque<D::TimerQuery>,
|
||||||
free_timer_queries: Vec<D::TimerQuery>,
|
free_timer_queries: Vec<D::TimerQuery>,
|
||||||
pub debug_ui_presenter: DebugUIPresenter<D>,
|
pub debug_ui_presenter: DebugUIPresenter<D>,
|
||||||
|
|
||||||
|
@ -165,6 +172,10 @@ where
|
||||||
let area_lut_texture = device.create_texture_from_png(resources, "area-lut");
|
let area_lut_texture = device.create_texture_from_png(resources, "area-lut");
|
||||||
let gamma_lut_texture = device.create_texture_from_png(resources, "gamma-lut");
|
let gamma_lut_texture = device.create_texture_from_png(resources, "gamma-lut");
|
||||||
|
|
||||||
|
let texture_metadata_texture = device.create_texture(
|
||||||
|
TextureFormat::RGBA16F,
|
||||||
|
Vector2I::new(TEXTURE_METADATA_TEXTURE_WIDTH, TEXTURE_METADATA_TEXTURE_HEIGHT));
|
||||||
|
|
||||||
let quad_vertex_positions_buffer = device.create_buffer();
|
let quad_vertex_positions_buffer = device.create_buffer();
|
||||||
device.allocate_buffer(
|
device.allocate_buffer(
|
||||||
&quad_vertex_positions_buffer,
|
&quad_vertex_positions_buffer,
|
||||||
|
@ -198,7 +209,8 @@ where
|
||||||
&device,
|
&device,
|
||||||
&tile_program,
|
&tile_program,
|
||||||
&tile_vertex_buffer,
|
&tile_vertex_buffer,
|
||||||
&quads_vertex_indices_buffer,
|
&quad_vertex_positions_buffer,
|
||||||
|
&quad_vertex_indices_buffer,
|
||||||
);
|
);
|
||||||
let tile_copy_vertex_array = CopyTileVertexArray::new(
|
let tile_copy_vertex_array = CopyTileVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
|
@ -225,6 +237,11 @@ where
|
||||||
let intermediate_dest_texture = device.create_texture(TextureFormat::RGBA8, window_size);
|
let intermediate_dest_texture = device.create_texture(TextureFormat::RGBA8, window_size);
|
||||||
let intermediate_dest_framebuffer = device.create_framebuffer(intermediate_dest_texture);
|
let intermediate_dest_framebuffer = device.create_framebuffer(intermediate_dest_texture);
|
||||||
|
|
||||||
|
let mut timer_queries = vec![];
|
||||||
|
for _ in 0..TIMER_QUERY_CACHE_SIZE {
|
||||||
|
timer_queries.push(device.create_timer_query());
|
||||||
|
}
|
||||||
|
|
||||||
let debug_ui_presenter = DebugUIPresenter::new(&device, resources, window_size);
|
let debug_ui_presenter = DebugUIPresenter::new(&device, resources, window_size);
|
||||||
|
|
||||||
Renderer {
|
Renderer {
|
||||||
|
@ -239,7 +256,6 @@ where
|
||||||
blit_vertex_array,
|
blit_vertex_array,
|
||||||
tile_vertex_array,
|
tile_vertex_array,
|
||||||
tile_copy_vertex_array,
|
tile_copy_vertex_array,
|
||||||
area_lut_texture,
|
|
||||||
tile_vertex_buffer,
|
tile_vertex_buffer,
|
||||||
quad_vertex_positions_buffer,
|
quad_vertex_positions_buffer,
|
||||||
quad_vertex_indices_buffer,
|
quad_vertex_indices_buffer,
|
||||||
|
@ -253,7 +269,9 @@ where
|
||||||
render_targets: vec![],
|
render_targets: vec![],
|
||||||
render_target_stack: vec![],
|
render_target_stack: vec![],
|
||||||
|
|
||||||
|
area_lut_texture,
|
||||||
gamma_lut_texture,
|
gamma_lut_texture,
|
||||||
|
texture_metadata_texture,
|
||||||
|
|
||||||
stencil_program,
|
stencil_program,
|
||||||
stencil_vertex_array,
|
stencil_vertex_array,
|
||||||
|
@ -262,9 +280,9 @@ where
|
||||||
reprojection_vertex_array,
|
reprojection_vertex_array,
|
||||||
|
|
||||||
stats: RenderStats::default(),
|
stats: RenderStats::default(),
|
||||||
current_timers: RenderTimers::new(),
|
current_timer: None,
|
||||||
pending_timers: VecDeque::new(),
|
pending_timers: VecDeque::new(),
|
||||||
free_timer_queries: vec![],
|
free_timer_queries: timer_queries,
|
||||||
debug_ui_presenter,
|
debug_ui_presenter,
|
||||||
|
|
||||||
framebuffer_flags: FramebufferFlags::empty(),
|
framebuffer_flags: FramebufferFlags::empty(),
|
||||||
|
@ -295,11 +313,12 @@ where
|
||||||
RenderCommand::DeclareRenderTarget { id, location } => {
|
RenderCommand::DeclareRenderTarget { id, location } => {
|
||||||
self.declare_render_target(id, location)
|
self.declare_render_target(id, location)
|
||||||
}
|
}
|
||||||
RenderCommand::AddFills(ref fills) => self.add_fills(fills),
|
RenderCommand::UploadTextureMetadata(ref metadata) => {
|
||||||
RenderCommand::FlushFills => {
|
self.upload_texture_metadata(metadata)
|
||||||
self.draw_buffered_fills();
|
|
||||||
self.begin_composite_timer_query();
|
|
||||||
}
|
}
|
||||||
|
RenderCommand::AddFills(ref fills) => self.add_fills(fills),
|
||||||
|
RenderCommand::FlushFills => self.draw_buffered_fills(),
|
||||||
|
RenderCommand::BeginTileDrawing => self.begin_tile_drawing(),
|
||||||
RenderCommand::PushRenderTarget(render_target_id) => {
|
RenderCommand::PushRenderTarget(render_target_id) => {
|
||||||
self.push_render_target(render_target_id)
|
self.push_render_target(render_target_id)
|
||||||
}
|
}
|
||||||
|
@ -320,13 +339,22 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn begin_tile_drawing(&mut self) {
|
||||||
|
if let Some(timer_query) = self.allocate_timer_query() {
|
||||||
|
self.device.begin_timer_query(&timer_query);
|
||||||
|
self.current_timer = Some(timer_query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn end_scene(&mut self) {
|
pub fn end_scene(&mut self) {
|
||||||
self.blit_intermediate_dest_framebuffer_if_necessary();
|
self.blit_intermediate_dest_framebuffer_if_necessary();
|
||||||
|
|
||||||
self.end_composite_timer_query();
|
|
||||||
self.pending_timers.push_back(mem::replace(&mut self.current_timers, RenderTimers::new()));
|
|
||||||
|
|
||||||
self.device.end_commands();
|
self.device.end_commands();
|
||||||
|
|
||||||
|
if let Some(timer_query) = self.current_timer.take() {
|
||||||
|
self.device.end_timer_query(&timer_query);
|
||||||
|
self.pending_timers.push_back(timer_query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_rendering(&mut self,
|
fn start_rendering(&mut self,
|
||||||
|
@ -351,32 +379,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift_rendering_time(&mut self) -> Option<RenderTime> {
|
pub fn shift_rendering_time(&mut self) -> Option<RenderTime> {
|
||||||
let timers = self.pending_timers.front()?;
|
if let Some(query) = self.pending_timers.pop_front() {
|
||||||
|
if let Some(time) = self.device.try_recv_timer_query(&query) {
|
||||||
// Accumulate stage-0 time.
|
self.free_timer_queries.push(query);
|
||||||
let mut total_stage_0_time = Duration::new(0, 0);
|
return Some(RenderTime { time });
|
||||||
for timer_query in &timers.stage_0 {
|
|
||||||
match self.device.try_recv_timer_query(timer_query) {
|
|
||||||
None => return None,
|
|
||||||
Some(stage_0_time) => total_stage_0_time += stage_0_time,
|
|
||||||
}
|
}
|
||||||
|
self.pending_timers.push_front(query);
|
||||||
}
|
}
|
||||||
|
None
|
||||||
// Get stage-1 time.
|
|
||||||
let stage_1_time = {
|
|
||||||
let stage_1_timer_query = timers.stage_1.as_ref().unwrap();
|
|
||||||
match self.device.try_recv_timer_query(stage_1_timer_query) {
|
|
||||||
None => return None,
|
|
||||||
Some(query) => query,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Recycle all timer queries.
|
|
||||||
let timers = self.pending_timers.pop_front().unwrap();
|
|
||||||
self.free_timer_queries.extend(timers.stage_0.into_iter());
|
|
||||||
self.free_timer_queries.push(timers.stage_1.unwrap());
|
|
||||||
|
|
||||||
Some(RenderTime { stage_0: total_stage_0_time, stage_1: stage_1_time })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -464,6 +474,34 @@ where
|
||||||
render_target.location = location;
|
render_target.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn upload_texture_metadata(&mut self, metadata: &[TextureMetadataEntry]) {
|
||||||
|
let padded_texel_size =
|
||||||
|
(util::alignup_i32(metadata.len() as i32, TEXTURE_METADATA_ENTRIES_PER_ROW) *
|
||||||
|
TEXTURE_METADATA_TEXTURE_WIDTH * 4) as usize;
|
||||||
|
let mut texels = Vec::with_capacity(padded_texel_size);
|
||||||
|
for entry in metadata {
|
||||||
|
texels.extend_from_slice(&[
|
||||||
|
f16::from_f32(entry.color_0_transform.m11()),
|
||||||
|
f16::from_f32(entry.color_0_transform.m21()),
|
||||||
|
f16::from_f32(entry.color_0_transform.m12()),
|
||||||
|
f16::from_f32(entry.color_0_transform.m22()),
|
||||||
|
f16::from_f32(entry.color_0_transform.m31()),
|
||||||
|
f16::from_f32(entry.color_0_transform.m32()),
|
||||||
|
f16::from_f32(entry.opacity),
|
||||||
|
f16::default(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
while texels.len() < padded_texel_size {
|
||||||
|
texels.push(f16::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
let texture = &mut self.texture_metadata_texture;
|
||||||
|
let width = TEXTURE_METADATA_TEXTURE_WIDTH;
|
||||||
|
let height = texels.len() as i32 / (4 * TEXTURE_METADATA_TEXTURE_WIDTH);
|
||||||
|
let rect = RectI::new(Vector2I::zero(), Vector2I::new(width, height));
|
||||||
|
self.device.upload_to_texture(texture, rect, TextureDataRef::F16(&texels));
|
||||||
|
}
|
||||||
|
|
||||||
fn upload_tiles(&mut self, tiles: &[Tile]) {
|
fn upload_tiles(&mut self, tiles: &[Tile]) {
|
||||||
self.device.allocate_buffer(&self.tile_vertex_buffer,
|
self.device.allocate_buffer(&self.tile_vertex_buffer,
|
||||||
BufferData::Memory(&tiles),
|
BufferData::Memory(&tiles),
|
||||||
|
@ -532,9 +570,6 @@ where
|
||||||
clear_color = Some(ColorF::default());
|
clear_color = Some(ColorF::default());
|
||||||
};
|
};
|
||||||
|
|
||||||
let timer_query = self.allocate_timer_query();
|
|
||||||
self.device.begin_timer_query(&timer_query);
|
|
||||||
|
|
||||||
debug_assert!(self.buffered_fills.len() <= u32::MAX as usize);
|
debug_assert!(self.buffered_fills.len() <= u32::MAX as usize);
|
||||||
self.device.draw_elements_instanced(6, self.buffered_fills.len() as u32, &RenderState {
|
self.device.draw_elements_instanced(6, self.buffered_fills.len() as u32, &RenderState {
|
||||||
target: &RenderTarget::Framebuffer(&self.fill_framebuffer),
|
target: &RenderTarget::Framebuffer(&self.fill_framebuffer),
|
||||||
|
@ -564,9 +599,6 @@ where
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
self.device.end_timer_query(&timer_query);
|
|
||||||
self.current_timers.stage_0.push(timer_query);
|
|
||||||
|
|
||||||
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS);
|
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS);
|
||||||
self.buffered_fills.clear();
|
self.buffered_fills.clear();
|
||||||
}
|
}
|
||||||
|
@ -607,7 +639,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut textures = vec![];
|
let mut textures = vec![&self.texture_metadata_texture];
|
||||||
let mut uniforms = vec![
|
let mut uniforms = vec![
|
||||||
(&self.tile_program.transform_uniform,
|
(&self.tile_program.transform_uniform,
|
||||||
UniformData::Mat4(self.tile_transform().to_columns())),
|
UniformData::Mat4(self.tile_transform().to_columns())),
|
||||||
|
@ -615,6 +647,10 @@ where
|
||||||
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
||||||
(&self.tile_program.framebuffer_size_uniform,
|
(&self.tile_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(draw_viewport.size().to_f32().0)),
|
UniformData::Vec2(draw_viewport.size().to_f32().0)),
|
||||||
|
(&self.tile_program.texture_metadata_uniform, UniformData::TextureUnit(0)),
|
||||||
|
(&self.tile_program.texture_metadata_size_uniform,
|
||||||
|
UniformData::IVec2(I32x2::new(TEXTURE_METADATA_TEXTURE_WIDTH,
|
||||||
|
TEXTURE_METADATA_TEXTURE_HEIGHT))),
|
||||||
];
|
];
|
||||||
|
|
||||||
if needs_readable_framebuffer {
|
if needs_readable_framebuffer {
|
||||||
|
@ -687,7 +723,7 @@ where
|
||||||
|
|
||||||
uniforms.push((&self.tile_program.ctrl_uniform, UniformData::Int(ctrl)));
|
uniforms.push((&self.tile_program.ctrl_uniform, UniformData::Int(ctrl)));
|
||||||
|
|
||||||
self.device.draw_elements(tile_count * 6, &RenderState {
|
self.device.draw_elements_instanced(6, tile_count, &RenderState {
|
||||||
target: &self.draw_render_target(),
|
target: &self.draw_render_target(),
|
||||||
program: &self.tile_program.program,
|
program: &self.tile_program.program,
|
||||||
vertex_array: &self.tile_vertex_array.vertex_array,
|
vertex_array: &self.tile_vertex_array.vertex_array,
|
||||||
|
@ -1036,23 +1072,8 @@ where
|
||||||
self.device.framebuffer_texture(&self.texture_page_framebuffer(id))
|
self.device.framebuffer_texture(&self.texture_page_framebuffer(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_timer_query(&mut self) -> D::TimerQuery {
|
fn allocate_timer_query(&mut self) -> Option<D::TimerQuery> {
|
||||||
match self.free_timer_queries.pop() {
|
self.free_timer_queries.pop()
|
||||||
Some(query) => query,
|
|
||||||
None => self.device.create_timer_query(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn begin_composite_timer_query(&mut self) {
|
|
||||||
let timer_query = self.allocate_timer_query();
|
|
||||||
self.device.begin_timer_query(&timer_query);
|
|
||||||
self.current_timers.stage_1 = Some(timer_query);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end_composite_timer_query(&mut self) {
|
|
||||||
if let Some(ref query) = self.current_timers.stage_1 {
|
|
||||||
self.device.end_timer_query(query);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,27 +1111,15 @@ impl Div<usize> for RenderStats {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RenderTimers<D> where D: Device {
|
|
||||||
stage_0: Vec<D::TimerQuery>,
|
|
||||||
stage_1: Option<D::TimerQuery>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> RenderTimers<D> where D: Device {
|
|
||||||
fn new() -> RenderTimers<D> {
|
|
||||||
RenderTimers { stage_0: vec![], stage_1: None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct RenderTime {
|
pub struct RenderTime {
|
||||||
pub stage_0: Duration,
|
pub time: Duration,
|
||||||
pub stage_1: Duration,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RenderTime {
|
impl Default for RenderTime {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> RenderTime {
|
fn default() -> RenderTime {
|
||||||
RenderTime { stage_0: Duration::new(0, 0), stage_1: Duration::new(0, 0) }
|
RenderTime { time: Duration::new(0, 0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,10 +1128,7 @@ impl Add<RenderTime> for RenderTime {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self, other: RenderTime) -> RenderTime {
|
fn add(self, other: RenderTime) -> RenderTime {
|
||||||
RenderTime {
|
RenderTime { time: self.time + other.time }
|
||||||
stage_0: self.stage_0 + other.stage_0,
|
|
||||||
stage_1: self.stage_1 + other.stage_1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ use pathfinder_resources::ResourceLoader;
|
||||||
|
|
||||||
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
||||||
const FILL_INSTANCE_SIZE: usize = 8;
|
const FILL_INSTANCE_SIZE: usize = 8;
|
||||||
const TILE_VERTEX_SIZE: usize = 40;
|
const TILE_INSTANCE_SIZE: usize = 12;
|
||||||
|
|
||||||
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
||||||
|
|
||||||
|
@ -155,83 +155,80 @@ impl<D> TileVertexArray<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub fn new(device: &D,
|
||||||
tile_program: &TileProgram<D>,
|
tile_program: &TileProgram<D>,
|
||||||
tile_vertex_buffer: &D::Buffer,
|
tile_vertex_buffer: &D::Buffer,
|
||||||
quads_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> TileVertexArray<D> {
|
-> TileVertexArray<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
|
|
||||||
let tile_position_attr =
|
let tile_offset_attr =
|
||||||
device.get_vertex_attr(&tile_program.program, "TilePosition").unwrap();
|
device.get_vertex_attr(&tile_program.program, "TileOffset").unwrap();
|
||||||
let color_0_tex_coord_attr =
|
let tile_origin_attr =
|
||||||
device.get_vertex_attr(&tile_program.program, "ColorTexCoord0").unwrap();
|
device.get_vertex_attr(&tile_program.program, "TileOrigin").unwrap();
|
||||||
let color_1_tex_coord_attr =
|
|
||||||
device.get_vertex_attr(&tile_program.program, "ColorTexCoord1").unwrap();
|
|
||||||
let mask_0_tex_coord_attr =
|
let mask_0_tex_coord_attr =
|
||||||
device.get_vertex_attr(&tile_program.program, "MaskTexCoord0").unwrap();
|
device.get_vertex_attr(&tile_program.program, "MaskTexCoord0").unwrap();
|
||||||
let mask_1_tex_coord_attr =
|
let mask_1_tex_coord_attr =
|
||||||
device.get_vertex_attr(&tile_program.program, "MaskTexCoord1").unwrap();
|
device.get_vertex_attr(&tile_program.program, "MaskTexCoord1").unwrap();
|
||||||
let mask_backdrop_attr =
|
let mask_backdrop_attr =
|
||||||
device.get_vertex_attr(&tile_program.program, "MaskBackdrop").unwrap();
|
device.get_vertex_attr(&tile_program.program, "MaskBackdrop").unwrap();
|
||||||
|
let color_attr = device.get_vertex_attr(&tile_program.program, "Color").unwrap();
|
||||||
|
|
||||||
device.bind_buffer(&vertex_array, tile_vertex_buffer, BufferTarget::Vertex);
|
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
||||||
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
device.configure_vertex_attr(&vertex_array, &tile_offset_attr, &VertexAttrDescriptor {
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::I16,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: TILE_VERTEX_SIZE,
|
stride: 4,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
divisor: 0,
|
divisor: 0,
|
||||||
buffer_index: 0,
|
buffer_index: 0,
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array,
|
device.bind_buffer(&vertex_array, tile_vertex_buffer, BufferTarget::Vertex);
|
||||||
&color_0_tex_coord_attr,
|
device.configure_vertex_attr(&vertex_array, &tile_origin_attr, &VertexAttrDescriptor {
|
||||||
&VertexAttrDescriptor {
|
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Float,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::F32,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: TILE_VERTEX_SIZE,
|
stride: TILE_INSTANCE_SIZE,
|
||||||
offset: 4,
|
offset: 0,
|
||||||
divisor: 0,
|
divisor: 1,
|
||||||
buffer_index: 0,
|
buffer_index: 1,
|
||||||
});
|
|
||||||
device.configure_vertex_attr(&vertex_array,
|
|
||||||
&color_1_tex_coord_attr,
|
|
||||||
&VertexAttrDescriptor {
|
|
||||||
size: 2,
|
|
||||||
class: VertexAttrClass::Float,
|
|
||||||
attr_type: VertexAttrType::F32,
|
|
||||||
stride: TILE_VERTEX_SIZE,
|
|
||||||
offset: 12,
|
|
||||||
divisor: 0,
|
|
||||||
buffer_index: 0,
|
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array, &mask_0_tex_coord_attr, &VertexAttrDescriptor {
|
device.configure_vertex_attr(&vertex_array, &mask_0_tex_coord_attr, &VertexAttrDescriptor {
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Float,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::F32,
|
attr_type: VertexAttrType::U8,
|
||||||
stride: TILE_VERTEX_SIZE,
|
stride: TILE_INSTANCE_SIZE,
|
||||||
offset: 20,
|
offset: 4,
|
||||||
divisor: 0,
|
divisor: 1,
|
||||||
buffer_index: 0,
|
buffer_index: 1,
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array, &mask_1_tex_coord_attr, &VertexAttrDescriptor {
|
device.configure_vertex_attr(&vertex_array, &mask_1_tex_coord_attr, &VertexAttrDescriptor {
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Float,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::F32,
|
attr_type: VertexAttrType::U8,
|
||||||
stride: TILE_VERTEX_SIZE,
|
stride: TILE_INSTANCE_SIZE,
|
||||||
offset: 28,
|
offset: 6,
|
||||||
divisor: 0,
|
divisor: 1,
|
||||||
buffer_index: 0,
|
buffer_index: 1,
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array, &mask_backdrop_attr, &VertexAttrDescriptor {
|
device.configure_vertex_attr(&vertex_array, &mask_backdrop_attr, &VertexAttrDescriptor {
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::I16,
|
attr_type: VertexAttrType::I8,
|
||||||
stride: TILE_VERTEX_SIZE,
|
stride: TILE_INSTANCE_SIZE,
|
||||||
offset: 36,
|
offset: 8,
|
||||||
divisor: 0,
|
divisor: 1,
|
||||||
buffer_index: 0,
|
buffer_index: 1,
|
||||||
});
|
});
|
||||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
device.configure_vertex_attr(&vertex_array, &color_attr, &VertexAttrDescriptor {
|
||||||
|
size: 1,
|
||||||
|
class: VertexAttrClass::Int,
|
||||||
|
attr_type: VertexAttrType::I16,
|
||||||
|
stride: TILE_INSTANCE_SIZE,
|
||||||
|
offset: 10,
|
||||||
|
divisor: 1,
|
||||||
|
buffer_index: 1,
|
||||||
|
});
|
||||||
|
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
|
||||||
|
|
||||||
TileVertexArray { vertex_array }
|
TileVertexArray { vertex_array }
|
||||||
}
|
}
|
||||||
|
@ -258,7 +255,7 @@ impl<D> CopyTileVertexArray<D> where D: Device {
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::I16,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: TILE_VERTEX_SIZE,
|
stride: TILE_INSTANCE_SIZE,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
divisor: 0,
|
divisor: 0,
|
||||||
buffer_index: 0,
|
buffer_index: 0,
|
||||||
|
@ -314,6 +311,8 @@ pub struct TileProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub transform_uniform: D::Uniform,
|
pub transform_uniform: D::Uniform,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub tile_size_uniform: D::Uniform,
|
||||||
|
pub texture_metadata_uniform: D::Uniform,
|
||||||
|
pub texture_metadata_size_uniform: D::Uniform,
|
||||||
pub dest_texture_uniform: D::Uniform,
|
pub dest_texture_uniform: D::Uniform,
|
||||||
pub color_texture_0_uniform: D::Uniform,
|
pub color_texture_0_uniform: D::Uniform,
|
||||||
pub color_texture_1_uniform: D::Uniform,
|
pub color_texture_1_uniform: D::Uniform,
|
||||||
|
@ -333,6 +332,8 @@ impl<D> TileProgram<D> where D: Device {
|
||||||
let program = device.create_program(resources, "tile");
|
let program = device.create_program(resources, "tile");
|
||||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||||
|
let texture_metadata_uniform = device.get_uniform(&program, "TextureMetadata");
|
||||||
|
let texture_metadata_size_uniform = device.get_uniform(&program, "TextureMetadataSize");
|
||||||
let dest_texture_uniform = device.get_uniform(&program, "DestTexture");
|
let dest_texture_uniform = device.get_uniform(&program, "DestTexture");
|
||||||
let color_texture_0_uniform = device.get_uniform(&program, "ColorTexture0");
|
let color_texture_0_uniform = device.get_uniform(&program, "ColorTexture0");
|
||||||
let color_texture_1_uniform = device.get_uniform(&program, "ColorTexture1");
|
let color_texture_1_uniform = device.get_uniform(&program, "ColorTexture1");
|
||||||
|
@ -349,6 +350,8 @@ impl<D> TileProgram<D> where D: Device {
|
||||||
program,
|
program,
|
||||||
transform_uniform,
|
transform_uniform,
|
||||||
tile_size_uniform,
|
tile_size_uniform,
|
||||||
|
texture_metadata_uniform,
|
||||||
|
texture_metadata_size_uniform,
|
||||||
dest_texture_uniform,
|
dest_texture_uniform,
|
||||||
color_texture_0_uniform,
|
color_texture_0_uniform,
|
||||||
color_texture_1_uniform,
|
color_texture_1_uniform,
|
||||||
|
|
|
@ -17,6 +17,7 @@ use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8};
|
use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8};
|
||||||
use pathfinder_geometry::rect::RectI;
|
use pathfinder_geometry::rect::RectI;
|
||||||
|
use pathfinder_geometry::transform2d::Transform2F;
|
||||||
use pathfinder_geometry::vector::Vector2I;
|
use pathfinder_geometry::vector::Vector2I;
|
||||||
use pathfinder_gpu::TextureSamplingFlags;
|
use pathfinder_gpu::TextureSamplingFlags;
|
||||||
use std::fmt::{Debug, Formatter, Result as DebugResult};
|
use std::fmt::{Debug, Formatter, Result as DebugResult};
|
||||||
|
@ -50,6 +51,9 @@ pub enum RenderCommand {
|
||||||
// TODO(pcwalton): Add a rect to this so we can render to subrects of a page.
|
// TODO(pcwalton): Add a rect to this so we can render to subrects of a page.
|
||||||
DeclareRenderTarget { id: RenderTargetId, location: TextureLocation },
|
DeclareRenderTarget { id: RenderTargetId, location: TextureLocation },
|
||||||
|
|
||||||
|
// Upload texture metadata.
|
||||||
|
UploadTextureMetadata(Vec<TextureMetadataEntry>),
|
||||||
|
|
||||||
// Adds fills to the queue.
|
// Adds fills to the queue.
|
||||||
AddFills(Vec<FillBatchPrimitive>),
|
AddFills(Vec<FillBatchPrimitive>),
|
||||||
|
|
||||||
|
@ -63,6 +67,9 @@ pub enum RenderCommand {
|
||||||
// Pops a render target from the stack.
|
// Pops a render target from the stack.
|
||||||
PopRenderTarget,
|
PopRenderTarget,
|
||||||
|
|
||||||
|
// Marks that tile compositing is about to begin.
|
||||||
|
BeginTileDrawing,
|
||||||
|
|
||||||
// Draws a batch of tiles to the render target on top of the stack.
|
// Draws a batch of tiles to the render target on top of the stack.
|
||||||
DrawTiles(TileBatch),
|
DrawTiles(TileBatch),
|
||||||
|
|
||||||
|
@ -117,6 +124,13 @@ pub struct TileObjectPrimitive {
|
||||||
pub backdrop: i8,
|
pub backdrop: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TextureMetadataEntry {
|
||||||
|
pub color_0_transform: Transform2F,
|
||||||
|
pub opacity: f32,
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Move `subpx` before `px` and remove `repr(packed)`.
|
// FIXME(pcwalton): Move `subpx` before `px` and remove `repr(packed)`.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
|
@ -129,27 +143,15 @@ pub struct FillBatchPrimitive {
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Tile {
|
pub struct Tile {
|
||||||
pub upper_left: TileVertex,
|
|
||||||
pub upper_right: TileVertex,
|
|
||||||
pub lower_left: TileVertex,
|
|
||||||
pub lower_right: TileVertex,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct TileVertex {
|
|
||||||
pub tile_x: i16,
|
pub tile_x: i16,
|
||||||
pub tile_y: i16,
|
pub tile_y: i16,
|
||||||
pub color_0_u: f32,
|
pub mask_0_u: u8,
|
||||||
pub color_0_v: f32,
|
pub mask_0_v: u8,
|
||||||
pub color_1_u: f32,
|
pub mask_1_u: u8,
|
||||||
pub color_1_v: f32,
|
pub mask_1_v: u8,
|
||||||
pub mask_0_u: f32,
|
pub mask_0_backdrop: i8,
|
||||||
pub mask_0_v: f32,
|
pub mask_1_backdrop: i8,
|
||||||
pub mask_1_u: f32,
|
pub color: u16,
|
||||||
pub mask_1_v: f32,
|
|
||||||
pub mask_0_backdrop: i16,
|
|
||||||
pub mask_1_backdrop: i16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for RenderCommand {
|
impl Debug for RenderCommand {
|
||||||
|
@ -165,12 +167,16 @@ impl Debug for RenderCommand {
|
||||||
RenderCommand::DeclareRenderTarget { id, location } => {
|
RenderCommand::DeclareRenderTarget { id, location } => {
|
||||||
write!(formatter, "DeclareRenderTarget({:?}, {:?})", id, location)
|
write!(formatter, "DeclareRenderTarget({:?}, {:?})", id, location)
|
||||||
}
|
}
|
||||||
|
RenderCommand::UploadTextureMetadata(ref metadata) => {
|
||||||
|
write!(formatter, "UploadTextureMetadata(x{})", metadata.len())
|
||||||
|
}
|
||||||
RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()),
|
RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()),
|
||||||
RenderCommand::FlushFills => write!(formatter, "FlushFills"),
|
RenderCommand::FlushFills => write!(formatter, "FlushFills"),
|
||||||
RenderCommand::PushRenderTarget(render_target_id) => {
|
RenderCommand::PushRenderTarget(render_target_id) => {
|
||||||
write!(formatter, "PushRenderTarget({:?})", render_target_id)
|
write!(formatter, "PushRenderTarget({:?})", render_target_id)
|
||||||
}
|
}
|
||||||
RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"),
|
RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"),
|
||||||
|
RenderCommand::BeginTileDrawing => write!(formatter, "BeginTileDrawing"),
|
||||||
RenderCommand::DrawTiles(ref batch) => {
|
RenderCommand::DrawTiles(ref batch) => {
|
||||||
write!(formatter,
|
write!(formatter,
|
||||||
"DrawTiles(x{}, C0 {:?}, C1 {:?}, M0 {:?}, {:?})",
|
"DrawTiles(x{}, C0 {:?}, C1 {:?}, M0 {:?}, {:?})",
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use crate::allocator::{AllocationMode, TextureAllocator};
|
use crate::allocator::{AllocationMode, TextureAllocator};
|
||||||
use crate::gpu_data::{RenderCommand, TextureLocation, TexturePageDescriptor, TexturePageId};
|
use crate::gpu_data::{RenderCommand, TextureLocation, TextureMetadataEntry};
|
||||||
|
use crate::gpu_data::{TexturePageDescriptor, TexturePageId};
|
||||||
use crate::scene::RenderTarget;
|
use crate::scene::RenderTarget;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use pathfinder_color::ColorU;
|
use pathfinder_color::ColorU;
|
||||||
use pathfinder_content::effects::{Filter, PatternFilter};
|
use pathfinder_content::effects::{Filter, PatternFilter};
|
||||||
|
@ -136,6 +136,27 @@ impl Paint {
|
||||||
Paint::Pattern(ref mut pattern) => pattern.apply_transform(*transform),
|
Paint::Pattern(ref mut pattern) => pattern.apply_transform(*transform),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn opacity(&self) -> u8 {
|
||||||
|
match *self {
|
||||||
|
Paint::Color(_) | Paint::Gradient(_) => !0,
|
||||||
|
Paint::Pattern(ref pattern) => pattern.opacity(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_opacity(&mut self, new_opacity: f32) {
|
||||||
|
match *self {
|
||||||
|
Paint::Color(ref mut color) => color.a = (color.a as f32 * new_opacity) as u8,
|
||||||
|
Paint::Gradient(ref mut gradient) => {
|
||||||
|
for stop in gradient.stops_mut() {
|
||||||
|
stop.color.a = (stop.color.a as f32 * new_opacity) as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Paint::Pattern(ref mut pattern) => {
|
||||||
|
pattern.set_opacity((pattern.opacity() as f32 * new_opacity) as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PaintInfo {
|
pub struct PaintInfo {
|
||||||
|
@ -167,6 +188,8 @@ pub struct PaintMetadata {
|
||||||
pub is_opaque: bool,
|
pub is_opaque: bool,
|
||||||
/// The filter to be applied to this paint.
|
/// The filter to be applied to this paint.
|
||||||
pub filter: PaintFilter,
|
pub filter: PaintFilter,
|
||||||
|
/// The paint opacity (global alpha, in canvas terminology).
|
||||||
|
pub opacity: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -292,6 +315,7 @@ impl Palette {
|
||||||
sampling_flags,
|
sampling_flags,
|
||||||
is_opaque: paint.is_opaque(),
|
is_opaque: paint.is_opaque(),
|
||||||
filter,
|
filter,
|
||||||
|
opacity: paint.opacity(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,8 +324,9 @@ impl Palette {
|
||||||
let texture_scale = allocator.page_scale(metadata.location.page);
|
let texture_scale = allocator.page_scale(metadata.location.page);
|
||||||
metadata.texture_transform = match paint {
|
metadata.texture_transform = match paint {
|
||||||
Paint::Color(_) => {
|
Paint::Color(_) => {
|
||||||
|
let matrix = Matrix2x2F(F32x4::default());
|
||||||
let vector = rect_to_inset_uv(metadata.location.rect, texture_scale).origin();
|
let vector = rect_to_inset_uv(metadata.location.rect, texture_scale).origin();
|
||||||
Transform2F { matrix: Matrix2x2F(F32x4::default()), vector } * render_transform.inverse()
|
Transform2F { matrix, vector } * render_transform.inverse()
|
||||||
}
|
}
|
||||||
Paint::Gradient(Gradient { line: gradient_line, radii: None, .. }) => {
|
Paint::Gradient(Gradient { line: gradient_line, radii: None, .. }) => {
|
||||||
let v0 = metadata.location.rect.to_f32().center().y() * texture_scale.y();
|
let v0 = metadata.location.rect.to_f32().center().y() * texture_scale.y();
|
||||||
|
@ -354,9 +379,18 @@ impl Palette {
|
||||||
let opacity_tile_page = opacity_tile_builder.tile_location.page;
|
let opacity_tile_page = opacity_tile_builder.tile_location.page;
|
||||||
let opacity_tile_transform = opacity_tile_builder.tile_transform(&allocator);
|
let opacity_tile_transform = opacity_tile_builder.tile_transform(&allocator);
|
||||||
|
|
||||||
|
// Create texture metadata.
|
||||||
|
let texture_metadata = paint_metadata.iter().map(|paint_metadata| {
|
||||||
|
TextureMetadataEntry {
|
||||||
|
color_0_transform: paint_metadata.texture_transform,
|
||||||
|
opacity: paint_metadata.opacity as f32 / 255.0,
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
// Create render commands.
|
// Create render commands.
|
||||||
let mut render_commands = vec![
|
let mut render_commands = vec![
|
||||||
RenderCommand::AllocateTexturePages(texture_page_descriptors)
|
RenderCommand::UploadTextureMetadata(texture_metadata),
|
||||||
|
RenderCommand::AllocateTexturePages(texture_page_descriptors),
|
||||||
];
|
];
|
||||||
for (index, metadata) in render_target_metadata.iter().enumerate() {
|
for (index, metadata) in render_target_metadata.iter().enumerate() {
|
||||||
let id = RenderTargetId(index as u32);
|
let id = RenderTargetId(index as u32);
|
||||||
|
@ -386,14 +420,6 @@ impl Palette {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaintMetadata {
|
impl PaintMetadata {
|
||||||
// TODO(pcwalton): Apply clamp/repeat to tile rect.
|
|
||||||
pub(crate) fn calculate_tex_coords(&self, tile_position: Vector2I) -> Vector2F {
|
|
||||||
let tile_size = vec2i(TILE_WIDTH as i32, TILE_HEIGHT as i32);
|
|
||||||
let position = (tile_position * tile_size).to_f32();
|
|
||||||
let tex_coords = self.texture_transform * position;
|
|
||||||
tex_coords
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn filter(&self) -> Filter {
|
pub(crate) fn filter(&self) -> Filter {
|
||||||
match self.filter {
|
match self.filter {
|
||||||
PaintFilter::None => Filter::None,
|
PaintFilter::None => Filter::None,
|
||||||
|
|
|
@ -143,7 +143,6 @@ impl Scene {
|
||||||
}),
|
}),
|
||||||
fill_rule: draw_path.fill_rule,
|
fill_rule: draw_path.fill_rule,
|
||||||
blend_mode: draw_path.blend_mode,
|
blend_mode: draw_path.blend_mode,
|
||||||
opacity: draw_path.opacity,
|
|
||||||
name: draw_path.name,
|
name: draw_path.name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -313,7 +312,6 @@ pub struct DrawPath {
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
fill_rule: FillRule,
|
fill_rule: FillRule,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,7 +353,6 @@ impl DrawPath {
|
||||||
clip_path: None,
|
clip_path: None,
|
||||||
fill_rule: FillRule::Winding,
|
fill_rule: FillRule::Winding,
|
||||||
blend_mode: BlendMode::SrcOver,
|
blend_mode: BlendMode::SrcOver,
|
||||||
opacity: !0,
|
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,16 +397,6 @@ impl DrawPath {
|
||||||
self.blend_mode = new_blend_mode
|
self.blend_mode = new_blend_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn opacity(&self) -> u8 {
|
|
||||||
self.opacity
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn set_opacity(&mut self, new_opacity: u8) {
|
|
||||||
self.opacity = new_opacity
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_name(&mut self, new_name: String) {
|
pub fn set_name(&mut self, new_name: String) {
|
||||||
self.name = new_name
|
self.name = new_name
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use crate::builder::{BuiltPath, ObjectBuilder, Occluder, SceneBuilder, SolidTiles};
|
use crate::builder::{BuiltPath, ObjectBuilder, Occluder, SceneBuilder, SolidTiles};
|
||||||
use crate::gpu_data::TileObjectPrimitive;
|
use crate::gpu_data::TileObjectPrimitive;
|
||||||
use crate::paint::PaintMetadata;
|
use crate::paint::{PaintId, PaintMetadata};
|
||||||
use pathfinder_content::effects::BlendMode;
|
use pathfinder_content::effects::BlendMode;
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::outline::{Contour, Outline, PointIndex};
|
use pathfinder_content::outline::{Contour, Outline, PointIndex};
|
||||||
|
@ -18,7 +18,6 @@ use pathfinder_content::segment::Segment;
|
||||||
use pathfinder_content::sorted_vector::SortedVector;
|
use pathfinder_content::sorted_vector::SortedVector;
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
use pathfinder_geometry::rect::{RectF, RectI};
|
use pathfinder_geometry::rect::{RectF, RectI};
|
||||||
use pathfinder_geometry::transform2d::Transform2F;
|
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -48,10 +47,9 @@ pub(crate) enum TilingPathInfo<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub(crate) struct DrawTilingPathInfo<'a> {
|
pub(crate) struct DrawTilingPathInfo<'a> {
|
||||||
|
pub(crate) paint_id: PaintId,
|
||||||
pub(crate) paint_metadata: &'a PaintMetadata,
|
pub(crate) paint_metadata: &'a PaintMetadata,
|
||||||
pub(crate) opacity_tile_transform: Transform2F,
|
|
||||||
pub(crate) blend_mode: BlendMode,
|
pub(crate) blend_mode: BlendMode,
|
||||||
pub(crate) opacity: u8,
|
|
||||||
pub(crate) built_clip_path: Option<&'a BuiltPath>,
|
pub(crate) built_clip_path: Option<&'a BuiltPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
//! Software occlusion culling.
|
//! Software occlusion culling.
|
||||||
|
|
||||||
use crate::builder::Occluder;
|
use crate::builder::Occluder;
|
||||||
use crate::gpu_data::{Tile, TileBatch, TileBatchTexture, TileVertex};
|
use crate::gpu_data::{Tile, TileBatch, TileBatchTexture};
|
||||||
use crate::paint::{PaintId, PaintMetadata};
|
use crate::paint::{PaintId, PaintMetadata};
|
||||||
use crate::tile_map::DenseTileMap;
|
use crate::tile_map::DenseTileMap;
|
||||||
use crate::tiles;
|
use crate::tiles;
|
||||||
use pathfinder_content::effects::{BlendMode, Filter};
|
use pathfinder_content::effects::{BlendMode, Filter};
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2i};
|
use pathfinder_geometry::vector::Vector2I;
|
||||||
use vec_map::VecMap;
|
use vec_map::VecMap;
|
||||||
|
|
||||||
pub(crate) struct ZBuffer {
|
pub(crate) struct ZBuffer {
|
||||||
|
@ -71,7 +71,8 @@ impl ZBuffer {
|
||||||
let tile_coords = self.buffer.index_to_coords(tile_index);
|
let tile_coords = self.buffer.index_to_coords(tile_index);
|
||||||
|
|
||||||
let depth_metadata = self.depth_metadata[depth as usize];
|
let depth_metadata = self.depth_metadata[depth as usize];
|
||||||
let paint_metadata = &paint_metadata[depth_metadata.paint_id.0 as usize];
|
let paint_id = depth_metadata.paint_id;
|
||||||
|
let paint_metadata = &paint_metadata[paint_id.0 as usize];
|
||||||
|
|
||||||
let tile_position = tile_coords + self.buffer.rect.origin();
|
let tile_position = tile_coords + self.buffer.rect.origin();
|
||||||
|
|
||||||
|
@ -103,7 +104,7 @@ impl ZBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
let batch = solid_tiles.batches.last_mut().unwrap();
|
let batch = solid_tiles.batches.last_mut().unwrap();
|
||||||
batch.tiles.push(Tile::new_solid_with_paint_metadata(tile_position, paint_metadata));
|
batch.tiles.push(Tile::new_solid_from_paint_id(tile_position, paint_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
solid_tiles
|
solid_tiles
|
||||||
|
@ -111,42 +112,17 @@ impl ZBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tile {
|
impl Tile {
|
||||||
pub(crate) fn new_solid_with_paint_metadata(tile_position: Vector2I,
|
pub(crate) fn new_solid_from_paint_id(tile_origin: Vector2I, paint_id: PaintId) -> Tile {
|
||||||
paint_metadata: &PaintMetadata)
|
|
||||||
-> Tile {
|
|
||||||
Tile {
|
Tile {
|
||||||
upper_left: TileVertex::new_solid_from_paint_metadata(tile_position, paint_metadata),
|
tile_x: tile_origin.x() as i16,
|
||||||
upper_right: TileVertex::new_solid_from_paint_metadata(tile_position + vec2i(1, 0),
|
tile_y: tile_origin.y() as i16,
|
||||||
paint_metadata),
|
|
||||||
lower_left: TileVertex::new_solid_from_paint_metadata(tile_position + vec2i(0, 1),
|
|
||||||
paint_metadata),
|
|
||||||
lower_right: TileVertex::new_solid_from_paint_metadata(tile_position + vec2i(1, 1),
|
|
||||||
paint_metadata),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TileVertex {
|
|
||||||
fn new_solid_from_uv(tile_position: Vector2I, color_0_uv: Vector2F) -> TileVertex {
|
|
||||||
TileVertex {
|
|
||||||
tile_x: tile_position.x() as i16,
|
|
||||||
tile_y: tile_position.y() as i16,
|
|
||||||
color_0_u: color_0_uv.x(),
|
|
||||||
color_0_v: color_0_uv.y(),
|
|
||||||
color_1_u: 0.0,
|
|
||||||
color_1_v: 0.0,
|
|
||||||
mask_0_u: 0.0,
|
|
||||||
mask_0_v: 0.0,
|
|
||||||
mask_1_u: 0.0,
|
|
||||||
mask_1_v: 0.0,
|
|
||||||
mask_0_backdrop: 0,
|
mask_0_backdrop: 0,
|
||||||
mask_1_backdrop: 0,
|
mask_1_backdrop: 0,
|
||||||
|
mask_0_u: 0,
|
||||||
|
mask_0_v: 0,
|
||||||
|
mask_1_u: 0,
|
||||||
|
mask_1_v: 0,
|
||||||
|
color: paint_id.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_solid_from_paint_metadata(tile_position: Vector2I, paint_metadata: &PaintMetadata)
|
|
||||||
-> TileVertex {
|
|
||||||
let color_uv = paint_metadata.calculate_tex_coords(tile_position);
|
|
||||||
TileVertex::new_solid_from_uv(tile_position, color_uv)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,11 +76,9 @@ precision highp sampler2D;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uniform sampler2D uColorTexture0;
|
uniform sampler2D uColorTexture0;
|
||||||
uniform sampler2D uColorTexture1;
|
|
||||||
uniform sampler2D uMaskTexture0;
|
uniform sampler2D uMaskTexture0;
|
||||||
uniform sampler2D uMaskTexture1;
|
uniform sampler2D uMaskTexture1;
|
||||||
uniform sampler2D uDestTexture;
|
uniform sampler2D uDestTexture;
|
||||||
|
@ -95,7 +93,7 @@ uniform int uCtrl;
|
||||||
in vec3 vMaskTexCoord0;
|
in vec3 vMaskTexCoord0;
|
||||||
in vec3 vMaskTexCoord1;
|
in vec3 vMaskTexCoord1;
|
||||||
in vec2 vColorTexCoord0;
|
in vec2 vColorTexCoord0;
|
||||||
in vec2 vColorTexCoord1;
|
in float vOpacity;
|
||||||
|
|
||||||
out vec4 oFragColor;
|
out vec4 oFragColor;
|
||||||
|
|
||||||
|
@ -575,11 +573,9 @@ void calculateColor(int ctrl){
|
||||||
uFilterParams2,
|
uFilterParams2,
|
||||||
color0Filter);
|
color0Filter);
|
||||||
}
|
}
|
||||||
if(((ctrl >> 7)& 0x1)!= 0)
|
|
||||||
color *= sampleColor(uColorTexture1, vColorTexCoord1);
|
|
||||||
|
|
||||||
|
|
||||||
color . a *= maskAlpha;
|
color . a *= maskAlpha * vOpacity;
|
||||||
|
|
||||||
|
|
||||||
int compositeOp =(ctrl >> 8)& 0xf;
|
int compositeOp =(ctrl >> 8)& 0xf;
|
||||||
|
|
|
@ -17,25 +17,39 @@ precision highp sampler2D;
|
||||||
|
|
||||||
uniform mat4 uTransform;
|
uniform mat4 uTransform;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
|
uniform sampler2D uTextureMetadata;
|
||||||
|
uniform ivec2 uTextureMetadataSize;
|
||||||
|
|
||||||
in ivec2 aTilePosition;
|
in ivec2 aTileOffset;
|
||||||
in vec2 aColorTexCoord0;
|
in ivec2 aTileOrigin;
|
||||||
in vec2 aColorTexCoord1;
|
in uvec2 aMaskTexCoord0;
|
||||||
in vec2 aMaskTexCoord0;
|
in uvec2 aMaskTexCoord1;
|
||||||
in vec2 aMaskTexCoord1;
|
|
||||||
in ivec2 aMaskBackdrop;
|
in ivec2 aMaskBackdrop;
|
||||||
|
in int aColor;
|
||||||
|
|
||||||
out vec3 vMaskTexCoord0;
|
out vec3 vMaskTexCoord0;
|
||||||
out vec3 vMaskTexCoord1;
|
out vec3 vMaskTexCoord1;
|
||||||
out vec2 vColorTexCoord0;
|
out vec2 vColorTexCoord0;
|
||||||
out vec2 vColorTexCoord1;
|
out float vOpacity;
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
vec2 position = vec2(aTilePosition)* uTileSize;
|
vec2 tileOrigin = vec2(aTileOrigin), tileOffset = vec2(aTileOffset);
|
||||||
vColorTexCoord0 = aColorTexCoord0;
|
vec2 position =(tileOrigin + tileOffset)* uTileSize;
|
||||||
vColorTexCoord1 = aColorTexCoord1;
|
|
||||||
vMaskTexCoord0 = vec3(aMaskTexCoord0, float(aMaskBackdrop . x));
|
vec2 maskTexCoord0 =(vec2(aMaskTexCoord0)+ tileOffset)/ 256.0;
|
||||||
vMaskTexCoord1 = vec3(aMaskTexCoord1, float(aMaskBackdrop . y));
|
vec2 maskTexCoord1 =(vec2(aMaskTexCoord1)+ tileOffset)/ 256.0;
|
||||||
|
|
||||||
|
vec2 textureMetadataScale = vec2(1.0)/ vec2(uTextureMetadataSize);
|
||||||
|
vec2 metadataEntryCoord = ivec2(aColor % 256 * 2, aColor / 256);
|
||||||
|
vec2 colorTexMatrix0Coord =(metadataEntryCoord + vec2(0.5, 0.5))* textureMetadataScale;
|
||||||
|
vec2 colorTexOffsetsCoord =(metadataEntryCoord + vec2(1.5, 0.5))* textureMetadataScale;
|
||||||
|
vec4 colorTexMatrix0 = texture(uTextureMetadata, colorTexMatrix0Coord);
|
||||||
|
vec4 colorTexOffsets = texture(uTextureMetadata, colorTexOffsetsCoord);
|
||||||
|
|
||||||
|
vColorTexCoord0 = mat2(colorTexMatrix0)* position + colorTexOffsets . xy;
|
||||||
|
vOpacity = colorTexOffsets . z;
|
||||||
|
vMaskTexCoord0 = vec3(maskTexCoord0, float(aMaskBackdrop . x));
|
||||||
|
vMaskTexCoord1 = vec3(maskTexCoord1, float(aMaskBackdrop . y));
|
||||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,9 @@ struct spvDescriptorSetBuffer0
|
||||||
constant float4* uFilterParams0 [[id(10)]];
|
constant float4* uFilterParams0 [[id(10)]];
|
||||||
constant float4* uFilterParams1 [[id(11)]];
|
constant float4* uFilterParams1 [[id(11)]];
|
||||||
constant float4* uFilterParams2 [[id(12)]];
|
constant float4* uFilterParams2 [[id(12)]];
|
||||||
texture2d<float> uColorTexture1 [[id(13)]];
|
texture2d<float> uDestTexture [[id(13)]];
|
||||||
sampler uColorTexture1Smplr [[id(14)]];
|
sampler uDestTextureSmplr [[id(14)]];
|
||||||
texture2d<float> uDestTexture [[id(15)]];
|
constant int* uCtrl [[id(15)]];
|
||||||
sampler uDestTextureSmplr [[id(16)]];
|
|
||||||
constant int* uCtrl [[id(17)]];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constant float3 _1003 = {};
|
constant float3 _1003 = {};
|
||||||
|
@ -40,7 +38,7 @@ struct main0_in
|
||||||
float3 vMaskTexCoord0 [[user(locn0)]];
|
float3 vMaskTexCoord0 [[user(locn0)]];
|
||||||
float3 vMaskTexCoord1 [[user(locn1)]];
|
float3 vMaskTexCoord1 [[user(locn1)]];
|
||||||
float2 vColorTexCoord0 [[user(locn2)]];
|
float2 vColorTexCoord0 [[user(locn2)]];
|
||||||
float2 vColorTexCoord1 [[user(locn3)]];
|
float vOpacity [[user(locn3)]];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
|
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
|
||||||
|
@ -534,7 +532,7 @@ float4 composite(thread const float4& srcColor, thread const texture2d<float> de
|
||||||
return float4(((srcColor.xyz * (srcColor.w * (1.0 - destColor.w))) + (blendedRGB * (srcColor.w * destColor.w))) + (destColor.xyz * (1.0 - srcColor.w)), 1.0);
|
return float4(((srcColor.xyz * (srcColor.w * (1.0 - destColor.w))) + (blendedRGB * (srcColor.w * destColor.w))) + (destColor.xyz * (1.0 - srcColor.w)), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateColor(thread const int& ctrl, thread texture2d<float> uMaskTexture0, thread const sampler uMaskTexture0Smplr, thread float3& vMaskTexCoord0, thread texture2d<float> uMaskTexture1, thread const sampler uMaskTexture1Smplr, thread float3& vMaskTexCoord1, thread float2& vColorTexCoord0, thread texture2d<float> uColorTexture0, thread const sampler uColorTexture0Smplr, thread texture2d<float> uGammaLUT, thread const sampler uGammaLUTSmplr, thread float2 uColorTexture0Size, thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread float4 uFilterParams0, thread float4 uFilterParams1, thread float4 uFilterParams2, thread texture2d<float> uColorTexture1, thread const sampler uColorTexture1Smplr, thread float2& vColorTexCoord1, thread texture2d<float> uDestTexture, thread const sampler uDestTextureSmplr, thread float4& oFragColor)
|
void calculateColor(thread const int& ctrl, thread texture2d<float> uMaskTexture0, thread const sampler uMaskTexture0Smplr, thread float3& vMaskTexCoord0, thread texture2d<float> uMaskTexture1, thread const sampler uMaskTexture1Smplr, thread float3& vMaskTexCoord1, thread float2& vColorTexCoord0, thread texture2d<float> uColorTexture0, thread const sampler uColorTexture0Smplr, thread texture2d<float> uGammaLUT, thread const sampler uGammaLUTSmplr, thread float2 uColorTexture0Size, thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread float4 uFilterParams0, thread float4 uFilterParams1, thread float4 uFilterParams2, thread float& vOpacity, thread texture2d<float> uDestTexture, thread const sampler uDestTextureSmplr, thread float4& oFragColor)
|
||||||
{
|
{
|
||||||
int maskCtrl0 = (ctrl >> 0) & 3;
|
int maskCtrl0 = (ctrl >> 0) & 3;
|
||||||
int maskCtrl1 = (ctrl >> 2) & 3;
|
int maskCtrl1 = (ctrl >> 2) & 3;
|
||||||
|
@ -561,20 +559,15 @@ void calculateColor(thread const int& ctrl, thread texture2d<float> uMaskTexture
|
||||||
int param_13 = color0Filter;
|
int param_13 = color0Filter;
|
||||||
color += filterColor(param_6, uColorTexture0, uColorTexture0Smplr, uGammaLUT, uGammaLUTSmplr, param_7, param_8, param_9, param_10, param_11, param_12, param_13);
|
color += filterColor(param_6, uColorTexture0, uColorTexture0Smplr, uGammaLUT, uGammaLUTSmplr, param_7, param_8, param_9, param_10, param_11, param_12, param_13);
|
||||||
}
|
}
|
||||||
if (((ctrl >> 7) & 1) != 0)
|
color.w *= (maskAlpha * vOpacity);
|
||||||
{
|
|
||||||
float2 param_14 = vColorTexCoord1;
|
|
||||||
color *= sampleColor(uColorTexture1, uColorTexture1Smplr, param_14);
|
|
||||||
}
|
|
||||||
color.w *= maskAlpha;
|
|
||||||
int compositeOp = (ctrl >> 8) & 15;
|
int compositeOp = (ctrl >> 8) & 15;
|
||||||
float4 param_15 = color;
|
float4 param_14 = color;
|
||||||
float2 param_16 = uFramebufferSize;
|
float2 param_15 = uFramebufferSize;
|
||||||
float2 param_17 = gl_FragCoord.xy;
|
float2 param_16 = gl_FragCoord.xy;
|
||||||
int param_18 = compositeOp;
|
int param_17 = compositeOp;
|
||||||
color = composite(param_15, uDestTexture, uDestTextureSmplr, param_16, param_17, param_18);
|
color = composite(param_14, uDestTexture, uDestTextureSmplr, param_15, param_16, param_17);
|
||||||
float3 _1304 = color.xyz * color.w;
|
float3 _1294 = color.xyz * color.w;
|
||||||
color = float4(_1304.x, _1304.y, _1304.z, color.w);
|
color = float4(_1294.x, _1294.y, _1294.z, color.w);
|
||||||
oFragColor = color;
|
oFragColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +575,7 @@ fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuff
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
int param = (*spvDescriptorSet0.uCtrl);
|
int param = (*spvDescriptorSet0.uCtrl);
|
||||||
calculateColor(param, spvDescriptorSet0.uMaskTexture0, spvDescriptorSet0.uMaskTexture0Smplr, in.vMaskTexCoord0, spvDescriptorSet0.uMaskTexture1, spvDescriptorSet0.uMaskTexture1Smplr, in.vMaskTexCoord1, in.vColorTexCoord0, spvDescriptorSet0.uColorTexture0, spvDescriptorSet0.uColorTexture0Smplr, spvDescriptorSet0.uGammaLUT, spvDescriptorSet0.uGammaLUTSmplr, (*spvDescriptorSet0.uColorTexture0Size), gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), (*spvDescriptorSet0.uFilterParams0), (*spvDescriptorSet0.uFilterParams1), (*spvDescriptorSet0.uFilterParams2), spvDescriptorSet0.uColorTexture1, spvDescriptorSet0.uColorTexture1Smplr, in.vColorTexCoord1, spvDescriptorSet0.uDestTexture, spvDescriptorSet0.uDestTextureSmplr, out.oFragColor);
|
calculateColor(param, spvDescriptorSet0.uMaskTexture0, spvDescriptorSet0.uMaskTexture0Smplr, in.vMaskTexCoord0, spvDescriptorSet0.uMaskTexture1, spvDescriptorSet0.uMaskTexture1Smplr, in.vMaskTexCoord1, in.vColorTexCoord0, spvDescriptorSet0.uColorTexture0, spvDescriptorSet0.uColorTexture0Smplr, spvDescriptorSet0.uGammaLUT, spvDescriptorSet0.uGammaLUTSmplr, (*spvDescriptorSet0.uColorTexture0Size), gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), (*spvDescriptorSet0.uFilterParams0), (*spvDescriptorSet0.uFilterParams1), (*spvDescriptorSet0.uFilterParams2), in.vOpacity, spvDescriptorSet0.uDestTexture, spvDescriptorSet0.uDestTextureSmplr, out.oFragColor);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@ using namespace metal;
|
||||||
struct spvDescriptorSetBuffer0
|
struct spvDescriptorSetBuffer0
|
||||||
{
|
{
|
||||||
constant float2* uTileSize [[id(0)]];
|
constant float2* uTileSize [[id(0)]];
|
||||||
constant float4x4* uTransform [[id(1)]];
|
constant int2* uTextureMetadataSize [[id(1)]];
|
||||||
|
texture2d<float> uTextureMetadata [[id(2)]];
|
||||||
|
sampler uTextureMetadataSmplr [[id(3)]];
|
||||||
|
constant float4x4* uTransform [[id(4)]];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct main0_out
|
struct main0_out
|
||||||
|
@ -15,28 +18,38 @@ struct main0_out
|
||||||
float3 vMaskTexCoord0 [[user(locn0)]];
|
float3 vMaskTexCoord0 [[user(locn0)]];
|
||||||
float3 vMaskTexCoord1 [[user(locn1)]];
|
float3 vMaskTexCoord1 [[user(locn1)]];
|
||||||
float2 vColorTexCoord0 [[user(locn2)]];
|
float2 vColorTexCoord0 [[user(locn2)]];
|
||||||
float2 vColorTexCoord1 [[user(locn3)]];
|
float vOpacity [[user(locn3)]];
|
||||||
float4 gl_Position [[position]];
|
float4 gl_Position [[position]];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct main0_in
|
struct main0_in
|
||||||
{
|
{
|
||||||
int2 aTilePosition [[attribute(0)]];
|
int2 aTileOffset [[attribute(0)]];
|
||||||
float2 aColorTexCoord0 [[attribute(1)]];
|
int2 aTileOrigin [[attribute(1)]];
|
||||||
float2 aColorTexCoord1 [[attribute(2)]];
|
uint2 aMaskTexCoord0 [[attribute(2)]];
|
||||||
float2 aMaskTexCoord0 [[attribute(3)]];
|
uint2 aMaskTexCoord1 [[attribute(3)]];
|
||||||
float2 aMaskTexCoord1 [[attribute(4)]];
|
int2 aMaskBackdrop [[attribute(4)]];
|
||||||
int2 aMaskBackdrop [[attribute(5)]];
|
int aColor [[attribute(5)]];
|
||||||
};
|
};
|
||||||
|
|
||||||
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
float2 tileOrigin = float2(in.aTileOrigin);
|
||||||
out.vColorTexCoord0 = in.aColorTexCoord0;
|
float2 tileOffset = float2(in.aTileOffset);
|
||||||
out.vColorTexCoord1 = in.aColorTexCoord1;
|
float2 position = (tileOrigin + tileOffset) * (*spvDescriptorSet0.uTileSize);
|
||||||
out.vMaskTexCoord0 = float3(in.aMaskTexCoord0, float(in.aMaskBackdrop.x));
|
float2 maskTexCoord0 = (float2(in.aMaskTexCoord0) + tileOffset) / float2(256.0);
|
||||||
out.vMaskTexCoord1 = float3(in.aMaskTexCoord1, float(in.aMaskBackdrop.y));
|
float2 maskTexCoord1 = (float2(in.aMaskTexCoord1) + tileOffset) / float2(256.0);
|
||||||
|
float2 textureMetadataScale = float2(1.0) / float2((*spvDescriptorSet0.uTextureMetadataSize));
|
||||||
|
float2 metadataEntryCoord = float2(int2((in.aColor % 256) * 2, in.aColor / 256));
|
||||||
|
float2 colorTexMatrix0Coord = (metadataEntryCoord + float2(0.5)) * textureMetadataScale;
|
||||||
|
float2 colorTexOffsetsCoord = (metadataEntryCoord + float2(1.5, 0.5)) * textureMetadataScale;
|
||||||
|
float4 colorTexMatrix0 = spvDescriptorSet0.uTextureMetadata.sample(spvDescriptorSet0.uTextureMetadataSmplr, colorTexMatrix0Coord, level(0.0));
|
||||||
|
float4 colorTexOffsets = spvDescriptorSet0.uTextureMetadata.sample(spvDescriptorSet0.uTextureMetadataSmplr, colorTexOffsetsCoord, level(0.0));
|
||||||
|
out.vColorTexCoord0 = (float2x2(float2(colorTexMatrix0.xy), float2(colorTexMatrix0.zw)) * position) + colorTexOffsets.xy;
|
||||||
|
out.vOpacity = colorTexOffsets.z;
|
||||||
|
out.vMaskTexCoord0 = float3(maskTexCoord0, float(in.aMaskBackdrop.x));
|
||||||
|
out.vMaskTexCoord1 = float3(maskTexCoord1, float(in.aMaskBackdrop.y));
|
||||||
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,11 +74,9 @@ precision highp sampler2D;
|
||||||
#define COMBINER_CTRL_MASK_1_SHIFT 2
|
#define COMBINER_CTRL_MASK_1_SHIFT 2
|
||||||
#define COMBINER_CTRL_COLOR_0_FILTER_SHIFT 4
|
#define COMBINER_CTRL_COLOR_0_FILTER_SHIFT 4
|
||||||
#define COMBINER_CTRL_COLOR_0_ENABLE_SHIFT 6
|
#define COMBINER_CTRL_COLOR_0_ENABLE_SHIFT 6
|
||||||
#define COMBINER_CTRL_COLOR_1_ENABLE_SHIFT 7
|
|
||||||
#define COMBINER_CTRL_COMPOSITE_SHIFT 8
|
#define COMBINER_CTRL_COMPOSITE_SHIFT 8
|
||||||
|
|
||||||
uniform sampler2D uColorTexture0;
|
uniform sampler2D uColorTexture0;
|
||||||
uniform sampler2D uColorTexture1;
|
|
||||||
uniform sampler2D uMaskTexture0;
|
uniform sampler2D uMaskTexture0;
|
||||||
uniform sampler2D uMaskTexture1;
|
uniform sampler2D uMaskTexture1;
|
||||||
uniform sampler2D uDestTexture;
|
uniform sampler2D uDestTexture;
|
||||||
|
@ -93,7 +91,7 @@ uniform int uCtrl;
|
||||||
in vec3 vMaskTexCoord0;
|
in vec3 vMaskTexCoord0;
|
||||||
in vec3 vMaskTexCoord1;
|
in vec3 vMaskTexCoord1;
|
||||||
in vec2 vColorTexCoord0;
|
in vec2 vColorTexCoord0;
|
||||||
in vec2 vColorTexCoord1;
|
in float vOpacity;
|
||||||
|
|
||||||
out vec4 oFragColor;
|
out vec4 oFragColor;
|
||||||
|
|
||||||
|
@ -573,11 +571,9 @@ void calculateColor(int ctrl) {
|
||||||
uFilterParams2,
|
uFilterParams2,
|
||||||
color0Filter);
|
color0Filter);
|
||||||
}
|
}
|
||||||
if (((ctrl >> COMBINER_CTRL_COLOR_1_ENABLE_SHIFT) & COMBINER_CTRL_COLOR_ENABLE_MASK) != 0)
|
|
||||||
color *= sampleColor(uColorTexture1, vColorTexCoord1);
|
|
||||||
|
|
||||||
// Apply mask.
|
// Apply mask and opacity.
|
||||||
color.a *= maskAlpha;
|
color.a *= maskAlpha * vOpacity;
|
||||||
|
|
||||||
// Apply composite.
|
// Apply composite.
|
||||||
int compositeOp = (ctrl >> COMBINER_CTRL_COMPOSITE_SHIFT) & COMBINER_CTRL_COMPOSITE_MASK;
|
int compositeOp = (ctrl >> COMBINER_CTRL_COMPOSITE_SHIFT) & COMBINER_CTRL_COMPOSITE_MASK;
|
||||||
|
|
|
@ -15,24 +15,38 @@ precision highp sampler2D;
|
||||||
|
|
||||||
uniform mat4 uTransform;
|
uniform mat4 uTransform;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
|
uniform sampler2D uTextureMetadata;
|
||||||
|
uniform ivec2 uTextureMetadataSize;
|
||||||
|
|
||||||
in ivec2 aTilePosition;
|
in ivec2 aTileOffset;
|
||||||
in vec2 aColorTexCoord0;
|
in ivec2 aTileOrigin;
|
||||||
in vec2 aColorTexCoord1;
|
in uvec2 aMaskTexCoord0;
|
||||||
in vec2 aMaskTexCoord0;
|
in uvec2 aMaskTexCoord1;
|
||||||
in vec2 aMaskTexCoord1;
|
|
||||||
in ivec2 aMaskBackdrop;
|
in ivec2 aMaskBackdrop;
|
||||||
|
in int aColor;
|
||||||
|
|
||||||
out vec3 vMaskTexCoord0;
|
out vec3 vMaskTexCoord0;
|
||||||
out vec3 vMaskTexCoord1;
|
out vec3 vMaskTexCoord1;
|
||||||
out vec2 vColorTexCoord0;
|
out vec2 vColorTexCoord0;
|
||||||
out vec2 vColorTexCoord1;
|
out float vOpacity;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 position = vec2(aTilePosition) * uTileSize;
|
vec2 tileOrigin = vec2(aTileOrigin), tileOffset = vec2(aTileOffset);
|
||||||
vColorTexCoord0 = aColorTexCoord0;
|
vec2 position = (tileOrigin + tileOffset) * uTileSize;
|
||||||
vColorTexCoord1 = aColorTexCoord1;
|
|
||||||
vMaskTexCoord0 = vec3(aMaskTexCoord0, float(aMaskBackdrop.x));
|
vec2 maskTexCoord0 = (vec2(aMaskTexCoord0) + tileOffset) / 256.0;
|
||||||
vMaskTexCoord1 = vec3(aMaskTexCoord1, float(aMaskBackdrop.y));
|
vec2 maskTexCoord1 = (vec2(aMaskTexCoord1) + tileOffset) / 256.0;
|
||||||
|
|
||||||
|
vec2 textureMetadataScale = vec2(1.0) / vec2(uTextureMetadataSize);
|
||||||
|
vec2 metadataEntryCoord = ivec2(aColor % 256 * 2, aColor / 256);
|
||||||
|
vec2 colorTexMatrix0Coord = (metadataEntryCoord + vec2(0.5, 0.5)) * textureMetadataScale;
|
||||||
|
vec2 colorTexOffsetsCoord = (metadataEntryCoord + vec2(1.5, 0.5)) * textureMetadataScale;
|
||||||
|
vec4 colorTexMatrix0 = texture(uTextureMetadata, colorTexMatrix0Coord);
|
||||||
|
vec4 colorTexOffsets = texture(uTextureMetadata, colorTexOffsetsCoord);
|
||||||
|
|
||||||
|
vColorTexCoord0 = mat2(colorTexMatrix0) * position + colorTexOffsets.xy;
|
||||||
|
vOpacity = colorTexOffsets.z;
|
||||||
|
vMaskTexCoord0 = vec3(maskTexCoord0, float(aMaskBackdrop.x));
|
||||||
|
vMaskTexCoord1 = vec3(maskTexCoord1, float(aMaskBackdrop.y));
|
||||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,14 +230,16 @@ impl BuiltSVG {
|
||||||
opacity: Opacity,
|
opacity: Opacity,
|
||||||
fill_rule: UsvgFillRule) {
|
fill_rule: UsvgFillRule) {
|
||||||
outline.transform(&state.transform);
|
outline.transform(&state.transform);
|
||||||
let paint = Paint::from_svg_paint(paint, &state.transform, &mut self.result_flags);
|
let paint = Paint::from_svg_paint(paint,
|
||||||
|
&state.transform,
|
||||||
|
opacity,
|
||||||
|
&mut self.result_flags);
|
||||||
let style = self.scene.push_paint(&paint);
|
let style = self.scene.push_paint(&paint);
|
||||||
let fill_rule = FillRule::from_usvg_fill_rule(fill_rule);
|
let fill_rule = FillRule::from_usvg_fill_rule(fill_rule);
|
||||||
let mut path = DrawPath::new(outline, style);
|
let mut path = DrawPath::new(outline, style);
|
||||||
path.set_clip_path(state.clip_path);
|
path.set_clip_path(state.clip_path);
|
||||||
path.set_fill_rule(fill_rule);
|
path.set_fill_rule(fill_rule);
|
||||||
path.set_name(name);
|
path.set_name(name);
|
||||||
path.set_opacity((opacity.value() * 255.0) as u8);
|
|
||||||
self.scene.push_path(path);
|
self.scene.push_path(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,6 +289,7 @@ impl Display for BuildResultFlags {
|
||||||
trait PaintExt {
|
trait PaintExt {
|
||||||
fn from_svg_paint(svg_paint: &UsvgPaint,
|
fn from_svg_paint(svg_paint: &UsvgPaint,
|
||||||
transform: &Transform2F,
|
transform: &Transform2F,
|
||||||
|
opacity: Opacity,
|
||||||
result_flags: &mut BuildResultFlags)
|
result_flags: &mut BuildResultFlags)
|
||||||
-> Self;
|
-> Self;
|
||||||
}
|
}
|
||||||
|
@ -295,6 +298,7 @@ impl PaintExt for Paint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_svg_paint(svg_paint: &UsvgPaint,
|
fn from_svg_paint(svg_paint: &UsvgPaint,
|
||||||
transform: &Transform2F,
|
transform: &Transform2F,
|
||||||
|
opacity: Opacity,
|
||||||
result_flags: &mut BuildResultFlags)
|
result_flags: &mut BuildResultFlags)
|
||||||
-> Paint {
|
-> Paint {
|
||||||
// TODO(pcwalton): Support gradients.
|
// TODO(pcwalton): Support gradients.
|
||||||
|
@ -307,6 +311,7 @@ impl PaintExt for Paint {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
paint.apply_transform(transform);
|
paint.apply_transform(transform);
|
||||||
|
paint.apply_opacity(opacity.value() as f32);
|
||||||
paint
|
paint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ pub trait SceneExt {
|
||||||
hinting_options: HintingOptions,
|
hinting_options: HintingOptions,
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
paint_id: PaintId)
|
paint_id: PaintId)
|
||||||
-> Result<(), GlyphLoadingError>
|
-> Result<(), GlyphLoadingError>
|
||||||
where F: Loader;
|
where F: Loader;
|
||||||
|
@ -48,7 +47,6 @@ pub trait SceneExt {
|
||||||
hinting_options: HintingOptions,
|
hinting_options: HintingOptions,
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
paint_id: PaintId)
|
paint_id: PaintId)
|
||||||
-> Result<(), GlyphLoadingError>;
|
-> Result<(), GlyphLoadingError>;
|
||||||
|
|
||||||
|
@ -61,7 +59,6 @@ pub trait SceneExt {
|
||||||
hinting_options: HintingOptions,
|
hinting_options: HintingOptions,
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
paint_id: PaintId)
|
paint_id: PaintId)
|
||||||
-> Result<(), GlyphLoadingError>;
|
-> Result<(), GlyphLoadingError>;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +73,6 @@ impl SceneExt for Scene {
|
||||||
hinting_options: HintingOptions,
|
hinting_options: HintingOptions,
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
paint_id: PaintId)
|
paint_id: PaintId)
|
||||||
-> Result<(), GlyphLoadingError>
|
-> Result<(), GlyphLoadingError>
|
||||||
where F: Loader {
|
where F: Loader {
|
||||||
|
@ -93,7 +89,6 @@ impl SceneExt for Scene {
|
||||||
let mut path = DrawPath::new(outline, paint_id);
|
let mut path = DrawPath::new(outline, paint_id);
|
||||||
path.set_clip_path(clip_path);
|
path.set_clip_path(clip_path);
|
||||||
path.set_blend_mode(blend_mode);
|
path.set_blend_mode(blend_mode);
|
||||||
path.set_opacity(opacity);
|
|
||||||
|
|
||||||
self.push_path(path);
|
self.push_path(path);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -107,7 +102,6 @@ impl SceneExt for Scene {
|
||||||
hinting_options: HintingOptions,
|
hinting_options: HintingOptions,
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
paint_id: PaintId)
|
paint_id: PaintId)
|
||||||
-> Result<(), GlyphLoadingError> {
|
-> Result<(), GlyphLoadingError> {
|
||||||
for glyph in &layout.glyphs {
|
for glyph in &layout.glyphs {
|
||||||
|
@ -124,7 +118,6 @@ impl SceneExt for Scene {
|
||||||
hinting_options,
|
hinting_options,
|
||||||
clip_path,
|
clip_path,
|
||||||
blend_mode,
|
blend_mode,
|
||||||
opacity,
|
|
||||||
paint_id)?;
|
paint_id)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -140,7 +133,6 @@ impl SceneExt for Scene {
|
||||||
hinting_options: HintingOptions,
|
hinting_options: HintingOptions,
|
||||||
clip_path: Option<ClipPathId>,
|
clip_path: Option<ClipPathId>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
opacity: u8,
|
|
||||||
paint_id: PaintId)
|
paint_id: PaintId)
|
||||||
-> Result<(), GlyphLoadingError> {
|
-> Result<(), GlyphLoadingError> {
|
||||||
let layout = skribo::layout(style, collection, text);
|
let layout = skribo::layout(style, collection, text);
|
||||||
|
@ -151,7 +143,6 @@ impl SceneExt for Scene {
|
||||||
hinting_options,
|
hinting_options,
|
||||||
clip_path,
|
clip_path,
|
||||||
blend_mode,
|
blend_mode,
|
||||||
opacity,
|
|
||||||
paint_id)
|
paint_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue