2019-01-14 17:20:36 -05:00
|
|
|
// pathfinder/renderer/src/builder.rs
|
|
|
|
//
|
|
|
|
// Copyright © 2019 The Pathfinder Project Developers.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
//! Packs data onto the GPU.
|
|
|
|
|
2019-04-29 21:16:55 -04:00
|
|
|
use crate::concurrent::executor::Executor;
|
2019-04-15 16:21:24 -04:00
|
|
|
use crate::gpu_data::{AlphaTileBatchPrimitive, RenderCommand};
|
2019-04-30 22:13:28 -04:00
|
|
|
use crate::options::{PreparedRenderOptions, RenderCommandListener};
|
2019-04-11 22:38:31 -04:00
|
|
|
use crate::scene::Scene;
|
2019-04-12 14:55:05 -04:00
|
|
|
use crate::tiles::Tiler;
|
2019-01-14 17:20:36 -05:00
|
|
|
use crate::z_buffer::ZBuffer;
|
2019-04-12 14:55:05 -04:00
|
|
|
use pathfinder_geometry::basic::rect::RectF32;
|
2019-04-15 16:21:24 -04:00
|
|
|
use std::sync::atomic::AtomicUsize;
|
2019-04-30 22:13:28 -04:00
|
|
|
use std::time::Instant;
|
2019-01-14 17:20:36 -05:00
|
|
|
use std::u16;
|
|
|
|
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) struct SceneBuilder<'a> {
|
2019-03-29 22:11:38 -04:00
|
|
|
scene: &'a Scene,
|
|
|
|
built_options: &'a PreparedRenderOptions,
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
pub(crate) next_alpha_tile_index: AtomicUsize,
|
|
|
|
pub(crate) z_buffer: ZBuffer,
|
|
|
|
pub(crate) listener: Box<dyn RenderCommandListener>,
|
2019-03-29 22:11:38 -04:00
|
|
|
}
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
impl<'a> SceneBuilder<'a> {
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) fn new(
|
2019-04-29 19:45:29 -04:00
|
|
|
scene: &'a Scene,
|
|
|
|
built_options: &'a PreparedRenderOptions,
|
|
|
|
listener: Box<dyn RenderCommandListener>,
|
|
|
|
) -> SceneBuilder<'a> {
|
2019-04-15 16:21:24 -04:00
|
|
|
let effective_view_box = scene.effective_view_box(built_options);
|
|
|
|
SceneBuilder {
|
|
|
|
scene,
|
|
|
|
built_options,
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
next_alpha_tile_index: AtomicUsize::new(0),
|
|
|
|
z_buffer: ZBuffer::new(effective_view_box),
|
|
|
|
listener,
|
2019-03-29 22:11:38 -04:00
|
|
|
}
|
|
|
|
}
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2019-04-29 21:16:55 -04:00
|
|
|
pub fn build<E>(&mut self, executor: &E) where E: Executor {
|
2019-04-30 22:13:28 -04:00
|
|
|
let start_time = Instant::now();
|
|
|
|
|
|
|
|
let bounding_quad = self.built_options.bounding_quad();
|
2019-04-15 16:21:24 -04:00
|
|
|
let object_count = self.scene.objects.len();
|
2019-04-30 22:13:28 -04:00
|
|
|
self.listener.send(RenderCommand::Start { bounding_quad, object_count });
|
|
|
|
|
|
|
|
self.listener.send(RenderCommand::AddShaders(self.scene.build_shaders()));
|
|
|
|
|
|
|
|
let effective_view_box = self.scene.effective_view_box(self.built_options);
|
2019-04-29 21:16:55 -04:00
|
|
|
let alpha_tiles = executor.flatten_into_vector(object_count, |object_index| {
|
|
|
|
self.build_object(object_index, effective_view_box, &self.built_options, &self.scene)
|
|
|
|
});
|
2019-04-30 22:13:28 -04:00
|
|
|
|
|
|
|
self.finish_building(alpha_tiles);
|
|
|
|
|
|
|
|
let build_time = Instant::now() - start_time;
|
|
|
|
self.listener.send(RenderCommand::Finish { build_time });
|
2019-04-15 16:21:24 -04:00
|
|
|
}
|
2019-03-29 22:11:38 -04:00
|
|
|
|
2019-04-29 19:45:29 -04:00
|
|
|
fn build_object(
|
|
|
|
&self,
|
|
|
|
object_index: usize,
|
|
|
|
view_box: RectF32,
|
|
|
|
built_options: &PreparedRenderOptions,
|
|
|
|
scene: &Scene,
|
|
|
|
) -> Vec<AlphaTileBatchPrimitive> {
|
2019-04-15 16:21:24 -04:00
|
|
|
let object = &scene.objects[object_index];
|
|
|
|
let outline = scene.apply_render_options(object.outline(), built_options);
|
2019-03-29 22:11:38 -04:00
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
let mut tiler = Tiler::new(self, &outline, view_box, object_index as u16);
|
|
|
|
tiler.generate_tiles();
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2019-04-30 22:13:28 -04:00
|
|
|
self.listener.send(RenderCommand::AddFills(tiler.built_object.fills));
|
2019-04-15 16:21:24 -04:00
|
|
|
tiler.built_object.alpha_tiles
|
2019-03-29 22:11:38 -04:00
|
|
|
}
|
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
fn cull_alpha_tiles(&self, alpha_tiles: &mut Vec<AlphaTileBatchPrimitive>) {
|
|
|
|
for alpha_tile in alpha_tiles {
|
|
|
|
let alpha_tile_coords = alpha_tile.tile_coords();
|
2019-04-29 19:45:29 -04:00
|
|
|
if self
|
|
|
|
.z_buffer
|
|
|
|
.test(alpha_tile_coords, alpha_tile.object_index as u32)
|
|
|
|
{
|
2019-03-29 22:11:38 -04:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-11 21:54:03 -04:00
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
// FIXME(pcwalton): Clean this up.
|
|
|
|
alpha_tile.tile_x_lo = 0xff;
|
|
|
|
alpha_tile.tile_y_lo = 0xff;
|
|
|
|
alpha_tile.tile_hi = 0xff;
|
2019-01-14 17:20:36 -05:00
|
|
|
}
|
|
|
|
}
|
2019-03-29 22:11:38 -04:00
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
fn pack_alpha_tiles(&mut self, alpha_tiles: Vec<AlphaTileBatchPrimitive>) {
|
|
|
|
let object_count = self.scene.objects.len() as u32;
|
|
|
|
let solid_tiles = self.z_buffer.build_solid_tiles(0..object_count);
|
|
|
|
if !solid_tiles.is_empty() {
|
|
|
|
self.listener.send(RenderCommand::SolidTile(solid_tiles));
|
|
|
|
}
|
|
|
|
if !alpha_tiles.is_empty() {
|
|
|
|
self.listener.send(RenderCommand::AlphaTile(alpha_tiles));
|
2019-03-29 22:11:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-15 16:21:24 -04:00
|
|
|
fn finish_building(&mut self, mut alpha_tiles: Vec<AlphaTileBatchPrimitive>) {
|
|
|
|
self.listener.send(RenderCommand::FlushFills);
|
|
|
|
self.cull_alpha_tiles(&mut alpha_tiles);
|
|
|
|
self.pack_alpha_tiles(alpha_tiles);
|
2019-03-29 22:11:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 18:09:37 -04:00
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
pub struct TileStats {
|
|
|
|
pub solid_tile_count: u32,
|
|
|
|
pub alpha_tile_count: u32,
|
|
|
|
}
|