Implement basic linear gradients.
This is not a very efficient implementation yet, but it seems to work.
This commit is contained in:
parent
740597d886
commit
5a21557a6d
|
@ -362,20 +362,6 @@ dependencies = [
|
||||||
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cocoa"
|
|
||||||
version = "0.20.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"core-graphics 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color-backtrace"
|
name = "color-backtrace"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -615,7 +601,7 @@ name = "demo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"foreign-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1731,9 +1717,9 @@ 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)",
|
||||||
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"block 0.1.6 (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)",
|
||||||
"cocoa 0.20.0 (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.5.0 (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.4.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)",
|
||||||
|
@ -2739,7 +2725,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
|
"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
|
||||||
"checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400"
|
"checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400"
|
||||||
"checksum cocoa 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a4736c86d51bd878b474400d9ec888156f4037015f5d09794fab9f26eab1ad4"
|
|
||||||
"checksum color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65d13f1078cc63c791d0deba0dd43db37c9ec02b311f10bed10b577016f3a957"
|
"checksum color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65d13f1078cc63c791d0deba0dd43db37c9ec02b311f10bed10b577016f3a957"
|
||||||
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
|
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
|
||||||
"checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680"
|
"checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680"
|
||||||
|
|
|
@ -28,6 +28,7 @@ use std::f32::consts::PI;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use text::FontCollection;
|
use text::FontCollection;
|
||||||
|
|
||||||
#[cfg(feature = "pf-text")]
|
#[cfg(feature = "pf-text")]
|
||||||
pub use text::TextMetrics;
|
pub use text::TextMetrics;
|
||||||
pub use text::CanvasFontContext;
|
pub use text::CanvasFontContext;
|
||||||
|
|
|
@ -21,6 +21,11 @@ pub struct ColorU {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColorU {
|
impl ColorU {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(r: u8, g: u8, b: u8, a: u8) -> ColorU {
|
||||||
|
ColorU { r, g, b, a }
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transparent_black() -> ColorU {
|
pub fn transparent_black() -> ColorU {
|
||||||
ColorU::from_u32(0)
|
ColorU::from_u32(0)
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::sorted_vector::SortedVector;
|
||||||
use pathfinder_color::ColorU;
|
use pathfinder_color::ColorU;
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
use pathfinder_simd::default::F32x4;
|
use pathfinder_simd::default::F32x4;
|
||||||
use std::cmp::{self, Ordering, PartialOrd};
|
use std::cmp::{Ordering, PartialOrd};
|
||||||
use std::convert;
|
use std::convert;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -25,8 +25,8 @@ pub struct Gradient {
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||||
pub struct ColorStop {
|
pub struct ColorStop {
|
||||||
pub color: ColorU,
|
|
||||||
pub offset: f32,
|
pub offset: f32,
|
||||||
|
pub color: ColorU,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Gradient {}
|
impl Eq for Gradient {}
|
||||||
|
@ -79,10 +79,11 @@ impl Gradient {
|
||||||
return ColorU::transparent_black();
|
return ColorU::transparent_black();
|
||||||
}
|
}
|
||||||
|
|
||||||
let lower_index = self.stops.binary_search_by(|stop| {
|
let last_index = self.stops.len() - 1;
|
||||||
|
let upper_index = self.stops.binary_search_by(|stop| {
|
||||||
stop.offset.partial_cmp(&t).unwrap_or(Ordering::Less)
|
stop.offset.partial_cmp(&t).unwrap_or(Ordering::Less)
|
||||||
}).unwrap_or_else(convert::identity);
|
}).unwrap_or_else(convert::identity).min(last_index);
|
||||||
let upper_index = cmp::min(lower_index + 1, self.stops.len() - 1);
|
let lower_index = if upper_index > 0 { upper_index - 1 } else { upper_index };
|
||||||
|
|
||||||
let lower_stop = &self.stops.array[lower_index];
|
let lower_stop = &self.stops.array[lower_index];
|
||||||
let upper_stop = &self.stops.array[upper_index];
|
let upper_stop = &self.stops.array[upper_index];
|
||||||
|
@ -104,3 +105,10 @@ impl Gradient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ColorStop {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(color: ColorU, offset: f32) -> ColorStop {
|
||||||
|
ColorStop { color, offset }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ path = "../../gpu"
|
||||||
path = "../../simd"
|
path = "../../simd"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
foreign-types = "0.5"
|
foreign-types = "0.3"
|
||||||
metal = "0.17"
|
metal = "0.17"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
|
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
|
||||||
|
|
|
@ -181,6 +181,11 @@ impl RectF {
|
||||||
RectF::from_points(self.origin() - amount, self.lower_right() + amount)
|
RectF::from_points(self.origin() - amount, self.lower_right() + amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn contract(self, amount: Vector2F) -> RectF {
|
||||||
|
RectF::from_points(self.origin() + amount, self.lower_right() - amount)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_i32(&self) -> RectI {
|
pub fn to_i32(&self) -> RectI {
|
||||||
RectI(self.0.to_i32x4())
|
RectI(self.0.to_i32x4())
|
||||||
|
@ -308,6 +313,11 @@ impl RectI {
|
||||||
.all_true()
|
.all_true()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn contract(self, amount: Vector2I) -> RectI {
|
||||||
|
RectI::from_points(self.origin() + amount, self.lower_right() - amount)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_f32(&self) -> RectF {
|
pub fn to_f32(&self) -> RectF {
|
||||||
RectF(self.0.to_f32x4())
|
RectF(self.0.to_f32x4())
|
||||||
|
|
|
@ -14,8 +14,8 @@ use crate::line_segment::LineSegment2F;
|
||||||
use crate::rect::RectF;
|
use crate::rect::RectF;
|
||||||
use crate::transform3d::Transform4F;
|
use crate::transform3d::Transform4F;
|
||||||
use crate::unit_vector::UnitVector;
|
use crate::unit_vector::UnitVector;
|
||||||
use crate::vector::{Vector2F, Vector2I};
|
use crate::vector::Vector2F;
|
||||||
use pathfinder_simd::default::{F32x4, I32x4};
|
use pathfinder_simd::default::F32x4;
|
||||||
use std::ops::{Mul, MulAssign, Sub};
|
use std::ops::{Mul, MulAssign, Sub};
|
||||||
|
|
||||||
/// A 2x2 matrix, optimized with SIMD, in column-major order.
|
/// A 2x2 matrix, optimized with SIMD, in column-major order.
|
||||||
|
@ -74,14 +74,17 @@ impl Matrix2x2F {
|
||||||
pub fn m11(&self) -> f32 {
|
pub fn m11(&self) -> f32 {
|
||||||
self.0[0]
|
self.0[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn m21(&self) -> f32 {
|
pub fn m21(&self) -> f32 {
|
||||||
self.0[1]
|
self.0[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn m12(&self) -> f32 {
|
pub fn m12(&self) -> f32 {
|
||||||
self.0[2]
|
self.0[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn m22(&self) -> f32 {
|
pub fn m22(&self) -> f32 {
|
||||||
self.0[3]
|
self.0[3]
|
||||||
|
@ -113,29 +116,6 @@ impl Mul<Vector2F> for Matrix2x2F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 2x2 integer matrix, optimized with SIMD, in column-major order.
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub struct Matrix2x2I(pub I32x4);
|
|
||||||
|
|
||||||
impl Matrix2x2I {
|
|
||||||
#[inline]
|
|
||||||
pub fn m11(&self) -> i32 {
|
|
||||||
self.0[0]
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn m21(&self) -> i32 {
|
|
||||||
self.0[1]
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn m12(&self) -> i32 {
|
|
||||||
self.0[2]
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn m22(&self) -> i32 {
|
|
||||||
self.0[3]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An affine transform, optimized with SIMD.
|
/// An affine transform, optimized with SIMD.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Transform2F {
|
pub struct Transform2F {
|
||||||
|
@ -346,10 +326,3 @@ impl MulAssign for Transform2F {
|
||||||
*self = *self * other
|
*self = *self * other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An affine integer transform, optimized with SIMD.
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub struct Transform2I {
|
|
||||||
pub matrix: Matrix2x2I,
|
|
||||||
pub vector: Vector2I,
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//! A SIMD-optimized point type.
|
//! A SIMD-optimized point type.
|
||||||
|
|
||||||
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
||||||
use std::ops::{Add, AddAssign, Mul, Neg, Sub};
|
use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub};
|
||||||
|
|
||||||
/// 2D points with 32-bit floating point coordinates.
|
/// 2D points with 32-bit floating point coordinates.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
@ -135,6 +135,15 @@ impl Vector2F {
|
||||||
Vector2F(self.0.yx())
|
Vector2F(self.0.yx())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the coefficient when the given vector `a` is projected onto this one.
|
||||||
|
///
|
||||||
|
/// That is, if this vector is `v` and this function returns `c`, then `proj_v a = cv`. In
|
||||||
|
/// other words, this function computes `(a⋅v) / (v⋅v)`.
|
||||||
|
#[inline]
|
||||||
|
pub fn projection_coefficient(self, a: Vector2F) -> f32 {
|
||||||
|
a.dot(self) / self.square_length()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_zero(self) -> bool {
|
pub fn is_zero(self) -> bool {
|
||||||
self == Vector2F::default()
|
self == Vector2F::default()
|
||||||
|
@ -182,6 +191,14 @@ impl Mul<Vector2F> for Vector2F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<Vector2F> for Vector2F {
|
||||||
|
type Output = Vector2F;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: Vector2F) -> Vector2F {
|
||||||
|
Vector2F(self.0 / other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Neg for Vector2F {
|
impl Neg for Vector2F {
|
||||||
type Output = Vector2F;
|
type Output = Vector2F;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -8,9 +8,9 @@ edition = "2018"
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
byteorder = "1.3"
|
byteorder = "1.3"
|
||||||
block = "0.1"
|
block = "0.1"
|
||||||
cocoa = "0.20"
|
cocoa = "0.19"
|
||||||
core-foundation = "0.7"
|
core-foundation = "0.7"
|
||||||
foreign-types = "0.5"
|
foreign-types = "0.3"
|
||||||
half = "1.4"
|
half = "1.4"
|
||||||
metal = "0.17"
|
metal = "0.17"
|
||||||
objc = "0.2"
|
objc = "0.2"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//! Packs data onto the GPU.
|
//! Packs data onto the GPU.
|
||||||
|
|
||||||
use crate::concurrent::executor::Executor;
|
use crate::concurrent::executor::Executor;
|
||||||
use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, FillBatchPrimitive, RenderCommand};
|
use crate::gpu_data::{AlphaTile, BuiltObject, FillBatchPrimitive, RenderCommand};
|
||||||
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
||||||
use crate::paint::{PaintInfo, PaintMetadata};
|
use crate::paint::{PaintInfo, PaintMetadata};
|
||||||
use crate::scene::Scene;
|
use crate::scene::Scene;
|
||||||
|
@ -23,6 +23,7 @@ use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||||
use pathfinder_geometry::rect::{RectF, RectI};
|
use pathfinder_geometry::rect::{RectF, RectI};
|
||||||
use pathfinder_geometry::util;
|
use pathfinder_geometry::util;
|
||||||
use pathfinder_simd::default::{F32x4, I32x4};
|
use pathfinder_simd::default::{F32x4, I32x4};
|
||||||
|
use std::i16;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::u16;
|
use std::u16;
|
||||||
|
@ -88,7 +89,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
built_options: &PreparedBuildOptions,
|
built_options: &PreparedBuildOptions,
|
||||||
scene: &Scene,
|
scene: &Scene,
|
||||||
paint_metadata: &[PaintMetadata],
|
paint_metadata: &[PaintMetadata],
|
||||||
) -> Vec<AlphaTileBatchPrimitive> {
|
) -> Vec<AlphaTile> {
|
||||||
let path_object = &scene.paths[path_index];
|
let path_object = &scene.paths[path_index];
|
||||||
let outline = scene.apply_render_options(path_object.outline(), built_options);
|
let outline = scene.apply_render_options(path_object.outline(), built_options);
|
||||||
let paint_id = path_object.paint();
|
let paint_id = path_object.paint();
|
||||||
|
@ -105,26 +106,29 @@ impl<'a> SceneBuilder<'a> {
|
||||||
tiler.built_object.alpha_tiles
|
tiler.built_object.alpha_tiles
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cull_alpha_tiles(&self, alpha_tiles: &mut Vec<AlphaTileBatchPrimitive>) {
|
fn cull_alpha_tiles(&self, alpha_tiles: &mut Vec<AlphaTile>) {
|
||||||
for alpha_tile in alpha_tiles {
|
for alpha_tile in alpha_tiles {
|
||||||
let alpha_tile_coords = alpha_tile.tile_coords();
|
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
||||||
if self
|
if self
|
||||||
.z_buffer
|
.z_buffer
|
||||||
.test(alpha_tile_coords, alpha_tile.object_index as u32)
|
.test(alpha_tile_coords, alpha_tile.upper_left.object_index as u32)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Clean this up.
|
// FIXME(pcwalton): Clean this up.
|
||||||
alpha_tile.tile_x_lo = 0xff;
|
alpha_tile.upper_left.tile_x = i16::MIN;
|
||||||
alpha_tile.tile_y_lo = 0xff;
|
alpha_tile.upper_left.tile_y = i16::MIN;
|
||||||
alpha_tile.tile_hi = 0xff;
|
alpha_tile.upper_right.tile_x = i16::MIN;
|
||||||
|
alpha_tile.upper_right.tile_y = i16::MIN;
|
||||||
|
alpha_tile.lower_left.tile_x = i16::MIN;
|
||||||
|
alpha_tile.lower_left.tile_y = i16::MIN;
|
||||||
|
alpha_tile.lower_right.tile_x = i16::MIN;
|
||||||
|
alpha_tile.lower_right.tile_y = i16::MIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pack_alpha_tiles(&mut self,
|
fn pack_alpha_tiles(&mut self, paint_metadata: &[PaintMetadata], alpha_tiles: Vec<AlphaTile>) {
|
||||||
paint_metadata: &[PaintMetadata],
|
|
||||||
alpha_tiles: Vec<AlphaTileBatchPrimitive>) {
|
|
||||||
let path_count = self.scene.paths.len() as u32;
|
let path_count = self.scene.paths.len() as u32;
|
||||||
let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths,
|
let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths,
|
||||||
paint_metadata,
|
paint_metadata,
|
||||||
|
@ -139,7 +143,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
|
|
||||||
fn finish_building(&mut self,
|
fn finish_building(&mut self,
|
||||||
paint_metadata: &[PaintMetadata],
|
paint_metadata: &[PaintMetadata],
|
||||||
mut alpha_tiles: Vec<AlphaTileBatchPrimitive>) {
|
mut alpha_tiles: Vec<AlphaTile>) {
|
||||||
self.listener.send(RenderCommand::FlushFills);
|
self.listener.send(RenderCommand::FlushFills);
|
||||||
self.cull_alpha_tiles(&mut alpha_tiles);
|
self.cull_alpha_tiles(&mut alpha_tiles);
|
||||||
self.pack_alpha_tiles(paint_metadata, alpha_tiles);
|
self.pack_alpha_tiles(paint_metadata, alpha_tiles);
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
|
|
||||||
use crate::gpu::debug::DebugUIPresenter;
|
use crate::gpu::debug::DebugUIPresenter;
|
||||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||||
use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive, PaintData};
|
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex};
|
||||||
use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive};
|
|
||||||
use crate::post::DefringingKernel;
|
use crate::post::DefringingKernel;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
use pathfinder_color::ColorF;
|
use pathfinder_color::ColorF;
|
||||||
|
@ -34,14 +33,17 @@ use std::u32;
|
||||||
static QUAD_VERTEX_POSITIONS: [u16; 8] = [0, 0, 1, 0, 1, 1, 0, 1];
|
static QUAD_VERTEX_POSITIONS: [u16; 8] = [0, 0, 1, 0, 1, 1, 0, 1];
|
||||||
static QUAD_VERTEX_INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3];
|
static QUAD_VERTEX_INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3];
|
||||||
|
|
||||||
|
pub(crate) const MASK_TILES_ACROSS: u32 = 256;
|
||||||
|
pub(crate) const MASK_TILES_DOWN: u32 = 256;
|
||||||
|
|
||||||
// FIXME(pcwalton): Shrink this again!
|
// FIXME(pcwalton): Shrink this again!
|
||||||
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * 256;
|
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
|
||||||
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * 256;
|
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * MASK_TILES_DOWN as i32;
|
||||||
|
|
||||||
// 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 SOLID_TILE_INSTANCE_SIZE: usize = 20;
|
const SOLID_TILE_VERTEX_SIZE: usize = 12;
|
||||||
const MASK_TILE_INSTANCE_SIZE: usize = 20;
|
const MASK_TILE_VERTEX_SIZE: usize = 16;
|
||||||
|
|
||||||
const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
||||||
|
|
||||||
|
@ -63,6 +65,8 @@ where
|
||||||
area_lut_texture: D::Texture,
|
area_lut_texture: D::Texture,
|
||||||
quad_vertex_positions_buffer: D::Buffer,
|
quad_vertex_positions_buffer: D::Buffer,
|
||||||
quad_vertex_indices_buffer: D::Buffer,
|
quad_vertex_indices_buffer: D::Buffer,
|
||||||
|
quads_vertex_indices_buffer: D::Buffer,
|
||||||
|
quads_vertex_indices_length: usize,
|
||||||
fill_vertex_array: FillVertexArray<D>,
|
fill_vertex_array: FillVertexArray<D>,
|
||||||
mask_framebuffer: D::Framebuffer,
|
mask_framebuffer: D::Framebuffer,
|
||||||
paint_texture: Option<D::Texture>,
|
paint_texture: Option<D::Texture>,
|
||||||
|
@ -132,6 +136,7 @@ where
|
||||||
BufferTarget::Index,
|
BufferTarget::Index,
|
||||||
BufferUploadMode::Static,
|
BufferUploadMode::Static,
|
||||||
);
|
);
|
||||||
|
let quads_vertex_indices_buffer = device.create_buffer();
|
||||||
|
|
||||||
let fill_vertex_array = FillVertexArray::new(
|
let fill_vertex_array = FillVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
|
@ -142,14 +147,12 @@ where
|
||||||
let alpha_tile_vertex_array = AlphaTileVertexArray::new(
|
let alpha_tile_vertex_array = AlphaTileVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
&alpha_tile_program,
|
&alpha_tile_program,
|
||||||
&quad_vertex_positions_buffer,
|
&quads_vertex_indices_buffer,
|
||||||
&quad_vertex_indices_buffer,
|
|
||||||
);
|
);
|
||||||
let solid_tile_vertex_array = SolidTileVertexArray::new(
|
let solid_tile_vertex_array = SolidTileVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
&solid_tile_program,
|
&solid_tile_program,
|
||||||
&quad_vertex_positions_buffer,
|
&quads_vertex_indices_buffer,
|
||||||
&quad_vertex_indices_buffer,
|
|
||||||
);
|
);
|
||||||
let postprocess_vertex_array = PostprocessVertexArray::new(
|
let postprocess_vertex_array = PostprocessVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
|
@ -187,6 +190,8 @@ where
|
||||||
area_lut_texture,
|
area_lut_texture,
|
||||||
quad_vertex_positions_buffer,
|
quad_vertex_positions_buffer,
|
||||||
quad_vertex_indices_buffer,
|
quad_vertex_indices_buffer,
|
||||||
|
quads_vertex_indices_buffer,
|
||||||
|
quads_vertex_indices_length: 0,
|
||||||
fill_vertex_array,
|
fill_vertex_array,
|
||||||
mask_framebuffer,
|
mask_framebuffer,
|
||||||
paint_texture: None,
|
paint_texture: None,
|
||||||
|
@ -237,10 +242,10 @@ where
|
||||||
self.draw_buffered_fills();
|
self.draw_buffered_fills();
|
||||||
self.begin_composite_timer_query();
|
self.begin_composite_timer_query();
|
||||||
}
|
}
|
||||||
RenderCommand::SolidTile(ref solid_tiles) => {
|
RenderCommand::SolidTile(ref solid_tile_vertices) => {
|
||||||
let count = solid_tiles.len();
|
let count = solid_tile_vertices.len() / 4;
|
||||||
self.stats.solid_tile_count += count;
|
self.stats.solid_tile_count += count;
|
||||||
self.upload_solid_tiles(solid_tiles);
|
self.upload_solid_tiles(solid_tile_vertices);
|
||||||
self.draw_solid_tiles(count as u32);
|
self.draw_solid_tiles(count as u32);
|
||||||
}
|
}
|
||||||
RenderCommand::AlphaTile(ref alpha_tiles) => {
|
RenderCommand::AlphaTile(ref alpha_tiles) => {
|
||||||
|
@ -370,22 +375,49 @@ where
|
||||||
TextureDataRef::U8(paint_texels));
|
TextureDataRef::U8(paint_texels));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) {
|
fn upload_solid_tiles(&mut self, solid_tile_vertices: &[SolidTileVertex]) {
|
||||||
self.device.allocate_buffer(
|
self.device.allocate_buffer(
|
||||||
&self.solid_tile_vertex_array.vertex_buffer,
|
&self.solid_tile_vertex_array.vertex_buffer,
|
||||||
BufferData::Memory(&solid_tiles),
|
BufferData::Memory(&solid_tile_vertices),
|
||||||
BufferTarget::Vertex,
|
BufferTarget::Vertex,
|
||||||
BufferUploadMode::Dynamic,
|
BufferUploadMode::Dynamic,
|
||||||
);
|
);
|
||||||
|
self.ensure_index_buffer(solid_tile_vertices.len() / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_alpha_tiles(&mut self, alpha_tiles: &[AlphaTileBatchPrimitive]) {
|
fn upload_alpha_tiles(&mut self, alpha_tiles: &[AlphaTile]) {
|
||||||
self.device.allocate_buffer(
|
self.device.allocate_buffer(
|
||||||
&self.alpha_tile_vertex_array.vertex_buffer,
|
&self.alpha_tile_vertex_array.vertex_buffer,
|
||||||
BufferData::Memory(&alpha_tiles),
|
BufferData::Memory(&alpha_tiles),
|
||||||
BufferTarget::Vertex,
|
BufferTarget::Vertex,
|
||||||
BufferUploadMode::Dynamic,
|
BufferUploadMode::Dynamic,
|
||||||
);
|
);
|
||||||
|
self.ensure_index_buffer(alpha_tiles.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_index_buffer(&mut self, mut length: usize) {
|
||||||
|
length = length.next_power_of_two();
|
||||||
|
if self.quads_vertex_indices_length >= length {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(pcwalton): Generate these with SIMD.
|
||||||
|
let mut indices: Vec<u32> = Vec::with_capacity(length * 6);
|
||||||
|
for index in 0..(length as u32) {
|
||||||
|
indices.extend_from_slice(&[
|
||||||
|
index * 4 + 0, index * 4 + 1, index * 4 + 2,
|
||||||
|
index * 4 + 1, index * 4 + 3, index * 4 + 2,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.device.allocate_buffer(
|
||||||
|
&self.quads_vertex_indices_buffer,
|
||||||
|
BufferData::Memory(&indices),
|
||||||
|
BufferTarget::Index,
|
||||||
|
BufferUploadMode::Static,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.quads_vertex_indices_length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_fills(&mut self, mut fills: &[FillBatchPrimitive]) {
|
fn add_fills(&mut self, mut fills: &[FillBatchPrimitive]) {
|
||||||
|
@ -465,7 +497,7 @@ where
|
||||||
Transform4F::from_scale(scale).translate(Vector4F::new(-1.0, 1.0, 0.0, 1.0))
|
Transform4F::from_scale(scale).translate(Vector4F::new(-1.0, 1.0, 0.0, 1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_alpha_tiles(&mut self, count: u32) {
|
fn draw_alpha_tiles(&mut self, tile_count: u32) {
|
||||||
let clear_color = self.clear_color_for_draw_operation();
|
let clear_color = self.clear_color_for_draw_operation();
|
||||||
|
|
||||||
let mut textures = vec![self.device.framebuffer_texture(&self.mask_framebuffer)];
|
let mut textures = vec![self.device.framebuffer_texture(&self.mask_framebuffer)];
|
||||||
|
@ -490,7 +522,7 @@ where
|
||||||
.0
|
.0
|
||||||
.to_f32x2())));
|
.to_f32x2())));
|
||||||
|
|
||||||
self.device.draw_elements_instanced(6, count, &RenderState {
|
self.device.draw_elements(tile_count * 6, &RenderState {
|
||||||
target: &self.draw_render_target(),
|
target: &self.draw_render_target(),
|
||||||
program: &self.alpha_tile_program.program,
|
program: &self.alpha_tile_program.program,
|
||||||
vertex_array: &self.alpha_tile_vertex_array.vertex_array,
|
vertex_array: &self.alpha_tile_vertex_array.vertex_array,
|
||||||
|
@ -512,7 +544,7 @@ where
|
||||||
self.preserve_draw_framebuffer();
|
self.preserve_draw_framebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_solid_tiles(&mut self, count: u32) {
|
fn draw_solid_tiles(&mut self, tile_count: u32) {
|
||||||
let clear_color = self.clear_color_for_draw_operation();
|
let clear_color = self.clear_color_for_draw_operation();
|
||||||
|
|
||||||
let mut textures = vec![];
|
let mut textures = vec![];
|
||||||
|
@ -530,7 +562,7 @@ where
|
||||||
uniforms.push((&self.solid_tile_program.paint_texture_size_uniform,
|
uniforms.push((&self.solid_tile_program.paint_texture_size_uniform,
|
||||||
UniformData::Vec2(self.device.texture_size(paint_texture).0.to_f32x2())));
|
UniformData::Vec2(self.device.texture_size(paint_texture).0.to_f32x2())));
|
||||||
|
|
||||||
self.device.draw_elements_instanced(6, count, &RenderState {
|
self.device.draw_elements(6 * tile_count, &RenderState {
|
||||||
target: &self.draw_render_target(),
|
target: &self.draw_render_target(),
|
||||||
program: &self.solid_tile_program.program,
|
program: &self.solid_tile_program.program,
|
||||||
vertex_array: &self.solid_tile_vertex_array.vertex_array,
|
vertex_array: &self.solid_tile_vertex_array.vertex_array,
|
||||||
|
@ -940,87 +972,57 @@ where
|
||||||
fn new(
|
fn new(
|
||||||
device: &D,
|
device: &D,
|
||||||
alpha_tile_program: &AlphaTileProgram<D>,
|
alpha_tile_program: &AlphaTileProgram<D>,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quads_vertex_indices_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer,
|
|
||||||
) -> AlphaTileVertexArray<D> {
|
) -> AlphaTileVertexArray<D> {
|
||||||
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
||||||
|
|
||||||
let tess_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "TessCoord")
|
let tile_position_attr =
|
||||||
.unwrap();
|
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
|
||||||
let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin")
|
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||||
.unwrap();
|
"ColorTexCoord").unwrap();
|
||||||
|
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||||
|
"MaskTexCoord").unwrap();
|
||||||
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop")
|
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let tile_index_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileIndex")
|
|
||||||
.unwrap();
|
|
||||||
let color_tex_matrix_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
|
||||||
"ColorTexMatrix").unwrap();
|
|
||||||
let color_tex_offset_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
|
||||||
"ColorTexOffset").unwrap();
|
|
||||||
|
|
||||||
// NB: The object must be of type `I16`, not `U16`, to work around a macOS Radeon
|
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||||
// driver bug.
|
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||||
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
|
||||||
device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor {
|
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::U16,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: 4,
|
stride: MASK_TILE_VERTEX_SIZE,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
divisor: 0,
|
divisor: 0,
|
||||||
buffer_index: 0,
|
buffer_index: 0,
|
||||||
});
|
});
|
||||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
|
||||||
device.configure_vertex_attr(&vertex_array, &tile_origin_attr, &VertexAttrDescriptor {
|
size: 2,
|
||||||
size: 3,
|
class: VertexAttrClass::FloatNorm,
|
||||||
class: VertexAttrClass::Int,
|
attr_type: VertexAttrType::U16,
|
||||||
attr_type: VertexAttrType::U8,
|
stride: MASK_TILE_VERTEX_SIZE,
|
||||||
stride: MASK_TILE_INSTANCE_SIZE,
|
offset: 4,
|
||||||
offset: 0,
|
divisor: 0,
|
||||||
divisor: 1,
|
buffer_index: 0,
|
||||||
buffer_index: 1,
|
});
|
||||||
|
device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor {
|
||||||
|
size: 2,
|
||||||
|
class: VertexAttrClass::FloatNorm,
|
||||||
|
attr_type: VertexAttrType::U16,
|
||||||
|
stride: MASK_TILE_VERTEX_SIZE,
|
||||||
|
offset: 8,
|
||||||
|
divisor: 0,
|
||||||
|
buffer_index: 0,
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor {
|
device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor {
|
||||||
size: 1,
|
|
||||||
class: VertexAttrClass::Int,
|
|
||||||
attr_type: VertexAttrType::I8,
|
|
||||||
stride: MASK_TILE_INSTANCE_SIZE,
|
|
||||||
offset: 3,
|
|
||||||
divisor: 1,
|
|
||||||
buffer_index: 1,
|
|
||||||
});
|
|
||||||
device.configure_vertex_attr(&vertex_array, &tile_index_attr, &VertexAttrDescriptor {
|
|
||||||
size: 1,
|
size: 1,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::I16,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: MASK_TILE_INSTANCE_SIZE,
|
stride: MASK_TILE_VERTEX_SIZE,
|
||||||
offset: 6,
|
offset: 12,
|
||||||
divisor: 1,
|
divisor: 0,
|
||||||
buffer_index: 1,
|
buffer_index: 0,
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array,
|
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||||
&color_tex_matrix_attr,
|
|
||||||
&VertexAttrDescriptor {
|
|
||||||
size: 4,
|
|
||||||
class: VertexAttrClass::FloatNorm,
|
|
||||||
attr_type: VertexAttrType::U16,
|
|
||||||
stride: MASK_TILE_INSTANCE_SIZE,
|
|
||||||
offset: 8,
|
|
||||||
divisor: 1,
|
|
||||||
buffer_index: 1,
|
|
||||||
});
|
|
||||||
device.configure_vertex_attr(&vertex_array,
|
|
||||||
&color_tex_offset_attr,
|
|
||||||
&VertexAttrDescriptor {
|
|
||||||
size: 2,
|
|
||||||
class: VertexAttrClass::FloatNorm,
|
|
||||||
attr_type: VertexAttrType::U16,
|
|
||||||
stride: MASK_TILE_INSTANCE_SIZE,
|
|
||||||
offset: 16,
|
|
||||||
divisor: 1,
|
|
||||||
buffer_index: 1,
|
|
||||||
});
|
|
||||||
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
|
|
||||||
|
|
||||||
AlphaTileVertexArray { vertex_array, vertex_buffer }
|
AlphaTileVertexArray { vertex_array, vertex_buffer }
|
||||||
}
|
}
|
||||||
|
@ -1041,65 +1043,39 @@ where
|
||||||
fn new(
|
fn new(
|
||||||
device: &D,
|
device: &D,
|
||||||
solid_tile_program: &SolidTileProgram<D>,
|
solid_tile_program: &SolidTileProgram<D>,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quads_vertex_indices_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer,
|
|
||||||
) -> SolidTileVertexArray<D> {
|
) -> SolidTileVertexArray<D> {
|
||||||
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
||||||
|
|
||||||
let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord")
|
let tile_position_attr =
|
||||||
.unwrap();
|
device.get_vertex_attr(&solid_tile_program.program, "TilePosition").unwrap();
|
||||||
let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin")
|
let color_tex_coord_attr =
|
||||||
.unwrap();
|
device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord").unwrap();
|
||||||
let color_tex_matrix_attr = device.get_vertex_attr(&solid_tile_program.program,
|
|
||||||
"ColorTexMatrix").unwrap();
|
|
||||||
let color_tex_offset_attr = device.get_vertex_attr(&solid_tile_program.program,
|
|
||||||
"ColorTexOffset").unwrap();
|
|
||||||
|
|
||||||
// NB: The object must be of type short, not unsigned short, to work around a macOS
|
// NB: The tile origin must be of type short, not unsigned short, to work around a macOS
|
||||||
// Radeon driver bug.
|
// Radeon driver bug.
|
||||||
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||||
device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor {
|
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||||
size: 2,
|
size: 2,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::U16,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: 4,
|
stride: SOLID_TILE_VERTEX_SIZE,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
divisor: 0,
|
divisor: 0,
|
||||||
buffer_index: 0,
|
buffer_index: 0,
|
||||||
});
|
});
|
||||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
|
||||||
device.configure_vertex_attr(&vertex_array, &tile_origin_attr, &VertexAttrDescriptor {
|
|
||||||
size: 2,
|
|
||||||
class: VertexAttrClass::Int,
|
|
||||||
attr_type: VertexAttrType::I16,
|
|
||||||
stride: SOLID_TILE_INSTANCE_SIZE,
|
|
||||||
offset: 0,
|
|
||||||
divisor: 1,
|
|
||||||
buffer_index: 1,
|
|
||||||
});
|
|
||||||
device.configure_vertex_attr(&vertex_array,
|
device.configure_vertex_attr(&vertex_array,
|
||||||
&color_tex_matrix_attr,
|
&color_tex_coord_attr,
|
||||||
&VertexAttrDescriptor {
|
&VertexAttrDescriptor {
|
||||||
size: 4,
|
size: 2,
|
||||||
class: VertexAttrClass::FloatNorm,
|
class: VertexAttrClass::FloatNorm,
|
||||||
attr_type: VertexAttrType::U16,
|
attr_type: VertexAttrType::U16,
|
||||||
stride: SOLID_TILE_INSTANCE_SIZE,
|
stride: SOLID_TILE_VERTEX_SIZE,
|
||||||
offset: 4,
|
offset: 4,
|
||||||
divisor: 1,
|
divisor: 0,
|
||||||
buffer_index: 1,
|
buffer_index: 0,
|
||||||
});
|
});
|
||||||
device.configure_vertex_attr(&vertex_array,
|
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||||
&color_tex_offset_attr,
|
|
||||||
&VertexAttrDescriptor {
|
|
||||||
size: 2,
|
|
||||||
class: VertexAttrClass::FloatNorm,
|
|
||||||
attr_type: VertexAttrType::U16,
|
|
||||||
stride: SOLID_TILE_INSTANCE_SIZE,
|
|
||||||
offset: 12,
|
|
||||||
divisor: 1,
|
|
||||||
buffer_index: 1,
|
|
||||||
});
|
|
||||||
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
|
|
||||||
|
|
||||||
SolidTileVertexArray { vertex_array, vertex_buffer }
|
SolidTileVertexArray { vertex_array, vertex_buffer }
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use std::time::Duration;
|
||||||
pub(crate) struct BuiltObject {
|
pub(crate) struct BuiltObject {
|
||||||
pub bounds: RectF,
|
pub bounds: RectF,
|
||||||
pub fills: Vec<FillBatchPrimitive>,
|
pub fills: Vec<FillBatchPrimitive>,
|
||||||
pub alpha_tiles: Vec<AlphaTileBatchPrimitive>,
|
pub alpha_tiles: Vec<AlphaTile>,
|
||||||
pub tiles: DenseTileMap<TileObjectPrimitive>,
|
pub tiles: DenseTileMap<TileObjectPrimitive>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ pub enum RenderCommand {
|
||||||
AddPaintData(PaintData),
|
AddPaintData(PaintData),
|
||||||
AddFills(Vec<FillBatchPrimitive>),
|
AddFills(Vec<FillBatchPrimitive>),
|
||||||
FlushFills,
|
FlushFills,
|
||||||
AlphaTile(Vec<AlphaTileBatchPrimitive>),
|
AlphaTile(Vec<AlphaTile>),
|
||||||
SolidTile(Vec<SolidTileBatchPrimitive>),
|
SolidTile(Vec<SolidTileVertex>),
|
||||||
Finish { build_time: Duration },
|
Finish { build_time: Duration },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,34 +69,35 @@ pub struct FillBatchPrimitive {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SolidTileBatchPrimitive {
|
pub struct SolidTileVertex {
|
||||||
pub tile_x: i16,
|
pub tile_x: i16,
|
||||||
pub tile_y: i16,
|
pub tile_y: i16,
|
||||||
pub texture_m00: u16,
|
pub color_u: u16,
|
||||||
pub texture_m10: u16,
|
pub color_v: u16,
|
||||||
pub texture_m01: u16,
|
|
||||||
pub texture_m11: u16,
|
|
||||||
pub texture_m02: u16,
|
|
||||||
pub texture_m12: u16,
|
|
||||||
pub object_index: u16,
|
pub object_index: u16,
|
||||||
pub pad: u16,
|
pub pad: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct AlphaTileBatchPrimitive {
|
pub struct AlphaTile {
|
||||||
pub tile_x_lo: u8,
|
pub upper_left: AlphaTileVertex,
|
||||||
pub tile_y_lo: u8,
|
pub upper_right: AlphaTileVertex,
|
||||||
pub tile_hi: u8,
|
pub lower_left: AlphaTileVertex,
|
||||||
pub backdrop: i8,
|
pub lower_right: AlphaTileVertex,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct AlphaTileVertex {
|
||||||
|
pub tile_x: i16,
|
||||||
|
pub tile_y: i16,
|
||||||
|
pub color_u: u16,
|
||||||
|
pub color_v: u16,
|
||||||
|
pub mask_u: u16,
|
||||||
|
pub mask_v: u16,
|
||||||
|
pub backdrop: i16,
|
||||||
pub object_index: u16,
|
pub object_index: u16,
|
||||||
pub tile_index: u16,
|
|
||||||
pub texture_m00: u16,
|
|
||||||
pub texture_m10: u16,
|
|
||||||
pub texture_m01: u16,
|
|
||||||
pub texture_m11: u16,
|
|
||||||
pub texture_m02: u16,
|
|
||||||
pub texture_m12: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for RenderCommand {
|
impl Debug for RenderCommand {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// pathfinder/renderer/src/paint.rs
|
// pathfinder/renderer/src/paint.rs
|
||||||
//
|
//
|
||||||
// Copyright © 2019 The Pathfinder Project Developers.
|
// Copyright © 2020 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
@ -10,17 +10,25 @@
|
||||||
|
|
||||||
use crate::allocator::{TextureAllocator, TextureLocation};
|
use crate::allocator::{TextureAllocator, TextureLocation};
|
||||||
use crate::gpu_data::PaintData;
|
use crate::gpu_data::PaintData;
|
||||||
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use pathfinder_color::ColorU;
|
use pathfinder_color::ColorU;
|
||||||
use pathfinder_content::gradient::Gradient;
|
use pathfinder_content::gradient::Gradient;
|
||||||
use pathfinder_geometry::rect::RectI;
|
use pathfinder_geometry::rect::{RectF, RectI};
|
||||||
use pathfinder_geometry::transform2d::{Matrix2x2I, Transform2I};
|
use pathfinder_geometry::transform2d::{Matrix2x2F, Transform2F};
|
||||||
use pathfinder_geometry::vector::Vector2I;
|
use pathfinder_geometry::util;
|
||||||
use pathfinder_simd::default::I32x4;
|
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||||
|
use pathfinder_simd::default::F32x4;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
const PAINT_TEXTURE_LENGTH: u32 = 1024;
|
const PAINT_TEXTURE_LENGTH: u32 = 1024;
|
||||||
const PAINT_TEXTURE_SCALE: u32 = 65536 / PAINT_TEXTURE_LENGTH;
|
const PAINT_TEXTURE_SCALE: f32 = 1.0 / PAINT_TEXTURE_LENGTH as f32;
|
||||||
|
|
||||||
|
// The size of a gradient tile.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): Choose this size dynamically!
|
||||||
|
const GRADIENT_TILE_LENGTH: u32 = 256;
|
||||||
|
const GRADIENT_TILE_SCALE: f32 = GRADIENT_TILE_LENGTH as f32 * PAINT_TEXTURE_SCALE;
|
||||||
|
|
||||||
const SOLID_COLOR_TILE_LENGTH: u32 = 16;
|
const SOLID_COLOR_TILE_LENGTH: u32 = 16;
|
||||||
const MAX_SOLID_COLORS_PER_TILE: u32 = SOLID_COLOR_TILE_LENGTH * SOLID_COLOR_TILE_LENGTH;
|
const MAX_SOLID_COLORS_PER_TILE: u32 = SOLID_COLOR_TILE_LENGTH * SOLID_COLOR_TILE_LENGTH;
|
||||||
|
@ -112,10 +120,13 @@ pub struct PaintInfo {
|
||||||
pub metadata: Vec<PaintMetadata>,
|
pub metadata: Vec<PaintMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(pcwalton): Add clamp/repeat options.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PaintMetadata {
|
pub struct PaintMetadata {
|
||||||
/// The transform to apply to the texture coordinates, in 0.16 fixed point.
|
/// The rectangle within the texture atlas.
|
||||||
pub tex_transform: Transform2I,
|
pub tex_rect: RectI,
|
||||||
|
/// The transform to apply to screen coordinates to translate them into UVs.
|
||||||
|
pub tex_transform: Transform2F,
|
||||||
/// True if this paint is fully opaque.
|
/// True if this paint is fully opaque.
|
||||||
pub is_opaque: bool,
|
pub is_opaque: bool,
|
||||||
}
|
}
|
||||||
|
@ -133,29 +144,61 @@ impl Palette {
|
||||||
paint_id
|
paint_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_paint_info(&self) -> PaintInfo {
|
pub fn build_paint_info(&self, view_box_size: Vector2I) -> PaintInfo {
|
||||||
let mut allocator = TextureAllocator::new(PAINT_TEXTURE_LENGTH);
|
let mut allocator = TextureAllocator::new(PAINT_TEXTURE_LENGTH);
|
||||||
let area = PAINT_TEXTURE_LENGTH as usize * PAINT_TEXTURE_LENGTH as usize;
|
let area = PAINT_TEXTURE_LENGTH as usize * PAINT_TEXTURE_LENGTH as usize;
|
||||||
let (mut texels, mut metadata) = (vec![0; area * 4], vec![]);
|
let (mut texels, mut metadata) = (vec![0; area * 4], vec![]);
|
||||||
|
|
||||||
let mut solid_color_tile_builder = SolidColorTileBuilder::new();
|
let mut solid_color_tile_builder = SolidColorTileBuilder::new();
|
||||||
|
|
||||||
for paint in &self.paints {
|
for paint in &self.paints {
|
||||||
let tex_transform;
|
let (texture_location, tex_transform);
|
||||||
match paint {
|
match paint {
|
||||||
Paint::Color(color) => {
|
Paint::Color(color) => {
|
||||||
// TODO(pcwalton): Handle other paint types.
|
texture_location = solid_color_tile_builder.allocate(&mut allocator);
|
||||||
let texture_location = solid_color_tile_builder.allocate(&mut allocator);
|
let vector = rect_to_inset_uv(texture_location.rect).origin();
|
||||||
|
tex_transform = Transform2F { matrix: Matrix2x2F(F32x4::default()), vector };
|
||||||
put_pixel(&mut texels, texture_location.rect.origin(), *color);
|
put_pixel(&mut texels, texture_location.rect.origin(), *color);
|
||||||
tex_transform = Transform2I {
|
|
||||||
matrix: Matrix2x2I(I32x4::default()),
|
|
||||||
vector: texture_location.rect.origin().scale(PAINT_TEXTURE_SCALE as i32) +
|
|
||||||
Vector2I::splat(PAINT_TEXTURE_SCALE as i32 / 2),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Paint::Gradient(_) => unimplemented!(),
|
Paint::Gradient(ref gradient) => {
|
||||||
|
// TODO(pcwalton): Optimize this:
|
||||||
|
// 1. Use repeating/clamp on the sides.
|
||||||
|
// 2. Choose an optimal size for the gradient that minimizes memory usage while
|
||||||
|
// retaining quality.
|
||||||
|
texture_location =
|
||||||
|
allocator.allocate(Vector2I::splat(GRADIENT_TILE_LENGTH as i32))
|
||||||
|
.expect("Failed to allocate space for the gradient!");
|
||||||
|
|
||||||
|
tex_transform =
|
||||||
|
Transform2F::from_translation(rect_to_uv(texture_location.rect).origin()) *
|
||||||
|
Transform2F::from_scale(Vector2F::splat(GRADIENT_TILE_SCALE) /
|
||||||
|
view_box_size.to_f32());
|
||||||
|
|
||||||
|
let gradient_line = tex_transform * gradient.line();
|
||||||
|
|
||||||
|
// TODO(pcwalton): Optimize this:
|
||||||
|
// 1. Calculate ∇t up front and use differencing in the inner loop.
|
||||||
|
// 2. Go four pixels at a time with SIMD.
|
||||||
|
for y in 0..(GRADIENT_TILE_LENGTH as i32) {
|
||||||
|
for x in 0..(GRADIENT_TILE_LENGTH as i32) {
|
||||||
|
let point = texture_location.rect.origin() + Vector2I::new(x, y);
|
||||||
|
let vector = point.to_f32().scale(1.0 / PAINT_TEXTURE_LENGTH as f32) -
|
||||||
|
gradient_line.from();
|
||||||
|
|
||||||
|
let mut t = gradient_line.vector().projection_coefficient(vector);
|
||||||
|
t = util::clamp(t, 0.0, 1.0);
|
||||||
|
|
||||||
|
put_pixel(&mut texels, point, gradient.sample(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.push(PaintMetadata { tex_transform, is_opaque: paint.is_opaque() });
|
metadata.push(PaintMetadata {
|
||||||
|
tex_rect: texture_location.rect,
|
||||||
|
tex_transform,
|
||||||
|
is_opaque: paint.is_opaque(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = Vector2I::splat(PAINT_TEXTURE_LENGTH as i32);
|
let size = Vector2I::splat(PAINT_TEXTURE_LENGTH as i32);
|
||||||
|
@ -169,8 +212,27 @@ impl Palette {
|
||||||
texels[index + 2] = color.b;
|
texels[index + 2] = color.b;
|
||||||
texels[index + 3] = color.a;
|
texels[index + 3] = color.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rect_to_uv(rect: RectI) -> RectF {
|
||||||
|
rect.to_f32().scale(1.0 / PAINT_TEXTURE_LENGTH as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect_to_inset_uv(rect: RectI) -> RectF {
|
||||||
|
rect_to_uv(rect).contract(Vector2F::splat(0.5 / PAINT_TEXTURE_LENGTH as f32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PaintMetadata {
|
||||||
|
// TODO(pcwalton): Apply clamp/repeat to tile rect.
|
||||||
|
pub(crate) fn calculate_tex_coords(&self, tile_position: Vector2I) -> Vector2F {
|
||||||
|
let tile_size = Vector2I::new(TILE_WIDTH as i32, TILE_HEIGHT as i32);
|
||||||
|
let tex_coords = self.tex_transform * tile_position.scale_xy(tile_size).to_f32();
|
||||||
|
tex_coords
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solid color allocation
|
||||||
|
|
||||||
struct SolidColorTileBuilder(Option<SolidColorTileBuilderData>);
|
struct SolidColorTileBuilder(Option<SolidColorTileBuilderData>);
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl Scene {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build_paint_info(&self) -> PaintInfo {
|
pub fn build_paint_info(&self) -> PaintInfo {
|
||||||
self.palette.build_paint_info()
|
self.palette.build_paint_info(self.view_box.size().to_i32())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use crate::builder::SceneBuilder;
|
use crate::builder::SceneBuilder;
|
||||||
use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive};
|
use crate::gpu::renderer::MASK_TILES_ACROSS;
|
||||||
|
use crate::gpu_data::{AlphaTile, AlphaTileVertex, BuiltObject, TileObjectPrimitive};
|
||||||
use crate::paint::PaintMetadata;
|
use crate::paint::PaintMetadata;
|
||||||
use pathfinder_content::outline::{Contour, Outline, PointIndex};
|
use pathfinder_content::outline::{Contour, Outline, PointIndex};
|
||||||
use pathfinder_content::segment::Segment;
|
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::Transform2I;
|
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -126,15 +126,32 @@ impl<'a> Tiler<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let alpha_tile = AlphaTileBatchPrimitive::new(
|
self.built_object.alpha_tiles.push(AlphaTile {
|
||||||
tile_coords,
|
upper_left: AlphaTileVertex::new(tile_coords,
|
||||||
tile.backdrop,
|
|
||||||
self.object_index,
|
|
||||||
tile.alpha_tile_index as u16,
|
tile.alpha_tile_index as u16,
|
||||||
self.paint_metadata.tex_transform,
|
Vector2I::default(),
|
||||||
);
|
self.object_index,
|
||||||
|
tile.backdrop as i16,
|
||||||
self.built_object.alpha_tiles.push(alpha_tile);
|
&self.paint_metadata),
|
||||||
|
upper_right: AlphaTileVertex::new(tile_coords,
|
||||||
|
tile.alpha_tile_index as u16,
|
||||||
|
Vector2I::new(1, 0),
|
||||||
|
self.object_index,
|
||||||
|
tile.backdrop as i16,
|
||||||
|
&self.paint_metadata),
|
||||||
|
lower_left: AlphaTileVertex::new(tile_coords,
|
||||||
|
tile.alpha_tile_index as u16,
|
||||||
|
Vector2I::new(0, 1),
|
||||||
|
self.object_index,
|
||||||
|
tile.backdrop as i16,
|
||||||
|
&self.paint_metadata),
|
||||||
|
lower_right: AlphaTileVertex::new(tile_coords,
|
||||||
|
tile.alpha_tile_index as u16,
|
||||||
|
Vector2I::splat(1),
|
||||||
|
self.object_index,
|
||||||
|
tile.backdrop as i16,
|
||||||
|
&self.paint_metadata),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,36 +543,39 @@ impl PartialOrd<ActiveEdge> for ActiveEdge {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AlphaTileBatchPrimitive {
|
impl AlphaTileVertex {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(tile_coords: Vector2I,
|
fn new(tile_origin: Vector2I,
|
||||||
backdrop: i8,
|
|
||||||
object_index: u16,
|
|
||||||
tile_index: u16,
|
tile_index: u16,
|
||||||
tex_transform: Transform2I)
|
tile_offset: Vector2I,
|
||||||
-> AlphaTileBatchPrimitive {
|
object_index: u16,
|
||||||
AlphaTileBatchPrimitive {
|
backdrop: i16,
|
||||||
tile_x_lo: (tile_coords.x() & 0xff) as u8,
|
paint_metadata: &PaintMetadata)
|
||||||
tile_y_lo: (tile_coords.y() & 0xff) as u8,
|
-> AlphaTileVertex {
|
||||||
tile_hi: (((tile_coords.x() >> 8) & 0x0f) | ((tile_coords.y() >> 4) & 0xf0)) as u8,
|
let tile_position = tile_origin + tile_offset;
|
||||||
backdrop,
|
let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_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_scale = 65535.0 / MASK_TILES_ACROSS as f32;
|
||||||
|
let mask_uv = Vector2I::new(mask_u, mask_v) + tile_offset;
|
||||||
|
let mask_uv = mask_uv.to_f32().scale(mask_scale).to_i32();
|
||||||
|
|
||||||
|
AlphaTileVertex {
|
||||||
|
tile_x: tile_position.x() as i16,
|
||||||
|
tile_y: tile_position.y() as i16,
|
||||||
|
color_u: color_uv.x() as u16,
|
||||||
|
color_v: color_uv.y() as u16,
|
||||||
|
mask_u: mask_uv.x() as u16,
|
||||||
|
mask_v: mask_uv.y() as u16,
|
||||||
object_index,
|
object_index,
|
||||||
tile_index,
|
backdrop,
|
||||||
texture_m00: tex_transform.matrix.m11() as u16,
|
|
||||||
texture_m10: tex_transform.matrix.m21() as u16,
|
|
||||||
texture_m01: tex_transform.matrix.m12() as u16,
|
|
||||||
texture_m11: tex_transform.matrix.m22() as u16,
|
|
||||||
texture_m02: tex_transform.vector.x() as u16,
|
|
||||||
texture_m12: tex_transform.vector.y() as u16,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tile_coords(&self) -> Vector2I {
|
pub fn tile_position(&self) -> Vector2I {
|
||||||
Vector2I::new(
|
Vector2I::new(self.tile_x as i32, self.tile_y as i32)
|
||||||
(self.tile_x_lo as i32) | (((self.tile_hi & 0xf) as i32) << 8),
|
|
||||||
(self.tile_y_lo as i32) | (((self.tile_hi & 0xf0) as i32) << 4),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,12 @@
|
||||||
|
|
||||||
//! Software occlusion culling.
|
//! Software occlusion culling.
|
||||||
|
|
||||||
use crate::gpu_data::SolidTileBatchPrimitive;
|
use crate::gpu_data::SolidTileVertex;
|
||||||
use crate::paint::PaintMetadata;
|
use crate::paint::PaintMetadata;
|
||||||
use crate::scene::PathObject;
|
use crate::scene::PathObject;
|
||||||
use crate::tile_map::DenseTileMap;
|
use crate::tile_map::DenseTileMap;
|
||||||
use crate::tiles;
|
use crate::tiles;
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::transform2d::Transform2I;
|
|
||||||
use pathfinder_geometry::vector::Vector2I;
|
use pathfinder_geometry::vector::Vector2I;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
||||||
|
@ -61,7 +60,7 @@ impl ZBuffer {
|
||||||
paths: &[PathObject],
|
paths: &[PathObject],
|
||||||
paint_metadata: &[PaintMetadata],
|
paint_metadata: &[PaintMetadata],
|
||||||
object_range: Range<u32>)
|
object_range: Range<u32>)
|
||||||
-> Vec<SolidTileBatchPrimitive> {
|
-> Vec<SolidTileVertex> {
|
||||||
let mut solid_tiles = vec![];
|
let mut solid_tiles = vec![];
|
||||||
for tile_index in 0..self.buffer.data.len() {
|
for tile_index in 0..self.buffer.data.len() {
|
||||||
let depth = self.buffer.data[tile_index].load(AtomicOrdering::Relaxed);
|
let depth = self.buffer.data[tile_index].load(AtomicOrdering::Relaxed);
|
||||||
|
@ -76,30 +75,39 @@ impl ZBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
let paint_id = paths[object_index as usize].paint();
|
let paint_id = paths[object_index as usize].paint();
|
||||||
let tex_transform = paint_metadata[paint_id.0 as usize].tex_transform;
|
let paint_metadata = &paint_metadata[paint_id.0 as usize];
|
||||||
|
|
||||||
solid_tiles.push(SolidTileBatchPrimitive::new(tile_coords + self.buffer.rect.origin(),
|
let tile_position = tile_coords + self.buffer.rect.origin();
|
||||||
object_index as u16,
|
let object_index = object_index as u16;
|
||||||
tex_transform));
|
|
||||||
|
solid_tiles.extend_from_slice(&[
|
||||||
|
SolidTileVertex::new(tile_position, object_index, paint_metadata),
|
||||||
|
SolidTileVertex::new(tile_position + Vector2I::new(1, 0),
|
||||||
|
object_index,
|
||||||
|
paint_metadata),
|
||||||
|
SolidTileVertex::new(tile_position + Vector2I::new(0, 1),
|
||||||
|
object_index,
|
||||||
|
paint_metadata),
|
||||||
|
SolidTileVertex::new(tile_position + Vector2I::new(1, 1),
|
||||||
|
object_index,
|
||||||
|
paint_metadata),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
solid_tiles
|
solid_tiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SolidTileBatchPrimitive {
|
impl SolidTileVertex {
|
||||||
fn new(tile_coords: Vector2I, object_index: u16, tex_transform: Transform2I)
|
fn new(tile_position: Vector2I, object_index: u16, paint_metadata: &PaintMetadata)
|
||||||
-> SolidTileBatchPrimitive {
|
-> SolidTileVertex {
|
||||||
SolidTileBatchPrimitive {
|
let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32();
|
||||||
tile_x: tile_coords.x() as i16,
|
SolidTileVertex {
|
||||||
tile_y: tile_coords.y() as i16,
|
tile_x: tile_position.x() as i16,
|
||||||
|
tile_y: tile_position.y() as i16,
|
||||||
object_index: object_index,
|
object_index: object_index,
|
||||||
texture_m00: tex_transform.matrix.m11() as u16,
|
color_u: color_uv.x() as u16,
|
||||||
texture_m10: tex_transform.matrix.m21() as u16,
|
color_v: color_uv.y() as u16,
|
||||||
texture_m01: tex_transform.matrix.m12() as u16,
|
|
||||||
texture_m11: tex_transform.matrix.m22() as u16,
|
|
||||||
texture_m02: tex_transform.vector.x() as u16,
|
|
||||||
texture_m12: tex_transform.vector.y() as u16,
|
|
||||||
pad: 0,
|
pad: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ uniform sampler2D uStencilTexture;
|
||||||
uniform sampler2D uPaintTexture;
|
uniform sampler2D uPaintTexture;
|
||||||
uniform vec2 uPaintTextureSize;
|
uniform vec2 uPaintTextureSize;
|
||||||
|
|
||||||
in vec2 vMaskTexCoord;
|
|
||||||
in vec2 vColorTexCoord;
|
in vec2 vColorTexCoord;
|
||||||
|
in vec2 vMaskTexCoord;
|
||||||
in float vBackdrop;
|
in float vBackdrop;
|
||||||
in vec4 vColor;
|
in vec4 vColor;
|
||||||
|
|
||||||
|
|
|
@ -18,32 +18,20 @@ uniform mat4 uTransform;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
uniform vec2 uStencilTextureSize;
|
uniform vec2 uStencilTextureSize;
|
||||||
|
|
||||||
in uvec2 aTessCoord;
|
in ivec2 aTilePosition;
|
||||||
in uvec3 aTileOrigin;
|
in vec2 aColorTexCoord;
|
||||||
in vec4 aColorTexMatrix;
|
in vec2 aMaskTexCoord;
|
||||||
in vec2 aColorTexOffset;
|
|
||||||
in int aBackdrop;
|
in int aBackdrop;
|
||||||
in int aTileIndex;
|
|
||||||
|
|
||||||
out vec2 vMaskTexCoord;
|
|
||||||
out vec2 vColorTexCoord;
|
out vec2 vColorTexCoord;
|
||||||
|
out vec2 vMaskTexCoord;
|
||||||
out float vBackdrop;
|
out float vBackdrop;
|
||||||
|
|
||||||
vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth){
|
|
||||||
uint tilesPerRow = uint(stencilTextureWidth / uTileSize . x);
|
|
||||||
uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow);
|
|
||||||
return vec2(tileOffset)* uTileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
vec2 tileOffset = vec2(aTessCoord)* uTileSize;
|
vec2 position = aTilePosition * uTileSize;
|
||||||
vec2 origin = vec2(aTileOrigin . xy)+ vec2(aTileOrigin . z & 15u, aTileOrigin . z >> 4u)* 256.0;
|
|
||||||
vec2 position = origin * uTileSize + tileOffset;
|
|
||||||
vec2 maskTexCoordOrigin = computeTileOffset(uint(aTileIndex), uStencilTextureSize . x);
|
|
||||||
vec2 maskTexCoord = maskTexCoordOrigin + tileOffset;
|
|
||||||
|
|
||||||
vMaskTexCoord = maskTexCoord / uStencilTextureSize;
|
vMaskTexCoord = aMaskTexCoord;
|
||||||
vColorTexCoord = mat2(aColorTexMatrix)* tileOffset + aColorTexOffset;
|
vColorTexCoord = aColorTexCoord;
|
||||||
vBackdrop = float(aBackdrop);
|
vBackdrop = float(aBackdrop);
|
||||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,14 @@ precision highp float;
|
||||||
uniform mat4 uTransform;
|
uniform mat4 uTransform;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
|
|
||||||
in uvec2 aTessCoord;
|
in ivec2 aTilePosition;
|
||||||
in ivec2 aTileOrigin;
|
in vec2 aColorTexCoord;
|
||||||
in vec4 aColorTexMatrix;
|
|
||||||
in vec2 aColorTexOffset;
|
|
||||||
|
|
||||||
out vec2 vColorTexCoord;
|
out vec2 vColorTexCoord;
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
vec2 tileOffset = vec2(aTessCoord)* uTileSize;
|
vec2 position = aTilePosition * uTileSize;
|
||||||
vec2 position = aTileOrigin * uTileSize + tileOffset;
|
vColorTexCoord = aColorTexCoord;
|
||||||
vColorTexCoord = mat2(aColorTexMatrix)* tileOffset + aColorTexOffset;
|
|
||||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ struct main0_out
|
||||||
|
|
||||||
struct main0_in
|
struct main0_in
|
||||||
{
|
{
|
||||||
float2 vMaskTexCoord [[user(locn0)]];
|
float2 vColorTexCoord [[user(locn0)]];
|
||||||
float2 vColorTexCoord [[user(locn1)]];
|
float2 vMaskTexCoord [[user(locn1)]];
|
||||||
float vBackdrop [[user(locn2)]];
|
float vBackdrop [[user(locn2)]];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
||||||
|
|
||||||
#include <metal_stdlib>
|
#include <metal_stdlib>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
@ -9,47 +7,31 @@ using namespace metal;
|
||||||
struct spvDescriptorSetBuffer0
|
struct spvDescriptorSetBuffer0
|
||||||
{
|
{
|
||||||
constant float2* uTileSize [[id(0)]];
|
constant float2* uTileSize [[id(0)]];
|
||||||
constant float2* uStencilTextureSize [[id(1)]];
|
constant float4x4* uTransform [[id(1)]];
|
||||||
constant float4x4* uTransform [[id(2)]];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct main0_out
|
struct main0_out
|
||||||
{
|
{
|
||||||
float2 vMaskTexCoord [[user(locn0)]];
|
float2 vColorTexCoord [[user(locn0)]];
|
||||||
float2 vColorTexCoord [[user(locn1)]];
|
float2 vMaskTexCoord [[user(locn1)]];
|
||||||
float vBackdrop [[user(locn2)]];
|
float vBackdrop [[user(locn2)]];
|
||||||
float4 gl_Position [[position]];
|
float4 gl_Position [[position]];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct main0_in
|
struct main0_in
|
||||||
{
|
{
|
||||||
uint2 aTessCoord [[attribute(0)]];
|
int2 aTilePosition [[attribute(0)]];
|
||||||
uint3 aTileOrigin [[attribute(1)]];
|
float2 aColorTexCoord [[attribute(1)]];
|
||||||
float4 aColorTexMatrix [[attribute(2)]];
|
float2 aMaskTexCoord [[attribute(2)]];
|
||||||
float2 aColorTexOffset [[attribute(3)]];
|
int aBackdrop [[attribute(3)]];
|
||||||
int aBackdrop [[attribute(4)]];
|
|
||||||
int aTileIndex [[attribute(5)]];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
float2 computeTileOffset(thread const uint& tileIndex, thread const float& stencilTextureWidth, thread float2 uTileSize)
|
|
||||||
{
|
|
||||||
uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x);
|
|
||||||
uint2 tileOffset = uint2(tileIndex % tilesPerRow, tileIndex / tilesPerRow);
|
|
||||||
return float2(tileOffset) * uTileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
float2 tileOffset = float2(in.aTessCoord) * (*spvDescriptorSet0.uTileSize);
|
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||||
float2 origin = float2(in.aTileOrigin.xy) + (float2(float(in.aTileOrigin.z & 15u), float(in.aTileOrigin.z >> 4u)) * 256.0);
|
out.vMaskTexCoord = in.aMaskTexCoord;
|
||||||
float2 position = (origin * (*spvDescriptorSet0.uTileSize)) + tileOffset;
|
out.vColorTexCoord = in.aColorTexCoord;
|
||||||
uint param = uint(in.aTileIndex);
|
|
||||||
float param_1 = (*spvDescriptorSet0.uStencilTextureSize).x;
|
|
||||||
float2 maskTexCoordOrigin = computeTileOffset(param, param_1, (*spvDescriptorSet0.uTileSize));
|
|
||||||
float2 maskTexCoord = maskTexCoordOrigin + tileOffset;
|
|
||||||
out.vMaskTexCoord = maskTexCoord / (*spvDescriptorSet0.uStencilTextureSize);
|
|
||||||
out.vColorTexCoord = (float2x2(float2(in.aColorTexMatrix.xy), float2(in.aColorTexMatrix.zw)) * tileOffset) + in.aColorTexOffset;
|
|
||||||
out.vBackdrop = float(in.aBackdrop);
|
out.vBackdrop = float(in.aBackdrop);
|
||||||
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;
|
||||||
|
|
|
@ -18,18 +18,15 @@ struct main0_out
|
||||||
|
|
||||||
struct main0_in
|
struct main0_in
|
||||||
{
|
{
|
||||||
uint2 aTessCoord [[attribute(0)]];
|
int2 aTilePosition [[attribute(0)]];
|
||||||
int2 aTileOrigin [[attribute(1)]];
|
float2 aColorTexCoord [[attribute(1)]];
|
||||||
float4 aColorTexMatrix [[attribute(2)]];
|
|
||||||
float2 aColorTexOffset [[attribute(3)]];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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 tileOffset = float2(in.aTessCoord) * (*spvDescriptorSet0.uTileSize);
|
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||||
float2 position = (float2(in.aTileOrigin) * (*spvDescriptorSet0.uTileSize)) + tileOffset;
|
out.vColorTexCoord = in.aColorTexCoord;
|
||||||
out.vColorTexCoord = (float2x2(float2(in.aColorTexMatrix.xy), float2(in.aColorTexMatrix.zw)) * tileOffset) + in.aColorTexOffset;
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// pathfinder/shaders/tile_alpha.fs.glsl
|
// pathfinder/shaders/tile_alpha.fs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2018 The Pathfinder Project Developers.
|
// Copyright © 2020 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
@ -16,8 +16,8 @@ uniform sampler2D uStencilTexture;
|
||||||
uniform sampler2D uPaintTexture;
|
uniform sampler2D uPaintTexture;
|
||||||
uniform vec2 uPaintTextureSize;
|
uniform vec2 uPaintTextureSize;
|
||||||
|
|
||||||
in vec2 vMaskTexCoord;
|
|
||||||
in vec2 vColorTexCoord;
|
in vec2 vColorTexCoord;
|
||||||
|
in vec2 vMaskTexCoord;
|
||||||
in float vBackdrop;
|
in float vBackdrop;
|
||||||
in vec4 vColor;
|
in vec4 vColor;
|
||||||
|
|
||||||
|
|
|
@ -16,32 +16,20 @@ uniform mat4 uTransform;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
uniform vec2 uStencilTextureSize;
|
uniform vec2 uStencilTextureSize;
|
||||||
|
|
||||||
in uvec2 aTessCoord;
|
in ivec2 aTilePosition;
|
||||||
in uvec3 aTileOrigin;
|
in vec2 aColorTexCoord;
|
||||||
in vec4 aColorTexMatrix;
|
in vec2 aMaskTexCoord;
|
||||||
in vec2 aColorTexOffset;
|
|
||||||
in int aBackdrop;
|
in int aBackdrop;
|
||||||
in int aTileIndex;
|
|
||||||
|
|
||||||
out vec2 vMaskTexCoord;
|
|
||||||
out vec2 vColorTexCoord;
|
out vec2 vColorTexCoord;
|
||||||
|
out vec2 vMaskTexCoord;
|
||||||
out float vBackdrop;
|
out float vBackdrop;
|
||||||
|
|
||||||
vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) {
|
|
||||||
uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x);
|
|
||||||
uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow);
|
|
||||||
return vec2(tileOffset) * uTileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 tileOffset = vec2(aTessCoord) * uTileSize;
|
vec2 position = aTilePosition * uTileSize;
|
||||||
vec2 origin = vec2(aTileOrigin.xy) + vec2(aTileOrigin.z & 15u, aTileOrigin.z >> 4u) * 256.0;
|
|
||||||
vec2 position = origin * uTileSize + tileOffset;
|
|
||||||
vec2 maskTexCoordOrigin = computeTileOffset(uint(aTileIndex), uStencilTextureSize.x);
|
|
||||||
vec2 maskTexCoord = maskTexCoordOrigin + tileOffset;
|
|
||||||
|
|
||||||
vMaskTexCoord = maskTexCoord / uStencilTextureSize;
|
vMaskTexCoord = aMaskTexCoord;
|
||||||
vColorTexCoord = mat2(aColorTexMatrix) * tileOffset + aColorTexOffset;
|
vColorTexCoord = aColorTexCoord;
|
||||||
vBackdrop = float(aBackdrop);
|
vBackdrop = float(aBackdrop);
|
||||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// pathfinder/shaders/tile_solid.vs.glsl
|
// pathfinder/shaders/tile_solid.vs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2019 The Pathfinder Project Developers.
|
// Copyright © 2020 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
@ -15,16 +15,13 @@ precision highp float;
|
||||||
uniform mat4 uTransform;
|
uniform mat4 uTransform;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
|
|
||||||
in uvec2 aTessCoord;
|
in ivec2 aTilePosition;
|
||||||
in ivec2 aTileOrigin;
|
in vec2 aColorTexCoord;
|
||||||
in vec4 aColorTexMatrix;
|
|
||||||
in vec2 aColorTexOffset;
|
|
||||||
|
|
||||||
out vec2 vColorTexCoord;
|
out vec2 vColorTexCoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 tileOffset = vec2(aTessCoord) * uTileSize;
|
vec2 position = aTilePosition * uTileSize;
|
||||||
vec2 position = aTileOrigin * uTileSize + tileOffset;
|
vColorTexCoord = aColorTexCoord;
|
||||||
vColorTexCoord = mat2(aColorTexMatrix) * tileOffset + aColorTexOffset;
|
|
||||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,14 @@ impl Add<F32x2> for F32x2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<F32x2> for F32x2 {
|
||||||
|
type Output = F32x2;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: F32x2) -> F32x2 {
|
||||||
|
unsafe { F32x2(simd_div(self.0, other.0)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<F32x2> for F32x2 {
|
impl Mul<F32x2> for F32x2 {
|
||||||
type Output = F32x2;
|
type Output = F32x2;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -380,6 +388,14 @@ impl Add<F32x4> for F32x4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<F32x4> for F32x4 {
|
||||||
|
type Output = F32x4;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: F32x4) -> F32x4 {
|
||||||
|
unsafe { F32x4(simd_div(self.0, other.0)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<F32x4> for F32x4 {
|
impl Mul<F32x4> for F32x4 {
|
||||||
type Output = F32x4;
|
type Output = F32x4;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -412,6 +428,18 @@ impl I32x2 {
|
||||||
I32x2::new(x, x)
|
I32x2::new(x, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn x(self) -> i32 {
|
||||||
|
self[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn y(self) -> i32 {
|
||||||
|
self[1]
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn packed_eq(self, other: I32x2) -> U32x2 {
|
pub fn packed_eq(self, other: I32x2) -> U32x2 {
|
||||||
unsafe { U32x2(simd_eq(self.0, other.0)) }
|
unsafe { U32x2(simd_eq(self.0, other.0)) }
|
||||||
|
@ -750,6 +778,7 @@ impl Index<usize> for U32x4 {
|
||||||
|
|
||||||
extern "platform-intrinsic" {
|
extern "platform-intrinsic" {
|
||||||
fn simd_add<T>(x: T, y: T) -> T;
|
fn simd_add<T>(x: T, y: T) -> T;
|
||||||
|
fn simd_div<T>(x: T, y: T) -> T;
|
||||||
fn simd_mul<T>(x: T, y: T) -> T;
|
fn simd_mul<T>(x: T, y: T) -> T;
|
||||||
fn simd_sub<T>(x: T, y: T) -> T;
|
fn simd_sub<T>(x: T, y: T) -> T;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::ops::{Add, BitAnd, BitOr, Index, IndexMut, Mul, Shr, Sub};
|
use std::ops::{Add, BitAnd, BitOr, Div, Index, IndexMut, Mul, Shr, Sub};
|
||||||
|
|
||||||
mod swizzle_f32x4;
|
mod swizzle_f32x4;
|
||||||
mod swizzle_i32x4;
|
mod swizzle_i32x4;
|
||||||
|
@ -166,6 +166,14 @@ impl Add<F32x2> for F32x2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<F32x2> for F32x2 {
|
||||||
|
type Output = F32x2;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: F32x2) -> F32x2 {
|
||||||
|
F32x2([self[0] / other[0], self[1] / other[1]])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<F32x2> for F32x2 {
|
impl Mul<F32x2> for F32x2 {
|
||||||
type Output = F32x2;
|
type Output = F32x2;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -403,6 +411,19 @@ impl Add<F32x4> for F32x4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<F32x4> for F32x4 {
|
||||||
|
type Output = F32x4;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: F32x4) -> F32x4 {
|
||||||
|
F32x4([
|
||||||
|
self[0] / other[0],
|
||||||
|
self[1] / other[1],
|
||||||
|
self[2] / other[2],
|
||||||
|
self[3] / other[3],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<F32x4> for F32x4 {
|
impl Mul<F32x4> for F32x4 {
|
||||||
type Output = F32x4;
|
type Output = F32x4;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -445,6 +466,18 @@ impl I32x2 {
|
||||||
I32x2([x, x])
|
I32x2([x, x])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn x(self) -> i32 {
|
||||||
|
self[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn y(self) -> i32 {
|
||||||
|
self[1]
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn packed_eq(self, other: I32x2) -> U32x2 {
|
pub fn packed_eq(self, other: I32x2) -> U32x2 {
|
||||||
U32x2([
|
U32x2([
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Index, IndexMut, Mul, Not, Shr, Sub};
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Index, IndexMut, Mul, Not, Shr, Sub};
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
use std::arch::x86::{__m128, __m128i};
|
use std::arch::x86::{__m128, __m128i};
|
||||||
|
@ -191,6 +191,14 @@ impl Add<F32x2> for F32x2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<F32x2> for F32x2 {
|
||||||
|
type Output = F32x2;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: F32x2) -> F32x2 {
|
||||||
|
(self.to_f32x4() / other.to_f32x4()).xy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<F32x2> for F32x2 {
|
impl Mul<F32x2> for F32x2 {
|
||||||
type Output = F32x2;
|
type Output = F32x2;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -423,6 +431,14 @@ impl Add<F32x4> for F32x4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<F32x4> for F32x4 {
|
||||||
|
type Output = F32x4;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: F32x4) -> F32x4 {
|
||||||
|
unsafe { F32x4(x86::_mm_div_ps(self.0, other.0)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<F32x4> for F32x4 {
|
impl Mul<F32x4> for F32x4 {
|
||||||
type Output = F32x4;
|
type Output = F32x4;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -461,6 +477,18 @@ impl I32x2 {
|
||||||
I32x2::new(x, x)
|
I32x2::new(x, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn x(self) -> i32 {
|
||||||
|
self[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn y(self) -> i32 {
|
||||||
|
self[1]
|
||||||
|
}
|
||||||
|
|
||||||
// Concatenations
|
// Concatenations
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in New Issue