diff --git a/export/src/lib.rs b/export/src/lib.rs index 6db4161c..167e3559 100644 --- a/export/src/lib.rs +++ b/export/src/lib.rs @@ -54,7 +54,7 @@ fn export_svg(scene: &Scene, writer: &mut W) -> io::Result<()> { view_box.size().y() )?; for &DrawPath { paint: paint_id, ref outline, ref name, .. } in scene.draw_paths() { - let paint = scene.palette().paints.get(paint_id.0 as usize).unwrap(); + let paint = scene.get_paint(paint_id); write!(writer, " (scene: &Scene, writer: &mut W) -> io::Result<()> { for &DrawPath { paint: paint_id, ref outline, .. } in scene.draw_paths() { // TODO(pcwalton): Gradients and patterns. - let paint = scene.palette().paints.get(paint_id.0 as usize).unwrap(); + let paint = scene.get_paint(paint_id); if paint.is_color() { pdf.set_fill_color(paint.base_color()); } @@ -182,7 +182,7 @@ fn export_ps(scene: &Scene, writer: &mut W) -> io::Result<()> { } // TODO(pcwalton): Gradients and patterns. - let paint = scene.palette().paints.get(paint_id.0 as usize).unwrap(); + let paint = scene.get_paint(paint_id); if paint.is_color() { let color = paint.base_color(); writeln!(writer, "{} {} {} setrgbcolor", color.r, color.g, color.b)?; diff --git a/renderer/src/concurrent/executor.rs b/renderer/src/concurrent/executor.rs index 150f4d32..dc32afa1 100644 --- a/renderer/src/concurrent/executor.rs +++ b/renderer/src/concurrent/executor.rs @@ -21,6 +21,7 @@ pub trait Executor { where T: Send, F: Fn(usize) -> T + Send + Sync; } +/// An executor that simply executes tasks sequentially in the same thread. pub struct SequentialExecutor; impl Executor for SequentialExecutor { diff --git a/renderer/src/concurrent/rayon.rs b/renderer/src/concurrent/rayon.rs index e11d28b1..f61724de 100644 --- a/renderer/src/concurrent/rayon.rs +++ b/renderer/src/concurrent/rayon.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! An implementation of the executor using the Rayon library. +//! An executor that parallelizes tasks across all CPUs using the Rayon library. use crate::concurrent::executor::Executor; use rayon::iter::{IntoParallelIterator, ParallelIterator}; +/// An executor that parallelizes tasks across all CPUs using the Rayon library. pub struct RayonExecutor; impl Executor for RayonExecutor { diff --git a/renderer/src/concurrent/scene_proxy.rs b/renderer/src/concurrent/scene_proxy.rs index e5a88db1..d0079bd3 100644 --- a/renderer/src/concurrent/scene_proxy.rs +++ b/renderer/src/concurrent/scene_proxy.rs @@ -32,17 +32,30 @@ use std::thread; const MAX_MESSAGES_IN_FLIGHT: usize = 1024; +/// A version of `Scene` that proxies all method calls out to a separate thread. pub struct SceneProxy { sender: Sender, receiver: Receiver, } impl SceneProxy { + /// Creates a new scene proxy using the given renderer GPU API level and executor to execute + /// CPU tasks. + /// + /// If you want to use multiple threads, you typically pass in a `RayonExecutor` here. If you + /// want to use a single thread (perhaps because you're in a WebAssembly environment), pass a + /// `SequentialExecutor`. pub fn new(renderer_level: RendererLevel, executor: E) -> SceneProxy where E: Executor + Send + 'static { SceneProxy::from_scene(Scene::new(), renderer_level, executor) } + /// Wraps an existing scene in a scene proxy using the given renderer GPU API level an executor + /// to execute CPU tasks. + /// + /// If you want to use multiple threads, you typically pass in a `RayonExecutor` here. If you + /// want to use a single thread (perhaps because you're in a WebAssembly environment), pass a + /// `SequentialExecutor`. pub fn from_scene(scene: Scene, renderer_level: RendererLevel, executor: E) -> SceneProxy where E: Executor + Send + 'static { @@ -58,22 +71,25 @@ impl SceneProxy { SceneProxy { sender: main_to_worker_sender, receiver: worker_to_main_receiver } } + /// Replaces the wrapped scene with a new one, discarding the old scene. #[inline] pub fn replace_scene(&self, new_scene: Scene) { self.sender.send(MainToWorkerMsg::ReplaceScene(new_scene)).unwrap(); } + /// Sets the view box of the scene, which defines the visible rectangle. #[inline] pub fn set_view_box(&self, new_view_box: RectF) { self.sender.send(MainToWorkerMsg::SetViewBox(new_view_box)).unwrap(); } + /// Constructs a scene and queues up the commands needed to render it. #[inline] pub fn build(&self, options: BuildOptions) { self.sender.send(MainToWorkerMsg::Build(options)).unwrap(); } - /// Sends all queued commands to the given renderer. + /// Sends all queued commands to the given renderer to render the wrapped scene. #[inline] pub fn render(&mut self, renderer: &mut Renderer) where D: Device { renderer.begin_scene(); @@ -104,6 +120,7 @@ impl SceneProxy { self.render(renderer); } + /// Returns a copy of the wrapped scene. #[inline] pub fn copy_scene(&self) -> Scene { let (sender, receiver) = crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT); diff --git a/renderer/src/gpu/d3d11/mod.rs b/renderer/src/gpu/d3d11/mod.rs index eebeb578..b3168830 100644 --- a/renderer/src/gpu/d3d11/mod.rs +++ b/renderer/src/gpu/d3d11/mod.rs @@ -8,5 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! A GPU compute-based renderer that uses functionality available in Direct3D 11. +//! +//! This renderer supports OpenGL at least 4.3, OpenGL ES at least 3.1, and Metal of any version. + pub mod renderer; pub mod shaders; diff --git a/renderer/src/gpu/d3d11/renderer.rs b/renderer/src/gpu/d3d11/renderer.rs index f8982f9d..fe7414b3 100644 --- a/renderer/src/gpu/d3d11/renderer.rs +++ b/renderer/src/gpu/d3d11/renderer.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! A GPU compute-based renderer that uses functionality available in Direct3D 11. +//! +//! This renderer supports OpenGL at least 4.3, OpenGL ES at least 3.1, and Metal of any version. + use crate::gpu::d3d11::shaders::{BOUND_WORKGROUP_SIZE, DICE_WORKGROUP_SIZE}; use crate::gpu::d3d11::shaders::{PROPAGATE_WORKGROUP_SIZE, ProgramsD3D11, SORT_WORKGROUP_SIZE}; use crate::gpu::perf::TimeCategory; diff --git a/renderer/src/gpu/d3d11/shaders.rs b/renderer/src/gpu/d3d11/shaders.rs index 52fe5f24..d5efdf5e 100644 --- a/renderer/src/gpu/d3d11/shaders.rs +++ b/renderer/src/gpu/d3d11/shaders.rs @@ -8,29 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Shaders and vertex specifications for the Direct3D 11-level renderer. + use crate::gpu::shaders::TileProgramCommon; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_gpu::{ComputeDimensions, Device}; use pathfinder_resources::ResourceLoader; -pub const BOUND_WORKGROUP_SIZE: u32 = 64; -pub const DICE_WORKGROUP_SIZE: u32 = 64; -pub const BIN_WORKGROUP_SIZE: u32 = 64; -pub const PROPAGATE_WORKGROUP_SIZE: u32 = 64; -pub const SORT_WORKGROUP_SIZE: u32 = 64; +pub(crate) const BOUND_WORKGROUP_SIZE: u32 = 64; +pub(crate) const DICE_WORKGROUP_SIZE: u32 = 64; +pub(crate) const BIN_WORKGROUP_SIZE: u32 = 64; +pub(crate) const PROPAGATE_WORKGROUP_SIZE: u32 = 64; +pub(crate) const SORT_WORKGROUP_SIZE: u32 = 64; -pub struct ProgramsD3D11 where D: Device { - pub bound_program: BoundProgramD3D11, - pub dice_program: DiceProgramD3D11, - pub bin_program: BinProgramD3D11, - pub propagate_program: PropagateProgramD3D11, - pub sort_program: SortProgramD3D11, - pub fill_program: FillProgramD3D11, - pub tile_program: TileProgramD3D11, +pub(crate) struct ProgramsD3D11 where D: Device { + pub(crate) bound_program: BoundProgramD3D11, + pub(crate) dice_program: DiceProgramD3D11, + pub(crate) bin_program: BinProgramD3D11, + pub(crate) propagate_program: PropagateProgramD3D11, + pub(crate) sort_program: SortProgramD3D11, + pub(crate) fill_program: FillProgramD3D11, + pub(crate) tile_program: TileProgramD3D11, } impl ProgramsD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D11 { ProgramsD3D11 { bound_program: BoundProgramD3D11::new(device, resources), dice_program: DiceProgramD3D11::new(device, resources), @@ -43,23 +45,23 @@ impl ProgramsD3D11 where D: Device { } } -pub struct PropagateProgramD3D11 where D: Device { - pub program: D::Program, - pub framebuffer_tile_size_uniform: D::Uniform, - pub column_count_uniform: D::Uniform, - pub first_alpha_tile_index_uniform: D::Uniform, - pub draw_metadata_storage_buffer: D::StorageBuffer, - pub clip_metadata_storage_buffer: D::StorageBuffer, - pub backdrops_storage_buffer: D::StorageBuffer, - pub draw_tiles_storage_buffer: D::StorageBuffer, - pub clip_tiles_storage_buffer: D::StorageBuffer, - pub z_buffer_storage_buffer: D::StorageBuffer, - pub first_tile_map_storage_buffer: D::StorageBuffer, - pub alpha_tiles_storage_buffer: D::StorageBuffer, +pub(crate) struct PropagateProgramD3D11 where D: Device { + pub(crate) program: D::Program, + pub(crate) framebuffer_tile_size_uniform: D::Uniform, + pub(crate) column_count_uniform: D::Uniform, + pub(crate) first_alpha_tile_index_uniform: D::Uniform, + pub(crate) draw_metadata_storage_buffer: D::StorageBuffer, + pub(crate) clip_metadata_storage_buffer: D::StorageBuffer, + pub(crate) backdrops_storage_buffer: D::StorageBuffer, + pub(crate) draw_tiles_storage_buffer: D::StorageBuffer, + pub(crate) clip_tiles_storage_buffer: D::StorageBuffer, + pub(crate) z_buffer_storage_buffer: D::StorageBuffer, + pub(crate) first_tile_map_storage_buffer: D::StorageBuffer, + pub(crate) alpha_tiles_storage_buffer: D::StorageBuffer, } impl PropagateProgramD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> PropagateProgramD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> PropagateProgramD3D11 { let mut program = device.create_compute_program(resources, "d3d11/propagate"); let local_size = ComputeDimensions { x: PROPAGATE_WORKGROUP_SIZE, y: 1, z: 1 }; device.set_compute_program_local_size(&mut program, local_size); @@ -93,18 +95,18 @@ impl PropagateProgramD3D11 where D: Device { } } -pub struct FillProgramD3D11 where D: Device { - pub program: D::Program, - pub dest_image: D::ImageParameter, - pub area_lut_texture: D::TextureParameter, - pub alpha_tile_range_uniform: D::Uniform, - pub fills_storage_buffer: D::StorageBuffer, - pub tiles_storage_buffer: D::StorageBuffer, - pub alpha_tiles_storage_buffer: D::StorageBuffer, +pub(crate) struct FillProgramD3D11 where D: Device { + pub(crate) program: D::Program, + pub(crate) dest_image: D::ImageParameter, + pub(crate) area_lut_texture: D::TextureParameter, + pub(crate) alpha_tile_range_uniform: D::Uniform, + pub(crate) fills_storage_buffer: D::StorageBuffer, + pub(crate) tiles_storage_buffer: D::StorageBuffer, + pub(crate) alpha_tiles_storage_buffer: D::StorageBuffer, } impl FillProgramD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgramD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgramD3D11 { let mut program = device.create_compute_program(resources, "d3d11/fill"); let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT / 4, z: 1 }; device.set_compute_program_local_size(&mut program, local_size); @@ -128,14 +130,14 @@ impl FillProgramD3D11 where D: Device { } } -pub struct TileProgramD3D11 where D: Device { - pub common: TileProgramCommon, - pub load_action_uniform: D::Uniform, - pub clear_color_uniform: D::Uniform, - pub framebuffer_tile_size_uniform: D::Uniform, - pub dest_image: D::ImageParameter, - pub tiles_storage_buffer: D::StorageBuffer, - pub first_tile_map_storage_buffer: D::StorageBuffer, +pub(crate) struct TileProgramD3D11 where D: Device { + pub(crate) common: TileProgramCommon, + pub(crate) load_action_uniform: D::Uniform, + pub(crate) clear_color_uniform: D::Uniform, + pub(crate) framebuffer_tile_size_uniform: D::Uniform, + pub(crate) dest_image: D::ImageParameter, + pub(crate) tiles_storage_buffer: D::StorageBuffer, + pub(crate) first_tile_map_storage_buffer: D::StorageBuffer, } impl TileProgramD3D11 where D: Device { @@ -164,20 +166,20 @@ impl TileProgramD3D11 where D: Device { } } -pub struct BinProgramD3D11 where D: Device { - pub program: D::Program, - pub microline_count_uniform: D::Uniform, - pub max_fill_count_uniform: D::Uniform, - pub microlines_storage_buffer: D::StorageBuffer, - pub metadata_storage_buffer: D::StorageBuffer, - pub indirect_draw_params_storage_buffer: D::StorageBuffer, - pub fills_storage_buffer: D::StorageBuffer, - pub tiles_storage_buffer: D::StorageBuffer, - pub backdrops_storage_buffer: D::StorageBuffer, +pub(crate) struct BinProgramD3D11 where D: Device { + pub(crate) program: D::Program, + pub(crate) microline_count_uniform: D::Uniform, + pub(crate) max_fill_count_uniform: D::Uniform, + pub(crate) microlines_storage_buffer: D::StorageBuffer, + pub(crate) metadata_storage_buffer: D::StorageBuffer, + pub(crate) indirect_draw_params_storage_buffer: D::StorageBuffer, + pub(crate) fills_storage_buffer: D::StorageBuffer, + pub(crate) tiles_storage_buffer: D::StorageBuffer, + pub(crate) backdrops_storage_buffer: D::StorageBuffer, } impl BinProgramD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> BinProgramD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> BinProgramD3D11 { let mut program = device.create_compute_program(resources, "d3d11/bin"); let dimensions = ComputeDimensions { x: BIN_WORKGROUP_SIZE, y: 1, z: 1 }; device.set_compute_program_local_size(&mut program, dimensions); @@ -207,22 +209,22 @@ impl BinProgramD3D11 where D: Device { } } -pub struct DiceProgramD3D11 where D: Device { - pub program: D::Program, - pub transform_uniform: D::Uniform, - pub translation_uniform: D::Uniform, - pub path_count_uniform: D::Uniform, - pub last_batch_segment_index_uniform: D::Uniform, - pub max_microline_count_uniform: D::Uniform, - pub compute_indirect_params_storage_buffer: D::StorageBuffer, - pub dice_metadata_storage_buffer: D::StorageBuffer, - pub points_storage_buffer: D::StorageBuffer, - pub input_indices_storage_buffer: D::StorageBuffer, - pub microlines_storage_buffer: D::StorageBuffer, +pub(crate) struct DiceProgramD3D11 where D: Device { + pub(crate) program: D::Program, + pub(crate) transform_uniform: D::Uniform, + pub(crate) translation_uniform: D::Uniform, + pub(crate) path_count_uniform: D::Uniform, + pub(crate) last_batch_segment_index_uniform: D::Uniform, + pub(crate) max_microline_count_uniform: D::Uniform, + pub(crate) compute_indirect_params_storage_buffer: D::StorageBuffer, + pub(crate) dice_metadata_storage_buffer: D::StorageBuffer, + pub(crate) points_storage_buffer: D::StorageBuffer, + pub(crate) input_indices_storage_buffer: D::StorageBuffer, + pub(crate) microlines_storage_buffer: D::StorageBuffer, } impl DiceProgramD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> DiceProgramD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> DiceProgramD3D11 { let mut program = device.create_compute_program(resources, "d3d11/dice"); let dimensions = ComputeDimensions { x: DICE_WORKGROUP_SIZE, y: 1, z: 1 }; device.set_compute_program_local_size(&mut program, dimensions); @@ -257,16 +259,16 @@ impl DiceProgramD3D11 where D: Device { } } -pub struct BoundProgramD3D11 where D: Device { - pub program: D::Program, - pub path_count_uniform: D::Uniform, - pub tile_count_uniform: D::Uniform, - pub tile_path_info_storage_buffer: D::StorageBuffer, - pub tiles_storage_buffer: D::StorageBuffer, +pub(crate) struct BoundProgramD3D11 where D: Device { + pub(crate) program: D::Program, + pub(crate) path_count_uniform: D::Uniform, + pub(crate) tile_count_uniform: D::Uniform, + pub(crate) tile_path_info_storage_buffer: D::StorageBuffer, + pub(crate) tiles_storage_buffer: D::StorageBuffer, } impl BoundProgramD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> BoundProgramD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> BoundProgramD3D11 { let mut program = device.create_compute_program(resources, "d3d11/bound"); let dimensions = ComputeDimensions { x: BOUND_WORKGROUP_SIZE, y: 1, z: 1 }; device.set_compute_program_local_size(&mut program, dimensions); @@ -287,16 +289,16 @@ impl BoundProgramD3D11 where D: Device { } } -pub struct SortProgramD3D11 where D: Device { - pub program: D::Program, - pub tile_count_uniform: D::Uniform, - pub tiles_storage_buffer: D::StorageBuffer, - pub first_tile_map_storage_buffer: D::StorageBuffer, - pub z_buffer_storage_buffer: D::StorageBuffer, +pub(crate) struct SortProgramD3D11 where D: Device { + pub(crate) program: D::Program, + pub(crate) tile_count_uniform: D::Uniform, + pub(crate) tiles_storage_buffer: D::StorageBuffer, + pub(crate) first_tile_map_storage_buffer: D::StorageBuffer, + pub(crate) z_buffer_storage_buffer: D::StorageBuffer, } impl SortProgramD3D11 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> SortProgramD3D11 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> SortProgramD3D11 { let mut program = device.create_compute_program(resources, "d3d11/sort"); let dimensions = ComputeDimensions { x: SORT_WORKGROUP_SIZE, y: 1, z: 1 }; device.set_compute_program_local_size(&mut program, dimensions); diff --git a/renderer/src/gpu/d3d9/mod.rs b/renderer/src/gpu/d3d9/mod.rs index 6f67f3bc..0383770c 100644 --- a/renderer/src/gpu/d3d9/mod.rs +++ b/renderer/src/gpu/d3d9/mod.rs @@ -8,5 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! A hybrid CPU-GPU renderer that only relies on functionality available in Direct3D 9. +//! +//! This renderer supports OpenGL at least 3.0, OpenGL ES at least 3.0, Metal of any version, and +//! WebGL at least 2.0. + pub mod renderer; pub mod shaders; diff --git a/renderer/src/gpu/d3d9/renderer.rs b/renderer/src/gpu/d3d9/renderer.rs index 5c134e97..d3295e78 100644 --- a/renderer/src/gpu/d3d9/renderer.rs +++ b/renderer/src/gpu/d3d9/renderer.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! A hybrid CPU-GPU renderer that only relies on functionality available in Direct3D 9. +//! +//! This renderer supports OpenGL at least 3.0, OpenGL ES at least 3.0, Metal of any version, and +//! WebGL at least 2.0. + use crate::gpu::blend::{BlendModeExt, ToBlendState}; use crate::gpu::perf::TimeCategory; use crate::gpu::renderer::{FramebufferFlags, MASK_FRAMEBUFFER_HEIGHT, MASK_FRAMEBUFFER_WIDTH}; diff --git a/renderer/src/gpu/d3d9/shaders.rs b/renderer/src/gpu/d3d9/shaders.rs index 82aabd7d..7e560ea0 100644 --- a/renderer/src/gpu/d3d9/shaders.rs +++ b/renderer/src/gpu/d3d9/shaders.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Shaders and vertex specifications for the Direct3D 9-level renderer. + use crate::gpu::shaders::{TILE_INSTANCE_SIZE, TileProgramCommon}; use pathfinder_gpu::{BufferTarget, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_resources::ResourceLoader; @@ -15,17 +17,17 @@ use pathfinder_resources::ResourceLoader; const FILL_INSTANCE_SIZE: usize = 12; const CLIP_TILE_INSTANCE_SIZE: usize = 16; -pub struct FillVertexArrayD3D9 where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct FillVertexArrayD3D9 where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl FillVertexArrayD3D9 where D: Device { - pub fn new(device: &D, - fill_program: &FillProgramD3D9, - vertex_buffer: &D::Buffer, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer) - -> FillVertexArrayD3D9 { + pub(crate) fn new(device: &D, + fill_program: &FillProgramD3D9, + vertex_buffer: &D::Buffer, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> FillVertexArrayD3D9 { let vertex_array = device.create_vertex_array(); let tess_coord_attr = device.get_vertex_attr(&fill_program.program, "TessCoord").unwrap(); @@ -68,17 +70,17 @@ impl FillVertexArrayD3D9 where D: Device { } } -pub struct TileVertexArrayD3D9 where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct TileVertexArrayD3D9 where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl TileVertexArrayD3D9 where D: Device { - pub fn new(device: &D, - tile_program: &TileProgramD3D9, - tile_vertex_buffer: &D::Buffer, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer) - -> TileVertexArrayD3D9 { + pub(crate) fn new(device: &D, + tile_program: &TileProgramD3D9, + tile_vertex_buffer: &D::Buffer, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> TileVertexArrayD3D9 { let vertex_array = device.create_vertex_array(); let tile_offset_attr = @@ -155,17 +157,17 @@ impl TileVertexArrayD3D9 where D: Device { } } -pub struct ClipTileCopyVertexArrayD3D9 where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct ClipTileCopyVertexArrayD3D9 where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl ClipTileCopyVertexArrayD3D9 where D: Device { - pub fn new(device: &D, - clip_tile_copy_program: &ClipTileCopyProgramD3D9, - vertex_buffer: &D::Buffer, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer) - -> ClipTileCopyVertexArrayD3D9 { + pub(crate) fn new(device: &D, + clip_tile_copy_program: &ClipTileCopyProgramD3D9, + vertex_buffer: &D::Buffer, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> ClipTileCopyVertexArrayD3D9 { let vertex_array = device.create_vertex_array(); let tile_offset_attr = @@ -199,17 +201,17 @@ impl ClipTileCopyVertexArrayD3D9 where D: Device { } } -pub struct ClipTileCombineVertexArrayD3D9 where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct ClipTileCombineVertexArrayD3D9 where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl ClipTileCombineVertexArrayD3D9 where D: Device { - pub fn new(device: &D, - clip_tile_combine_program: &ClipTileCombineProgramD3D9, - vertex_buffer: &D::Buffer, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer) - -> ClipTileCombineVertexArrayD3D9 { + pub(crate) fn new(device: &D, + clip_tile_combine_program: &ClipTileCombineProgramD3D9, + vertex_buffer: &D::Buffer, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> ClipTileCombineVertexArrayD3D9 { let vertex_array = device.create_vertex_array(); let tile_offset_attr = @@ -276,16 +278,16 @@ impl ClipTileCombineVertexArrayD3D9 where D: Device { } } -pub struct CopyTileVertexArray where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct CopyTileVertexArray where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl CopyTileVertexArray where D: Device { - pub fn new(device: &D, - copy_tile_program: &CopyTileProgram, - copy_tile_vertex_buffer: &D::Buffer, - quads_vertex_indices_buffer: &D::Buffer) - -> CopyTileVertexArray { + pub(crate) fn new(device: &D, + copy_tile_program: &CopyTileProgram, + copy_tile_vertex_buffer: &D::Buffer, + quads_vertex_indices_buffer: &D::Buffer) + -> CopyTileVertexArray { let vertex_array = device.create_vertex_array(); let tile_position_attr = @@ -307,11 +309,11 @@ impl CopyTileVertexArray where D: Device { } } -pub struct FillProgramD3D9 where D: Device { - pub program: D::Program, - pub framebuffer_size_uniform: D::Uniform, - pub tile_size_uniform: D::Uniform, - pub area_lut_texture: D::TextureParameter, +pub(crate) struct FillProgramD3D9 where D: Device { + pub(crate) program: D::Program, + pub(crate) framebuffer_size_uniform: D::Uniform, + pub(crate) tile_size_uniform: D::Uniform, + pub(crate) area_lut_texture: D::TextureParameter, } impl FillProgramD3D9 where D: Device { @@ -329,10 +331,10 @@ impl FillProgramD3D9 where D: Device { } } -pub struct TileProgramD3D9 where D: Device { - pub common: TileProgramCommon, - pub dest_texture: D::TextureParameter, - pub transform_uniform: D::Uniform, +pub(crate) struct TileProgramD3D9 where D: Device { + pub(crate) common: TileProgramCommon, + pub(crate) dest_texture: D::TextureParameter, + pub(crate) transform_uniform: D::Uniform, } impl TileProgramD3D9 where D: Device { @@ -345,14 +347,15 @@ impl TileProgramD3D9 where D: Device { } } -pub struct ClipTileCombineProgramD3D9 where D: Device { - pub program: D::Program, - pub src_texture: D::TextureParameter, - pub framebuffer_size_uniform: D::Uniform, +pub(crate) struct ClipTileCombineProgramD3D9 where D: Device { + pub(crate) program: D::Program, + pub(crate) src_texture: D::TextureParameter, + pub(crate) framebuffer_size_uniform: D::Uniform, } impl ClipTileCombineProgramD3D9 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileCombineProgramD3D9 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) + -> ClipTileCombineProgramD3D9 { let program = device.create_raster_program(resources, "d3d9/tile_clip_combine"); let src_texture = device.get_texture_parameter(&program, "Src"); let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); @@ -360,14 +363,14 @@ impl ClipTileCombineProgramD3D9 where D: Device { } } -pub struct ClipTileCopyProgramD3D9 where D: Device { - pub program: D::Program, - pub src_texture: D::TextureParameter, - pub framebuffer_size_uniform: D::Uniform, +pub(crate) struct ClipTileCopyProgramD3D9 where D: Device { + pub(crate) program: D::Program, + pub(crate) src_texture: D::TextureParameter, + pub(crate) framebuffer_size_uniform: D::Uniform, } impl ClipTileCopyProgramD3D9 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileCopyProgramD3D9 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileCopyProgramD3D9 { let program = device.create_raster_program(resources, "d3d9/tile_clip_copy"); let src_texture = device.get_texture_parameter(&program, "Src"); let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); @@ -375,16 +378,16 @@ impl ClipTileCopyProgramD3D9 where D: Device { } } -pub struct CopyTileProgram where D: Device { - pub program: D::Program, - pub transform_uniform: D::Uniform, - pub tile_size_uniform: D::Uniform, - pub framebuffer_size_uniform: D::Uniform, - pub src_texture: D::TextureParameter, +pub(crate) struct CopyTileProgram where D: Device { + pub(crate) program: D::Program, + pub(crate) transform_uniform: D::Uniform, + pub(crate) tile_size_uniform: D::Uniform, + pub(crate) framebuffer_size_uniform: D::Uniform, + pub(crate) src_texture: D::TextureParameter, } impl CopyTileProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> CopyTileProgram { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> CopyTileProgram { let program = device.create_raster_program(resources, "d3d9/tile_copy"); let transform_uniform = device.get_uniform(&program, "Transform"); let tile_size_uniform = device.get_uniform(&program, "TileSize"); @@ -400,36 +403,16 @@ impl CopyTileProgram where D: Device { } } -pub struct D3D9Programs where D: Device { - pub fill_program: FillProgramD3D9, - pub tile_program: TileProgramD3D9, - pub tile_clip_combine_program: ClipTileCombineProgramD3D9, - pub tile_clip_copy_program: ClipTileCopyProgramD3D9, - pub tile_copy_program: CopyTileProgram, -} - -impl D3D9Programs where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> D3D9Programs { - D3D9Programs { - fill_program: FillProgramD3D9::new(device, resources), - tile_program: TileProgramD3D9::new(device, resources), - tile_clip_combine_program: ClipTileCombineProgramD3D9::new(device, resources), - tile_clip_copy_program: ClipTileCopyProgramD3D9::new(device, resources), - tile_copy_program: CopyTileProgram::new(device, resources), - } - } -} - -pub struct ProgramsD3D9 where D: Device { - pub fill_program: FillProgramD3D9, - pub tile_program: TileProgramD3D9, - pub tile_clip_copy_program: ClipTileCopyProgramD3D9, - pub tile_clip_combine_program: ClipTileCombineProgramD3D9, - pub tile_copy_program: CopyTileProgram, +pub(crate) struct ProgramsD3D9 where D: Device { + pub(crate) fill_program: FillProgramD3D9, + pub(crate) tile_program: TileProgramD3D9, + pub(crate) tile_clip_copy_program: ClipTileCopyProgramD3D9, + pub(crate) tile_clip_combine_program: ClipTileCombineProgramD3D9, + pub(crate) tile_copy_program: CopyTileProgram, } impl ProgramsD3D9 where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D9 { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D9 { ProgramsD3D9 { fill_program: FillProgramD3D9::new(device, resources), tile_program: TileProgramD3D9::new(device, resources), diff --git a/renderer/src/gpu/debug.rs b/renderer/src/gpu/debug.rs index ea7e9e31..665e8f21 100644 --- a/renderer/src/gpu/debug.rs +++ b/renderer/src/gpu/debug.rs @@ -39,8 +39,13 @@ const PERFORMANCE_WINDOW_HEIGHT_D3D11: i32 = LINE_HEIGHT * 10 + PADDING + 2; const INFO_WINDOW_WIDTH: i32 = 425; const INFO_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 2 + PADDING + 2; +/// Manages the debug UI. pub struct DebugUIPresenter where D: Device { + /// The general UI presenter object. + /// + /// You can use this to draw your own application-specific debug widgets. pub ui_presenter: UIPresenter, + cpu_samples: SampleBuffer, gpu_samples: SampleBuffer, backend_name: &'static str, @@ -49,11 +54,11 @@ pub struct DebugUIPresenter where D: Device { } impl DebugUIPresenter where D: Device { - pub fn new(device: &D, - resources: &dyn ResourceLoader, - framebuffer_size: Vector2I, - renderer_level: RendererLevel) - -> DebugUIPresenter { + pub(crate) fn new(device: &D, + resources: &dyn ResourceLoader, + framebuffer_size: Vector2I, + renderer_level: RendererLevel) + -> DebugUIPresenter { let ui_presenter = UIPresenter::new(device, resources, framebuffer_size); DebugUIPresenter { ui_presenter, @@ -65,19 +70,19 @@ impl DebugUIPresenter where D: Device { } } - pub fn add_sample(&mut self, stats: RenderStats, rendering_time: RenderTime) { + pub(crate) fn add_sample(&mut self, stats: RenderStats, rendering_time: RenderTime) { self.cpu_samples.push(stats); self.gpu_samples.push(rendering_time); } - pub fn draw(&self, device: &D, allocator: &mut GPUMemoryAllocator) { + pub(crate) fn draw(&self, device: &D, allocator: &mut GPUMemoryAllocator) { self.draw_stats_window(device, allocator); self.draw_performance_window(device, allocator); self.draw_info_window(device, allocator); } #[inline] - pub fn set_framebuffer_size(&mut self, new_framebuffer_size: Vector2I) { + pub(crate) fn set_framebuffer_size(&mut self, new_framebuffer_size: Vector2I) { self.ui_presenter.set_framebuffer_size(new_framebuffer_size) } diff --git a/renderer/src/gpu/options.rs b/renderer/src/gpu/options.rs index e5b6aa97..1a8f6051 100644 --- a/renderer/src/gpu/options.rs +++ b/renderer/src/gpu/options.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Various options that control how the renderer behaves. + use pathfinder_color::ColorF; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::Vector2I; @@ -57,6 +59,7 @@ impl Default for RendererOptions where D: Device { } impl RendererLevel { + /// Returns a suitable renderer level for the given device. pub fn default_for_device(device: &D) -> RendererLevel where D: Device { match device.feature_level() { FeatureLevel::D3D10 => RendererLevel::D3D9, @@ -65,12 +68,17 @@ impl RendererLevel { } } +/// Where the rendered content should go. #[derive(Clone)] pub enum DestFramebuffer where D: Device { + /// The rendered content should go to the default framebuffer (e.g. the window in OpenGL). Default { + /// The rectangle within the window to draw in, in device pixels. viewport: RectI, + /// The total size of the window in device pixels. window_size: Vector2I, }, + /// The rendered content should go to a non-default framebuffer (off-screen, typically). Other(D::Framebuffer), } @@ -81,16 +89,18 @@ impl Default for DestFramebuffer where D: Device { } } -impl DestFramebuffer -where - D: Device, -{ +impl DestFramebuffer where D: Device { + /// Returns a `DestFramebuffer` object that renders to the entire contents of the default + /// framebuffer. + /// + /// The `window_size` parameter specifies the size of the window in device pixels. #[inline] pub fn full_window(window_size: Vector2I) -> DestFramebuffer { let viewport = RectI::new(Vector2I::default(), window_size); DestFramebuffer::Default { viewport, window_size } } + /// Returns the size of the destination buffer, in device pixels. #[inline] pub fn window_size(&self, device: &D) -> Vector2I { match *self { diff --git a/renderer/src/gpu/perf.rs b/renderer/src/gpu/perf.rs index e891ffdb..81db829e 100644 --- a/renderer/src/gpu/perf.rs +++ b/renderer/src/gpu/perf.rs @@ -16,15 +16,30 @@ use std::mem; use std::ops::{Add, Div}; use std::time::Duration; +/// Various GPU-side statistics about rendering. #[derive(Clone, Copy, Debug, Default)] pub struct RenderStats { + /// The total number of path objects in the scene. pub path_count: usize, + /// The number of fill operations it took to render the scene. + /// + /// A fill operation is a single edge in a 16x16 device pixel tile. pub fill_count: usize, + /// The total number of 16x16 device pixel tile masks generated. pub alpha_tile_count: usize, + /// The total number of 16x16 tiles needed to render the scene, including both alpha tiles and + /// solid-color tiles. pub total_tile_count: usize, + /// The amount of CPU time it took to build the scene. pub cpu_build_time: Duration, + /// The number of GPU API draw calls it took to render the scene. pub drawcall_count: u32, + /// The number of bytes of VRAM Pathfinder has allocated. + /// + /// This may be higher than `gpu_bytes_committed` because Pathfinder caches some data for + /// faster reuse. pub gpu_bytes_allocated: u64, + /// The number of bytes of VRAM Pathfinder actually used for the frame. pub gpu_bytes_committed: u64, } @@ -203,16 +218,28 @@ fn total_time_of_timer_futures(futures: &[TimerFuture]) -> Option Duration { self.dice_time + self.bin_time + self.fill_time + self.composite_time + self.other_time diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index d3ed432b..ce434dc7 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -144,6 +144,23 @@ pub(crate) struct MaskStorage { } impl Renderer where D: Device { + /// Creates a new renderer ready to render Pathfinder content. + /// + /// Arguments: + /// + /// * `device`: The GPU device to render with. This effectively specifies the system GPU API + /// Pathfinder will use (OpenGL, Metal, etc.) + /// + /// * `resources`: Where Pathfinder should find shaders, lookup tables, and other data. + /// This is typically either an `EmbeddedResourceLoader` to use resources included in the + /// Pathfinder library or (less commonly) a `FilesystemResourceLoader` to use resources + /// stored in a directory on disk. + /// + /// * `mode`: Renderer options that can't be changed after the renderer is created. Most + /// notably, this specifies the API level (D3D9 or D3D11). + /// + /// * `options`: Renderer options that can be changed after the renderer is created. Most + /// importantly, this specifies where the output should go (to a window or off-screen). pub fn new(device: D, resources: &dyn ResourceLoader, mode: RendererMode, @@ -290,10 +307,14 @@ impl Renderer where D: Device { } } + /// Destroys this renderer and returns the embedded GPU device. pub fn destroy(self) -> D { self.core.device } + /// Performs work necessary to begin rendering a scene. + /// + /// This must be called before `render_command()`. pub fn begin_scene(&mut self) { self.core.framebuffer_flags = FramebufferFlags::empty(); @@ -304,6 +325,11 @@ impl Renderer where D: Device { self.core.alpha_tile_count = 0; } + /// Issues a rendering command to the renderer. + /// + /// These commands are generated from methods like `Scene::build()`. + /// + /// `begin_scene()` must have been called first. pub fn render_command(&mut self, command: &RenderCommand) { debug!("render command: {:?}", command); match *command { @@ -352,6 +378,13 @@ impl Renderer where D: Device { } } + /// Finishes rendering a scene. + /// + /// `begin_scene()` and all `render_command()` calls must have been issued before calling this + /// method. + /// + /// Note that, after calling this method, you might need to flush the output to the screen via + /// `swap_buffers()`, `present()`, or a similar method that your windowing library offers. pub fn end_scene(&mut self) { self.clear_dest_framebuffer_if_necessary(); self.blit_intermediate_dest_framebuffer_if_necessary(); @@ -451,34 +484,69 @@ impl Renderer where D: Device { self.last_rendering_time = None; } + /// Returns GPU timing information for the last frame, if present. pub fn last_rendering_time(&self) -> Option { self.last_rendering_time } + /// Returns a reference to the GPU device. + /// + /// This can be useful to issue GPU commands manually via the low-level `pathfinder_gpu` + /// abstraction. (Of course, you can also use your platform API such as OpenGL directly + /// alongside Pathfinder.) #[inline] pub fn device(&self) -> &D { &self.core.device } + /// Returns a mutable reference to the GPU device. + /// + /// This can be useful to issue GPU commands manually via the low-level `pathfinder_gpu` + /// abstraction. (Of course, you can also use your platform API such as OpenGL directly + /// alongside Pathfinder.) #[inline] pub fn device_mut(&mut self) -> &mut D { &mut self.core.device } + /// Returns the `RendererMode` this renderer was created with. #[inline] pub fn mode(&self) -> &RendererMode { &self.core.mode } + /// Returns the current rendering options. #[inline] pub fn options(&self) -> &RendererOptions { &self.core.options } + /// Returns a mutable reference to the current rendering options, allowing them to be changed. + /// + /// Among other things, you can use this function to change the destination of rendering + /// output without having to recreate the renderer. + /// + /// After changing the destination framebuffer size, you must call + /// `dest_framebuffer_size_changed()`. pub fn options_mut(&mut self) -> &mut RendererOptions { &mut self.core.options } + /// Notifies Pathfinder that the size of the output framebuffer has changed. + /// + /// You must call this function after changing the `dest_framebuffer` member of + /// `RendererOptions` to a target with a different size. + #[inline] + pub fn dest_framebuffer_size_changed(&mut self) { + let new_framebuffer_size = self.core.main_viewport().size(); + if let Some(ref mut debug_ui_presenter) = self.debug_ui_presenter { + debug_ui_presenter.ui_presenter.set_framebuffer_size(new_framebuffer_size); + } + } + + /// Returns a mutable reference to the debug UI. + /// + /// You can use this function to draw custom debug widgets on screen, as the demo does. #[inline] pub fn debug_ui_presenter_mut(&mut self) -> DebugUIPresenterInfo { DebugUIPresenterInfo { @@ -488,34 +556,38 @@ impl Renderer where D: Device { } } + /// Turns off Pathfinder's use of the depth buffer. #[inline] - pub fn dest_framebuffer_size_changed(&mut self) { - let new_framebuffer_size = self.core.main_viewport().size(); - if let Some(ref mut debug_ui_presenter) = self.debug_ui_presenter { - debug_ui_presenter.ui_presenter.set_framebuffer_size(new_framebuffer_size); - } - } - - #[inline] + #[deprecated] pub fn disable_depth(&mut self) { self.core.renderer_flags.remove(RendererFlags::USE_DEPTH); } + /// Turns on Pathfinder's use of the depth buffer. #[inline] + #[deprecated] pub fn enable_depth(&mut self) { self.core.renderer_flags.insert(RendererFlags::USE_DEPTH); } + /// Returns various GPU-side statistics about rendering, averaged over the last few frames. #[inline] pub fn stats(&self) -> &RenderStats { &self.core.stats } + /// Returns a GPU-side vertex buffer containing 2D vertices of a unit square. + /// + /// This can be handy for custom rendering. #[inline] pub fn quad_vertex_positions_buffer(&self) -> &D::Buffer { self.core.allocator.get_general_buffer(self.core.quad_vertex_positions_buffer_id) } + /// Returns a GPU-side 32-bit unsigned index buffer of triangles necessary to render a quad + /// with the buffer returned by `quad_vertex_positions_buffer()`. + /// + /// This can be handy for custom rendering. #[inline] pub fn quad_vertex_indices_buffer(&self) -> &D::Buffer { self.core.allocator.get_index_buffer(self.core.quad_vertex_indices_buffer_id) @@ -684,6 +756,10 @@ impl Renderer where D: Device { self.core.stats.drawcall_count += 1; } + + /// Draws a texture that was originally drawn with `old_transform` with `new_transform` by + /// transforming in screen space. + #[deprecated] pub fn reproject_texture(&mut self, texture: &D::Texture, old_transform: &Transform4F, @@ -814,21 +890,19 @@ impl Renderer where D: Device { self.core.stats.drawcall_count += 1; } + /// Returns the output viewport in the destination framebuffer, as specified in the render + /// options. #[inline] pub fn draw_viewport(&self) -> RectI { self.core.draw_viewport() } + /// Returns the destination framebuffer, wrapped in a render target. #[inline] pub fn draw_render_target(&self) -> RenderTarget { self.core.draw_render_target() } - #[inline] - pub fn render_stats(&self) -> &RenderStats { - &self.core.stats - } - fn compute_filter_params(&self, filter: &Filter, blend_mode: BlendMode, @@ -1085,14 +1159,14 @@ impl RendererCore where D: Device { } } - pub fn draw_viewport(&self) -> RectI { + pub(crate) fn draw_viewport(&self) -> RectI { match self.render_target_stack.last() { Some(&render_target_id) => self.render_target_location(render_target_id).rect, None => self.main_viewport(), } } - pub fn draw_render_target(&self) -> RenderTarget { + pub(crate) fn draw_render_target(&self) -> RenderTarget { match self.render_target_stack.last() { Some(&render_target_id) => { let texture_page_id = self.render_target_location(render_target_id).page; @@ -1248,8 +1322,14 @@ pub(crate) struct PatternTexturePage { pub(crate) must_preserve_contents: bool, } +/// A mutable reference to the debug UI presenter. +/// +/// You can use this structure to draw custom debug widgets on screen, as the demo does. pub struct DebugUIPresenterInfo<'a, D> where D: Device { + /// The GPU device. pub device: &'a mut D, + /// The GPU memory allocator. pub allocator: &'a mut GPUMemoryAllocator, + /// The debug UI presenter, useful for drawing custom debug widgets on screen. pub debug_ui_presenter: &'a mut DebugUIPresenter, } diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index 84bd0482..ee85c000 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -15,16 +15,16 @@ use pathfinder_resources::ResourceLoader; // TODO(pcwalton): Replace with `mem::size_of` calls? pub(crate) const TILE_INSTANCE_SIZE: usize = 16; -pub struct BlitVertexArray where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct BlitVertexArray where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl BlitVertexArray where D: Device { - pub fn new(device: &D, - blit_program: &BlitProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer) - -> BlitVertexArray { + pub(crate) fn new(device: &D, + blit_program: &BlitProgram, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> BlitVertexArray { let vertex_array = device.create_vertex_array(); let position_attr = device.get_vertex_attr(&blit_program.program, "Position").unwrap(); @@ -44,12 +44,12 @@ impl BlitVertexArray where D: Device { } } -pub struct VertexArraysCore where D: Device { - pub blit_vertex_array: BlitVertexArray, +pub(crate) struct VertexArraysCore where D: Device { + pub(crate) blit_vertex_array: BlitVertexArray, } impl VertexArraysCore where D: Device { - pub fn new(device: &D, + pub(crate) fn new(device: &D, programs: &ProgramsCore, quad_vertex_positions_buffer: &D::Buffer, quad_vertex_indices_buffer: &D::Buffer) @@ -63,16 +63,16 @@ impl VertexArraysCore where D: Device { } } -pub struct ClearVertexArray where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct ClearVertexArray where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl ClearVertexArray where D: Device { - pub fn new(device: &D, - clear_program: &ClearProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer) - -> ClearVertexArray { + pub(crate) fn new(device: &D, + clear_program: &ClearProgram, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> ClearVertexArray { let vertex_array = device.create_vertex_array(); let position_attr = device.get_vertex_attr(&clear_program.program, "Position").unwrap(); @@ -92,15 +92,15 @@ impl ClearVertexArray where D: Device { } } -pub struct BlitProgram where D: Device { - pub program: D::Program, - pub dest_rect_uniform: D::Uniform, - pub framebuffer_size_uniform: D::Uniform, - pub src_texture: D::TextureParameter, +pub(crate) struct BlitProgram where D: Device { + pub(crate) program: D::Program, + pub(crate) dest_rect_uniform: D::Uniform, + pub(crate) framebuffer_size_uniform: D::Uniform, + pub(crate) src_texture: D::TextureParameter, } impl BlitProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram { let program = device.create_raster_program(resources, "blit"); let dest_rect_uniform = device.get_uniform(&program, "DestRect"); let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); @@ -109,27 +109,27 @@ impl BlitProgram where D: Device { } } -pub struct ProgramsCore where D: Device { - pub blit_program: BlitProgram, +pub(crate) struct ProgramsCore where D: Device { + pub(crate) blit_program: BlitProgram, } impl ProgramsCore where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsCore { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsCore { ProgramsCore { blit_program: BlitProgram::new(device, resources), } } } -pub struct ClearProgram where D: Device { - pub program: D::Program, - pub rect_uniform: D::Uniform, - pub framebuffer_size_uniform: D::Uniform, - pub color_uniform: D::Uniform, +pub(crate) struct ClearProgram where D: Device { + pub(crate) program: D::Program, + pub(crate) rect_uniform: D::Uniform, + pub(crate) framebuffer_size_uniform: D::Uniform, + pub(crate) color_uniform: D::Uniform, } impl ClearProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClearProgram { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ClearProgram { let program = device.create_raster_program(resources, "clear"); let rect_uniform = device.get_uniform(&program, "Rect"); let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); @@ -138,20 +138,20 @@ impl ClearProgram where D: Device { } } -pub struct TileProgramCommon where D: Device { - pub program: D::Program, - pub tile_size_uniform: D::Uniform, - pub texture_metadata_texture: D::TextureParameter, - pub texture_metadata_size_uniform: D::Uniform, - pub z_buffer_texture: D::TextureParameter, - pub z_buffer_texture_size_uniform: D::Uniform, - pub color_texture_0: D::TextureParameter, - pub color_texture_size_0_uniform: D::Uniform, - pub color_texture_1: D::TextureParameter, - pub mask_texture_0: D::TextureParameter, - pub mask_texture_size_0_uniform: D::Uniform, - pub gamma_lut_texture: D::TextureParameter, - pub framebuffer_size_uniform: D::Uniform, +pub(crate) struct TileProgramCommon where D: Device { + pub(crate) program: D::Program, + pub(crate) tile_size_uniform: D::Uniform, + pub(crate) texture_metadata_texture: D::TextureParameter, + pub(crate) texture_metadata_size_uniform: D::Uniform, + pub(crate) z_buffer_texture: D::TextureParameter, + pub(crate) z_buffer_texture_size_uniform: D::Uniform, + pub(crate) color_texture_0: D::TextureParameter, + pub(crate) color_texture_size_0_uniform: D::Uniform, + pub(crate) color_texture_1: D::TextureParameter, + pub(crate) mask_texture_0: D::TextureParameter, + pub(crate) mask_texture_size_0_uniform: D::Uniform, + pub(crate) gamma_lut_texture: D::TextureParameter, + pub(crate) framebuffer_size_uniform: D::Uniform, } impl TileProgramCommon where D: Device { @@ -187,25 +187,25 @@ impl TileProgramCommon where D: Device { } } -pub struct StencilProgram where D: Device { - pub program: D::Program, +pub(crate) struct StencilProgram where D: Device { + pub(crate) program: D::Program, } impl StencilProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram { let program = device.create_raster_program(resources, "stencil"); StencilProgram { program } } } -pub struct StencilVertexArray where D: Device { - pub vertex_array: D::VertexArray, - pub vertex_buffer: D::Buffer, - pub index_buffer: D::Buffer, +pub(crate) struct StencilVertexArray where D: Device { + pub(crate) vertex_array: D::VertexArray, + pub(crate) vertex_buffer: D::Buffer, + pub(crate) index_buffer: D::Buffer, } impl StencilVertexArray where D: Device { - pub fn new(device: &D, stencil_program: &StencilProgram) -> StencilVertexArray { + pub(crate) fn new(device: &D, stencil_program: &StencilProgram) -> StencilVertexArray { let vertex_array = device.create_vertex_array(); let vertex_buffer = device.create_buffer(BufferUploadMode::Static); let index_buffer = device.create_buffer(BufferUploadMode::Static); @@ -228,15 +228,15 @@ impl StencilVertexArray where D: Device { } } -pub struct ReprojectionProgram where D: Device { - pub program: D::Program, - pub old_transform_uniform: D::Uniform, - pub new_transform_uniform: D::Uniform, - pub texture: D::TextureParameter, +pub(crate) struct ReprojectionProgram where D: Device { + pub(crate) program: D::Program, + pub(crate) old_transform_uniform: D::Uniform, + pub(crate) new_transform_uniform: D::Uniform, + pub(crate) texture: D::TextureParameter, } impl ReprojectionProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram { + pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram { let program = device.create_raster_program(resources, "reproject"); let old_transform_uniform = device.get_uniform(&program, "OldTransform"); let new_transform_uniform = device.get_uniform(&program, "NewTransform"); @@ -245,17 +245,16 @@ impl ReprojectionProgram where D: Device { } } -pub struct ReprojectionVertexArray where D: Device { - pub vertex_array: D::VertexArray, +pub(crate) struct ReprojectionVertexArray where D: Device { + pub(crate) vertex_array: D::VertexArray, } impl ReprojectionVertexArray where D: Device { - pub fn new( - device: &D, - reprojection_program: &ReprojectionProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer, - ) -> ReprojectionVertexArray { + pub(crate) fn new(device: &D, + reprojection_program: &ReprojectionProgram, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> ReprojectionVertexArray { let vertex_array = device.create_vertex_array(); let position_attr = device.get_vertex_attr(&reprojection_program.program, "Position") .unwrap(); diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index ac43b530..d6ad7b8e 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -17,13 +17,13 @@ extern crate log; pub mod concurrent; pub mod gpu; -pub mod gpu_data; pub mod options; pub mod paint; pub mod scene; mod allocator; mod builder; +mod gpu_data; mod tile_map; mod tiler; mod tiles; diff --git a/renderer/src/options.rs b/renderer/src/options.rs index 646bdda4..cc739cad 100644 --- a/renderer/src/options.rs +++ b/renderer/src/options.rs @@ -18,20 +18,30 @@ use pathfinder_geometry::transform3d::Perspective; use pathfinder_geometry::vector::{Vector2F, Vector4F}; use pathfinder_content::clip::PolygonClipper3D; +/// A sink for the render commands that scenes build. +/// +/// In single-threaded operation, this object typically buffers commands into an array and then, +/// once scene building is complete, commands are all sent to the output at once. In multithreaded +/// operation, on the other hand, commands are sent to the renderer on the fly as they're built. +/// The latter is generally preferable for performance, because it allows the CPU and GPU to run +/// concurrently. However, it requires a multithreaded environment, which may not always be +/// available. pub struct RenderCommandListener<'a> { send_fn: RenderCommandSendFunction<'a>, } +/// The callback function that receives the render commands from the scene builder. pub type RenderCommandSendFunction<'a> = Box; impl<'a> RenderCommandListener<'a> { + /// Wraps a render command callback in a `RenderCommandListener`. #[inline] pub fn new(send_fn: RenderCommandSendFunction<'a>) -> RenderCommandListener<'a> { RenderCommandListener { send_fn } } #[inline] - pub fn send(&self, render_command: RenderCommand) { + pub(crate) fn send(&self, render_command: RenderCommand) { (self.send_fn)(render_command) } } @@ -39,8 +49,12 @@ impl<'a> RenderCommandListener<'a> { /// Options that influence scene building. #[derive(Clone, Default)] pub struct BuildOptions { + /// A global transform to be applied to the scene. pub transform: RenderTransform, + /// Expands outlines by the given number of device pixels. This is useful to perform *stem + /// darkening* for fonts, to mitigate the thinness of gamma-corrected fonts. pub dilation: Vector2F, + /// True if subpixel antialiasing for LCD screens is to be performed. pub subpixel_aa_enabled: bool, } @@ -54,9 +68,12 @@ impl BuildOptions { } } +/// A global transform to apply to the scene. #[derive(Clone)] pub enum RenderTransform { + /// A 2D transform. Transform2D(Transform2F), + /// A perspective transform. (This will soon be removed in favor of a revised 3D approach.) Perspective(Perspective), } diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index 878f9caf..052a3111 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -34,8 +34,8 @@ use std::sync::Arc; const GRADIENT_TILE_LENGTH: u32 = 256; #[derive(Clone)] -pub struct Palette { - pub paints: Vec, +pub(crate) struct Palette { + pub(crate) paints: Vec, render_targets: Vec, cache: HashMap, allocator: TextureAllocator, @@ -90,7 +90,7 @@ impl Debug for PaintContents { impl Palette { #[inline] - pub fn new(scene_id: SceneId) -> Palette { + pub(crate) fn new(scene_id: SceneId) -> Palette { Palette { paints: vec![], render_targets: vec![], @@ -266,62 +266,62 @@ impl PaintOverlay { } } -pub struct PaintInfo { +pub(crate) struct PaintInfo { /// The render commands needed to prepare the textures. - pub render_commands: Vec, + pub(crate) render_commands: Vec, /// The metadata for each paint. /// /// The indices of this vector are paint IDs. - pub paint_metadata: Vec, + pub(crate) paint_metadata: Vec, /// The metadata for each render target. /// /// The indices of this vector are render target IDs. - pub render_target_metadata: Vec, + pub(crate) render_target_metadata: Vec, } #[derive(Debug)] -pub struct PaintMetadata { +pub(crate) struct PaintMetadata { /// Metadata associated with the color texture, if applicable. - pub color_texture_metadata: Option, + pub(crate) color_texture_metadata: Option, /// The base color that the color texture gets mixed into. - pub base_color: ColorU, - pub blend_mode: BlendMode, + pub(crate) base_color: ColorU, + pub(crate) blend_mode: BlendMode, /// True if this paint is fully opaque. - pub is_opaque: bool, + pub(crate) is_opaque: bool, } #[derive(Debug)] -pub struct PaintColorTextureMetadata { +pub(crate) struct PaintColorTextureMetadata { /// The location of the paint. - pub location: TextureLocation, + pub(crate) location: TextureLocation, /// The scale for the page this paint is on. - pub page_scale: Vector2F, + pub(crate) page_scale: Vector2F, /// The transform to apply to screen coordinates to translate them into UVs. - pub transform: Transform2F, + pub(crate) transform: Transform2F, /// The sampling mode for the texture. - pub sampling_flags: TextureSamplingFlags, + pub(crate) sampling_flags: TextureSamplingFlags, /// The filter to be applied to this paint. - pub filter: PaintFilter, + pub(crate) filter: PaintFilter, /// How the color texture is to be composited over the base color. - pub composite_op: PaintCompositeOp, + pub(crate) composite_op: PaintCompositeOp, } #[derive(Clone, Copy, Debug)] -pub struct RadialGradientMetadata { +pub(crate) struct RadialGradientMetadata { /// The line segment that connects the two circles. - pub line: LineSegment2F, + pub(crate) line: LineSegment2F, /// The radii of the two circles. - pub radii: F32x2, + pub(crate) radii: F32x2, } #[derive(Clone, Copy, Debug)] -pub struct RenderTargetMetadata { +pub(crate) struct RenderTargetMetadata { /// The location of the render target. - pub location: TextureLocation, + pub(crate) location: TextureLocation, } #[derive(Debug)] -pub enum PaintFilter { +pub(crate) enum PaintFilter { None, RadialGradient { /// The line segment that connects the two circles. @@ -334,7 +334,7 @@ pub enum PaintFilter { impl Palette { #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn push_paint(&mut self, paint: &Paint) -> PaintId { + pub(crate) fn push_paint(&mut self, paint: &Paint) -> PaintId { if let Some(paint_id) = self.cache.get(paint) { return *paint_id; } @@ -345,7 +345,7 @@ impl Palette { paint_id } - pub fn push_render_target(&mut self, render_target: RenderTarget) -> RenderTargetId { + pub(crate) fn push_render_target(&mut self, render_target: RenderTarget) -> RenderTargetId { let id = self.render_targets.len() as u32; let metadata = RenderTargetMetadata { @@ -356,7 +356,7 @@ impl Palette { RenderTargetId { scene: self.scene_id.0, render_target: id } } - pub fn build_paint_info(&mut self, render_transform: Transform2F) -> PaintInfo { + pub(crate) fn build_paint_info(&mut self, render_transform: Transform2F) -> PaintInfo { let mut paint_metadata = vec![]; // Assign paint locations. diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 693abb13..ac032bcc 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A set of paths to be rendered. +//! The vector scene to be rendered. use crate::builder::SceneBuilder; use crate::concurrent::executor::Executor; @@ -34,6 +34,7 @@ use std::u64; static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0); +/// The vector scene to be rendered. #[derive(Clone)] pub struct Scene { display_list: Vec, @@ -156,7 +157,7 @@ impl Scene { } #[inline] - pub fn build_paint_info(&mut self, render_transform: Transform2F) -> PaintInfo { + pub(crate) fn build_paint_info(&mut self, render_transform: Transform2F) -> PaintInfo { self.palette.build_paint_info(render_transform) } @@ -281,8 +282,8 @@ impl Scene { } #[inline] - pub fn palette(&self) -> &Palette { - &self.palette + pub fn get_paint(&self, paint_id: PaintId) -> &Paint { + self.palette.paints.get(paint_id.0 as usize).expect("No paint with that ID!") } #[inline]