mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #7710 - mrobinson:small-dl-refactor, r=pcwalton
A few small bits of refactoring to prepare for more advanced DisplayList layerization This will be useful when PaintLayers that contain DisplayLists instead of StackingContexts need to draw themselves. This is a simple preparatory refactoring and doesn't change any behavior. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7710) <!-- Reviewable:end -->
This commit is contained in:
commit
09b970af4a
2 changed files with 143 additions and 151 deletions
|
@ -15,7 +15,7 @@
|
|||
//! low-level drawing primitives.
|
||||
|
||||
use azure::azure::AzFloat;
|
||||
use azure::azure_hl::Color;
|
||||
use azure::azure_hl::{Color, DrawTarget};
|
||||
use display_list::optimizer::DisplayListOptimizer;
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use euclid::num::Zero;
|
||||
|
@ -97,7 +97,7 @@ pub struct DisplayList {
|
|||
/// Child stacking contexts.
|
||||
pub children: LinkedList<Arc<StackingContext>>,
|
||||
/// Child PaintLayers that will be rendered on top of everything else.
|
||||
pub layered_children: LinkedList<PaintLayer>,
|
||||
pub layered_children: LinkedList<Arc<PaintLayer>>,
|
||||
}
|
||||
|
||||
impl DisplayList {
|
||||
|
@ -116,27 +116,6 @@ impl DisplayList {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sort all children by their z-index and split layered children into their own
|
||||
/// section of the display list.
|
||||
/// TODO(mrobinson): This should properly handle unlayered children that are on
|
||||
/// top of layered children.
|
||||
#[inline]
|
||||
pub fn sort_and_layerize_children(&mut self) {
|
||||
let mut children: SmallVec<[Arc<StackingContext>; 8]> = SmallVec::new();
|
||||
while let Some(stacking_context) = self.children.pop_front() {
|
||||
children.push(stacking_context);
|
||||
}
|
||||
children.sort_by(|this, other| this.z_index.cmp(&other.z_index));
|
||||
|
||||
for stacking_context in children.into_iter() {
|
||||
match stacking_context.layer_id {
|
||||
Some(layer_id) => self.layered_children.push_back(
|
||||
PaintLayer::new(layer_id, color::transparent(), stacking_context)),
|
||||
None => self.children.push_back(stacking_context),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends all display items from `other` into `self`, preserving stacking order and emptying
|
||||
/// `other` in the process.
|
||||
#[inline]
|
||||
|
@ -237,6 +216,113 @@ impl DisplayList {
|
|||
paint_layer.stacking_context.print_with_tree(print_tree);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws the DisplayList in stacking context order according to the steps in CSS 2.1 § E.2.
|
||||
fn draw_into_context(&self,
|
||||
draw_target: &DrawTarget,
|
||||
paint_context: &mut PaintContext,
|
||||
transform: &Matrix4,
|
||||
clip_rect: Option<&Rect<Au>>) {
|
||||
let mut paint_subcontext = PaintContext {
|
||||
draw_target: draw_target.clone(),
|
||||
font_context: &mut *paint_context.font_context,
|
||||
page_rect: paint_context.page_rect,
|
||||
screen_rect: paint_context.screen_rect,
|
||||
clip_rect: clip_rect.map(|clip_rect| *clip_rect),
|
||||
transient_clip: None,
|
||||
layer_kind: paint_context.layer_kind,
|
||||
};
|
||||
|
||||
if opts::get().dump_display_list_optimized {
|
||||
self.print(format!("Optimized display list. Tile bounds: {:?}",
|
||||
paint_context.page_rect));
|
||||
}
|
||||
|
||||
// Set up our clip rect and transform.
|
||||
let old_transform = paint_subcontext.draw_target.get_transform();
|
||||
let xform_2d = Matrix2D::new(transform.m11, transform.m12,
|
||||
transform.m21, transform.m22,
|
||||
transform.m41, transform.m42);
|
||||
paint_subcontext.draw_target.set_transform(&xform_2d);
|
||||
paint_subcontext.push_clip_if_applicable();
|
||||
|
||||
// Steps 1 and 2: Borders and background for the root.
|
||||
for display_item in &self.background_and_borders {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 3: Positioned descendants with negative z-indices.
|
||||
for positioned_kid in &self.children {
|
||||
if positioned_kid.z_index >= 0 {
|
||||
break
|
||||
}
|
||||
let new_transform =
|
||||
transform.translate(positioned_kid.bounds
|
||||
.origin
|
||||
.x
|
||||
.to_nearest_px() as AzFloat,
|
||||
positioned_kid.bounds
|
||||
.origin
|
||||
.y
|
||||
.to_nearest_px() as AzFloat,
|
||||
0.0);
|
||||
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
||||
&new_transform,
|
||||
Some(&positioned_kid.overflow))
|
||||
}
|
||||
|
||||
// Step 4: Block backgrounds and borders.
|
||||
for display_item in &self.block_backgrounds_and_borders {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 5: Floats.
|
||||
for display_item in &self.floats {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// TODO(pcwalton): Step 6: Inlines that generate stacking contexts.
|
||||
|
||||
// Step 7: Content.
|
||||
for display_item in &self.content {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 8: Positioned descendants with `z-index: auto`.
|
||||
for display_item in &self.positioned_content {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 9: Positioned descendants with nonnegative, numeric z-indices.
|
||||
for positioned_kid in &self.children {
|
||||
if positioned_kid.z_index < 0 {
|
||||
continue
|
||||
}
|
||||
let new_transform =
|
||||
transform.translate(positioned_kid.bounds
|
||||
.origin
|
||||
.x
|
||||
.to_nearest_px() as AzFloat,
|
||||
positioned_kid.bounds
|
||||
.origin
|
||||
.y
|
||||
.to_nearest_px() as AzFloat,
|
||||
0.0);
|
||||
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
||||
&new_transform,
|
||||
Some(&positioned_kid.overflow))
|
||||
}
|
||||
|
||||
// Step 10: Outlines.
|
||||
for display_item in &self.outlines {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Undo our clipping and transform.
|
||||
paint_subcontext.remove_transient_clip_if_applicable();
|
||||
paint_subcontext.pop_clip_if_applicable();
|
||||
paint_subcontext.draw_target.set_transform(&old_transform)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(HeapSizeOf, Deserialize, Serialize)]
|
||||
|
@ -341,107 +427,11 @@ impl StackingContext {
|
|||
clip_rect: Option<&Rect<Au>>) {
|
||||
let temporary_draw_target =
|
||||
paint_context.get_or_create_temporary_draw_target(&self.filters, self.blend_mode);
|
||||
{
|
||||
let mut paint_subcontext = PaintContext {
|
||||
draw_target: temporary_draw_target.clone(),
|
||||
font_context: &mut *paint_context.font_context,
|
||||
page_rect: paint_context.page_rect,
|
||||
screen_rect: paint_context.screen_rect,
|
||||
clip_rect: clip_rect.map(|clip_rect| *clip_rect),
|
||||
transient_clip: None,
|
||||
layer_kind: paint_context.layer_kind,
|
||||
};
|
||||
|
||||
if opts::get().dump_display_list_optimized {
|
||||
display_list.print(format!("Optimized display list. Tile bounds: {:?}",
|
||||
paint_context.page_rect));
|
||||
}
|
||||
|
||||
// Set up our clip rect and transform.
|
||||
let old_transform = paint_subcontext.draw_target.get_transform();
|
||||
let xform_2d = Matrix2D::new(transform.m11, transform.m12,
|
||||
transform.m21, transform.m22,
|
||||
transform.m41, transform.m42);
|
||||
paint_subcontext.draw_target.set_transform(&xform_2d);
|
||||
paint_subcontext.push_clip_if_applicable();
|
||||
|
||||
// Steps 1 and 2: Borders and background for the root.
|
||||
for display_item in &display_list.background_and_borders {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 3: Positioned descendants with negative z-indices.
|
||||
for positioned_kid in &display_list.children {
|
||||
if positioned_kid.z_index >= 0 {
|
||||
break
|
||||
}
|
||||
let new_transform =
|
||||
transform.translate(positioned_kid.bounds
|
||||
.origin
|
||||
.x
|
||||
.to_nearest_px() as AzFloat,
|
||||
positioned_kid.bounds
|
||||
.origin
|
||||
.y
|
||||
.to_nearest_px() as AzFloat,
|
||||
0.0);
|
||||
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
||||
&new_transform,
|
||||
Some(&positioned_kid.overflow))
|
||||
}
|
||||
|
||||
// Step 4: Block backgrounds and borders.
|
||||
for display_item in &display_list.block_backgrounds_and_borders {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 5: Floats.
|
||||
for display_item in &display_list.floats {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// TODO(pcwalton): Step 6: Inlines that generate stacking contexts.
|
||||
|
||||
// Step 7: Content.
|
||||
for display_item in &display_list.content {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 8: Positioned descendants with `z-index: auto`.
|
||||
for display_item in &display_list.positioned_content {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Step 9: Positioned descendants with nonnegative, numeric z-indices.
|
||||
for positioned_kid in &self.display_list.children {
|
||||
if positioned_kid.z_index < 0 {
|
||||
continue
|
||||
}
|
||||
let new_transform =
|
||||
transform.translate(positioned_kid.bounds
|
||||
.origin
|
||||
.x
|
||||
.to_nearest_px() as AzFloat,
|
||||
positioned_kid.bounds
|
||||
.origin
|
||||
.y
|
||||
.to_nearest_px() as AzFloat,
|
||||
0.0);
|
||||
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
||||
&new_transform,
|
||||
Some(&positioned_kid.overflow))
|
||||
}
|
||||
|
||||
// Step 10: Outlines.
|
||||
for display_item in &display_list.outlines {
|
||||
display_item.draw_into_context(&mut paint_subcontext)
|
||||
}
|
||||
|
||||
// Undo our clipping and transform.
|
||||
paint_subcontext.remove_transient_clip_if_applicable();
|
||||
paint_subcontext.pop_clip_if_applicable();
|
||||
paint_subcontext.draw_target.set_transform(&old_transform)
|
||||
}
|
||||
display_list.draw_into_context(&temporary_draw_target,
|
||||
paint_context,
|
||||
transform,
|
||||
clip_rect);
|
||||
|
||||
paint_context.draw_temporary_draw_target_if_necessary(&temporary_draw_target,
|
||||
&self.filters,
|
||||
|
@ -692,8 +682,8 @@ impl StackingContextLayerCreator {
|
|||
stacking_context.display_list.layered_children.back().unwrap().id.companion_layer_id();
|
||||
let child_stacking_context =
|
||||
Arc::new(stacking_context.create_layered_child(next_layer_id, display_list));
|
||||
stacking_context.display_list.layered_children.push_back(
|
||||
PaintLayer::new(next_layer_id, color::transparent(), child_stacking_context));
|
||||
stacking_context.display_list.layered_children.push_back(Arc::new(
|
||||
PaintLayer::new(next_layer_id, color::transparent(), child_stacking_context)));
|
||||
self.all_following_children_need_layers = true;
|
||||
}
|
||||
}
|
||||
|
@ -704,7 +694,7 @@ impl StackingContextLayerCreator {
|
|||
if let Some(layer_id) = stacking_context.layer_id {
|
||||
self.finish_building_current_layer(parent_stacking_context);
|
||||
parent_stacking_context.display_list.layered_children.push_back(
|
||||
PaintLayer::new(layer_id, color::transparent(), stacking_context));
|
||||
Arc::new(PaintLayer::new(layer_id, color::transparent(), stacking_context)));
|
||||
|
||||
// We have started processing layered stacking contexts, so any stacking context that
|
||||
// we process from now on needs its own layer to ensure proper rendering order.
|
||||
|
@ -722,17 +712,18 @@ impl StackingContextLayerCreator {
|
|||
}
|
||||
|
||||
/// Returns the stacking context in the given tree of stacking contexts with a specific layer ID.
|
||||
pub fn find_stacking_context_with_layer_id(this: &Arc<StackingContext>, layer_id: LayerId)
|
||||
-> Option<Arc<StackingContext>> {
|
||||
pub fn find_layer_with_layer_id(this: &Arc<StackingContext>,
|
||||
layer_id: LayerId)
|
||||
-> Option<Arc<PaintLayer>> {
|
||||
for kid in &this.display_list.layered_children {
|
||||
if let Some(stacking_context) = kid.find_stacking_context_with_layer_id(layer_id) {
|
||||
return Some(stacking_context);
|
||||
if let Some(paint_layer) = PaintLayer::find_layer_with_layer_id(&kid, layer_id) {
|
||||
return Some(paint_layer);
|
||||
}
|
||||
}
|
||||
|
||||
for kid in &this.display_list.children {
|
||||
if let Some(stacking_context) = find_stacking_context_with_layer_id(kid, layer_id) {
|
||||
return Some(stacking_context);
|
||||
if let Some(paint_layer) = find_layer_with_layer_id(kid, layer_id) {
|
||||
return Some(paint_layer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,14 +60,14 @@ impl PaintLayer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_stacking_context_with_layer_id(&self,
|
||||
layer_id: LayerId)
|
||||
-> Option<Arc<StackingContext>> {
|
||||
if self.id == layer_id {
|
||||
return Some(self.stacking_context.clone());
|
||||
pub fn find_layer_with_layer_id(this: &Arc<PaintLayer>,
|
||||
layer_id: LayerId)
|
||||
-> Option<Arc<PaintLayer>> {
|
||||
if this.id == layer_id {
|
||||
return Some(this.clone());
|
||||
}
|
||||
|
||||
display_list::find_stacking_context_with_layer_id(&self.stacking_context, layer_id)
|
||||
display_list::find_layer_with_layer_id(&this.stacking_context, layer_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ pub struct PaintTask<C> {
|
|||
time_profiler_chan: time::ProfilerChan,
|
||||
|
||||
/// The root paint layer sent to us by the layout thread.
|
||||
root_paint_layer: Option<PaintLayer>,
|
||||
root_paint_layer: Option<Arc<PaintLayer>>,
|
||||
|
||||
/// Permission to send paint messages to the compositor
|
||||
paint_permission: bool,
|
||||
|
@ -216,7 +216,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
match message {
|
||||
Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, paint_layer)) => {
|
||||
self.current_epoch = Some(epoch);
|
||||
self.root_paint_layer = Some(paint_layer);
|
||||
self.root_paint_layer = Some(Arc::new(paint_layer));
|
||||
|
||||
if !self.paint_permission {
|
||||
debug!("PaintTask: paint ready msg");
|
||||
|
@ -296,9 +296,9 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
layer_kind: LayerKind) {
|
||||
time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || {
|
||||
// Bail out if there is no appropriate layer.
|
||||
let stacking_context = if let Some(ref paint_layer) = self.root_paint_layer {
|
||||
match paint_layer.find_stacking_context_with_layer_id(layer_id) {
|
||||
Some(stacking_context) => stacking_context,
|
||||
let paint_layer = if let Some(ref root_paint_layer) = self.root_paint_layer {
|
||||
match PaintLayer::find_layer_with_layer_id(root_paint_layer, layer_id) {
|
||||
Some(paint_layer) => paint_layer,
|
||||
None => return,
|
||||
}
|
||||
} else {
|
||||
|
@ -313,7 +313,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
let thread_id = i % self.worker_threads.len();
|
||||
self.worker_threads[thread_id].paint_tile(thread_id,
|
||||
tile,
|
||||
stacking_context.clone(),
|
||||
paint_layer.clone(),
|
||||
scale,
|
||||
layer_kind);
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
self.current_epoch.unwrap());
|
||||
|
||||
fn build_from_paint_layer(properties: &mut Vec<LayerProperties>,
|
||||
paint_layer: &PaintLayer,
|
||||
paint_layer: &Arc<PaintLayer>,
|
||||
page_position: &Point2D<Au>,
|
||||
transform: &Matrix4,
|
||||
perspective: &Matrix4,
|
||||
|
@ -470,12 +470,12 @@ impl WorkerThreadProxy {
|
|||
fn paint_tile(&mut self,
|
||||
thread_id: usize,
|
||||
tile: BufferRequest,
|
||||
stacking_context: Arc<StackingContext>,
|
||||
paint_layer: Arc<PaintLayer>,
|
||||
scale: f32,
|
||||
layer_kind: LayerKind) {
|
||||
let msg = MsgToWorkerThread::PaintTile(thread_id,
|
||||
tile,
|
||||
stacking_context,
|
||||
paint_layer,
|
||||
scale,
|
||||
layer_kind);
|
||||
self.sender.send(msg).unwrap()
|
||||
|
@ -540,10 +540,10 @@ impl WorkerThread {
|
|||
loop {
|
||||
match self.receiver.recv().unwrap() {
|
||||
MsgToWorkerThread::Exit => break,
|
||||
MsgToWorkerThread::PaintTile(thread_id, tile, stacking_context, scale, layer_kind) => {
|
||||
MsgToWorkerThread::PaintTile(thread_id, tile, paint_layer, scale, layer_kind) => {
|
||||
let buffer = self.optimize_and_paint_tile(thread_id,
|
||||
tile,
|
||||
stacking_context,
|
||||
paint_layer,
|
||||
scale,
|
||||
layer_kind);
|
||||
self.sender.send(MsgFromWorkerThread::PaintedTile(buffer)).unwrap()
|
||||
|
@ -576,10 +576,11 @@ impl WorkerThread {
|
|||
fn optimize_and_paint_tile(&mut self,
|
||||
thread_id: usize,
|
||||
mut tile: BufferRequest,
|
||||
stacking_context: Arc<StackingContext>,
|
||||
paint_layer: Arc<PaintLayer>,
|
||||
scale: f32,
|
||||
layer_kind: LayerKind)
|
||||
-> Box<LayerBuffer> {
|
||||
let stacking_context = &paint_layer.stacking_context;
|
||||
let size = Size2D::new(tile.screen_rect.size.width as i32,
|
||||
tile.screen_rect.size.height as i32);
|
||||
let mut buffer = self.create_layer_buffer(&mut tile, scale);
|
||||
|
@ -683,7 +684,7 @@ impl WorkerThread {
|
|||
|
||||
enum MsgToWorkerThread {
|
||||
Exit,
|
||||
PaintTile(usize, BufferRequest, Arc<StackingContext>, f32, LayerKind),
|
||||
PaintTile(usize, BufferRequest, Arc<PaintLayer>, f32, LayerKind),
|
||||
}
|
||||
|
||||
enum MsgFromWorkerThread {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue