mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
make gradient ramps late bound
Removes ResourceContext type. This makes scenes and fragments nearly identical. Should they be merged?
This commit is contained in:
parent
782e7d51d2
commit
c0fcdbad58
|
@ -18,7 +18,7 @@ use piet_gpu::{PixelFormat, RenderConfig};
|
|||
use piet_gpu_hal::{QueryPool, Session};
|
||||
use piet_scene::glyph::pinot::{types::Tag, FontDataRef};
|
||||
use piet_scene::glyph::{GlyphContext, GlyphProvider};
|
||||
use piet_scene::{Affine, Rect, ResourceContext, Scene, SceneFragment};
|
||||
use piet_scene::{Affine, Rect, Scene, SceneFragment};
|
||||
|
||||
/// State and resources for rendering a scene.
|
||||
pub struct PgpuRenderer {
|
||||
|
@ -105,23 +105,17 @@ impl PgpuRenderer {
|
|||
/// Encoded streams and resources describing a vector graphics scene.
|
||||
pub struct PgpuScene {
|
||||
scene: Scene,
|
||||
rcx: ResourceContext,
|
||||
}
|
||||
|
||||
impl PgpuScene {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
scene: Scene::default(),
|
||||
rcx: ResourceContext::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn builder(&mut self) -> PgpuSceneBuilder {
|
||||
self.rcx.advance();
|
||||
PgpuSceneBuilder(piet_scene::SceneBuilder::for_scene(
|
||||
&mut self.scene,
|
||||
&mut self.rcx,
|
||||
))
|
||||
PgpuSceneBuilder(piet_scene::SceneBuilder::for_scene(&mut self.scene))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use piet_gpu_hal::{
|
|||
};
|
||||
|
||||
use piet_gpu::{samples, RenderDriver, Renderer, SimpleText};
|
||||
use piet_scene::{ResourceContext, Scene, SceneBuilder};
|
||||
use piet_scene::{Scene, SceneBuilder};
|
||||
|
||||
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
|
||||
fn main() {
|
||||
|
@ -115,13 +115,12 @@ impl GfxState {
|
|||
}
|
||||
let mut text = SimpleText::new();
|
||||
let mut scene = Scene::default();
|
||||
let mut rcx = ResourceContext::default();
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene, &mut rcx);
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene);
|
||||
samples::render_anim_frame(&mut builder, self.current_frame);
|
||||
//samples::render_tiger(&mut builder, false);
|
||||
render_info(&mut text, &mut builder, &info_string);
|
||||
builder.finish();
|
||||
if let Err(e) = self.render_driver.upload_scene(&self.session, &scene, &rcx) {
|
||||
if let Err(e) = self.render_driver.upload_scene(&self.session, &scene) {
|
||||
println!("error in uploading: {}", e);
|
||||
}
|
||||
let (image_idx, acquisition_semaphore) = self.swapchain.next().unwrap();
|
||||
|
|
|
@ -7,7 +7,7 @@ use clap::{App, Arg};
|
|||
use piet_gpu_hal::{BufferUsage, Error, Instance, InstanceFlags, Session};
|
||||
|
||||
use piet_gpu::{samples, PicoSvg, RenderDriver, Renderer};
|
||||
use piet_scene::{ResourceContext, Scene, SceneBuilder};
|
||||
use piet_scene::{Scene, SceneBuilder};
|
||||
|
||||
const WIDTH: usize = 2048;
|
||||
const HEIGHT: usize = 1536;
|
||||
|
@ -229,12 +229,10 @@ fn main() -> Result<(), Error> {
|
|||
.get_matches();
|
||||
let instance = Instance::new(InstanceFlags::default())?;
|
||||
let mut scene = Scene::default();
|
||||
let mut rcx = ResourceContext::default();
|
||||
unsafe {
|
||||
let device = instance.device()?;
|
||||
let session = Session::new(device);
|
||||
rcx.advance();
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene, &mut rcx);
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene);
|
||||
if let Some(input) = matches.value_of("INPUT") {
|
||||
let mut scale = matches
|
||||
.value_of("scale")
|
||||
|
@ -257,7 +255,7 @@ fn main() -> Result<(), Error> {
|
|||
let renderer = Renderer::new(&session, WIDTH, HEIGHT, 1)?;
|
||||
let mut render_driver = RenderDriver::new(&session, 1, renderer);
|
||||
let start = std::time::Instant::now();
|
||||
render_driver.upload_scene(&session, &scene, &rcx)?;
|
||||
render_driver.upload_scene(&session, &scene)?;
|
||||
let image_usage = BufferUsage::MAP_READ | BufferUsage::COPY_DST;
|
||||
let image_buf = session.create_buffer((WIDTH * HEIGHT * 4) as u64, image_usage)?;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use piet_gpu::{samples, PicoSvg, RenderDriver, Renderer, SimpleText};
|
||||
use piet_gpu_hal::{Error, ImageLayout, Instance, InstanceFlags, Session};
|
||||
use piet_scene::{ResourceContext, Scene, SceneBuilder};
|
||||
use piet_scene::{Scene, SceneBuilder};
|
||||
|
||||
use clap::{App, Arg};
|
||||
|
||||
|
@ -60,7 +60,6 @@ fn main() -> Result<(), Error> {
|
|||
let instance = Instance::new(InstanceFlags::default())?;
|
||||
let mut info_string = "info".to_string();
|
||||
let mut scene = Scene::default();
|
||||
let mut rcx = ResourceContext::default();
|
||||
let mut simple_text = piet_gpu::SimpleText::new();
|
||||
unsafe {
|
||||
let display_handle = window.raw_display_handle();
|
||||
|
@ -117,17 +116,15 @@ fn main() -> Result<(), Error> {
|
|||
}
|
||||
|
||||
if let Some(svg) = &svg {
|
||||
rcx.advance();
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene, &mut rcx);
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene);
|
||||
samples::render_svg(&mut builder, svg, false);
|
||||
render_info(&mut simple_text, &mut builder, &info_string);
|
||||
builder.finish();
|
||||
if let Err(e) = render_driver.upload_scene(&session, &scene, &rcx) {
|
||||
if let Err(e) = render_driver.upload_scene(&session, &scene) {
|
||||
println!("error in uploading: {}", e);
|
||||
}
|
||||
} else {
|
||||
rcx.advance();
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene, &mut rcx);
|
||||
let mut builder = SceneBuilder::for_scene(&mut scene);
|
||||
|
||||
const N_SAMPLES: usize = 4;
|
||||
match sample_index % N_SAMPLES {
|
||||
|
@ -142,7 +139,7 @@ fn main() -> Result<(), Error> {
|
|||
}
|
||||
render_info(&mut simple_text, &mut builder, &info_string);
|
||||
builder.finish();
|
||||
if let Err(e) = render_driver.upload_scene(&session, &scene, &rcx) {
|
||||
if let Err(e) = render_driver.upload_scene(&session, &scene) {
|
||||
println!("error in uploading: {}", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
mod pico_svg;
|
||||
mod ramp;
|
||||
mod render_driver;
|
||||
pub mod samples;
|
||||
mod simple_text;
|
||||
|
@ -7,6 +8,7 @@ pub mod stages;
|
|||
pub use piet_scene as scene;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use scene::ResourcePatch;
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub use render_driver::RenderDriver;
|
||||
|
@ -17,7 +19,7 @@ use piet_gpu_hal::{
|
|||
DescriptorSet, Error, Image, ImageLayout, Pipeline, QueryPool, Session,
|
||||
};
|
||||
|
||||
use piet_scene::{ResourceContext, Scene};
|
||||
use piet_scene::Scene;
|
||||
|
||||
pub use pico_svg::PicoSvg;
|
||||
use stages::{ClipBinding, ElementBinding, ElementCode, DRAW_PART_SIZE, PATHSEG_PART_SIZE};
|
||||
|
@ -154,6 +156,9 @@ pub struct Renderer {
|
|||
|
||||
gradient_bufs: Vec<Buffer>,
|
||||
gradients: Image,
|
||||
|
||||
ramps: ramp::RampCache,
|
||||
drawdata_patches: Vec<(usize, u32)>,
|
||||
}
|
||||
|
||||
impl RenderConfig {
|
||||
|
@ -364,6 +369,9 @@ impl Renderer {
|
|||
.build(&session, &k4_pipeline)?;
|
||||
|
||||
let scene_stats = Default::default();
|
||||
let ramps = ramp::RampCache::default();
|
||||
let drawdata_patches = vec![];
|
||||
|
||||
Ok(Renderer {
|
||||
width,
|
||||
height,
|
||||
|
@ -403,26 +411,34 @@ impl Renderer {
|
|||
_bg_image: bg_image,
|
||||
gradient_bufs,
|
||||
gradients,
|
||||
ramps,
|
||||
drawdata_patches,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn upload_scene(
|
||||
&mut self,
|
||||
scene: &Scene,
|
||||
rcx: &ResourceContext,
|
||||
buf_ix: usize,
|
||||
) -> Result<(), Error> {
|
||||
pub fn upload_scene(&mut self, scene: &Scene, buf_ix: usize) -> Result<(), Error> {
|
||||
self.drawdata_patches.clear();
|
||||
self.scene_stats = SceneStats::from_scene(scene);
|
||||
|
||||
self.ramps.advance();
|
||||
let data = scene.data();
|
||||
let stop_data = &data.resources.stops;
|
||||
for patch in &data.resources.patches {
|
||||
match patch {
|
||||
ResourcePatch::Ramp { offset, stops } => {
|
||||
let ramp_id = self.ramps.add(&stop_data[stops.clone()]);
|
||||
self.drawdata_patches.push((*offset, ramp_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
self.upload_config(buf_ix)?;
|
||||
{
|
||||
let mut mapped_scene = self.scene_bufs[buf_ix].map_write(..)?;
|
||||
write_scene(scene, &mut mapped_scene);
|
||||
write_scene(scene, &self.drawdata_patches, &mut mapped_scene);
|
||||
}
|
||||
|
||||
// Upload gradient data.
|
||||
let ramp_data = rcx.ramp_data();
|
||||
let ramp_data = self.ramps.data();
|
||||
if !ramp_data.is_empty() {
|
||||
assert!(
|
||||
self.gradient_bufs[buf_ix].size() as usize
|
||||
|
@ -870,12 +886,28 @@ impl SceneStats {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_scene(scene: &Scene, buf: &mut BufWrite) {
|
||||
fn write_scene(scene: &Scene, drawdata_patches: &[(usize, u32)], buf: &mut BufWrite) {
|
||||
let data = scene.data();
|
||||
buf.extend_slice(&data.drawtag_stream);
|
||||
let n_drawobj = data.drawtag_stream.len();
|
||||
buf.fill_zero(padding(n_drawobj, DRAW_PART_SIZE as usize) * DRAWTAG_SIZE);
|
||||
buf.extend_slice(&data.drawdata_stream);
|
||||
if !drawdata_patches.is_empty() {
|
||||
let mut pos = 0;
|
||||
for patch in drawdata_patches {
|
||||
let offset = patch.0;
|
||||
let value = patch.1;
|
||||
if pos < offset {
|
||||
buf.extend_slice(&data.drawdata_stream[pos..offset]);
|
||||
}
|
||||
buf.push(value);
|
||||
pos = offset + 4;
|
||||
}
|
||||
if pos < data.drawdata_stream.len() {
|
||||
buf.extend_slice(&data.drawdata_stream[pos..])
|
||||
}
|
||||
} else {
|
||||
buf.extend_slice(&data.drawdata_stream);
|
||||
}
|
||||
buf.extend_slice(&data.transform_stream);
|
||||
buf.extend_slice(&data.linewidth_stream);
|
||||
buf.extend_slice(&data.tag_stream);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::brush::{Color, GradientStop, GradientStops};
|
||||
use piet_scene::{Color, GradientStop, GradientStops};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
const N_SAMPLES: usize = 512;
|
||||
|
@ -21,12 +22,6 @@ impl RampCache {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.epoch = 0;
|
||||
self.map.clear();
|
||||
self.data.clear();
|
||||
}
|
||||
|
||||
pub fn add(&mut self, stops: &[GradientStop]) -> u32 {
|
||||
if let Some(entry) = self.map.get_mut(stops) {
|
||||
entry.1 = self.epoch;
|
|
@ -15,7 +15,7 @@
|
|||
// Also licensed under MIT license, at your choice.
|
||||
|
||||
use piet_gpu_hal::{CmdBuf, Error, Image, QueryPool, Semaphore, Session, SubmittedCmdBuf};
|
||||
use piet_scene::{ResourceContext, Scene};
|
||||
use piet_scene::Scene;
|
||||
|
||||
use crate::{MemoryHeader, Renderer, SceneStats};
|
||||
|
||||
|
@ -86,15 +86,10 @@ impl RenderDriver {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn upload_scene(
|
||||
&mut self,
|
||||
session: &Session,
|
||||
scene: &Scene,
|
||||
rcx: &ResourceContext,
|
||||
) -> Result<(), Error> {
|
||||
pub fn upload_scene(&mut self, session: &Session, scene: &Scene) -> Result<(), Error> {
|
||||
let stats = SceneStats::from_scene(scene);
|
||||
self.ensure_scene_buffers(session, &stats)?;
|
||||
self.renderer.upload_scene(scene, rcx, self.buf_ix)
|
||||
self.renderer.upload_scene(scene, self.buf_ix)
|
||||
}
|
||||
|
||||
fn ensure_scene_buffers(&mut self, session: &Session, stats: &SceneStats) -> Result<(), Error> {
|
||||
|
|
|
@ -168,7 +168,10 @@ pub fn render_blend_grid(sb: &mut SceneBuilder) {
|
|||
let i = ix % 4;
|
||||
let j = ix / 4;
|
||||
let transform = Affine::translate(i as f32 * 225., j as f32 * 225.);
|
||||
render_blend_square(sb, blend.into(), transform);
|
||||
let square = blend_square(blend.into());
|
||||
sb.append(&square, Some(transform));
|
||||
// sb.append(&square, Some(transform));
|
||||
// render_blend_square(sb, blend.into(), transform);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,6 +268,101 @@ fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affin
|
|||
sb.pop_layer();
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn blend_square(blend: BlendMode) -> SceneFragment {
|
||||
let mut fragment = SceneFragment::default();
|
||||
let mut sb = SceneBuilder::for_fragment(&mut fragment);
|
||||
// Inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
|
||||
let rect = Rect::from_origin_size(Point::new(0., 0.), 200., 200.);
|
||||
let stops = &[
|
||||
GradientStop {
|
||||
color: Color::rgb8(0, 0, 0),
|
||||
offset: 0.0,
|
||||
},
|
||||
GradientStop {
|
||||
color: Color::rgb8(255, 255, 255),
|
||||
offset: 1.0,
|
||||
},
|
||||
][..];
|
||||
let linear = Brush::LinearGradient(LinearGradient {
|
||||
start: Point::new(0.0, 0.0),
|
||||
end: Point::new(200.0, 0.0),
|
||||
stops: stops.into(),
|
||||
extend: ExtendMode::Pad,
|
||||
});
|
||||
sb.fill(Fill::NonZero, &linear, None, rect.elements());
|
||||
const GRADIENTS: &[(f32, f32, Color)] = &[
|
||||
(150., 0., Color::rgb8(64, 240, 255)),
|
||||
(175., 100., Color::rgb8(240, 96, 255)),
|
||||
(125., 200., Color::rgb8(255, 192, 64)),
|
||||
];
|
||||
for (x, y, c) in GRADIENTS {
|
||||
let mut color2 = c.clone();
|
||||
color2.a = 0;
|
||||
let stops = &[
|
||||
GradientStop {
|
||||
color: c.clone(),
|
||||
offset: 0.0,
|
||||
},
|
||||
GradientStop {
|
||||
color: color2,
|
||||
offset: 1.0,
|
||||
},
|
||||
][..];
|
||||
let rad = Brush::RadialGradient(RadialGradient {
|
||||
center0: Point::new(*x, *y),
|
||||
center1: Point::new(*x, *y),
|
||||
radius0: 0.0,
|
||||
radius1: 100.0,
|
||||
stops: stops.into(),
|
||||
extend: ExtendMode::Pad,
|
||||
});
|
||||
sb.fill(Fill::NonZero, &rad, None, rect.elements());
|
||||
}
|
||||
const COLORS: &[Color] = &[
|
||||
Color::rgb8(0, 0, 255),
|
||||
Color::rgb8(0, 255, 0),
|
||||
Color::rgb8(255, 0, 0),
|
||||
];
|
||||
sb.push_layer(Mix::Normal.into(), rect.elements());
|
||||
for (i, c) in COLORS.iter().enumerate() {
|
||||
let stops = &[
|
||||
GradientStop {
|
||||
color: Color::rgb8(255, 255, 255),
|
||||
offset: 0.0,
|
||||
},
|
||||
GradientStop {
|
||||
color: c.clone(),
|
||||
offset: 1.0,
|
||||
},
|
||||
][..];
|
||||
let linear = Brush::LinearGradient(LinearGradient {
|
||||
start: Point::new(0.0, 0.0),
|
||||
end: Point::new(0.0, 200.0),
|
||||
stops: stops.into(),
|
||||
extend: ExtendMode::Pad,
|
||||
});
|
||||
sb.transform(Affine::IDENTITY);
|
||||
sb.push_layer(blend, rect.elements());
|
||||
// squash the ellipse
|
||||
let a = Affine::translate(100., 100.)
|
||||
* Affine::rotate(std::f32::consts::FRAC_PI_3 * (i * 2 + 1) as f32)
|
||||
* Affine::scale(1.0, 0.357)
|
||||
* Affine::translate(-100., -100.);
|
||||
sb.transform(a);
|
||||
sb.fill(
|
||||
Fill::NonZero,
|
||||
&linear,
|
||||
None,
|
||||
make_ellipse(100., 100., 90., 90.),
|
||||
);
|
||||
sb.pop_layer();
|
||||
}
|
||||
sb.pop_layer();
|
||||
sb.finish();
|
||||
fragment
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn render_anim_frame(sb: &mut SceneBuilder, text: &mut SimpleText, i: usize) {
|
||||
sb.fill(
|
||||
|
|
31
piet-scene/src/resource.rs
Normal file
31
piet-scene/src/resource.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use crate::brush::GradientStop;
|
||||
use core::ops::Range;
|
||||
|
||||
#[derive(Default)]
|
||||
/// Collection of late bound resources for a scene or scene fragment.
|
||||
pub struct ResourceBundle {
|
||||
/// Sequence of resource patches.
|
||||
pub patches: Vec<ResourcePatch>,
|
||||
/// Cache of gradient stops, referenced by range from the patches.
|
||||
pub stops: Vec<GradientStop>,
|
||||
}
|
||||
|
||||
impl ResourceBundle {
|
||||
/// Clears the resource set.
|
||||
pub(crate) fn clear(&mut self) {
|
||||
self.patches.clear();
|
||||
self.stops.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Description of a late bound resource.
|
||||
pub enum ResourcePatch {
|
||||
/// Gradient ramp resource.
|
||||
Ramp {
|
||||
/// Byte offset to the ramp id in the draw data stream.
|
||||
offset: usize,
|
||||
/// Range of the gradient stops in the resource set.
|
||||
stops: Range<usize>,
|
||||
},
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
mod gradient;
|
||||
|
||||
use crate::brush::GradientStop;
|
||||
use gradient::RampCache;
|
||||
|
||||
/// Context for caching resources across rendering operations.
|
||||
#[derive(Default)]
|
||||
pub struct ResourceContext {
|
||||
ramps: RampCache,
|
||||
}
|
||||
|
||||
impl ResourceContext {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn advance(&mut self) {
|
||||
self.ramps.advance();
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.ramps.clear();
|
||||
}
|
||||
|
||||
pub fn add_ramp(&mut self, stops: &[GradientStop]) -> u32 {
|
||||
self.ramps.add(stops)
|
||||
}
|
||||
|
||||
pub fn ramp_data(&self) -> &[u32] {
|
||||
&self.ramps.data()
|
||||
}
|
||||
}
|
|
@ -15,12 +15,8 @@
|
|||
// Also licensed under MIT license, at your choice.
|
||||
|
||||
use super::style::{Fill, Stroke};
|
||||
use super::{
|
||||
Affine, BlendMode, FragmentResources, PathElement, ResourcePatch, Scene, SceneData,
|
||||
SceneFragment,
|
||||
};
|
||||
use crate::brush::*;
|
||||
use crate::resource::ResourceContext;
|
||||
use super::{Affine, BlendMode, PathElement, Scene, SceneData, SceneFragment};
|
||||
use crate::{brush::*, ResourcePatch};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use core::borrow::Borrow;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -28,37 +24,27 @@ use smallvec::SmallVec;
|
|||
/// Builder for constructing a scene or scene fragment.
|
||||
pub struct SceneBuilder<'a> {
|
||||
scene: &'a mut SceneData,
|
||||
resources: ResourceData<'a>,
|
||||
layers: SmallVec<[BlendMode; 8]>,
|
||||
}
|
||||
|
||||
impl<'a> SceneBuilder<'a> {
|
||||
/// Creates a new builder for filling a scene. Any current content in the scene
|
||||
/// will be cleared.
|
||||
pub fn for_scene(scene: &'a mut Scene, rcx: &'a mut ResourceContext) -> Self {
|
||||
Self::new(&mut scene.data, ResourceData::Scene(rcx))
|
||||
pub fn for_scene(scene: &'a mut Scene) -> Self {
|
||||
Self::new(&mut scene.data, false)
|
||||
}
|
||||
|
||||
/// Creates a new builder for filling a scene fragment. Any current content in
|
||||
/// the fragment will be cleared.
|
||||
pub fn for_fragment(fragment: &'a mut SceneFragment) -> Self {
|
||||
Self::new(
|
||||
&mut fragment.data,
|
||||
ResourceData::Fragment(&mut fragment.resources),
|
||||
)
|
||||
Self::new(&mut fragment.data, true)
|
||||
}
|
||||
|
||||
/// Creates a new builder for constructing a scene.
|
||||
fn new(scene: &'a mut SceneData, mut resources: ResourceData<'a>) -> Self {
|
||||
let is_fragment = match resources {
|
||||
ResourceData::Fragment(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
fn new(scene: &'a mut SceneData, is_fragment: bool) -> Self {
|
||||
scene.reset(is_fragment);
|
||||
resources.clear();
|
||||
Self {
|
||||
scene,
|
||||
resources,
|
||||
layers: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +147,6 @@ impl<'a> SceneBuilder<'a> {
|
|||
|
||||
/// Appends a fragment to the scene.
|
||||
pub fn append(&mut self, fragment: &SceneFragment, transform: Option<Affine>) {
|
||||
let drawdata_base = self.scene.drawdata_stream.len();
|
||||
let mut cur_transform = self.scene.transform_stream.last().copied();
|
||||
if let Some(transform) = transform {
|
||||
if cur_transform.is_none() {
|
||||
|
@ -172,39 +157,6 @@ impl<'a> SceneBuilder<'a> {
|
|||
self.encode_transform(Affine::IDENTITY);
|
||||
}
|
||||
self.scene.append(&fragment.data, &transform);
|
||||
match &mut self.resources {
|
||||
ResourceData::Scene(res) => {
|
||||
for patch in &fragment.resources.patches {
|
||||
match patch {
|
||||
ResourcePatch::Ramp {
|
||||
drawdata_offset,
|
||||
stops,
|
||||
} => {
|
||||
let stops = &fragment.resources.stops[stops.clone()];
|
||||
let ramp_id = res.add_ramp(stops);
|
||||
let patch_base = *drawdata_offset + drawdata_base;
|
||||
(&mut self.scene.drawdata_stream[patch_base..patch_base + 4])
|
||||
.copy_from_slice(bytemuck::bytes_of(&ramp_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ResourceData::Fragment(res) => {
|
||||
let stops_base = res.stops.len();
|
||||
res.stops.extend_from_slice(&fragment.resources.stops);
|
||||
res.patches.extend(fragment.resources.patches.iter().map(
|
||||
|pending| match pending {
|
||||
ResourcePatch::Ramp {
|
||||
drawdata_offset,
|
||||
stops,
|
||||
} => ResourcePatch::Ramp {
|
||||
drawdata_offset: drawdata_offset + drawdata_base,
|
||||
stops: stops.start + stops_base..stops.end + stops_base,
|
||||
},
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
// Prevent fragments from affecting transform state. Should we allow this?
|
||||
if let Some(transform) = cur_transform {
|
||||
self.transform(transform);
|
||||
|
@ -325,19 +277,15 @@ impl<'a> SceneBuilder<'a> {
|
|||
}
|
||||
|
||||
fn add_ramp(&mut self, stops: &[GradientStop]) -> u32 {
|
||||
match &mut self.resources {
|
||||
ResourceData::Scene(res) => res.add_ramp(stops),
|
||||
ResourceData::Fragment(res) => {
|
||||
let stops_start = res.stops.len();
|
||||
res.stops.extend_from_slice(stops);
|
||||
let id = res.patches.len() as u32;
|
||||
res.patches.push(ResourcePatch::Ramp {
|
||||
drawdata_offset: self.scene.drawdata_stream.len(),
|
||||
stops: stops_start..stops_start + stops.len(),
|
||||
});
|
||||
id
|
||||
}
|
||||
}
|
||||
let offset = self.scene.drawdata_stream.len();
|
||||
let resources = &mut self.scene.resources;
|
||||
let stops_start = resources.stops.len();
|
||||
resources.stops.extend_from_slice(stops);
|
||||
resources.patches.push(ResourcePatch::Ramp {
|
||||
offset,
|
||||
stops: stops_start..stops_start + stops.len(),
|
||||
});
|
||||
0
|
||||
}
|
||||
|
||||
/// Start a clip.
|
||||
|
@ -366,22 +314,6 @@ impl<'a> SceneBuilder<'a> {
|
|||
self.scene.n_clip += 1;
|
||||
}
|
||||
}
|
||||
enum ResourceData<'a> {
|
||||
Fragment(&'a mut FragmentResources),
|
||||
Scene(&'a mut ResourceContext),
|
||||
}
|
||||
|
||||
impl ResourceData<'_> {
|
||||
fn clear(&mut self) {
|
||||
match self {
|
||||
Self::Fragment(res) => {
|
||||
res.patches.clear();
|
||||
res.stops.clear();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tags for draw objects. See shader/drawtag.h for the authoritative source.
|
||||
const DRAWTAG_FILLCOLOR: u32 = 0x44;
|
||||
|
|
|
@ -22,11 +22,9 @@ pub use blend::{BlendMode, Compose, Mix};
|
|||
pub use builder::SceneBuilder;
|
||||
pub use style::*;
|
||||
|
||||
use super::brush::*;
|
||||
use super::geometry::{Affine, Point};
|
||||
use super::path::PathElement;
|
||||
|
||||
use core::ops::Range;
|
||||
use super::resource::{ResourceBundle, ResourcePatch};
|
||||
|
||||
/// Raw data streams describing an encoded scene.
|
||||
#[derive(Default)]
|
||||
|
@ -40,6 +38,7 @@ pub struct SceneData {
|
|||
pub n_path: u32,
|
||||
pub n_pathseg: u32,
|
||||
pub n_clip: u32,
|
||||
pub resources: ResourceBundle,
|
||||
}
|
||||
|
||||
impl SceneData {
|
||||
|
@ -57,6 +56,7 @@ impl SceneData {
|
|||
self.n_path = 0;
|
||||
self.n_pathseg = 0;
|
||||
self.n_clip = 0;
|
||||
self.resources.clear();
|
||||
if !is_fragment {
|
||||
self.transform_stream
|
||||
.push(Affine::new(&[1.0, 0.0, 0.0, 1.0, 0.0, 0.0]));
|
||||
|
@ -65,9 +65,11 @@ impl SceneData {
|
|||
}
|
||||
|
||||
fn append(&mut self, other: &SceneData, transform: &Option<Affine>) {
|
||||
let stops_base = self.resources.stops.len();
|
||||
let drawdata_base = self.drawdata_stream.len();
|
||||
if let Some(transform) = *transform {
|
||||
self.transform_stream
|
||||
.extend(other.transform_stream.iter().map(|x| *x * transform));
|
||||
.extend(other.transform_stream.iter().map(|x| transform * *x));
|
||||
} else {
|
||||
self.transform_stream
|
||||
.extend_from_slice(&other.transform_stream);
|
||||
|
@ -82,6 +84,20 @@ impl SceneData {
|
|||
self.n_path += other.n_path;
|
||||
self.n_pathseg += other.n_pathseg;
|
||||
self.n_clip += other.n_clip;
|
||||
self.resources
|
||||
.stops
|
||||
.extend_from_slice(&other.resources.stops);
|
||||
self.resources
|
||||
.patches
|
||||
.extend(other.resources.patches.iter().map(|patch| match patch {
|
||||
ResourcePatch::Ramp { offset, stops } => {
|
||||
let stops = stops.start + stops_base..stops.end + stops_base;
|
||||
ResourcePatch::Ramp {
|
||||
offset: drawdata_base + offset,
|
||||
stops,
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +119,6 @@ impl Scene {
|
|||
#[derive(Default)]
|
||||
pub struct SceneFragment {
|
||||
data: SceneData,
|
||||
resources: FragmentResources,
|
||||
}
|
||||
|
||||
impl SceneFragment {
|
||||
|
@ -122,16 +137,3 @@ impl SceneFragment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct FragmentResources {
|
||||
patches: Vec<ResourcePatch>,
|
||||
stops: Vec<GradientStop>,
|
||||
}
|
||||
|
||||
enum ResourcePatch {
|
||||
Ramp {
|
||||
drawdata_offset: usize,
|
||||
stops: Range<usize>,
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue