Auto merge of #390 - pcwalton:docs-renderer, r=pcwalton
Add API docs for the renderer and associated types
This commit is contained in:
commit
d4ec17554b
|
@ -54,7 +54,7 @@ fn export_svg<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
||||||
view_box.size().y()
|
view_box.size().y()
|
||||||
)?;
|
)?;
|
||||||
for &DrawPath { paint: paint_id, ref outline, ref name, .. } in scene.draw_paths() {
|
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, " <path")?;
|
write!(writer, " <path")?;
|
||||||
if !name.is_empty() {
|
if !name.is_empty() {
|
||||||
write!(writer, " id=\"{}\"", name)?;
|
write!(writer, " id=\"{}\"", name)?;
|
||||||
|
@ -78,7 +78,7 @@ fn export_pdf<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
||||||
|
|
||||||
for &DrawPath { paint: paint_id, ref outline, .. } in scene.draw_paths() {
|
for &DrawPath { paint: paint_id, ref outline, .. } in scene.draw_paths() {
|
||||||
// TODO(pcwalton): Gradients and patterns.
|
// 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() {
|
if paint.is_color() {
|
||||||
pdf.set_fill_color(paint.base_color());
|
pdf.set_fill_color(paint.base_color());
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ fn export_ps<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pcwalton): Gradients and patterns.
|
// 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() {
|
if paint.is_color() {
|
||||||
let color = paint.base_color();
|
let color = paint.base_color();
|
||||||
writeln!(writer, "{} {} {} setrgbcolor", color.r, color.g, color.b)?;
|
writeln!(writer, "{} {} {} setrgbcolor", color.r, color.g, color.b)?;
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub trait Executor {
|
||||||
where T: Send, F: Fn(usize) -> T + Send + Sync;
|
where T: Send, F: Fn(usize) -> T + Send + Sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An executor that simply executes tasks sequentially in the same thread.
|
||||||
pub struct SequentialExecutor;
|
pub struct SequentialExecutor;
|
||||||
|
|
||||||
impl Executor for SequentialExecutor {
|
impl Executor for SequentialExecutor {
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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 crate::concurrent::executor::Executor;
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
|
/// An executor that parallelizes tasks across all CPUs using the Rayon library.
|
||||||
pub struct RayonExecutor;
|
pub struct RayonExecutor;
|
||||||
|
|
||||||
impl Executor for RayonExecutor {
|
impl Executor for RayonExecutor {
|
||||||
|
|
|
@ -32,17 +32,30 @@ use std::thread;
|
||||||
|
|
||||||
const MAX_MESSAGES_IN_FLIGHT: usize = 1024;
|
const MAX_MESSAGES_IN_FLIGHT: usize = 1024;
|
||||||
|
|
||||||
|
/// A version of `Scene` that proxies all method calls out to a separate thread.
|
||||||
pub struct SceneProxy {
|
pub struct SceneProxy {
|
||||||
sender: Sender<MainToWorkerMsg>,
|
sender: Sender<MainToWorkerMsg>,
|
||||||
receiver: Receiver<RenderCommand>,
|
receiver: Receiver<RenderCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SceneProxy {
|
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<E>(renderer_level: RendererLevel, executor: E) -> SceneProxy
|
pub fn new<E>(renderer_level: RendererLevel, executor: E) -> SceneProxy
|
||||||
where E: Executor + Send + 'static {
|
where E: Executor + Send + 'static {
|
||||||
SceneProxy::from_scene(Scene::new(), renderer_level, executor)
|
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<E>(scene: Scene, renderer_level: RendererLevel, executor: E)
|
pub fn from_scene<E>(scene: Scene, renderer_level: RendererLevel, executor: E)
|
||||||
-> SceneProxy
|
-> SceneProxy
|
||||||
where E: Executor + Send + 'static {
|
where E: Executor + Send + 'static {
|
||||||
|
@ -58,22 +71,25 @@ impl SceneProxy {
|
||||||
SceneProxy { sender: main_to_worker_sender, receiver: worker_to_main_receiver }
|
SceneProxy { sender: main_to_worker_sender, receiver: worker_to_main_receiver }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces the wrapped scene with a new one, discarding the old scene.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn replace_scene(&self, new_scene: Scene) {
|
pub fn replace_scene(&self, new_scene: Scene) {
|
||||||
self.sender.send(MainToWorkerMsg::ReplaceScene(new_scene)).unwrap();
|
self.sender.send(MainToWorkerMsg::ReplaceScene(new_scene)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the view box of the scene, which defines the visible rectangle.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_view_box(&self, new_view_box: RectF) {
|
pub fn set_view_box(&self, new_view_box: RectF) {
|
||||||
self.sender.send(MainToWorkerMsg::SetViewBox(new_view_box)).unwrap();
|
self.sender.send(MainToWorkerMsg::SetViewBox(new_view_box)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a scene and queues up the commands needed to render it.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build(&self, options: BuildOptions) {
|
pub fn build(&self, options: BuildOptions) {
|
||||||
self.sender.send(MainToWorkerMsg::Build(options)).unwrap();
|
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]
|
#[inline]
|
||||||
pub fn render<D>(&mut self, renderer: &mut Renderer<D>) where D: Device {
|
pub fn render<D>(&mut self, renderer: &mut Renderer<D>) where D: Device {
|
||||||
renderer.begin_scene();
|
renderer.begin_scene();
|
||||||
|
@ -104,6 +120,7 @@ impl SceneProxy {
|
||||||
self.render(renderer);
|
self.render(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a copy of the wrapped scene.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn copy_scene(&self) -> Scene {
|
pub fn copy_scene(&self) -> Scene {
|
||||||
let (sender, receiver) = crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
|
let (sender, receiver) = crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
|
||||||
|
|
|
@ -8,5 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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 renderer;
|
||||||
pub mod shaders;
|
pub mod shaders;
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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::{BOUND_WORKGROUP_SIZE, DICE_WORKGROUP_SIZE};
|
||||||
use crate::gpu::d3d11::shaders::{PROPAGATE_WORKGROUP_SIZE, ProgramsD3D11, SORT_WORKGROUP_SIZE};
|
use crate::gpu::d3d11::shaders::{PROPAGATE_WORKGROUP_SIZE, ProgramsD3D11, SORT_WORKGROUP_SIZE};
|
||||||
use crate::gpu::perf::TimeCategory;
|
use crate::gpu::perf::TimeCategory;
|
||||||
|
|
|
@ -8,29 +8,31 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Shaders and vertex specifications for the Direct3D 11-level renderer.
|
||||||
|
|
||||||
use crate::gpu::shaders::TileProgramCommon;
|
use crate::gpu::shaders::TileProgramCommon;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
use pathfinder_gpu::{ComputeDimensions, Device};
|
use pathfinder_gpu::{ComputeDimensions, Device};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
|
|
||||||
pub const BOUND_WORKGROUP_SIZE: u32 = 64;
|
pub(crate) const BOUND_WORKGROUP_SIZE: u32 = 64;
|
||||||
pub const DICE_WORKGROUP_SIZE: u32 = 64;
|
pub(crate) const DICE_WORKGROUP_SIZE: u32 = 64;
|
||||||
pub const BIN_WORKGROUP_SIZE: u32 = 64;
|
pub(crate) const BIN_WORKGROUP_SIZE: u32 = 64;
|
||||||
pub const PROPAGATE_WORKGROUP_SIZE: u32 = 64;
|
pub(crate) const PROPAGATE_WORKGROUP_SIZE: u32 = 64;
|
||||||
pub const SORT_WORKGROUP_SIZE: u32 = 64;
|
pub(crate) const SORT_WORKGROUP_SIZE: u32 = 64;
|
||||||
|
|
||||||
pub struct ProgramsD3D11<D> where D: Device {
|
pub(crate) struct ProgramsD3D11<D> where D: Device {
|
||||||
pub bound_program: BoundProgramD3D11<D>,
|
pub(crate) bound_program: BoundProgramD3D11<D>,
|
||||||
pub dice_program: DiceProgramD3D11<D>,
|
pub(crate) dice_program: DiceProgramD3D11<D>,
|
||||||
pub bin_program: BinProgramD3D11<D>,
|
pub(crate) bin_program: BinProgramD3D11<D>,
|
||||||
pub propagate_program: PropagateProgramD3D11<D>,
|
pub(crate) propagate_program: PropagateProgramD3D11<D>,
|
||||||
pub sort_program: SortProgramD3D11<D>,
|
pub(crate) sort_program: SortProgramD3D11<D>,
|
||||||
pub fill_program: FillProgramD3D11<D>,
|
pub(crate) fill_program: FillProgramD3D11<D>,
|
||||||
pub tile_program: TileProgramD3D11<D>,
|
pub(crate) tile_program: TileProgramD3D11<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ProgramsD3D11<D> where D: Device {
|
impl<D> ProgramsD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D11<D> {
|
||||||
ProgramsD3D11 {
|
ProgramsD3D11 {
|
||||||
bound_program: BoundProgramD3D11::new(device, resources),
|
bound_program: BoundProgramD3D11::new(device, resources),
|
||||||
dice_program: DiceProgramD3D11::new(device, resources),
|
dice_program: DiceProgramD3D11::new(device, resources),
|
||||||
|
@ -43,23 +45,23 @@ impl<D> ProgramsD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PropagateProgramD3D11<D> where D: Device {
|
pub(crate) struct PropagateProgramD3D11<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub framebuffer_tile_size_uniform: D::Uniform,
|
pub(crate) framebuffer_tile_size_uniform: D::Uniform,
|
||||||
pub column_count_uniform: D::Uniform,
|
pub(crate) column_count_uniform: D::Uniform,
|
||||||
pub first_alpha_tile_index_uniform: D::Uniform,
|
pub(crate) first_alpha_tile_index_uniform: D::Uniform,
|
||||||
pub draw_metadata_storage_buffer: D::StorageBuffer,
|
pub(crate) draw_metadata_storage_buffer: D::StorageBuffer,
|
||||||
pub clip_metadata_storage_buffer: D::StorageBuffer,
|
pub(crate) clip_metadata_storage_buffer: D::StorageBuffer,
|
||||||
pub backdrops_storage_buffer: D::StorageBuffer,
|
pub(crate) backdrops_storage_buffer: D::StorageBuffer,
|
||||||
pub draw_tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) draw_tiles_storage_buffer: D::StorageBuffer,
|
||||||
pub clip_tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) clip_tiles_storage_buffer: D::StorageBuffer,
|
||||||
pub z_buffer_storage_buffer: D::StorageBuffer,
|
pub(crate) z_buffer_storage_buffer: D::StorageBuffer,
|
||||||
pub first_tile_map_storage_buffer: D::StorageBuffer,
|
pub(crate) first_tile_map_storage_buffer: D::StorageBuffer,
|
||||||
pub alpha_tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) alpha_tiles_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> PropagateProgramD3D11<D> where D: Device {
|
impl<D> PropagateProgramD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> PropagateProgramD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> PropagateProgramD3D11<D> {
|
||||||
let mut program = device.create_compute_program(resources, "d3d11/propagate");
|
let mut program = device.create_compute_program(resources, "d3d11/propagate");
|
||||||
let local_size = ComputeDimensions { x: PROPAGATE_WORKGROUP_SIZE, y: 1, z: 1 };
|
let local_size = ComputeDimensions { x: PROPAGATE_WORKGROUP_SIZE, y: 1, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, local_size);
|
device.set_compute_program_local_size(&mut program, local_size);
|
||||||
|
@ -93,18 +95,18 @@ impl<D> PropagateProgramD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FillProgramD3D11<D> where D: Device {
|
pub(crate) struct FillProgramD3D11<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub dest_image: D::ImageParameter,
|
pub(crate) dest_image: D::ImageParameter,
|
||||||
pub area_lut_texture: D::TextureParameter,
|
pub(crate) area_lut_texture: D::TextureParameter,
|
||||||
pub alpha_tile_range_uniform: D::Uniform,
|
pub(crate) alpha_tile_range_uniform: D::Uniform,
|
||||||
pub fills_storage_buffer: D::StorageBuffer,
|
pub(crate) fills_storage_buffer: D::StorageBuffer,
|
||||||
pub tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) tiles_storage_buffer: D::StorageBuffer,
|
||||||
pub alpha_tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) alpha_tiles_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FillProgramD3D11<D> where D: Device {
|
impl<D> FillProgramD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgramD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgramD3D11<D> {
|
||||||
let mut program = device.create_compute_program(resources, "d3d11/fill");
|
let mut program = device.create_compute_program(resources, "d3d11/fill");
|
||||||
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT / 4, z: 1 };
|
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT / 4, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, local_size);
|
device.set_compute_program_local_size(&mut program, local_size);
|
||||||
|
@ -128,14 +130,14 @@ impl<D> FillProgramD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TileProgramD3D11<D> where D: Device {
|
pub(crate) struct TileProgramD3D11<D> where D: Device {
|
||||||
pub common: TileProgramCommon<D>,
|
pub(crate) common: TileProgramCommon<D>,
|
||||||
pub load_action_uniform: D::Uniform,
|
pub(crate) load_action_uniform: D::Uniform,
|
||||||
pub clear_color_uniform: D::Uniform,
|
pub(crate) clear_color_uniform: D::Uniform,
|
||||||
pub framebuffer_tile_size_uniform: D::Uniform,
|
pub(crate) framebuffer_tile_size_uniform: D::Uniform,
|
||||||
pub dest_image: D::ImageParameter,
|
pub(crate) dest_image: D::ImageParameter,
|
||||||
pub tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) tiles_storage_buffer: D::StorageBuffer,
|
||||||
pub first_tile_map_storage_buffer: D::StorageBuffer,
|
pub(crate) first_tile_map_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> TileProgramD3D11<D> where D: Device {
|
impl<D> TileProgramD3D11<D> where D: Device {
|
||||||
|
@ -164,20 +166,20 @@ impl<D> TileProgramD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BinProgramD3D11<D> where D: Device {
|
pub(crate) struct BinProgramD3D11<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub microline_count_uniform: D::Uniform,
|
pub(crate) microline_count_uniform: D::Uniform,
|
||||||
pub max_fill_count_uniform: D::Uniform,
|
pub(crate) max_fill_count_uniform: D::Uniform,
|
||||||
pub microlines_storage_buffer: D::StorageBuffer,
|
pub(crate) microlines_storage_buffer: D::StorageBuffer,
|
||||||
pub metadata_storage_buffer: D::StorageBuffer,
|
pub(crate) metadata_storage_buffer: D::StorageBuffer,
|
||||||
pub indirect_draw_params_storage_buffer: D::StorageBuffer,
|
pub(crate) indirect_draw_params_storage_buffer: D::StorageBuffer,
|
||||||
pub fills_storage_buffer: D::StorageBuffer,
|
pub(crate) fills_storage_buffer: D::StorageBuffer,
|
||||||
pub tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) tiles_storage_buffer: D::StorageBuffer,
|
||||||
pub backdrops_storage_buffer: D::StorageBuffer,
|
pub(crate) backdrops_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> BinProgramD3D11<D> where D: Device {
|
impl<D> BinProgramD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BinProgramD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> BinProgramD3D11<D> {
|
||||||
let mut program = device.create_compute_program(resources, "d3d11/bin");
|
let mut program = device.create_compute_program(resources, "d3d11/bin");
|
||||||
let dimensions = ComputeDimensions { x: BIN_WORKGROUP_SIZE, y: 1, z: 1 };
|
let dimensions = ComputeDimensions { x: BIN_WORKGROUP_SIZE, y: 1, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, dimensions);
|
device.set_compute_program_local_size(&mut program, dimensions);
|
||||||
|
@ -207,22 +209,22 @@ impl<D> BinProgramD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DiceProgramD3D11<D> where D: Device {
|
pub(crate) struct DiceProgramD3D11<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub transform_uniform: D::Uniform,
|
pub(crate) transform_uniform: D::Uniform,
|
||||||
pub translation_uniform: D::Uniform,
|
pub(crate) translation_uniform: D::Uniform,
|
||||||
pub path_count_uniform: D::Uniform,
|
pub(crate) path_count_uniform: D::Uniform,
|
||||||
pub last_batch_segment_index_uniform: D::Uniform,
|
pub(crate) last_batch_segment_index_uniform: D::Uniform,
|
||||||
pub max_microline_count_uniform: D::Uniform,
|
pub(crate) max_microline_count_uniform: D::Uniform,
|
||||||
pub compute_indirect_params_storage_buffer: D::StorageBuffer,
|
pub(crate) compute_indirect_params_storage_buffer: D::StorageBuffer,
|
||||||
pub dice_metadata_storage_buffer: D::StorageBuffer,
|
pub(crate) dice_metadata_storage_buffer: D::StorageBuffer,
|
||||||
pub points_storage_buffer: D::StorageBuffer,
|
pub(crate) points_storage_buffer: D::StorageBuffer,
|
||||||
pub input_indices_storage_buffer: D::StorageBuffer,
|
pub(crate) input_indices_storage_buffer: D::StorageBuffer,
|
||||||
pub microlines_storage_buffer: D::StorageBuffer,
|
pub(crate) microlines_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> DiceProgramD3D11<D> where D: Device {
|
impl<D> DiceProgramD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> DiceProgramD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> DiceProgramD3D11<D> {
|
||||||
let mut program = device.create_compute_program(resources, "d3d11/dice");
|
let mut program = device.create_compute_program(resources, "d3d11/dice");
|
||||||
let dimensions = ComputeDimensions { x: DICE_WORKGROUP_SIZE, y: 1, z: 1 };
|
let dimensions = ComputeDimensions { x: DICE_WORKGROUP_SIZE, y: 1, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, dimensions);
|
device.set_compute_program_local_size(&mut program, dimensions);
|
||||||
|
@ -257,16 +259,16 @@ impl<D> DiceProgramD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BoundProgramD3D11<D> where D: Device {
|
pub(crate) struct BoundProgramD3D11<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub path_count_uniform: D::Uniform,
|
pub(crate) path_count_uniform: D::Uniform,
|
||||||
pub tile_count_uniform: D::Uniform,
|
pub(crate) tile_count_uniform: D::Uniform,
|
||||||
pub tile_path_info_storage_buffer: D::StorageBuffer,
|
pub(crate) tile_path_info_storage_buffer: D::StorageBuffer,
|
||||||
pub tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) tiles_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> BoundProgramD3D11<D> where D: Device {
|
impl<D> BoundProgramD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BoundProgramD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> BoundProgramD3D11<D> {
|
||||||
let mut program = device.create_compute_program(resources, "d3d11/bound");
|
let mut program = device.create_compute_program(resources, "d3d11/bound");
|
||||||
let dimensions = ComputeDimensions { x: BOUND_WORKGROUP_SIZE, y: 1, z: 1 };
|
let dimensions = ComputeDimensions { x: BOUND_WORKGROUP_SIZE, y: 1, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, dimensions);
|
device.set_compute_program_local_size(&mut program, dimensions);
|
||||||
|
@ -287,16 +289,16 @@ impl<D> BoundProgramD3D11<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SortProgramD3D11<D> where D: Device {
|
pub(crate) struct SortProgramD3D11<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub tile_count_uniform: D::Uniform,
|
pub(crate) tile_count_uniform: D::Uniform,
|
||||||
pub tiles_storage_buffer: D::StorageBuffer,
|
pub(crate) tiles_storage_buffer: D::StorageBuffer,
|
||||||
pub first_tile_map_storage_buffer: D::StorageBuffer,
|
pub(crate) first_tile_map_storage_buffer: D::StorageBuffer,
|
||||||
pub z_buffer_storage_buffer: D::StorageBuffer,
|
pub(crate) z_buffer_storage_buffer: D::StorageBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> SortProgramD3D11<D> where D: Device {
|
impl<D> SortProgramD3D11<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> SortProgramD3D11<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> SortProgramD3D11<D> {
|
||||||
let mut program = device.create_compute_program(resources, "d3d11/sort");
|
let mut program = device.create_compute_program(resources, "d3d11/sort");
|
||||||
let dimensions = ComputeDimensions { x: SORT_WORKGROUP_SIZE, y: 1, z: 1 };
|
let dimensions = ComputeDimensions { x: SORT_WORKGROUP_SIZE, y: 1, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, dimensions);
|
device.set_compute_program_local_size(&mut program, dimensions);
|
||||||
|
|
|
@ -8,5 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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 renderer;
|
||||||
pub mod shaders;
|
pub mod shaders;
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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::blend::{BlendModeExt, ToBlendState};
|
||||||
use crate::gpu::perf::TimeCategory;
|
use crate::gpu::perf::TimeCategory;
|
||||||
use crate::gpu::renderer::{FramebufferFlags, MASK_FRAMEBUFFER_HEIGHT, MASK_FRAMEBUFFER_WIDTH};
|
use crate::gpu::renderer::{FramebufferFlags, MASK_FRAMEBUFFER_HEIGHT, MASK_FRAMEBUFFER_WIDTH};
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Shaders and vertex specifications for the Direct3D 9-level renderer.
|
||||||
|
|
||||||
use crate::gpu::shaders::{TILE_INSTANCE_SIZE, TileProgramCommon};
|
use crate::gpu::shaders::{TILE_INSTANCE_SIZE, TileProgramCommon};
|
||||||
use pathfinder_gpu::{BufferTarget, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
use pathfinder_gpu::{BufferTarget, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
|
@ -15,17 +17,17 @@ use pathfinder_resources::ResourceLoader;
|
||||||
const FILL_INSTANCE_SIZE: usize = 12;
|
const FILL_INSTANCE_SIZE: usize = 12;
|
||||||
const CLIP_TILE_INSTANCE_SIZE: usize = 16;
|
const CLIP_TILE_INSTANCE_SIZE: usize = 16;
|
||||||
|
|
||||||
pub struct FillVertexArrayD3D9<D> where D: Device {
|
pub(crate) struct FillVertexArrayD3D9<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FillVertexArrayD3D9<D> where D: Device {
|
impl<D> FillVertexArrayD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
fill_program: &FillProgramD3D9<D>,
|
fill_program: &FillProgramD3D9<D>,
|
||||||
vertex_buffer: &D::Buffer,
|
vertex_buffer: &D::Buffer,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> FillVertexArrayD3D9<D> {
|
-> FillVertexArrayD3D9<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
|
|
||||||
let tess_coord_attr = device.get_vertex_attr(&fill_program.program, "TessCoord").unwrap();
|
let tess_coord_attr = device.get_vertex_attr(&fill_program.program, "TessCoord").unwrap();
|
||||||
|
@ -68,17 +70,17 @@ impl<D> FillVertexArrayD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TileVertexArrayD3D9<D> where D: Device {
|
pub(crate) struct TileVertexArrayD3D9<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> TileVertexArrayD3D9<D> where D: Device {
|
impl<D> TileVertexArrayD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
tile_program: &TileProgramD3D9<D>,
|
tile_program: &TileProgramD3D9<D>,
|
||||||
tile_vertex_buffer: &D::Buffer,
|
tile_vertex_buffer: &D::Buffer,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> TileVertexArrayD3D9<D> {
|
-> TileVertexArrayD3D9<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
|
|
||||||
let tile_offset_attr =
|
let tile_offset_attr =
|
||||||
|
@ -155,17 +157,17 @@ impl<D> TileVertexArrayD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClipTileCopyVertexArrayD3D9<D> where D: Device {
|
pub(crate) struct ClipTileCopyVertexArrayD3D9<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClipTileCopyVertexArrayD3D9<D> where D: Device {
|
impl<D> ClipTileCopyVertexArrayD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
clip_tile_copy_program: &ClipTileCopyProgramD3D9<D>,
|
clip_tile_copy_program: &ClipTileCopyProgramD3D9<D>,
|
||||||
vertex_buffer: &D::Buffer,
|
vertex_buffer: &D::Buffer,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> ClipTileCopyVertexArrayD3D9<D> {
|
-> ClipTileCopyVertexArrayD3D9<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
|
|
||||||
let tile_offset_attr =
|
let tile_offset_attr =
|
||||||
|
@ -199,17 +201,17 @@ impl<D> ClipTileCopyVertexArrayD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClipTileCombineVertexArrayD3D9<D> where D: Device {
|
pub(crate) struct ClipTileCombineVertexArrayD3D9<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClipTileCombineVertexArrayD3D9<D> where D: Device {
|
impl<D> ClipTileCombineVertexArrayD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
clip_tile_combine_program: &ClipTileCombineProgramD3D9<D>,
|
clip_tile_combine_program: &ClipTileCombineProgramD3D9<D>,
|
||||||
vertex_buffer: &D::Buffer,
|
vertex_buffer: &D::Buffer,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> ClipTileCombineVertexArrayD3D9<D> {
|
-> ClipTileCombineVertexArrayD3D9<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
|
|
||||||
let tile_offset_attr =
|
let tile_offset_attr =
|
||||||
|
@ -276,16 +278,16 @@ impl<D> ClipTileCombineVertexArrayD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CopyTileVertexArray<D> where D: Device {
|
pub(crate) struct CopyTileVertexArray<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> CopyTileVertexArray<D> where D: Device {
|
impl<D> CopyTileVertexArray<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
copy_tile_program: &CopyTileProgram<D>,
|
copy_tile_program: &CopyTileProgram<D>,
|
||||||
copy_tile_vertex_buffer: &D::Buffer,
|
copy_tile_vertex_buffer: &D::Buffer,
|
||||||
quads_vertex_indices_buffer: &D::Buffer)
|
quads_vertex_indices_buffer: &D::Buffer)
|
||||||
-> CopyTileVertexArray<D> {
|
-> CopyTileVertexArray<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
|
|
||||||
let tile_position_attr =
|
let tile_position_attr =
|
||||||
|
@ -307,11 +309,11 @@ impl<D> CopyTileVertexArray<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FillProgramD3D9<D> where D: Device {
|
pub(crate) struct FillProgramD3D9<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub(crate) tile_size_uniform: D::Uniform,
|
||||||
pub area_lut_texture: D::TextureParameter,
|
pub(crate) area_lut_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FillProgramD3D9<D> where D: Device {
|
impl<D> FillProgramD3D9<D> where D: Device {
|
||||||
|
@ -329,10 +331,10 @@ impl<D> FillProgramD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TileProgramD3D9<D> where D: Device {
|
pub(crate) struct TileProgramD3D9<D> where D: Device {
|
||||||
pub common: TileProgramCommon<D>,
|
pub(crate) common: TileProgramCommon<D>,
|
||||||
pub dest_texture: D::TextureParameter,
|
pub(crate) dest_texture: D::TextureParameter,
|
||||||
pub transform_uniform: D::Uniform,
|
pub(crate) transform_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> TileProgramD3D9<D> where D: Device {
|
impl<D> TileProgramD3D9<D> where D: Device {
|
||||||
|
@ -345,14 +347,15 @@ impl<D> TileProgramD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClipTileCombineProgramD3D9<D> where D: Device {
|
pub(crate) struct ClipTileCombineProgramD3D9<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub src_texture: D::TextureParameter,
|
pub(crate) src_texture: D::TextureParameter,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClipTileCombineProgramD3D9<D> where D: Device {
|
impl<D> ClipTileCombineProgramD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileCombineProgramD3D9<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader)
|
||||||
|
-> ClipTileCombineProgramD3D9<D> {
|
||||||
let program = device.create_raster_program(resources, "d3d9/tile_clip_combine");
|
let program = device.create_raster_program(resources, "d3d9/tile_clip_combine");
|
||||||
let src_texture = device.get_texture_parameter(&program, "Src");
|
let src_texture = device.get_texture_parameter(&program, "Src");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
|
@ -360,14 +363,14 @@ impl<D> ClipTileCombineProgramD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClipTileCopyProgramD3D9<D> where D: Device {
|
pub(crate) struct ClipTileCopyProgramD3D9<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub src_texture: D::TextureParameter,
|
pub(crate) src_texture: D::TextureParameter,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClipTileCopyProgramD3D9<D> where D: Device {
|
impl<D> ClipTileCopyProgramD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileCopyProgramD3D9<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileCopyProgramD3D9<D> {
|
||||||
let program = device.create_raster_program(resources, "d3d9/tile_clip_copy");
|
let program = device.create_raster_program(resources, "d3d9/tile_clip_copy");
|
||||||
let src_texture = device.get_texture_parameter(&program, "Src");
|
let src_texture = device.get_texture_parameter(&program, "Src");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
|
@ -375,16 +378,16 @@ impl<D> ClipTileCopyProgramD3D9<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CopyTileProgram<D> where D: Device {
|
pub(crate) struct CopyTileProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub transform_uniform: D::Uniform,
|
pub(crate) transform_uniform: D::Uniform,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub(crate) tile_size_uniform: D::Uniform,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
pub src_texture: D::TextureParameter,
|
pub(crate) src_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> CopyTileProgram<D> where D: Device {
|
impl<D> CopyTileProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> CopyTileProgram<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> CopyTileProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "d3d9/tile_copy");
|
let program = device.create_raster_program(resources, "d3d9/tile_copy");
|
||||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||||
|
@ -400,36 +403,16 @@ impl<D> CopyTileProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct D3D9Programs<D> where D: Device {
|
pub(crate) struct ProgramsD3D9<D> where D: Device {
|
||||||
pub fill_program: FillProgramD3D9<D>,
|
pub(crate) fill_program: FillProgramD3D9<D>,
|
||||||
pub tile_program: TileProgramD3D9<D>,
|
pub(crate) tile_program: TileProgramD3D9<D>,
|
||||||
pub tile_clip_combine_program: ClipTileCombineProgramD3D9<D>,
|
pub(crate) tile_clip_copy_program: ClipTileCopyProgramD3D9<D>,
|
||||||
pub tile_clip_copy_program: ClipTileCopyProgramD3D9<D>,
|
pub(crate) tile_clip_combine_program: ClipTileCombineProgramD3D9<D>,
|
||||||
pub tile_copy_program: CopyTileProgram<D>,
|
pub(crate) tile_copy_program: CopyTileProgram<D>,
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> D3D9Programs<D> where D: Device {
|
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> D3D9Programs<D> {
|
|
||||||
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<D> where D: Device {
|
|
||||||
pub fill_program: FillProgramD3D9<D>,
|
|
||||||
pub tile_program: TileProgramD3D9<D>,
|
|
||||||
pub tile_clip_copy_program: ClipTileCopyProgramD3D9<D>,
|
|
||||||
pub tile_clip_combine_program: ClipTileCombineProgramD3D9<D>,
|
|
||||||
pub tile_copy_program: CopyTileProgram<D>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ProgramsD3D9<D> where D: Device {
|
impl<D> ProgramsD3D9<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D9<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsD3D9<D> {
|
||||||
ProgramsD3D9 {
|
ProgramsD3D9 {
|
||||||
fill_program: FillProgramD3D9::new(device, resources),
|
fill_program: FillProgramD3D9::new(device, resources),
|
||||||
tile_program: TileProgramD3D9::new(device, resources),
|
tile_program: TileProgramD3D9::new(device, resources),
|
||||||
|
|
|
@ -39,8 +39,13 @@ const PERFORMANCE_WINDOW_HEIGHT_D3D11: i32 = LINE_HEIGHT * 10 + PADDING + 2;
|
||||||
const INFO_WINDOW_WIDTH: i32 = 425;
|
const INFO_WINDOW_WIDTH: i32 = 425;
|
||||||
const INFO_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 2 + PADDING + 2;
|
const INFO_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 2 + PADDING + 2;
|
||||||
|
|
||||||
|
/// Manages the debug UI.
|
||||||
pub struct DebugUIPresenter<D> where D: Device {
|
pub struct DebugUIPresenter<D> where D: Device {
|
||||||
|
/// The general UI presenter object.
|
||||||
|
///
|
||||||
|
/// You can use this to draw your own application-specific debug widgets.
|
||||||
pub ui_presenter: UIPresenter<D>,
|
pub ui_presenter: UIPresenter<D>,
|
||||||
|
|
||||||
cpu_samples: SampleBuffer<RenderStats>,
|
cpu_samples: SampleBuffer<RenderStats>,
|
||||||
gpu_samples: SampleBuffer<RenderTime>,
|
gpu_samples: SampleBuffer<RenderTime>,
|
||||||
backend_name: &'static str,
|
backend_name: &'static str,
|
||||||
|
@ -49,11 +54,11 @@ pub struct DebugUIPresenter<D> where D: Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> DebugUIPresenter<D> where D: Device {
|
impl<D> DebugUIPresenter<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
resources: &dyn ResourceLoader,
|
resources: &dyn ResourceLoader,
|
||||||
framebuffer_size: Vector2I,
|
framebuffer_size: Vector2I,
|
||||||
renderer_level: RendererLevel)
|
renderer_level: RendererLevel)
|
||||||
-> DebugUIPresenter<D> {
|
-> DebugUIPresenter<D> {
|
||||||
let ui_presenter = UIPresenter::new(device, resources, framebuffer_size);
|
let ui_presenter = UIPresenter::new(device, resources, framebuffer_size);
|
||||||
DebugUIPresenter {
|
DebugUIPresenter {
|
||||||
ui_presenter,
|
ui_presenter,
|
||||||
|
@ -65,19 +70,19 @@ impl<D> DebugUIPresenter<D> 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.cpu_samples.push(stats);
|
||||||
self.gpu_samples.push(rendering_time);
|
self.gpu_samples.push(rendering_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self, device: &D, allocator: &mut GPUMemoryAllocator<D>) {
|
pub(crate) fn draw(&self, device: &D, allocator: &mut GPUMemoryAllocator<D>) {
|
||||||
self.draw_stats_window(device, allocator);
|
self.draw_stats_window(device, allocator);
|
||||||
self.draw_performance_window(device, allocator);
|
self.draw_performance_window(device, allocator);
|
||||||
self.draw_info_window(device, allocator);
|
self.draw_info_window(device, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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)
|
self.ui_presenter.set_framebuffer_size(new_framebuffer_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Various options that control how the renderer behaves.
|
||||||
|
|
||||||
use pathfinder_color::ColorF;
|
use pathfinder_color::ColorF;
|
||||||
use pathfinder_geometry::rect::RectI;
|
use pathfinder_geometry::rect::RectI;
|
||||||
use pathfinder_geometry::vector::Vector2I;
|
use pathfinder_geometry::vector::Vector2I;
|
||||||
|
@ -57,6 +59,7 @@ impl<D> Default for RendererOptions<D> where D: Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RendererLevel {
|
impl RendererLevel {
|
||||||
|
/// Returns a suitable renderer level for the given device.
|
||||||
pub fn default_for_device<D>(device: &D) -> RendererLevel where D: Device {
|
pub fn default_for_device<D>(device: &D) -> RendererLevel where D: Device {
|
||||||
match device.feature_level() {
|
match device.feature_level() {
|
||||||
FeatureLevel::D3D10 => RendererLevel::D3D9,
|
FeatureLevel::D3D10 => RendererLevel::D3D9,
|
||||||
|
@ -65,12 +68,17 @@ impl RendererLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Where the rendered content should go.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum DestFramebuffer<D> where D: Device {
|
pub enum DestFramebuffer<D> where D: Device {
|
||||||
|
/// The rendered content should go to the default framebuffer (e.g. the window in OpenGL).
|
||||||
Default {
|
Default {
|
||||||
|
/// The rectangle within the window to draw in, in device pixels.
|
||||||
viewport: RectI,
|
viewport: RectI,
|
||||||
|
/// The total size of the window in device pixels.
|
||||||
window_size: Vector2I,
|
window_size: Vector2I,
|
||||||
},
|
},
|
||||||
|
/// The rendered content should go to a non-default framebuffer (off-screen, typically).
|
||||||
Other(D::Framebuffer),
|
Other(D::Framebuffer),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,16 +89,18 @@ impl<D> Default for DestFramebuffer<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> DestFramebuffer<D>
|
impl<D> DestFramebuffer<D> where D: Device {
|
||||||
where
|
/// Returns a `DestFramebuffer` object that renders to the entire contents of the default
|
||||||
D: Device,
|
/// framebuffer.
|
||||||
{
|
///
|
||||||
|
/// The `window_size` parameter specifies the size of the window in device pixels.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn full_window(window_size: Vector2I) -> DestFramebuffer<D> {
|
pub fn full_window(window_size: Vector2I) -> DestFramebuffer<D> {
|
||||||
let viewport = RectI::new(Vector2I::default(), window_size);
|
let viewport = RectI::new(Vector2I::default(), window_size);
|
||||||
DestFramebuffer::Default { viewport, window_size }
|
DestFramebuffer::Default { viewport, window_size }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the size of the destination buffer, in device pixels.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn window_size(&self, device: &D) -> Vector2I {
|
pub fn window_size(&self, device: &D) -> Vector2I {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -16,15 +16,30 @@ use std::mem;
|
||||||
use std::ops::{Add, Div};
|
use std::ops::{Add, Div};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Various GPU-side statistics about rendering.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct RenderStats {
|
pub struct RenderStats {
|
||||||
|
/// The total number of path objects in the scene.
|
||||||
pub path_count: usize,
|
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,
|
pub fill_count: usize,
|
||||||
|
/// The total number of 16x16 device pixel tile masks generated.
|
||||||
pub alpha_tile_count: usize,
|
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,
|
pub total_tile_count: usize,
|
||||||
|
/// The amount of CPU time it took to build the scene.
|
||||||
pub cpu_build_time: Duration,
|
pub cpu_build_time: Duration,
|
||||||
|
/// The number of GPU API draw calls it took to render the scene.
|
||||||
pub drawcall_count: u32,
|
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,
|
pub gpu_bytes_allocated: u64,
|
||||||
|
/// The number of bytes of VRAM Pathfinder actually used for the frame.
|
||||||
pub gpu_bytes_committed: u64,
|
pub gpu_bytes_committed: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,16 +218,28 @@ fn total_time_of_timer_futures<D>(futures: &[TimerFuture<D>]) -> Option<Duration
|
||||||
Some(total)
|
Some(total)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The amount of GPU time it took to render the scene, broken up into stages.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct RenderTime {
|
pub struct RenderTime {
|
||||||
|
/// How much GPU time it took to divide all edges in the scene into small lines.
|
||||||
|
///
|
||||||
|
/// This will be zero in the D3D9-level backend, since in that backend dicing is done on CPU.
|
||||||
pub dice_time: Duration,
|
pub dice_time: Duration,
|
||||||
|
/// How much GPU time it took to assign those diced microlines to tiles.
|
||||||
|
///
|
||||||
|
/// This will be zero in the D3D9-level backend, since in that backend binning is done on CPU.
|
||||||
pub bin_time: Duration,
|
pub bin_time: Duration,
|
||||||
|
/// How much GPU time it took to draw fills (i.e. render edges) to masks.
|
||||||
pub fill_time: Duration,
|
pub fill_time: Duration,
|
||||||
|
/// How much GPU time it took to draw the contents of the tiles to the output.
|
||||||
pub composite_time: Duration,
|
pub composite_time: Duration,
|
||||||
|
/// How much GPU time it took to execute miscellaneous tasks other than dicing, binning,
|
||||||
|
/// filling, and compositing.
|
||||||
pub other_time: Duration,
|
pub other_time: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderTime {
|
impl RenderTime {
|
||||||
|
/// The total GPU time it took to render the scene.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn total_time(&self) -> Duration {
|
pub fn total_time(&self) -> Duration {
|
||||||
self.dice_time + self.bin_time + self.fill_time + self.composite_time + self.other_time
|
self.dice_time + self.bin_time + self.fill_time + self.composite_time + self.other_time
|
||||||
|
|
|
@ -144,6 +144,23 @@ pub(crate) struct MaskStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> Renderer<D> where D: Device {
|
impl<D> Renderer<D> 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,
|
pub fn new(device: D,
|
||||||
resources: &dyn ResourceLoader,
|
resources: &dyn ResourceLoader,
|
||||||
mode: RendererMode,
|
mode: RendererMode,
|
||||||
|
@ -290,10 +307,14 @@ impl<D> Renderer<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Destroys this renderer and returns the embedded GPU device.
|
||||||
pub fn destroy(self) -> D {
|
pub fn destroy(self) -> D {
|
||||||
self.core.device
|
self.core.device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs work necessary to begin rendering a scene.
|
||||||
|
///
|
||||||
|
/// This must be called before `render_command()`.
|
||||||
pub fn begin_scene(&mut self) {
|
pub fn begin_scene(&mut self) {
|
||||||
self.core.framebuffer_flags = FramebufferFlags::empty();
|
self.core.framebuffer_flags = FramebufferFlags::empty();
|
||||||
|
|
||||||
|
@ -304,6 +325,11 @@ impl<D> Renderer<D> where D: Device {
|
||||||
self.core.alpha_tile_count = 0;
|
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) {
|
pub fn render_command(&mut self, command: &RenderCommand) {
|
||||||
debug!("render command: {:?}", command);
|
debug!("render command: {:?}", command);
|
||||||
match *command {
|
match *command {
|
||||||
|
@ -352,6 +378,13 @@ impl<D> Renderer<D> 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) {
|
pub fn end_scene(&mut self) {
|
||||||
self.clear_dest_framebuffer_if_necessary();
|
self.clear_dest_framebuffer_if_necessary();
|
||||||
self.blit_intermediate_dest_framebuffer_if_necessary();
|
self.blit_intermediate_dest_framebuffer_if_necessary();
|
||||||
|
@ -451,34 +484,69 @@ impl<D> Renderer<D> where D: Device {
|
||||||
self.last_rendering_time = None;
|
self.last_rendering_time = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns GPU timing information for the last frame, if present.
|
||||||
pub fn last_rendering_time(&self) -> Option<RenderTime> {
|
pub fn last_rendering_time(&self) -> Option<RenderTime> {
|
||||||
self.last_rendering_time
|
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]
|
#[inline]
|
||||||
pub fn device(&self) -> &D {
|
pub fn device(&self) -> &D {
|
||||||
&self.core.device
|
&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]
|
#[inline]
|
||||||
pub fn device_mut(&mut self) -> &mut D {
|
pub fn device_mut(&mut self) -> &mut D {
|
||||||
&mut self.core.device
|
&mut self.core.device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the `RendererMode` this renderer was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mode(&self) -> &RendererMode {
|
pub fn mode(&self) -> &RendererMode {
|
||||||
&self.core.mode
|
&self.core.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the current rendering options.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn options(&self) -> &RendererOptions<D> {
|
pub fn options(&self) -> &RendererOptions<D> {
|
||||||
&self.core.options
|
&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<D> {
|
pub fn options_mut(&mut self) -> &mut RendererOptions<D> {
|
||||||
&mut self.core.options
|
&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]
|
#[inline]
|
||||||
pub fn debug_ui_presenter_mut(&mut self) -> DebugUIPresenterInfo<D> {
|
pub fn debug_ui_presenter_mut(&mut self) -> DebugUIPresenterInfo<D> {
|
||||||
DebugUIPresenterInfo {
|
DebugUIPresenterInfo {
|
||||||
|
@ -488,34 +556,38 @@ impl<D> Renderer<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turns off Pathfinder's use of the depth buffer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dest_framebuffer_size_changed(&mut self) {
|
#[deprecated]
|
||||||
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]
|
|
||||||
pub fn disable_depth(&mut self) {
|
pub fn disable_depth(&mut self) {
|
||||||
self.core.renderer_flags.remove(RendererFlags::USE_DEPTH);
|
self.core.renderer_flags.remove(RendererFlags::USE_DEPTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turns on Pathfinder's use of the depth buffer.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[deprecated]
|
||||||
pub fn enable_depth(&mut self) {
|
pub fn enable_depth(&mut self) {
|
||||||
self.core.renderer_flags.insert(RendererFlags::USE_DEPTH);
|
self.core.renderer_flags.insert(RendererFlags::USE_DEPTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns various GPU-side statistics about rendering, averaged over the last few frames.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stats(&self) -> &RenderStats {
|
pub fn stats(&self) -> &RenderStats {
|
||||||
&self.core.stats
|
&self.core.stats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a GPU-side vertex buffer containing 2D vertices of a unit square.
|
||||||
|
///
|
||||||
|
/// This can be handy for custom rendering.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn quad_vertex_positions_buffer(&self) -> &D::Buffer {
|
pub fn quad_vertex_positions_buffer(&self) -> &D::Buffer {
|
||||||
self.core.allocator.get_general_buffer(self.core.quad_vertex_positions_buffer_id)
|
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]
|
#[inline]
|
||||||
pub fn quad_vertex_indices_buffer(&self) -> &D::Buffer {
|
pub fn quad_vertex_indices_buffer(&self) -> &D::Buffer {
|
||||||
self.core.allocator.get_index_buffer(self.core.quad_vertex_indices_buffer_id)
|
self.core.allocator.get_index_buffer(self.core.quad_vertex_indices_buffer_id)
|
||||||
|
@ -684,6 +756,10 @@ impl<D> Renderer<D> where D: Device {
|
||||||
self.core.stats.drawcall_count += 1;
|
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,
|
pub fn reproject_texture(&mut self,
|
||||||
texture: &D::Texture,
|
texture: &D::Texture,
|
||||||
old_transform: &Transform4F,
|
old_transform: &Transform4F,
|
||||||
|
@ -814,21 +890,19 @@ impl<D> Renderer<D> where D: Device {
|
||||||
self.core.stats.drawcall_count += 1;
|
self.core.stats.drawcall_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the output viewport in the destination framebuffer, as specified in the render
|
||||||
|
/// options.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw_viewport(&self) -> RectI {
|
pub fn draw_viewport(&self) -> RectI {
|
||||||
self.core.draw_viewport()
|
self.core.draw_viewport()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the destination framebuffer, wrapped in a render target.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw_render_target(&self) -> RenderTarget<D> {
|
pub fn draw_render_target(&self) -> RenderTarget<D> {
|
||||||
self.core.draw_render_target()
|
self.core.draw_render_target()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn render_stats(&self) -> &RenderStats {
|
|
||||||
&self.core.stats
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_filter_params(&self,
|
fn compute_filter_params(&self,
|
||||||
filter: &Filter,
|
filter: &Filter,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
|
@ -1085,14 +1159,14 @@ impl<D> RendererCore<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_viewport(&self) -> RectI {
|
pub(crate) fn draw_viewport(&self) -> RectI {
|
||||||
match self.render_target_stack.last() {
|
match self.render_target_stack.last() {
|
||||||
Some(&render_target_id) => self.render_target_location(render_target_id).rect,
|
Some(&render_target_id) => self.render_target_location(render_target_id).rect,
|
||||||
None => self.main_viewport(),
|
None => self.main_viewport(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_render_target(&self) -> RenderTarget<D> {
|
pub(crate) fn draw_render_target(&self) -> RenderTarget<D> {
|
||||||
match self.render_target_stack.last() {
|
match self.render_target_stack.last() {
|
||||||
Some(&render_target_id) => {
|
Some(&render_target_id) => {
|
||||||
let texture_page_id = self.render_target_location(render_target_id).page;
|
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,
|
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 {
|
pub struct DebugUIPresenterInfo<'a, D> where D: Device {
|
||||||
|
/// The GPU device.
|
||||||
pub device: &'a mut D,
|
pub device: &'a mut D,
|
||||||
|
/// The GPU memory allocator.
|
||||||
pub allocator: &'a mut GPUMemoryAllocator<D>,
|
pub allocator: &'a mut GPUMemoryAllocator<D>,
|
||||||
|
/// The debug UI presenter, useful for drawing custom debug widgets on screen.
|
||||||
pub debug_ui_presenter: &'a mut DebugUIPresenter<D>,
|
pub debug_ui_presenter: &'a mut DebugUIPresenter<D>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,16 @@ use pathfinder_resources::ResourceLoader;
|
||||||
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
||||||
pub(crate) const TILE_INSTANCE_SIZE: usize = 16;
|
pub(crate) const TILE_INSTANCE_SIZE: usize = 16;
|
||||||
|
|
||||||
pub struct BlitVertexArray<D> where D: Device {
|
pub(crate) struct BlitVertexArray<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> BlitVertexArray<D> where D: Device {
|
impl<D> BlitVertexArray<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
blit_program: &BlitProgram<D>,
|
blit_program: &BlitProgram<D>,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> BlitVertexArray<D> {
|
-> BlitVertexArray<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
let position_attr = device.get_vertex_attr(&blit_program.program, "Position").unwrap();
|
let position_attr = device.get_vertex_attr(&blit_program.program, "Position").unwrap();
|
||||||
|
|
||||||
|
@ -44,12 +44,12 @@ impl<D> BlitVertexArray<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VertexArraysCore<D> where D: Device {
|
pub(crate) struct VertexArraysCore<D> where D: Device {
|
||||||
pub blit_vertex_array: BlitVertexArray<D>,
|
pub(crate) blit_vertex_array: BlitVertexArray<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> VertexArraysCore<D> where D: Device {
|
impl<D> VertexArraysCore<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
programs: &ProgramsCore<D>,
|
programs: &ProgramsCore<D>,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
|
@ -63,16 +63,16 @@ impl<D> VertexArraysCore<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClearVertexArray<D> where D: Device {
|
pub(crate) struct ClearVertexArray<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClearVertexArray<D> where D: Device {
|
impl<D> ClearVertexArray<D> where D: Device {
|
||||||
pub fn new(device: &D,
|
pub(crate) fn new(device: &D,
|
||||||
clear_program: &ClearProgram<D>,
|
clear_program: &ClearProgram<D>,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_indices_buffer: &D::Buffer)
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
-> ClearVertexArray<D> {
|
-> ClearVertexArray<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
let position_attr = device.get_vertex_attr(&clear_program.program, "Position").unwrap();
|
let position_attr = device.get_vertex_attr(&clear_program.program, "Position").unwrap();
|
||||||
|
|
||||||
|
@ -92,15 +92,15 @@ impl<D> ClearVertexArray<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlitProgram<D> where D: Device {
|
pub(crate) struct BlitProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub dest_rect_uniform: D::Uniform,
|
pub(crate) dest_rect_uniform: D::Uniform,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
pub src_texture: D::TextureParameter,
|
pub(crate) src_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> BlitProgram<D> where D: Device {
|
impl<D> BlitProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "blit");
|
let program = device.create_raster_program(resources, "blit");
|
||||||
let dest_rect_uniform = device.get_uniform(&program, "DestRect");
|
let dest_rect_uniform = device.get_uniform(&program, "DestRect");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
|
@ -109,27 +109,27 @@ impl<D> BlitProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProgramsCore<D> where D: Device {
|
pub(crate) struct ProgramsCore<D> where D: Device {
|
||||||
pub blit_program: BlitProgram<D>,
|
pub(crate) blit_program: BlitProgram<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ProgramsCore<D> where D: Device {
|
impl<D> ProgramsCore<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsCore<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ProgramsCore<D> {
|
||||||
ProgramsCore {
|
ProgramsCore {
|
||||||
blit_program: BlitProgram::new(device, resources),
|
blit_program: BlitProgram::new(device, resources),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClearProgram<D> where D: Device {
|
pub(crate) struct ClearProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub rect_uniform: D::Uniform,
|
pub(crate) rect_uniform: D::Uniform,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
pub color_uniform: D::Uniform,
|
pub(crate) color_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClearProgram<D> where D: Device {
|
impl<D> ClearProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClearProgram<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ClearProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "clear");
|
let program = device.create_raster_program(resources, "clear");
|
||||||
let rect_uniform = device.get_uniform(&program, "Rect");
|
let rect_uniform = device.get_uniform(&program, "Rect");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
|
@ -138,20 +138,20 @@ impl<D> ClearProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TileProgramCommon<D> where D: Device {
|
pub(crate) struct TileProgramCommon<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub(crate) tile_size_uniform: D::Uniform,
|
||||||
pub texture_metadata_texture: D::TextureParameter,
|
pub(crate) texture_metadata_texture: D::TextureParameter,
|
||||||
pub texture_metadata_size_uniform: D::Uniform,
|
pub(crate) texture_metadata_size_uniform: D::Uniform,
|
||||||
pub z_buffer_texture: D::TextureParameter,
|
pub(crate) z_buffer_texture: D::TextureParameter,
|
||||||
pub z_buffer_texture_size_uniform: D::Uniform,
|
pub(crate) z_buffer_texture_size_uniform: D::Uniform,
|
||||||
pub color_texture_0: D::TextureParameter,
|
pub(crate) color_texture_0: D::TextureParameter,
|
||||||
pub color_texture_size_0_uniform: D::Uniform,
|
pub(crate) color_texture_size_0_uniform: D::Uniform,
|
||||||
pub color_texture_1: D::TextureParameter,
|
pub(crate) color_texture_1: D::TextureParameter,
|
||||||
pub mask_texture_0: D::TextureParameter,
|
pub(crate) mask_texture_0: D::TextureParameter,
|
||||||
pub mask_texture_size_0_uniform: D::Uniform,
|
pub(crate) mask_texture_size_0_uniform: D::Uniform,
|
||||||
pub gamma_lut_texture: D::TextureParameter,
|
pub(crate) gamma_lut_texture: D::TextureParameter,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub(crate) framebuffer_size_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> TileProgramCommon<D> where D: Device {
|
impl<D> TileProgramCommon<D> where D: Device {
|
||||||
|
@ -187,25 +187,25 @@ impl<D> TileProgramCommon<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StencilProgram<D> where D: Device {
|
pub(crate) struct StencilProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> StencilProgram<D> where D: Device {
|
impl<D> StencilProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "stencil");
|
let program = device.create_raster_program(resources, "stencil");
|
||||||
StencilProgram { program }
|
StencilProgram { program }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StencilVertexArray<D> where D: Device {
|
pub(crate) struct StencilVertexArray<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
pub vertex_buffer: D::Buffer,
|
pub(crate) vertex_buffer: D::Buffer,
|
||||||
pub index_buffer: D::Buffer,
|
pub(crate) index_buffer: D::Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> StencilVertexArray<D> where D: Device {
|
impl<D> StencilVertexArray<D> where D: Device {
|
||||||
pub fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> {
|
pub(crate) fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> {
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
let vertex_buffer = device.create_buffer(BufferUploadMode::Static);
|
let vertex_buffer = device.create_buffer(BufferUploadMode::Static);
|
||||||
let index_buffer = device.create_buffer(BufferUploadMode::Static);
|
let index_buffer = device.create_buffer(BufferUploadMode::Static);
|
||||||
|
@ -228,15 +228,15 @@ impl<D> StencilVertexArray<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReprojectionProgram<D> where D: Device {
|
pub(crate) struct ReprojectionProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub(crate) program: D::Program,
|
||||||
pub old_transform_uniform: D::Uniform,
|
pub(crate) old_transform_uniform: D::Uniform,
|
||||||
pub new_transform_uniform: D::Uniform,
|
pub(crate) new_transform_uniform: D::Uniform,
|
||||||
pub texture: D::TextureParameter,
|
pub(crate) texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ReprojectionProgram<D> where D: Device {
|
impl<D> ReprojectionProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
|
pub(crate) fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "reproject");
|
let program = device.create_raster_program(resources, "reproject");
|
||||||
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
|
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
|
||||||
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
|
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
|
||||||
|
@ -245,17 +245,16 @@ impl<D> ReprojectionProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReprojectionVertexArray<D> where D: Device {
|
pub(crate) struct ReprojectionVertexArray<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub(crate) vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ReprojectionVertexArray<D> where D: Device {
|
impl<D> ReprojectionVertexArray<D> where D: Device {
|
||||||
pub fn new(
|
pub(crate) fn new(device: &D,
|
||||||
device: &D,
|
reprojection_program: &ReprojectionProgram<D>,
|
||||||
reprojection_program: &ReprojectionProgram<D>,
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
quad_vertex_indices_buffer: &D::Buffer,
|
-> ReprojectionVertexArray<D> {
|
||||||
) -> ReprojectionVertexArray<D> {
|
|
||||||
let vertex_array = device.create_vertex_array();
|
let vertex_array = device.create_vertex_array();
|
||||||
let position_attr = device.get_vertex_attr(&reprojection_program.program, "Position")
|
let position_attr = device.get_vertex_attr(&reprojection_program.program, "Position")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -17,13 +17,13 @@ extern crate log;
|
||||||
|
|
||||||
pub mod concurrent;
|
pub mod concurrent;
|
||||||
pub mod gpu;
|
pub mod gpu;
|
||||||
pub mod gpu_data;
|
|
||||||
pub mod options;
|
pub mod options;
|
||||||
pub mod paint;
|
pub mod paint;
|
||||||
pub mod scene;
|
pub mod scene;
|
||||||
|
|
||||||
mod allocator;
|
mod allocator;
|
||||||
mod builder;
|
mod builder;
|
||||||
|
mod gpu_data;
|
||||||
mod tile_map;
|
mod tile_map;
|
||||||
mod tiler;
|
mod tiler;
|
||||||
mod tiles;
|
mod tiles;
|
||||||
|
|
|
@ -18,20 +18,30 @@ use pathfinder_geometry::transform3d::Perspective;
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector4F};
|
use pathfinder_geometry::vector::{Vector2F, Vector4F};
|
||||||
use pathfinder_content::clip::PolygonClipper3D;
|
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> {
|
pub struct RenderCommandListener<'a> {
|
||||||
send_fn: RenderCommandSendFunction<'a>,
|
send_fn: RenderCommandSendFunction<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The callback function that receives the render commands from the scene builder.
|
||||||
pub type RenderCommandSendFunction<'a> = Box<dyn Fn(RenderCommand) + Send + Sync + 'a>;
|
pub type RenderCommandSendFunction<'a> = Box<dyn Fn(RenderCommand) + Send + Sync + 'a>;
|
||||||
|
|
||||||
impl<'a> RenderCommandListener<'a> {
|
impl<'a> RenderCommandListener<'a> {
|
||||||
|
/// Wraps a render command callback in a `RenderCommandListener`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(send_fn: RenderCommandSendFunction<'a>) -> RenderCommandListener<'a> {
|
pub fn new(send_fn: RenderCommandSendFunction<'a>) -> RenderCommandListener<'a> {
|
||||||
RenderCommandListener { send_fn }
|
RenderCommandListener { send_fn }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn send(&self, render_command: RenderCommand) {
|
pub(crate) fn send(&self, render_command: RenderCommand) {
|
||||||
(self.send_fn)(render_command)
|
(self.send_fn)(render_command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +49,12 @@ impl<'a> RenderCommandListener<'a> {
|
||||||
/// Options that influence scene building.
|
/// Options that influence scene building.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct BuildOptions {
|
pub struct BuildOptions {
|
||||||
|
/// A global transform to be applied to the scene.
|
||||||
pub transform: RenderTransform,
|
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,
|
pub dilation: Vector2F,
|
||||||
|
/// True if subpixel antialiasing for LCD screens is to be performed.
|
||||||
pub subpixel_aa_enabled: bool,
|
pub subpixel_aa_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +68,12 @@ impl BuildOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A global transform to apply to the scene.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum RenderTransform {
|
pub enum RenderTransform {
|
||||||
|
/// A 2D transform.
|
||||||
Transform2D(Transform2F),
|
Transform2D(Transform2F),
|
||||||
|
/// A perspective transform. (This will soon be removed in favor of a revised 3D approach.)
|
||||||
Perspective(Perspective),
|
Perspective(Perspective),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ use std::sync::Arc;
|
||||||
const GRADIENT_TILE_LENGTH: u32 = 256;
|
const GRADIENT_TILE_LENGTH: u32 = 256;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Palette {
|
pub(crate) struct Palette {
|
||||||
pub paints: Vec<Paint>,
|
pub(crate) paints: Vec<Paint>,
|
||||||
render_targets: Vec<RenderTargetData>,
|
render_targets: Vec<RenderTargetData>,
|
||||||
cache: HashMap<Paint, PaintId>,
|
cache: HashMap<Paint, PaintId>,
|
||||||
allocator: TextureAllocator,
|
allocator: TextureAllocator,
|
||||||
|
@ -90,7 +90,7 @@ impl Debug for PaintContents {
|
||||||
|
|
||||||
impl Palette {
|
impl Palette {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(scene_id: SceneId) -> Palette {
|
pub(crate) fn new(scene_id: SceneId) -> Palette {
|
||||||
Palette {
|
Palette {
|
||||||
paints: vec![],
|
paints: vec![],
|
||||||
render_targets: 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.
|
/// The render commands needed to prepare the textures.
|
||||||
pub render_commands: Vec<RenderCommand>,
|
pub(crate) render_commands: Vec<RenderCommand>,
|
||||||
/// The metadata for each paint.
|
/// The metadata for each paint.
|
||||||
///
|
///
|
||||||
/// The indices of this vector are paint IDs.
|
/// The indices of this vector are paint IDs.
|
||||||
pub paint_metadata: Vec<PaintMetadata>,
|
pub(crate) paint_metadata: Vec<PaintMetadata>,
|
||||||
/// The metadata for each render target.
|
/// The metadata for each render target.
|
||||||
///
|
///
|
||||||
/// The indices of this vector are render target IDs.
|
/// The indices of this vector are render target IDs.
|
||||||
pub render_target_metadata: Vec<RenderTargetMetadata>,
|
pub(crate) render_target_metadata: Vec<RenderTargetMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PaintMetadata {
|
pub(crate) struct PaintMetadata {
|
||||||
/// Metadata associated with the color texture, if applicable.
|
/// Metadata associated with the color texture, if applicable.
|
||||||
pub color_texture_metadata: Option<PaintColorTextureMetadata>,
|
pub(crate) color_texture_metadata: Option<PaintColorTextureMetadata>,
|
||||||
/// The base color that the color texture gets mixed into.
|
/// The base color that the color texture gets mixed into.
|
||||||
pub base_color: ColorU,
|
pub(crate) base_color: ColorU,
|
||||||
pub blend_mode: BlendMode,
|
pub(crate) blend_mode: BlendMode,
|
||||||
/// True if this paint is fully opaque.
|
/// True if this paint is fully opaque.
|
||||||
pub is_opaque: bool,
|
pub(crate) is_opaque: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PaintColorTextureMetadata {
|
pub(crate) struct PaintColorTextureMetadata {
|
||||||
/// The location of the paint.
|
/// The location of the paint.
|
||||||
pub location: TextureLocation,
|
pub(crate) location: TextureLocation,
|
||||||
/// The scale for the page this paint is on.
|
/// 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.
|
/// 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.
|
/// The sampling mode for the texture.
|
||||||
pub sampling_flags: TextureSamplingFlags,
|
pub(crate) sampling_flags: TextureSamplingFlags,
|
||||||
/// The filter to be applied to this paint.
|
/// 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.
|
/// 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)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct RadialGradientMetadata {
|
pub(crate) struct RadialGradientMetadata {
|
||||||
/// The line segment that connects the two circles.
|
/// The line segment that connects the two circles.
|
||||||
pub line: LineSegment2F,
|
pub(crate) line: LineSegment2F,
|
||||||
/// The radii of the two circles.
|
/// The radii of the two circles.
|
||||||
pub radii: F32x2,
|
pub(crate) radii: F32x2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct RenderTargetMetadata {
|
pub(crate) struct RenderTargetMetadata {
|
||||||
/// The location of the render target.
|
/// The location of the render target.
|
||||||
pub location: TextureLocation,
|
pub(crate) location: TextureLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PaintFilter {
|
pub(crate) enum PaintFilter {
|
||||||
None,
|
None,
|
||||||
RadialGradient {
|
RadialGradient {
|
||||||
/// The line segment that connects the two circles.
|
/// The line segment that connects the two circles.
|
||||||
|
@ -334,7 +334,7 @@ pub enum PaintFilter {
|
||||||
|
|
||||||
impl Palette {
|
impl Palette {
|
||||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
#[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) {
|
if let Some(paint_id) = self.cache.get(paint) {
|
||||||
return *paint_id;
|
return *paint_id;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ impl Palette {
|
||||||
paint_id
|
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 id = self.render_targets.len() as u32;
|
||||||
|
|
||||||
let metadata = RenderTargetMetadata {
|
let metadata = RenderTargetMetadata {
|
||||||
|
@ -356,7 +356,7 @@ impl Palette {
|
||||||
RenderTargetId { scene: self.scene_id.0, render_target: id }
|
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![];
|
let mut paint_metadata = vec![];
|
||||||
|
|
||||||
// Assign paint locations.
|
// Assign paint locations.
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//! A set of paths to be rendered.
|
//! The vector scene to be rendered.
|
||||||
|
|
||||||
use crate::builder::SceneBuilder;
|
use crate::builder::SceneBuilder;
|
||||||
use crate::concurrent::executor::Executor;
|
use crate::concurrent::executor::Executor;
|
||||||
|
@ -34,6 +34,7 @@ use std::u64;
|
||||||
|
|
||||||
static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0);
|
static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
/// The vector scene to be rendered.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
display_list: Vec<DisplayItem>,
|
display_list: Vec<DisplayItem>,
|
||||||
|
@ -156,7 +157,7 @@ impl Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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)
|
self.palette.build_paint_info(render_transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,8 +282,8 @@ impl Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn palette(&self) -> &Palette {
|
pub fn get_paint(&self, paint_id: PaintId) -> &Paint {
|
||||||
&self.palette
|
self.palette.paints.get(paint_id.0 as usize).expect("No paint with that ID!")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in New Issue