зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1549271 - Create render task graph earlier during frame building. r=nical
This moves creation of the render task graph to be slightly earlier during frame building. Instead of creeating the render tasks during prepare_prims, they are created during the take_context call for pictures, before recursing into primitives. This means that in future we can have a surface that targets multiple render tasks (e.g. for multiple dirty regions), which may create a different batch set for each region. Differential Revision: https://phabricator.services.mozilla.com/D29994 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d0fdaea75f
Коммит
effaccc4f6
|
@ -1043,8 +1043,9 @@ impl AlphaBatchBuilder {
|
||||||
.expect("BUG: 3d primitive was not assigned a surface");
|
.expect("BUG: 3d primitive was not assigned a surface");
|
||||||
let (uv_rect_address, _) = render_tasks.resolve_surface(
|
let (uv_rect_address, _) = render_tasks.resolve_surface(
|
||||||
ctx.surfaces[raster_config.surface_index.0]
|
ctx.surfaces[raster_config.surface_index.0]
|
||||||
.surface
|
.render_tasks
|
||||||
.expect("BUG: no surface"),
|
.expect("BUG: no surface")
|
||||||
|
.root,
|
||||||
gpu_cache,
|
gpu_cache,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1097,7 +1098,10 @@ impl AlphaBatchBuilder {
|
||||||
render_tasks,
|
render_tasks,
|
||||||
).unwrap_or(OPAQUE_TASK_ADDRESS);
|
).unwrap_or(OPAQUE_TASK_ADDRESS);
|
||||||
|
|
||||||
let surface = ctx.surfaces[raster_config.surface_index.0].surface;
|
let surface = ctx
|
||||||
|
.surfaces[raster_config.surface_index.0]
|
||||||
|
.render_tasks
|
||||||
|
.map(|s| s.root);
|
||||||
|
|
||||||
match raster_config.composite_mode {
|
match raster_config.composite_mode {
|
||||||
PictureCompositeMode::TileCache { .. } => {
|
PictureCompositeMode::TileCache { .. } => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::hit_test::{HitTester, HitTestingScene};
|
||||||
use crate::hit_test::HitTestingSceneStats;
|
use crate::hit_test::HitTestingSceneStats;
|
||||||
use crate::internal_types::{FastHashMap, PlaneSplitter};
|
use crate::internal_types::{FastHashMap, PlaneSplitter};
|
||||||
use crate::picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
|
use crate::picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
|
||||||
use crate::picture::{RetainedTiles, TileCache, DirtyRegion};
|
use crate::picture::{RetainedTiles, TileCache, DirtyRegion, SurfaceRenderTasks};
|
||||||
use crate::prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer};
|
use crate::prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer};
|
||||||
#[cfg(feature = "replay")]
|
#[cfg(feature = "replay")]
|
||||||
use crate::prim_store::{PrimitiveStoreStats};
|
use crate::prim_store::{PrimitiveStoreStats};
|
||||||
|
@ -29,6 +29,7 @@ use crate::segment::SegmentBuilder;
|
||||||
use std::{f32, mem};
|
use std::{f32, mem};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use crate::tiling::{Frame, RenderPassKind, RenderTargetContext, RenderTarget};
|
use crate::tiling::{Frame, RenderPassKind, RenderTargetContext, RenderTarget};
|
||||||
|
use crate::util::MaxRect;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -444,7 +445,10 @@ impl FrameBuilder {
|
||||||
.surfaces
|
.surfaces
|
||||||
.first_mut()
|
.first_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.surface = Some(root_render_task_id);
|
.render_tasks = Some(SurfaceRenderTasks {
|
||||||
|
root: root_render_task_id,
|
||||||
|
port: root_render_task_id,
|
||||||
|
});
|
||||||
|
|
||||||
// Push a default dirty region which culls primitives
|
// Push a default dirty region which culls primitives
|
||||||
// against the screen world rect, in absence of any
|
// against the screen world rect, in absence of any
|
||||||
|
@ -460,6 +464,7 @@ impl FrameBuilder {
|
||||||
.pictures[self.root_pic_index.0]
|
.pictures[self.root_pic_index.0]
|
||||||
.take_context(
|
.take_context(
|
||||||
self.root_pic_index,
|
self.root_pic_index,
|
||||||
|
WorldRect::max_rect(),
|
||||||
root_spatial_node_index,
|
root_spatial_node_index,
|
||||||
root_spatial_node_index,
|
root_spatial_node_index,
|
||||||
ROOT_SURFACE_INDEX,
|
ROOT_SURFACE_INDEX,
|
||||||
|
@ -492,17 +497,6 @@ impl FrameBuilder {
|
||||||
|
|
||||||
frame_state.pop_dirty_region();
|
frame_state.pop_dirty_region();
|
||||||
|
|
||||||
let child_tasks = frame_state
|
|
||||||
.surfaces[ROOT_SURFACE_INDEX.0]
|
|
||||||
.take_render_tasks();
|
|
||||||
|
|
||||||
for child_task_id in child_tasks {
|
|
||||||
frame_state.render_tasks.add_dependency(
|
|
||||||
root_render_task_id,
|
|
||||||
child_task_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(root_render_task_id)
|
Some(root_render_task_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1780,6 +1780,17 @@ pub struct SurfaceIndex(pub usize);
|
||||||
|
|
||||||
pub const ROOT_SURFACE_INDEX: SurfaceIndex = SurfaceIndex(0);
|
pub const ROOT_SURFACE_INDEX: SurfaceIndex = SurfaceIndex(0);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct SurfaceRenderTasks {
|
||||||
|
/// The root of the render task chain for this surface. This
|
||||||
|
/// is attached to parent tasks, and also the surface that
|
||||||
|
/// gets added during batching.
|
||||||
|
pub root: RenderTaskId,
|
||||||
|
/// The port of the render task change for this surface. This
|
||||||
|
/// is where child tasks for this surface get attached to.
|
||||||
|
pub port: RenderTaskId,
|
||||||
|
}
|
||||||
|
|
||||||
/// Information about an offscreen surface. For now,
|
/// Information about an offscreen surface. For now,
|
||||||
/// it contains information about the size and coordinate
|
/// it contains information about the size and coordinate
|
||||||
/// system of the surface. In the future, it will contain
|
/// system of the surface. In the future, it will contain
|
||||||
|
@ -1799,9 +1810,7 @@ pub struct SurfaceInfo {
|
||||||
pub raster_spatial_node_index: SpatialNodeIndex,
|
pub raster_spatial_node_index: SpatialNodeIndex,
|
||||||
pub surface_spatial_node_index: SpatialNodeIndex,
|
pub surface_spatial_node_index: SpatialNodeIndex,
|
||||||
/// This is set when the render task is created.
|
/// This is set when the render task is created.
|
||||||
pub surface: Option<RenderTaskId>,
|
pub render_tasks: Option<SurfaceRenderTasks>,
|
||||||
/// A list of render tasks that are dependencies of this surface.
|
|
||||||
pub tasks: Vec<RenderTaskId>,
|
|
||||||
/// How much the local surface rect should be inflated (for blur radii).
|
/// How much the local surface rect should be inflated (for blur radii).
|
||||||
pub inflation_factor: f32,
|
pub inflation_factor: f32,
|
||||||
/// The device pixel ratio specific to this surface.
|
/// The device pixel ratio specific to this surface.
|
||||||
|
@ -1839,21 +1848,14 @@ impl SurfaceInfo {
|
||||||
SurfaceInfo {
|
SurfaceInfo {
|
||||||
rect: PictureRect::zero(),
|
rect: PictureRect::zero(),
|
||||||
map_local_to_surface,
|
map_local_to_surface,
|
||||||
surface: None,
|
render_tasks: None,
|
||||||
raster_spatial_node_index,
|
raster_spatial_node_index,
|
||||||
surface_spatial_node_index,
|
surface_spatial_node_index,
|
||||||
tasks: Vec::new(),
|
|
||||||
inflation_factor,
|
inflation_factor,
|
||||||
device_pixel_scale,
|
device_pixel_scale,
|
||||||
allow_subpixel_aa,
|
allow_subpixel_aa,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take the set of child render tasks for this surface. This is
|
|
||||||
/// used when constructing the render task tree.
|
|
||||||
pub fn take_render_tasks(&mut self) -> Vec<RenderTaskId> {
|
|
||||||
mem::replace(&mut self.tasks, Vec::new())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -2152,7 +2154,7 @@ pub struct PicturePrimitive {
|
||||||
pub prim_list: PrimitiveList,
|
pub prim_list: PrimitiveList,
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", serde(skip))]
|
#[cfg_attr(feature = "capture", serde(skip))]
|
||||||
pub state: Option<(PictureState, PictureContext)>,
|
pub state: Option<PictureState>,
|
||||||
|
|
||||||
/// The pipeline that the primitives on this picture belong to.
|
/// The pipeline that the primitives on this picture belong to.
|
||||||
pub pipeline_id: PipelineId,
|
pub pipeline_id: PipelineId,
|
||||||
|
@ -2350,9 +2352,10 @@ impl PicturePrimitive {
|
||||||
pub fn take_context(
|
pub fn take_context(
|
||||||
&mut self,
|
&mut self,
|
||||||
pic_index: PictureIndex,
|
pic_index: PictureIndex,
|
||||||
|
clipped_prim_bounding_rect: WorldRect,
|
||||||
surface_spatial_node_index: SpatialNodeIndex,
|
surface_spatial_node_index: SpatialNodeIndex,
|
||||||
raster_spatial_node_index: SpatialNodeIndex,
|
raster_spatial_node_index: SpatialNodeIndex,
|
||||||
surface_index: SurfaceIndex,
|
parent_surface_index: SurfaceIndex,
|
||||||
frame_state: &mut FrameBuildingState,
|
frame_state: &mut FrameBuildingState,
|
||||||
frame_context: &FrameBuildingContext,
|
frame_context: &FrameBuildingContext,
|
||||||
) -> Option<(PictureContext, PictureState, PrimitiveList)> {
|
) -> Option<(PictureContext, PictureState, PrimitiveList)> {
|
||||||
|
@ -2378,7 +2381,7 @@ impl PicturePrimitive {
|
||||||
(
|
(
|
||||||
raster_spatial_node_index,
|
raster_spatial_node_index,
|
||||||
surface_spatial_node_index,
|
surface_spatial_node_index,
|
||||||
surface_index,
|
parent_surface_index,
|
||||||
0.0,
|
0.0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2418,6 +2421,304 @@ impl PicturePrimitive {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (is_composite, is_passthrough) = match self.raster_config {
|
||||||
|
Some(ref rc @ RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
|
||||||
|
// For a picture surface, just push any child tasks and tile
|
||||||
|
// blits up to the parent surface.
|
||||||
|
let port = frame_state
|
||||||
|
.surfaces[parent_surface_index.0]
|
||||||
|
.render_tasks
|
||||||
|
.expect("bug: no render tasks set for parent!")
|
||||||
|
.port;
|
||||||
|
|
||||||
|
frame_state
|
||||||
|
.surfaces[rc.surface_index.0]
|
||||||
|
.render_tasks = Some(SurfaceRenderTasks {
|
||||||
|
root: RenderTaskId::INVALID,
|
||||||
|
port,
|
||||||
|
});
|
||||||
|
|
||||||
|
(false, false)
|
||||||
|
},
|
||||||
|
Some(ref raster_config) => {
|
||||||
|
let pic_rect = PictureRect::from_untyped(&self.snapped_local_rect.to_untyped());
|
||||||
|
|
||||||
|
let device_pixel_scale = frame_state
|
||||||
|
.surfaces[raster_config.surface_index.0]
|
||||||
|
.device_pixel_scale;
|
||||||
|
|
||||||
|
let (clipped, unclipped) = match get_raster_rects(
|
||||||
|
pic_rect,
|
||||||
|
&map_pic_to_raster,
|
||||||
|
&map_raster_to_world,
|
||||||
|
clipped_prim_bounding_rect,
|
||||||
|
device_pixel_scale,
|
||||||
|
) {
|
||||||
|
Some(info) => info,
|
||||||
|
None => {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let transform = map_pic_to_raster.get_transform();
|
||||||
|
|
||||||
|
let (root, port) = match raster_config.composite_mode {
|
||||||
|
PictureCompositeMode::TileCache { .. } => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
PictureCompositeMode::Filter(FilterOp::Blur(blur_radius)) => {
|
||||||
|
let blur_std_deviation = blur_radius * device_pixel_scale.0;
|
||||||
|
let scale_factors = scale_factors(&transform);
|
||||||
|
let blur_std_deviation = DeviceSize::new(
|
||||||
|
blur_std_deviation * scale_factors.0,
|
||||||
|
blur_std_deviation * scale_factors.1
|
||||||
|
);
|
||||||
|
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
|
||||||
|
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil() as i32;
|
||||||
|
|
||||||
|
// The clipped field is the part of the picture that is visible
|
||||||
|
// on screen. The unclipped field is the screen-space rect of
|
||||||
|
// the complete picture, if no screen / clip-chain was applied
|
||||||
|
// (this includes the extra space for blur region). To ensure
|
||||||
|
// that we draw a large enough part of the picture to get correct
|
||||||
|
// blur results, inflate that clipped area by the blur range, and
|
||||||
|
// then intersect with the total screen rect, to minimize the
|
||||||
|
// allocation size.
|
||||||
|
let mut device_rect = clipped
|
||||||
|
.inflate(inflation_factor, inflation_factor)
|
||||||
|
.intersection(&unclipped.to_i32())
|
||||||
|
.unwrap();
|
||||||
|
// Adjust the size to avoid introducing sampling errors during the down-scaling passes.
|
||||||
|
// what would be even better is to rasterize the picture at the down-scaled size
|
||||||
|
// directly.
|
||||||
|
device_rect.size = RenderTask::adjusted_blur_source_size(
|
||||||
|
device_rect.size,
|
||||||
|
blur_std_deviation,
|
||||||
|
);
|
||||||
|
|
||||||
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
&pic_rect,
|
||||||
|
&transform,
|
||||||
|
&device_rect,
|
||||||
|
device_pixel_scale,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
let picture_task = RenderTask::new_picture(
|
||||||
|
RenderTaskLocation::Dynamic(None, device_rect.size),
|
||||||
|
unclipped.size,
|
||||||
|
pic_index,
|
||||||
|
device_rect.origin,
|
||||||
|
Vec::new(),
|
||||||
|
uv_rect_kind,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
device_pixel_scale,
|
||||||
|
);
|
||||||
|
|
||||||
|
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||||
|
|
||||||
|
let blur_render_task = RenderTask::new_blur(
|
||||||
|
blur_std_deviation,
|
||||||
|
picture_task_id,
|
||||||
|
frame_state.render_tasks,
|
||||||
|
RenderTargetKind::Color,
|
||||||
|
ClearMode::Transparent,
|
||||||
|
);
|
||||||
|
|
||||||
|
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
||||||
|
|
||||||
|
(render_task_id, picture_task_id)
|
||||||
|
}
|
||||||
|
PictureCompositeMode::Filter(FilterOp::DropShadow(_, blur_radius, _)) => {
|
||||||
|
let blur_std_deviation = blur_radius * device_pixel_scale.0;
|
||||||
|
let blur_range = (blur_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
|
||||||
|
let rounded_std_dev = blur_std_deviation.round();
|
||||||
|
let rounded_std_dev = DeviceSize::new(rounded_std_dev, rounded_std_dev);
|
||||||
|
// The clipped field is the part of the picture that is visible
|
||||||
|
// on screen. The unclipped field is the screen-space rect of
|
||||||
|
// the complete picture, if no screen / clip-chain was applied
|
||||||
|
// (this includes the extra space for blur region). To ensure
|
||||||
|
// that we draw a large enough part of the picture to get correct
|
||||||
|
// blur results, inflate that clipped area by the blur range, and
|
||||||
|
// then intersect with the total screen rect, to minimize the
|
||||||
|
// allocation size.
|
||||||
|
let mut device_rect = clipped.inflate(blur_range, blur_range)
|
||||||
|
.intersection(&unclipped.to_i32())
|
||||||
|
.unwrap();
|
||||||
|
device_rect.size = RenderTask::adjusted_blur_source_size(
|
||||||
|
device_rect.size,
|
||||||
|
rounded_std_dev,
|
||||||
|
);
|
||||||
|
|
||||||
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
&pic_rect,
|
||||||
|
&transform,
|
||||||
|
&device_rect,
|
||||||
|
device_pixel_scale,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut picture_task = RenderTask::new_picture(
|
||||||
|
RenderTaskLocation::Dynamic(None, device_rect.size),
|
||||||
|
unclipped.size,
|
||||||
|
pic_index,
|
||||||
|
device_rect.origin,
|
||||||
|
Vec::new(),
|
||||||
|
uv_rect_kind,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
device_pixel_scale,
|
||||||
|
);
|
||||||
|
picture_task.mark_for_saving();
|
||||||
|
|
||||||
|
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||||
|
|
||||||
|
let blur_render_task = RenderTask::new_blur(
|
||||||
|
rounded_std_dev,
|
||||||
|
picture_task_id,
|
||||||
|
frame_state.render_tasks,
|
||||||
|
RenderTargetKind::Color,
|
||||||
|
ClearMode::Transparent,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.secondary_render_task_id = Some(picture_task_id);
|
||||||
|
|
||||||
|
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
||||||
|
|
||||||
|
(render_task_id, picture_task_id)
|
||||||
|
}
|
||||||
|
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {
|
||||||
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
&pic_rect,
|
||||||
|
&transform,
|
||||||
|
&clipped,
|
||||||
|
device_pixel_scale,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
let picture_task = RenderTask::new_picture(
|
||||||
|
RenderTaskLocation::Dynamic(None, clipped.size),
|
||||||
|
unclipped.size,
|
||||||
|
pic_index,
|
||||||
|
clipped.origin,
|
||||||
|
Vec::new(),
|
||||||
|
uv_rect_kind,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
device_pixel_scale,
|
||||||
|
);
|
||||||
|
|
||||||
|
let readback_task_id = frame_state.render_tasks.add(
|
||||||
|
RenderTask::new_readback(clipped)
|
||||||
|
);
|
||||||
|
|
||||||
|
frame_state.render_tasks.add_dependency(
|
||||||
|
frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port,
|
||||||
|
readback_task_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.secondary_render_task_id = Some(readback_task_id);
|
||||||
|
|
||||||
|
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||||
|
|
||||||
|
(render_task_id, render_task_id)
|
||||||
|
}
|
||||||
|
PictureCompositeMode::Filter(..) => {
|
||||||
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
&pic_rect,
|
||||||
|
&transform,
|
||||||
|
&clipped,
|
||||||
|
device_pixel_scale,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
let picture_task = RenderTask::new_picture(
|
||||||
|
RenderTaskLocation::Dynamic(None, clipped.size),
|
||||||
|
unclipped.size,
|
||||||
|
pic_index,
|
||||||
|
clipped.origin,
|
||||||
|
Vec::new(),
|
||||||
|
uv_rect_kind,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
device_pixel_scale,
|
||||||
|
);
|
||||||
|
|
||||||
|
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||||
|
|
||||||
|
(render_task_id, render_task_id)
|
||||||
|
}
|
||||||
|
PictureCompositeMode::ComponentTransferFilter(..) => {
|
||||||
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
&pic_rect,
|
||||||
|
&transform,
|
||||||
|
&clipped,
|
||||||
|
device_pixel_scale,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
let picture_task = RenderTask::new_picture(
|
||||||
|
RenderTaskLocation::Dynamic(None, clipped.size),
|
||||||
|
unclipped.size,
|
||||||
|
pic_index,
|
||||||
|
clipped.origin,
|
||||||
|
Vec::new(),
|
||||||
|
uv_rect_kind,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
device_pixel_scale,
|
||||||
|
);
|
||||||
|
|
||||||
|
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||||
|
|
||||||
|
(render_task_id, render_task_id)
|
||||||
|
}
|
||||||
|
PictureCompositeMode::MixBlend(..) |
|
||||||
|
PictureCompositeMode::Blit(_) => {
|
||||||
|
// The SplitComposite shader used for 3d contexts doesn't snap
|
||||||
|
// to pixels, so we shouldn't snap our uv coordinates either.
|
||||||
|
let supports_snapping = match self.context_3d {
|
||||||
|
Picture3DContext::In{ .. } => false,
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
&pic_rect,
|
||||||
|
&transform,
|
||||||
|
&clipped,
|
||||||
|
device_pixel_scale,
|
||||||
|
supports_snapping,
|
||||||
|
);
|
||||||
|
|
||||||
|
let picture_task = RenderTask::new_picture(
|
||||||
|
RenderTaskLocation::Dynamic(None, clipped.size),
|
||||||
|
unclipped.size,
|
||||||
|
pic_index,
|
||||||
|
clipped.origin,
|
||||||
|
Vec::new(),
|
||||||
|
uv_rect_kind,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
device_pixel_scale,
|
||||||
|
);
|
||||||
|
|
||||||
|
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||||
|
|
||||||
|
(render_task_id, render_task_id)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
frame_state.surfaces[raster_config.surface_index.0].render_tasks = Some(SurfaceRenderTasks {
|
||||||
|
root,
|
||||||
|
port,
|
||||||
|
});
|
||||||
|
|
||||||
|
frame_state.render_tasks.add_dependency(
|
||||||
|
frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port,
|
||||||
|
root,
|
||||||
|
);
|
||||||
|
|
||||||
|
(true, false)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
(false, true)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let state = PictureState {
|
let state = PictureState {
|
||||||
//TODO: check for MAX_CACHE_SIZE here?
|
//TODO: check for MAX_CACHE_SIZE here?
|
||||||
map_local_to_pic,
|
map_local_to_pic,
|
||||||
|
@ -2427,18 +2728,6 @@ impl PicturePrimitive {
|
||||||
plane_splitter,
|
plane_splitter,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (is_composite, is_passthrough) = match self.raster_config {
|
|
||||||
Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
|
|
||||||
(false, false)
|
|
||||||
},
|
|
||||||
Some(_) => {
|
|
||||||
(true, false)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
(false, true)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dirty_region_count = 0;
|
let mut dirty_region_count = 0;
|
||||||
|
|
||||||
// If this is a picture cache, push the dirty region to ensure any
|
// If this is a picture cache, push the dirty region to ensure any
|
||||||
|
@ -2488,10 +2777,10 @@ impl PicturePrimitive {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.prim_list = prim_list;
|
self.prim_list = prim_list;
|
||||||
self.state = Some((state, context));
|
self.state = Some(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_state_and_context(&mut self) -> (PictureState, PictureContext) {
|
pub fn take_state(&mut self) -> PictureState {
|
||||||
self.state.take().expect("bug: no state present!")
|
self.state.take().expect("bug: no state present!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2876,14 +3165,11 @@ impl PicturePrimitive {
|
||||||
|
|
||||||
pub fn prepare_for_render(
|
pub fn prepare_for_render(
|
||||||
&mut self,
|
&mut self,
|
||||||
pic_index: PictureIndex,
|
|
||||||
clipped_prim_bounding_rect: WorldRect,
|
|
||||||
surface_index: SurfaceIndex,
|
|
||||||
frame_context: &FrameBuildingContext,
|
frame_context: &FrameBuildingContext,
|
||||||
frame_state: &mut FrameBuildingState,
|
frame_state: &mut FrameBuildingState,
|
||||||
data_stores: &mut DataStores,
|
data_stores: &mut DataStores,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let (mut pic_state_for_children, pic_context) = self.take_state_and_context();
|
let mut pic_state_for_children = self.take_state();
|
||||||
|
|
||||||
if let Some(ref mut splitter) = pic_state_for_children.plane_splitter {
|
if let Some(ref mut splitter) = pic_state_for_children.plane_splitter {
|
||||||
self.resolve_split_planes(splitter, frame_state);
|
self.resolve_split_planes(splitter, frame_state);
|
||||||
|
@ -2896,36 +3182,6 @@ impl PicturePrimitive {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (raster_spatial_node_index, child_tasks, device_pixel_scale) = {
|
|
||||||
let surface_info = &mut frame_state.surfaces[raster_config.surface_index.0];
|
|
||||||
(
|
|
||||||
surface_info.raster_spatial_node_index,
|
|
||||||
surface_info.take_render_tasks(),
|
|
||||||
surface_info.device_pixel_scale,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (map_raster_to_world, map_pic_to_raster) = create_raster_mappers(
|
|
||||||
self.spatial_node_index,
|
|
||||||
raster_spatial_node_index,
|
|
||||||
frame_context.screen_world_rect,
|
|
||||||
frame_context.clip_scroll_tree,
|
|
||||||
);
|
|
||||||
|
|
||||||
let pic_rect = PictureRect::from_untyped(&self.snapped_local_rect.to_untyped());
|
|
||||||
|
|
||||||
let (clipped, unclipped) = match get_raster_rects(
|
|
||||||
pic_rect,
|
|
||||||
&map_pic_to_raster,
|
|
||||||
&map_raster_to_world,
|
|
||||||
clipped_prim_bounding_rect,
|
|
||||||
device_pixel_scale,
|
|
||||||
) {
|
|
||||||
Some(info) => info,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
let transform = map_pic_to_raster.get_transform();
|
|
||||||
|
|
||||||
// TODO(gw): Almost all of the Picture types below use extra_gpu_cache_data
|
// TODO(gw): Almost all of the Picture types below use extra_gpu_cache_data
|
||||||
// to store the same type of data. The exception is the filter
|
// to store the same type of data. The exception is the filter
|
||||||
// with a ColorMatrix, which stores the color matrix here. It's
|
// with a ColorMatrix, which stores the color matrix here. It's
|
||||||
|
@ -2933,136 +3189,10 @@ impl PicturePrimitive {
|
||||||
// Perhaps store the color matrix after the common data, even though
|
// Perhaps store the color matrix after the common data, even though
|
||||||
// it's not used by that shader.
|
// it's not used by that shader.
|
||||||
|
|
||||||
let surface = match raster_config.composite_mode {
|
match raster_config.composite_mode {
|
||||||
PictureCompositeMode::TileCache { .. } => {
|
PictureCompositeMode::TileCache { .. } => {}
|
||||||
// For a picture surface, just push any child tasks and tile
|
PictureCompositeMode::Filter(FilterOp::Blur(..)) => {}
|
||||||
// blits up to the parent surface.
|
PictureCompositeMode::Filter(FilterOp::DropShadow(offset, _, color)) => {
|
||||||
let surface = &mut frame_state.surfaces[surface_index.0];
|
|
||||||
surface.tasks.extend(child_tasks);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
PictureCompositeMode::Filter(FilterOp::Blur(blur_radius)) => {
|
|
||||||
let blur_std_deviation = blur_radius * device_pixel_scale.0;
|
|
||||||
let scale_factors = scale_factors(&transform);
|
|
||||||
let blur_std_deviation = DeviceSize::new(
|
|
||||||
blur_std_deviation * scale_factors.0,
|
|
||||||
blur_std_deviation * scale_factors.1
|
|
||||||
);
|
|
||||||
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
|
|
||||||
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil() as i32;
|
|
||||||
|
|
||||||
// The clipped field is the part of the picture that is visible
|
|
||||||
// on screen. The unclipped field is the screen-space rect of
|
|
||||||
// the complete picture, if no screen / clip-chain was applied
|
|
||||||
// (this includes the extra space for blur region). To ensure
|
|
||||||
// that we draw a large enough part of the picture to get correct
|
|
||||||
// blur results, inflate that clipped area by the blur range, and
|
|
||||||
// then intersect with the total screen rect, to minimize the
|
|
||||||
// allocation size.
|
|
||||||
let mut device_rect = clipped
|
|
||||||
.inflate(inflation_factor, inflation_factor)
|
|
||||||
.intersection(&unclipped.to_i32())
|
|
||||||
.unwrap();
|
|
||||||
// Adjust the size to avoid introducing sampling errors during the down-scaling passes.
|
|
||||||
// what would be even better is to rasterize the picture at the down-scaled size
|
|
||||||
// directly.
|
|
||||||
device_rect.size = RenderTask::adjusted_blur_source_size(
|
|
||||||
device_rect.size,
|
|
||||||
blur_std_deviation,
|
|
||||||
);
|
|
||||||
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
|
||||||
&pic_rect,
|
|
||||||
&transform,
|
|
||||||
&device_rect,
|
|
||||||
device_pixel_scale,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
let picture_task = RenderTask::new_picture(
|
|
||||||
RenderTaskLocation::Dynamic(None, device_rect.size),
|
|
||||||
unclipped.size,
|
|
||||||
pic_index,
|
|
||||||
device_rect.origin,
|
|
||||||
child_tasks,
|
|
||||||
uv_rect_kind,
|
|
||||||
pic_context.raster_spatial_node_index,
|
|
||||||
device_pixel_scale,
|
|
||||||
);
|
|
||||||
|
|
||||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
|
||||||
|
|
||||||
let blur_render_task = RenderTask::new_blur(
|
|
||||||
blur_std_deviation,
|
|
||||||
picture_task_id,
|
|
||||||
frame_state.render_tasks,
|
|
||||||
RenderTargetKind::Color,
|
|
||||||
ClearMode::Transparent,
|
|
||||||
);
|
|
||||||
|
|
||||||
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
|
||||||
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
|
||||||
|
|
||||||
render_task_id
|
|
||||||
}
|
|
||||||
PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color)) => {
|
|
||||||
let blur_std_deviation = blur_radius * device_pixel_scale.0;
|
|
||||||
let blur_range = (blur_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
|
|
||||||
let rounded_std_dev = blur_std_deviation.round();
|
|
||||||
let rounded_std_dev = DeviceSize::new(rounded_std_dev, rounded_std_dev);
|
|
||||||
// The clipped field is the part of the picture that is visible
|
|
||||||
// on screen. The unclipped field is the screen-space rect of
|
|
||||||
// the complete picture, if no screen / clip-chain was applied
|
|
||||||
// (this includes the extra space for blur region). To ensure
|
|
||||||
// that we draw a large enough part of the picture to get correct
|
|
||||||
// blur results, inflate that clipped area by the blur range, and
|
|
||||||
// then intersect with the total screen rect, to minimize the
|
|
||||||
// allocation size.
|
|
||||||
let mut device_rect = clipped.inflate(blur_range, blur_range)
|
|
||||||
.intersection(&unclipped.to_i32())
|
|
||||||
.unwrap();
|
|
||||||
device_rect.size = RenderTask::adjusted_blur_source_size(
|
|
||||||
device_rect.size,
|
|
||||||
rounded_std_dev,
|
|
||||||
);
|
|
||||||
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
|
||||||
&pic_rect,
|
|
||||||
&transform,
|
|
||||||
&device_rect,
|
|
||||||
device_pixel_scale,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut picture_task = RenderTask::new_picture(
|
|
||||||
RenderTaskLocation::Dynamic(None, device_rect.size),
|
|
||||||
unclipped.size,
|
|
||||||
pic_index,
|
|
||||||
device_rect.origin,
|
|
||||||
child_tasks,
|
|
||||||
uv_rect_kind,
|
|
||||||
pic_context.raster_spatial_node_index,
|
|
||||||
device_pixel_scale,
|
|
||||||
);
|
|
||||||
picture_task.mark_for_saving();
|
|
||||||
|
|
||||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
|
||||||
|
|
||||||
let blur_render_task = RenderTask::new_blur(
|
|
||||||
rounded_std_dev,
|
|
||||||
picture_task_id,
|
|
||||||
frame_state.render_tasks,
|
|
||||||
RenderTargetKind::Color,
|
|
||||||
ClearMode::Transparent,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.secondary_render_task_id = Some(picture_task_id);
|
|
||||||
|
|
||||||
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
|
||||||
|
|
||||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||||
// TODO(gw): This is very hacky code below! It stores an extra
|
// TODO(gw): This is very hacky code below! It stores an extra
|
||||||
// brush primitive below for the special case of a
|
// brush primitive below for the special case of a
|
||||||
|
@ -3090,40 +3220,8 @@ impl PicturePrimitive {
|
||||||
request.push(shadow_rect);
|
request.push(shadow_rect);
|
||||||
request.push([0.0, 0.0, 0.0, 0.0]);
|
request.push([0.0, 0.0, 0.0, 0.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_task_id
|
|
||||||
}
|
|
||||||
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
|
||||||
&pic_rect,
|
|
||||||
&transform,
|
|
||||||
&clipped,
|
|
||||||
device_pixel_scale,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
let picture_task = RenderTask::new_picture(
|
|
||||||
RenderTaskLocation::Dynamic(None, clipped.size),
|
|
||||||
unclipped.size,
|
|
||||||
pic_index,
|
|
||||||
clipped.origin,
|
|
||||||
child_tasks,
|
|
||||||
uv_rect_kind,
|
|
||||||
pic_context.raster_spatial_node_index,
|
|
||||||
device_pixel_scale,
|
|
||||||
);
|
|
||||||
|
|
||||||
let readback_task_id = frame_state.render_tasks.add(
|
|
||||||
RenderTask::new_readback(clipped)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.secondary_render_task_id = Some(readback_task_id);
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(readback_task_id);
|
|
||||||
|
|
||||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
|
||||||
render_task_id
|
|
||||||
}
|
}
|
||||||
|
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {}
|
||||||
PictureCompositeMode::Filter(ref filter) => {
|
PictureCompositeMode::Filter(ref filter) => {
|
||||||
if let FilterOp::ColorMatrix(m) = *filter {
|
if let FilterOp::ColorMatrix(m) = *filter {
|
||||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||||
|
@ -3132,92 +3230,14 @@ impl PicturePrimitive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
|
||||||
&pic_rect,
|
|
||||||
&transform,
|
|
||||||
&clipped,
|
|
||||||
device_pixel_scale,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
let picture_task = RenderTask::new_picture(
|
|
||||||
RenderTaskLocation::Dynamic(None, clipped.size),
|
|
||||||
unclipped.size,
|
|
||||||
pic_index,
|
|
||||||
clipped.origin,
|
|
||||||
child_tasks,
|
|
||||||
uv_rect_kind,
|
|
||||||
pic_context.raster_spatial_node_index,
|
|
||||||
device_pixel_scale,
|
|
||||||
);
|
|
||||||
|
|
||||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
|
||||||
render_task_id
|
|
||||||
}
|
}
|
||||||
PictureCompositeMode::ComponentTransferFilter(handle) => {
|
PictureCompositeMode::ComponentTransferFilter(handle) => {
|
||||||
let filter_data = &mut data_stores.filter_data[handle];
|
let filter_data = &mut data_stores.filter_data[handle];
|
||||||
filter_data.update(frame_state);
|
filter_data.update(frame_state);
|
||||||
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
|
||||||
&pic_rect,
|
|
||||||
&transform,
|
|
||||||
&clipped,
|
|
||||||
device_pixel_scale,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
let picture_task = RenderTask::new_picture(
|
|
||||||
RenderTaskLocation::Dynamic(None, clipped.size),
|
|
||||||
unclipped.size,
|
|
||||||
pic_index,
|
|
||||||
clipped.origin,
|
|
||||||
child_tasks,
|
|
||||||
uv_rect_kind,
|
|
||||||
pic_context.raster_spatial_node_index,
|
|
||||||
device_pixel_scale,
|
|
||||||
);
|
|
||||||
|
|
||||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
|
||||||
render_task_id
|
|
||||||
}
|
}
|
||||||
PictureCompositeMode::MixBlend(..) |
|
PictureCompositeMode::MixBlend(..) |
|
||||||
PictureCompositeMode::Blit(_) => {
|
PictureCompositeMode::Blit(_) => {}
|
||||||
// The SplitComposite shader used for 3d contexts doesn't snap
|
}
|
||||||
// to pixels, so we shouldn't snap our uv coordinates either.
|
|
||||||
let supports_snapping = match self.context_3d {
|
|
||||||
Picture3DContext::In{ .. } => false,
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
|
||||||
&pic_rect,
|
|
||||||
&transform,
|
|
||||||
&clipped,
|
|
||||||
device_pixel_scale,
|
|
||||||
supports_snapping,
|
|
||||||
);
|
|
||||||
|
|
||||||
let picture_task = RenderTask::new_picture(
|
|
||||||
RenderTaskLocation::Dynamic(None, clipped.size),
|
|
||||||
unclipped.size,
|
|
||||||
pic_index,
|
|
||||||
clipped.origin,
|
|
||||||
child_tasks,
|
|
||||||
uv_rect_kind,
|
|
||||||
pic_context.raster_spatial_node_index,
|
|
||||||
device_pixel_scale,
|
|
||||||
);
|
|
||||||
|
|
||||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
|
||||||
render_task_id
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
frame_state.surfaces[raster_config.surface_index.0].surface = Some(surface);
|
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -988,7 +988,10 @@ impl BrushSegment {
|
||||||
);
|
);
|
||||||
|
|
||||||
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
||||||
frame_state.surfaces[surface_index.0].tasks.push(clip_task_id);
|
frame_state.render_tasks.add_dependency(
|
||||||
|
frame_state.surfaces[surface_index.0].render_tasks.unwrap().port,
|
||||||
|
clip_task_id,
|
||||||
|
);
|
||||||
ClipMaskKind::Mask(clip_task_id)
|
ClipMaskKind::Mask(clip_task_id)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -2470,8 +2473,13 @@ impl PrimitiveStore {
|
||||||
PrimitiveInstanceKind::Picture { pic_index ,.. } => {
|
PrimitiveInstanceKind::Picture { pic_index ,.. } => {
|
||||||
let pic = &mut self.pictures[pic_index.0];
|
let pic = &mut self.pictures[pic_index.0];
|
||||||
|
|
||||||
|
let clipped_prim_bounding_rect = scratch
|
||||||
|
.prim_info[prim_instance.visibility_info.0 as usize]
|
||||||
|
.clipped_world_rect;
|
||||||
|
|
||||||
match pic.take_context(
|
match pic.take_context(
|
||||||
pic_index,
|
pic_index,
|
||||||
|
clipped_prim_bounding_rect,
|
||||||
pic_context.surface_spatial_node_index,
|
pic_context.surface_spatial_node_index,
|
||||||
pic_context.raster_spatial_node_index,
|
pic_context.raster_spatial_node_index,
|
||||||
pic_context.surface_index,
|
pic_context.surface_index,
|
||||||
|
@ -2484,6 +2492,8 @@ impl PrimitiveStore {
|
||||||
println!("\tculled for carrying an invisible composite filter");
|
println!("\tculled for carrying an invisible composite filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3071,9 +3081,6 @@ impl PrimitiveStore {
|
||||||
let pic = &mut self.pictures[pic_index.0];
|
let pic = &mut self.pictures[pic_index.0];
|
||||||
let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
|
let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
|
||||||
if pic.prepare_for_render(
|
if pic.prepare_for_render(
|
||||||
*pic_index,
|
|
||||||
prim_info.clipped_world_rect,
|
|
||||||
pic_context.surface_index,
|
|
||||||
frame_context,
|
frame_context,
|
||||||
frame_state,
|
frame_state,
|
||||||
data_stores,
|
data_stores,
|
||||||
|
@ -3747,7 +3754,10 @@ impl PrimitiveInstance {
|
||||||
let clip_task_index = ClipTaskIndex(scratch.clip_mask_instances.len() as _);
|
let clip_task_index = ClipTaskIndex(scratch.clip_mask_instances.len() as _);
|
||||||
scratch.clip_mask_instances.push(ClipMaskKind::Mask(clip_task_id));
|
scratch.clip_mask_instances.push(ClipMaskKind::Mask(clip_task_id));
|
||||||
prim_info.clip_task_index = clip_task_index;
|
prim_info.clip_task_index = clip_task_index;
|
||||||
frame_state.surfaces[pic_context.surface_index.0].tasks.push(clip_task_id);
|
frame_state.render_tasks.add_dependency(
|
||||||
|
frame_state.surfaces[pic_context.surface_index.0].render_tasks.unwrap().port,
|
||||||
|
clip_task_id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче