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)",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "color-backtrace"
|
||||
version = "0.3.0"
|
||||
|
@ -615,7 +601,7 @@ name = "demo"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"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)",
|
||||
"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)",
|
||||
|
@ -1731,9 +1717,9 @@ 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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
|
@ -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 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.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_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"
|
||||
|
|
|
@ -28,6 +28,7 @@ use std::f32::consts::PI;
|
|||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use text::FontCollection;
|
||||
|
||||
#[cfg(feature = "pf-text")]
|
||||
pub use text::TextMetrics;
|
||||
pub use text::CanvasFontContext;
|
||||
|
|
|
@ -21,6 +21,11 @@ pub struct ColorU {
|
|||
}
|
||||
|
||||
impl ColorU {
|
||||
#[inline]
|
||||
pub fn new(r: u8, g: u8, b: u8, a: u8) -> ColorU {
|
||||
ColorU { r, g, b, a }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transparent_black() -> ColorU {
|
||||
ColorU::from_u32(0)
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::sorted_vector::SortedVector;
|
|||
use pathfinder_color::ColorU;
|
||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::cmp::{self, Ordering, PartialOrd};
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
use std::convert;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
|
@ -25,8 +25,8 @@ pub struct Gradient {
|
|||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||
pub struct ColorStop {
|
||||
pub color: ColorU,
|
||||
pub offset: f32,
|
||||
pub color: ColorU,
|
||||
}
|
||||
|
||||
impl Eq for Gradient {}
|
||||
|
@ -79,10 +79,11 @@ impl Gradient {
|
|||
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)
|
||||
}).unwrap_or_else(convert::identity);
|
||||
let upper_index = cmp::min(lower_index + 1, self.stops.len() - 1);
|
||||
}).unwrap_or_else(convert::identity).min(last_index);
|
||||
let lower_index = if upper_index > 0 { upper_index - 1 } else { upper_index };
|
||||
|
||||
let lower_stop = &self.stops.array[lower_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"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
foreign-types = "0.5"
|
||||
foreign-types = "0.3"
|
||||
metal = "0.17"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
|
||||
|
|
|
@ -181,6 +181,11 @@ impl RectF {
|
|||
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]
|
||||
pub fn to_i32(&self) -> RectI {
|
||||
RectI(self.0.to_i32x4())
|
||||
|
@ -308,6 +313,11 @@ impl RectI {
|
|||
.all_true()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contract(self, amount: Vector2I) -> RectI {
|
||||
RectI::from_points(self.origin() + amount, self.lower_right() - amount)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> RectF {
|
||||
RectF(self.0.to_f32x4())
|
||||
|
|
|
@ -14,8 +14,8 @@ use crate::line_segment::LineSegment2F;
|
|||
use crate::rect::RectF;
|
||||
use crate::transform3d::Transform4F;
|
||||
use crate::unit_vector::UnitVector;
|
||||
use crate::vector::{Vector2F, Vector2I};
|
||||
use pathfinder_simd::default::{F32x4, I32x4};
|
||||
use crate::vector::Vector2F;
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::ops::{Mul, MulAssign, Sub};
|
||||
|
||||
/// A 2x2 matrix, optimized with SIMD, in column-major order.
|
||||
|
@ -74,14 +74,17 @@ impl Matrix2x2F {
|
|||
pub fn m11(&self) -> f32 {
|
||||
self.0[0]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m21(&self) -> f32 {
|
||||
self.0[1]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m12(&self) -> f32 {
|
||||
self.0[2]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m22(&self) -> f32 {
|
||||
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.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Transform2F {
|
||||
|
@ -346,10 +326,3 @@ impl MulAssign for Transform2F {
|
|||
*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.
|
||||
|
||||
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.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
|
@ -135,6 +135,15 @@ impl Vector2F {
|
|||
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]
|
||||
pub fn is_zero(self) -> bool {
|
||||
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 {
|
||||
type Output = Vector2F;
|
||||
#[inline]
|
||||
|
|
|
@ -8,9 +8,9 @@ edition = "2018"
|
|||
bitflags = "1.0"
|
||||
byteorder = "1.3"
|
||||
block = "0.1"
|
||||
cocoa = "0.20"
|
||||
cocoa = "0.19"
|
||||
core-foundation = "0.7"
|
||||
foreign-types = "0.5"
|
||||
foreign-types = "0.3"
|
||||
half = "1.4"
|
||||
metal = "0.17"
|
||||
objc = "0.2"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//! Packs data onto the GPU.
|
||||
|
||||
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::paint::{PaintInfo, PaintMetadata};
|
||||
use crate::scene::Scene;
|
||||
|
@ -23,6 +23,7 @@ use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
|||
use pathfinder_geometry::rect::{RectF, RectI};
|
||||
use pathfinder_geometry::util;
|
||||
use pathfinder_simd::default::{F32x4, I32x4};
|
||||
use std::i16;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::Instant;
|
||||
use std::u16;
|
||||
|
@ -88,7 +89,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
built_options: &PreparedBuildOptions,
|
||||
scene: &Scene,
|
||||
paint_metadata: &[PaintMetadata],
|
||||
) -> Vec<AlphaTileBatchPrimitive> {
|
||||
) -> Vec<AlphaTile> {
|
||||
let path_object = &scene.paths[path_index];
|
||||
let outline = scene.apply_render_options(path_object.outline(), built_options);
|
||||
let paint_id = path_object.paint();
|
||||
|
@ -105,26 +106,29 @@ impl<'a> SceneBuilder<'a> {
|
|||
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 {
|
||||
let alpha_tile_coords = alpha_tile.tile_coords();
|
||||
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
||||
if self
|
||||
.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;
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): Clean this up.
|
||||
alpha_tile.tile_x_lo = 0xff;
|
||||
alpha_tile.tile_y_lo = 0xff;
|
||||
alpha_tile.tile_hi = 0xff;
|
||||
alpha_tile.upper_left.tile_x = i16::MIN;
|
||||
alpha_tile.upper_left.tile_y = i16::MIN;
|
||||
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,
|
||||
paint_metadata: &[PaintMetadata],
|
||||
alpha_tiles: Vec<AlphaTileBatchPrimitive>) {
|
||||
fn pack_alpha_tiles(&mut self, paint_metadata: &[PaintMetadata], alpha_tiles: Vec<AlphaTile>) {
|
||||
let path_count = self.scene.paths.len() as u32;
|
||||
let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths,
|
||||
paint_metadata,
|
||||
|
@ -139,7 +143,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
|
||||
fn finish_building(&mut self,
|
||||
paint_metadata: &[PaintMetadata],
|
||||
mut alpha_tiles: Vec<AlphaTileBatchPrimitive>) {
|
||||
mut alpha_tiles: Vec<AlphaTile>) {
|
||||
self.listener.send(RenderCommand::FlushFills);
|
||||
self.cull_alpha_tiles(&mut alpha_tiles);
|
||||
self.pack_alpha_tiles(paint_metadata, alpha_tiles);
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
|
||||
use crate::gpu::debug::DebugUIPresenter;
|
||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||
use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive, PaintData};
|
||||
use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive};
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex};
|
||||
use crate::post::DefringingKernel;
|
||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||
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_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!
|
||||
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * 256;
|
||||
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT 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 * MASK_TILES_DOWN as i32;
|
||||
|
||||
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
||||
const FILL_INSTANCE_SIZE: usize = 8;
|
||||
const SOLID_TILE_INSTANCE_SIZE: usize = 20;
|
||||
const MASK_TILE_INSTANCE_SIZE: usize = 20;
|
||||
const SOLID_TILE_VERTEX_SIZE: usize = 12;
|
||||
const MASK_TILE_VERTEX_SIZE: usize = 16;
|
||||
|
||||
const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
||||
|
||||
|
@ -63,6 +65,8 @@ where
|
|||
area_lut_texture: D::Texture,
|
||||
quad_vertex_positions_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>,
|
||||
mask_framebuffer: D::Framebuffer,
|
||||
paint_texture: Option<D::Texture>,
|
||||
|
@ -132,6 +136,7 @@ where
|
|||
BufferTarget::Index,
|
||||
BufferUploadMode::Static,
|
||||
);
|
||||
let quads_vertex_indices_buffer = device.create_buffer();
|
||||
|
||||
let fill_vertex_array = FillVertexArray::new(
|
||||
&device,
|
||||
|
@ -142,14 +147,12 @@ where
|
|||
let alpha_tile_vertex_array = AlphaTileVertexArray::new(
|
||||
&device,
|
||||
&alpha_tile_program,
|
||||
&quad_vertex_positions_buffer,
|
||||
&quad_vertex_indices_buffer,
|
||||
&quads_vertex_indices_buffer,
|
||||
);
|
||||
let solid_tile_vertex_array = SolidTileVertexArray::new(
|
||||
&device,
|
||||
&solid_tile_program,
|
||||
&quad_vertex_positions_buffer,
|
||||
&quad_vertex_indices_buffer,
|
||||
&quads_vertex_indices_buffer,
|
||||
);
|
||||
let postprocess_vertex_array = PostprocessVertexArray::new(
|
||||
&device,
|
||||
|
@ -187,6 +190,8 @@ where
|
|||
area_lut_texture,
|
||||
quad_vertex_positions_buffer,
|
||||
quad_vertex_indices_buffer,
|
||||
quads_vertex_indices_buffer,
|
||||
quads_vertex_indices_length: 0,
|
||||
fill_vertex_array,
|
||||
mask_framebuffer,
|
||||
paint_texture: None,
|
||||
|
@ -237,10 +242,10 @@ where
|
|||
self.draw_buffered_fills();
|
||||
self.begin_composite_timer_query();
|
||||
}
|
||||
RenderCommand::SolidTile(ref solid_tiles) => {
|
||||
let count = solid_tiles.len();
|
||||
RenderCommand::SolidTile(ref solid_tile_vertices) => {
|
||||
let count = solid_tile_vertices.len() / 4;
|
||||
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);
|
||||
}
|
||||
RenderCommand::AlphaTile(ref alpha_tiles) => {
|
||||
|
@ -370,22 +375,49 @@ where
|
|||
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.solid_tile_vertex_array.vertex_buffer,
|
||||
BufferData::Memory(&solid_tiles),
|
||||
BufferData::Memory(&solid_tile_vertices),
|
||||
BufferTarget::Vertex,
|
||||
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.alpha_tile_vertex_array.vertex_buffer,
|
||||
BufferData::Memory(&alpha_tiles),
|
||||
BufferTarget::Vertex,
|
||||
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]) {
|
||||
|
@ -465,7 +497,7 @@ where
|
|||
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 mut textures = vec![self.device.framebuffer_texture(&self.mask_framebuffer)];
|
||||
|
@ -490,7 +522,7 @@ where
|
|||
.0
|
||||
.to_f32x2())));
|
||||
|
||||
self.device.draw_elements_instanced(6, count, &RenderState {
|
||||
self.device.draw_elements(tile_count * 6, &RenderState {
|
||||
target: &self.draw_render_target(),
|
||||
program: &self.alpha_tile_program.program,
|
||||
vertex_array: &self.alpha_tile_vertex_array.vertex_array,
|
||||
|
@ -512,7 +544,7 @@ where
|
|||
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 mut textures = vec![];
|
||||
|
@ -530,7 +562,7 @@ where
|
|||
uniforms.push((&self.solid_tile_program.paint_texture_size_uniform,
|
||||
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(),
|
||||
program: &self.solid_tile_program.program,
|
||||
vertex_array: &self.solid_tile_vertex_array.vertex_array,
|
||||
|
@ -940,87 +972,57 @@ where
|
|||
fn new(
|
||||
device: &D,
|
||||
alpha_tile_program: &AlphaTileProgram<D>,
|
||||
quad_vertex_positions_buffer: &D::Buffer,
|
||||
quad_vertex_indices_buffer: &D::Buffer,
|
||||
quads_vertex_indices_buffer: &D::Buffer,
|
||||
) -> AlphaTileVertexArray<D> {
|
||||
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")
|
||||
.unwrap();
|
||||
let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin")
|
||||
.unwrap();
|
||||
let tile_position_attr =
|
||||
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
|
||||
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||
"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")
|
||||
.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
|
||||
// driver bug.
|
||||
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor {
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: 4,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tile_origin_attr, &VertexAttrDescriptor {
|
||||
size: 3,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::U8,
|
||||
stride: MASK_TILE_INSTANCE_SIZE,
|
||||
offset: 0,
|
||||
divisor: 1,
|
||||
buffer_index: 1,
|
||||
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 4,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
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 {
|
||||
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,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: MASK_TILE_INSTANCE_SIZE,
|
||||
offset: 6,
|
||||
divisor: 1,
|
||||
buffer_index: 1,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 12,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array,
|
||||
&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);
|
||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
AlphaTileVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
|
@ -1041,65 +1043,39 @@ where
|
|||
fn new(
|
||||
device: &D,
|
||||
solid_tile_program: &SolidTileProgram<D>,
|
||||
quad_vertex_positions_buffer: &D::Buffer,
|
||||
quad_vertex_indices_buffer: &D::Buffer,
|
||||
quads_vertex_indices_buffer: &D::Buffer,
|
||||
) -> SolidTileVertexArray<D> {
|
||||
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")
|
||||
.unwrap();
|
||||
let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin")
|
||||
.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();
|
||||
let tile_position_attr =
|
||||
device.get_vertex_attr(&solid_tile_program.program, "TilePosition").unwrap();
|
||||
let color_tex_coord_attr =
|
||||
device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord").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.
|
||||
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor {
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: 4,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: SOLID_TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 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,
|
||||
&color_tex_matrix_attr,
|
||||
&color_tex_coord_attr,
|
||||
&VertexAttrDescriptor {
|
||||
size: 4,
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: SOLID_TILE_INSTANCE_SIZE,
|
||||
stride: SOLID_TILE_VERTEX_SIZE,
|
||||
offset: 4,
|
||||
divisor: 1,
|
||||
buffer_index: 1,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array,
|
||||
&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);
|
||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
SolidTileVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ use std::time::Duration;
|
|||
pub(crate) struct BuiltObject {
|
||||
pub bounds: RectF,
|
||||
pub fills: Vec<FillBatchPrimitive>,
|
||||
pub alpha_tiles: Vec<AlphaTileBatchPrimitive>,
|
||||
pub alpha_tiles: Vec<AlphaTile>,
|
||||
pub tiles: DenseTileMap<TileObjectPrimitive>,
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ pub enum RenderCommand {
|
|||
AddPaintData(PaintData),
|
||||
AddFills(Vec<FillBatchPrimitive>),
|
||||
FlushFills,
|
||||
AlphaTile(Vec<AlphaTileBatchPrimitive>),
|
||||
SolidTile(Vec<SolidTileBatchPrimitive>),
|
||||
AlphaTile(Vec<AlphaTile>),
|
||||
SolidTile(Vec<SolidTileVertex>),
|
||||
Finish { build_time: Duration },
|
||||
}
|
||||
|
||||
|
@ -69,34 +69,35 @@ pub struct FillBatchPrimitive {
|
|||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct SolidTileBatchPrimitive {
|
||||
pub struct SolidTileVertex {
|
||||
pub tile_x: i16,
|
||||
pub tile_y: i16,
|
||||
pub texture_m00: u16,
|
||||
pub texture_m10: u16,
|
||||
pub texture_m01: u16,
|
||||
pub texture_m11: u16,
|
||||
pub texture_m02: u16,
|
||||
pub texture_m12: u16,
|
||||
pub color_u: u16,
|
||||
pub color_v: u16,
|
||||
pub object_index: u16,
|
||||
pub pad: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct AlphaTileBatchPrimitive {
|
||||
pub tile_x_lo: u8,
|
||||
pub tile_y_lo: u8,
|
||||
pub tile_hi: u8,
|
||||
pub backdrop: i8,
|
||||
pub struct AlphaTile {
|
||||
pub upper_left: AlphaTileVertex,
|
||||
pub upper_right: AlphaTileVertex,
|
||||
pub lower_left: AlphaTileVertex,
|
||||
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 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 {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// 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
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
|
@ -10,17 +10,25 @@
|
|||
|
||||
use crate::allocator::{TextureAllocator, TextureLocation};
|
||||
use crate::gpu_data::PaintData;
|
||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||
use hashbrown::HashMap;
|
||||
use pathfinder_color::ColorU;
|
||||
use pathfinder_content::gradient::Gradient;
|
||||
use pathfinder_geometry::rect::RectI;
|
||||
use pathfinder_geometry::transform2d::{Matrix2x2I, Transform2I};
|
||||
use pathfinder_geometry::vector::Vector2I;
|
||||
use pathfinder_simd::default::I32x4;
|
||||
use pathfinder_geometry::rect::{RectF, RectI};
|
||||
use pathfinder_geometry::transform2d::{Matrix2x2F, Transform2F};
|
||||
use pathfinder_geometry::util;
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
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 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>,
|
||||
}
|
||||
|
||||
// TODO(pcwalton): Add clamp/repeat options.
|
||||
#[derive(Debug)]
|
||||
pub struct PaintMetadata {
|
||||
/// The transform to apply to the texture coordinates, in 0.16 fixed point.
|
||||
pub tex_transform: Transform2I,
|
||||
/// The rectangle within the texture atlas.
|
||||
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.
|
||||
pub is_opaque: bool,
|
||||
}
|
||||
|
@ -133,29 +144,61 @@ impl Palette {
|
|||
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 area = PAINT_TEXTURE_LENGTH as usize * PAINT_TEXTURE_LENGTH as usize;
|
||||
let (mut texels, mut metadata) = (vec![0; area * 4], vec![]);
|
||||
|
||||
let mut solid_color_tile_builder = SolidColorTileBuilder::new();
|
||||
|
||||
for paint in &self.paints {
|
||||
let tex_transform;
|
||||
let (texture_location, tex_transform);
|
||||
match paint {
|
||||
Paint::Color(color) => {
|
||||
// TODO(pcwalton): Handle other paint types.
|
||||
let texture_location = solid_color_tile_builder.allocate(&mut allocator);
|
||||
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);
|
||||
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);
|
||||
|
@ -169,9 +212,28 @@ impl Palette {
|
|||
texels[index + 2] = color.b;
|
||||
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 SolidColorTileBuilderData {
|
||||
|
|
|
@ -47,7 +47,7 @@ impl Scene {
|
|||
|
||||
#[inline]
|
||||
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)]
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
// except according to those terms.
|
||||
|
||||
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 pathfinder_content::outline::{Contour, Outline, PointIndex};
|
||||
use pathfinder_content::segment::Segment;
|
||||
use pathfinder_content::sorted_vector::SortedVector;
|
||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||
use pathfinder_geometry::rect::{RectF, RectI};
|
||||
use pathfinder_geometry::transform2d::Transform2I;
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||
use std::cmp::Ordering;
|
||||
use std::mem;
|
||||
|
@ -126,15 +126,32 @@ impl<'a> Tiler<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let alpha_tile = AlphaTileBatchPrimitive::new(
|
||||
tile_coords,
|
||||
tile.backdrop,
|
||||
self.object_index,
|
||||
self.built_object.alpha_tiles.push(AlphaTile {
|
||||
upper_left: AlphaTileVertex::new(tile_coords,
|
||||
tile.alpha_tile_index as u16,
|
||||
self.paint_metadata.tex_transform,
|
||||
);
|
||||
|
||||
self.built_object.alpha_tiles.push(alpha_tile);
|
||||
Vector2I::default(),
|
||||
self.object_index,
|
||||
tile.backdrop as i16,
|
||||
&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]
|
||||
fn new(tile_coords: Vector2I,
|
||||
backdrop: i8,
|
||||
object_index: u16,
|
||||
fn new(tile_origin: Vector2I,
|
||||
tile_index: u16,
|
||||
tex_transform: Transform2I)
|
||||
-> AlphaTileBatchPrimitive {
|
||||
AlphaTileBatchPrimitive {
|
||||
tile_x_lo: (tile_coords.x() & 0xff) as u8,
|
||||
tile_y_lo: (tile_coords.y() & 0xff) as u8,
|
||||
tile_hi: (((tile_coords.x() >> 8) & 0x0f) | ((tile_coords.y() >> 4) & 0xf0)) as u8,
|
||||
backdrop,
|
||||
tile_offset: Vector2I,
|
||||
object_index: u16,
|
||||
backdrop: i16,
|
||||
paint_metadata: &PaintMetadata)
|
||||
-> AlphaTileVertex {
|
||||
let tile_position = tile_origin + tile_offset;
|
||||
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,
|
||||
tile_index,
|
||||
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,
|
||||
backdrop,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tile_coords(&self) -> Vector2I {
|
||||
Vector2I::new(
|
||||
(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),
|
||||
)
|
||||
pub fn tile_position(&self) -> Vector2I {
|
||||
Vector2I::new(self.tile_x as i32, self.tile_y as i32)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,12 @@
|
|||
|
||||
//! Software occlusion culling.
|
||||
|
||||
use crate::gpu_data::SolidTileBatchPrimitive;
|
||||
use crate::gpu_data::SolidTileVertex;
|
||||
use crate::paint::PaintMetadata;
|
||||
use crate::scene::PathObject;
|
||||
use crate::tile_map::DenseTileMap;
|
||||
use crate::tiles;
|
||||
use pathfinder_geometry::rect::RectF;
|
||||
use pathfinder_geometry::transform2d::Transform2I;
|
||||
use pathfinder_geometry::vector::Vector2I;
|
||||
use std::ops::Range;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
||||
|
@ -61,7 +60,7 @@ impl ZBuffer {
|
|||
paths: &[PathObject],
|
||||
paint_metadata: &[PaintMetadata],
|
||||
object_range: Range<u32>)
|
||||
-> Vec<SolidTileBatchPrimitive> {
|
||||
-> Vec<SolidTileVertex> {
|
||||
let mut solid_tiles = vec![];
|
||||
for tile_index in 0..self.buffer.data.len() {
|
||||
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 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(),
|
||||
object_index as u16,
|
||||
tex_transform));
|
||||
let tile_position = tile_coords + self.buffer.rect.origin();
|
||||
let object_index = object_index as u16;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl SolidTileBatchPrimitive {
|
||||
fn new(tile_coords: Vector2I, object_index: u16, tex_transform: Transform2I)
|
||||
-> SolidTileBatchPrimitive {
|
||||
SolidTileBatchPrimitive {
|
||||
tile_x: tile_coords.x() as i16,
|
||||
tile_y: tile_coords.y() as i16,
|
||||
impl SolidTileVertex {
|
||||
fn new(tile_position: Vector2I, object_index: u16, paint_metadata: &PaintMetadata)
|
||||
-> SolidTileVertex {
|
||||
let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32();
|
||||
SolidTileVertex {
|
||||
tile_x: tile_position.x() as i16,
|
||||
tile_y: tile_position.y() as i16,
|
||||
object_index: object_index,
|
||||
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,
|
||||
color_u: color_uv.x() as u16,
|
||||
color_v: color_uv.y() as u16,
|
||||
pad: 0,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ uniform sampler2D uStencilTexture;
|
|||
uniform sampler2D uPaintTexture;
|
||||
uniform vec2 uPaintTextureSize;
|
||||
|
||||
in vec2 vMaskTexCoord;
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vBackdrop;
|
||||
in vec4 vColor;
|
||||
|
||||
|
|
|
@ -18,32 +18,20 @@ uniform mat4 uTransform;
|
|||
uniform vec2 uTileSize;
|
||||
uniform vec2 uStencilTextureSize;
|
||||
|
||||
in uvec2 aTessCoord;
|
||||
in uvec3 aTileOrigin;
|
||||
in vec4 aColorTexMatrix;
|
||||
in vec2 aColorTexOffset;
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
in vec2 aMaskTexCoord;
|
||||
in int aBackdrop;
|
||||
in int aTileIndex;
|
||||
|
||||
out vec2 vMaskTexCoord;
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
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(){
|
||||
vec2 tileOffset = vec2(aTessCoord)* 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;
|
||||
vec2 position = aTilePosition * uTileSize;
|
||||
|
||||
vMaskTexCoord = maskTexCoord / uStencilTextureSize;
|
||||
vColorTexCoord = mat2(aColorTexMatrix)* tileOffset + aColorTexOffset;
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -17,17 +17,14 @@ precision highp float;
|
|||
uniform mat4 uTransform;
|
||||
uniform vec2 uTileSize;
|
||||
|
||||
in uvec2 aTessCoord;
|
||||
in ivec2 aTileOrigin;
|
||||
in vec4 aColorTexMatrix;
|
||||
in vec2 aColorTexOffset;
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
|
||||
void main(){
|
||||
vec2 tileOffset = vec2(aTessCoord)* uTileSize;
|
||||
vec2 position = aTileOrigin * uTileSize + tileOffset;
|
||||
vColorTexCoord = mat2(aColorTexMatrix)* tileOffset + aColorTexOffset;
|
||||
vec2 position = aTilePosition * uTileSize;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ struct main0_out
|
|||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vMaskTexCoord [[user(locn0)]];
|
||||
float2 vColorTexCoord [[user(locn1)]];
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vBackdrop [[user(locn2)]];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
|
@ -9,47 +7,31 @@ using namespace metal;
|
|||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
constant float2* uTileSize [[id(0)]];
|
||||
constant float2* uStencilTextureSize [[id(1)]];
|
||||
constant float4x4* uTransform [[id(2)]];
|
||||
constant float4x4* uTransform [[id(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 vMaskTexCoord [[user(locn0)]];
|
||||
float2 vColorTexCoord [[user(locn1)]];
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vBackdrop [[user(locn2)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
uint2 aTessCoord [[attribute(0)]];
|
||||
uint3 aTileOrigin [[attribute(1)]];
|
||||
float4 aColorTexMatrix [[attribute(2)]];
|
||||
float2 aColorTexOffset [[attribute(3)]];
|
||||
int aBackdrop [[attribute(4)]];
|
||||
int aTileIndex [[attribute(5)]];
|
||||
int2 aTilePosition [[attribute(0)]];
|
||||
float2 aColorTexCoord [[attribute(1)]];
|
||||
float2 aMaskTexCoord [[attribute(2)]];
|
||||
int aBackdrop [[attribute(3)]];
|
||||
};
|
||||
|
||||
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)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float2 tileOffset = float2(in.aTessCoord) * (*spvDescriptorSet0.uTileSize);
|
||||
float2 origin = float2(in.aTileOrigin.xy) + (float2(float(in.aTileOrigin.z & 15u), float(in.aTileOrigin.z >> 4u)) * 256.0);
|
||||
float2 position = (origin * (*spvDescriptorSet0.uTileSize)) + tileOffset;
|
||||
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;
|
||||
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||
out.vMaskTexCoord = in.aMaskTexCoord;
|
||||
out.vColorTexCoord = in.aColorTexCoord;
|
||||
out.vBackdrop = float(in.aBackdrop);
|
||||
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
||||
return out;
|
||||
|
|
|
@ -18,18 +18,15 @@ struct main0_out
|
|||
|
||||
struct main0_in
|
||||
{
|
||||
uint2 aTessCoord [[attribute(0)]];
|
||||
int2 aTileOrigin [[attribute(1)]];
|
||||
float4 aColorTexMatrix [[attribute(2)]];
|
||||
float2 aColorTexOffset [[attribute(3)]];
|
||||
int2 aTilePosition [[attribute(0)]];
|
||||
float2 aColorTexCoord [[attribute(1)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float2 tileOffset = float2(in.aTessCoord) * (*spvDescriptorSet0.uTileSize);
|
||||
float2 position = (float2(in.aTileOrigin) * (*spvDescriptorSet0.uTileSize)) + tileOffset;
|
||||
out.vColorTexCoord = (float2x2(float2(in.aColorTexMatrix.xy), float2(in.aColorTexMatrix.zw)) * tileOffset) + in.aColorTexOffset;
|
||||
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||
out.vColorTexCoord = in.aColorTexCoord;
|
||||
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// 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
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
|
@ -16,8 +16,8 @@ uniform sampler2D uStencilTexture;
|
|||
uniform sampler2D uPaintTexture;
|
||||
uniform vec2 uPaintTextureSize;
|
||||
|
||||
in vec2 vMaskTexCoord;
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vBackdrop;
|
||||
in vec4 vColor;
|
||||
|
||||
|
|
|
@ -16,32 +16,20 @@ uniform mat4 uTransform;
|
|||
uniform vec2 uTileSize;
|
||||
uniform vec2 uStencilTextureSize;
|
||||
|
||||
in uvec2 aTessCoord;
|
||||
in uvec3 aTileOrigin;
|
||||
in vec4 aColorTexMatrix;
|
||||
in vec2 aColorTexOffset;
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
in vec2 aMaskTexCoord;
|
||||
in int aBackdrop;
|
||||
in int aTileIndex;
|
||||
|
||||
out vec2 vMaskTexCoord;
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
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() {
|
||||
vec2 tileOffset = vec2(aTessCoord) * 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;
|
||||
vec2 position = aTilePosition * uTileSize;
|
||||
|
||||
vMaskTexCoord = maskTexCoord / uStencilTextureSize;
|
||||
vColorTexCoord = mat2(aColorTexMatrix) * tileOffset + aColorTexOffset;
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// 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
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
|
@ -15,16 +15,13 @@ precision highp float;
|
|||
uniform mat4 uTransform;
|
||||
uniform vec2 uTileSize;
|
||||
|
||||
in uvec2 aTessCoord;
|
||||
in ivec2 aTileOrigin;
|
||||
in vec4 aColorTexMatrix;
|
||||
in vec2 aColorTexOffset;
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
|
||||
void main() {
|
||||
vec2 tileOffset = vec2(aTessCoord) * uTileSize;
|
||||
vec2 position = aTileOrigin * uTileSize + tileOffset;
|
||||
vColorTexCoord = mat2(aColorTexMatrix) * tileOffset + aColorTexOffset;
|
||||
vec2 position = aTilePosition * uTileSize;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
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 {
|
||||
type Output = F32x2;
|
||||
#[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 {
|
||||
type Output = F32x4;
|
||||
#[inline]
|
||||
|
@ -412,6 +428,18 @@ impl I32x2 {
|
|||
I32x2::new(x, x)
|
||||
}
|
||||
|
||||
// Accessors
|
||||
|
||||
#[inline]
|
||||
pub fn x(self) -> i32 {
|
||||
self[0]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn y(self) -> i32 {
|
||||
self[1]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn packed_eq(self, other: I32x2) -> U32x2 {
|
||||
unsafe { U32x2(simd_eq(self.0, other.0)) }
|
||||
|
@ -750,6 +778,7 @@ impl Index<usize> for U32x4 {
|
|||
|
||||
extern "platform-intrinsic" {
|
||||
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_sub<T>(x: T, y: T) -> T;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use std::f32;
|
||||
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_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 {
|
||||
type Output = F32x2;
|
||||
#[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 {
|
||||
type Output = F32x4;
|
||||
#[inline]
|
||||
|
@ -445,6 +466,18 @@ impl I32x2 {
|
|||
I32x2([x, x])
|
||||
}
|
||||
|
||||
// Accessors
|
||||
|
||||
#[inline]
|
||||
pub fn x(self) -> i32 {
|
||||
self[0]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn y(self) -> i32 {
|
||||
self[1]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn packed_eq(self, other: I32x2) -> U32x2 {
|
||||
U32x2([
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use std::cmp::PartialEq;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
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")]
|
||||
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 {
|
||||
type Output = F32x2;
|
||||
#[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 {
|
||||
type Output = F32x4;
|
||||
#[inline]
|
||||
|
@ -461,6 +477,18 @@ impl I32x2 {
|
|||
I32x2::new(x, x)
|
||||
}
|
||||
|
||||
// Accessors
|
||||
|
||||
#[inline]
|
||||
pub fn x(self) -> i32 {
|
||||
self[0]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn y(self) -> i32 {
|
||||
self[1]
|
||||
}
|
||||
|
||||
// Concatenations
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Reference in New Issue