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