Skip to content
This repository was archived by the owner on Jul 10, 2023. It is now read-only.

Commit 5af8c6b

Browse files
author
bors-servo
committed
Auto merge of #210 - mrobinson:paint-order, r=glennw
Respect paint order when painting RenderContext3D children Instead of painting RenderContext3D on top of all other layers, have them try to respect paint order. This fixes iframe render order, since iframes create a new RenderContext3D, but layers on top of them might not. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/rust-layers/210) <!-- Reviewable:end -->
2 parents 70d630d + 12bf05b commit 5af8c6b

File tree

1 file changed

+100
-80
lines changed

1 file changed

+100
-80
lines changed

src/rendergl.rs

Lines changed: 100 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -329,25 +329,69 @@ impl SolidColorProgram {
329329
}
330330
}
331331

332-
struct RenderLayer<T> {
332+
struct RenderContextChild<T> {
333+
layer: Option<Rc<Layer<T>>>,
334+
context: Option<RenderContext3D<T>>,
333335
paint_order: usize,
334336
z_center: f32,
335-
layer: Rc<Layer<T>>,
336337
}
337338

338339
pub struct RenderContext3D<T>{
339-
layers: Vec<RenderLayer<T>>,
340-
child_contexts: Vec<RenderContext3D<T>>,
340+
children: Vec<RenderContextChild<T>>,
341341
clip_rect: Option<Rect<f32>>,
342342
}
343343

344344
impl<T> RenderContext3D<T> {
345-
fn new(layer: Rc<Layer<T>>, parent_clip_rect: Option<Rect<f32>>) -> RenderContext3D<T> {
346-
RenderContext3D {
347-
layers: vec!(),
348-
child_contexts: vec!(),
349-
clip_rect: RenderContext3D::calculate_context_clip(layer, parent_clip_rect),
345+
fn new(layer: Rc<Layer<T>>) -> RenderContext3D<T> {
346+
let mut render_context = RenderContext3D {
347+
children: vec!(),
348+
clip_rect: RenderContext3D::calculate_context_clip(layer.clone(), None),
349+
};
350+
layer.build(&mut render_context);
351+
render_context.sort_children();
352+
render_context
353+
}
354+
355+
fn build_child(layer: Rc<Layer<T>>,
356+
parent_clip_rect: Option<Rect<f32>>)
357+
-> Option<RenderContext3D<T>> {
358+
let clip_rect = RenderContext3D::calculate_context_clip(layer.clone(), parent_clip_rect);
359+
if let Some(ref clip_rect) = clip_rect {
360+
if clip_rect.is_empty() {
361+
return None;
362+
}
350363
}
364+
365+
let mut render_context = RenderContext3D {
366+
children: vec!(),
367+
clip_rect: clip_rect,
368+
};
369+
370+
for child in layer.children().iter() {
371+
child.build(&mut render_context);
372+
}
373+
374+
render_context.sort_children();
375+
Some(render_context)
376+
}
377+
378+
fn sort_children(&mut self) {
379+
// TODO(gw): This is basically what FF does, which breaks badly
380+
// when there are intersecting polygons. Need to split polygons
381+
// to handle this case correctly (Blink uses a BSP tree).
382+
self.children.sort_by(|a, b| {
383+
if a.z_center < b.z_center {
384+
Ordering::Less
385+
} else if a.z_center > b.z_center {
386+
Ordering::Greater
387+
} else if a.paint_order < b.paint_order {
388+
Ordering::Less
389+
} else if a.paint_order > b.paint_order {
390+
Ordering::Greater
391+
} else {
392+
Ordering::Equal
393+
}
394+
});
351395
}
352396

353397
fn calculate_context_clip(layer: Rc<Layer<T>>,
@@ -372,22 +416,17 @@ impl<T> RenderContext3D<T> {
372416
}
373417
}
374418

375-
fn add_layer(&mut self,
376-
layer: Rc<Layer<T>>,
419+
fn add_child(&mut self,
420+
layer: Option<Rc<Layer<T>>>,
421+
child_context: Option<RenderContext3D<T>>,
377422
z_center: f32) {
378-
let render_layer = RenderLayer {
423+
let paint_order = self.children.len();
424+
self.children.push(RenderContextChild {
379425
layer: layer,
426+
context: child_context,
380427
z_center: z_center,
381-
paint_order: self.layers.len(),
382-
};
383-
self.layers.push(render_layer);
384-
}
385-
386-
fn has_empty_clip_rect(&self) -> bool {
387-
match self.clip_rect {
388-
Some(ref clip_rect) => clip_rect.is_empty(),
389-
None => false,
390-
}
428+
paint_order: paint_order,
429+
});
391430
}
392431
}
393432

@@ -397,28 +436,27 @@ pub trait RenderContext3DBuilder<T> {
397436

398437
impl<T> RenderContext3DBuilder<T> for Rc<Layer<T>> {
399438
fn build(&self, current_context: &mut RenderContext3D<T>) {
400-
// If this layer has not been entirely clipped
401-
if let Some(ref screen_rect) = self.transform_state.borrow().screen_rect {
402-
current_context.add_layer(self.clone(),
403-
screen_rect.z_center);
404-
}
405-
406-
if self.children().len() == 0 {
407-
return;
408-
}
439+
let (layer, z_center) = match self.transform_state.borrow().screen_rect {
440+
Some(ref rect) => (Some(self.clone()), rect.z_center),
441+
None => (None, 0.), // Layer is entirely clipped.
442+
};
409443

410-
let current_context = if self.establishes_3d_context {
411-
let new_context = RenderContext3D::new(self.clone(), current_context.clip_rect);
412-
if new_context.has_empty_clip_rect() {
444+
if !self.children.borrow().is_empty() && self.establishes_3d_context {
445+
let child_context =
446+
RenderContext3D::build_child(self.clone(), current_context.clip_rect);
447+
if child_context.is_some() {
448+
current_context.add_child(layer, child_context, z_center);
413449
return;
414450
}
415-
416-
current_context.child_contexts.push(new_context);
417-
current_context.child_contexts.last_mut().unwrap()
418-
} else {
419-
current_context
420451
};
421452

453+
// If we are completely clipped out, don't add anything to this context.
454+
if layer.is_none() {
455+
return;
456+
}
457+
458+
current_context.add_child(layer, None, z_center);
459+
422460
for child in self.children().iter() {
423461
child.build(current_context);
424462
}
@@ -713,44 +751,28 @@ impl RenderContext {
713751
}
714752

715753
fn render_3d_context<T>(&self,
716-
context: &mut RenderContext3D<T>,
754+
context: &RenderContext3D<T>,
717755
transform: &Matrix4,
718756
projection: &Matrix4,
719757
gfx_context: &NativeDisplay) {
758+
if context.children.is_empty() {
759+
return;
760+
}
720761

721-
// Rendering order as specified in:
722-
// http://dev.w3.org/csswg/css-transforms/#3d-rendering-contexts
723-
if context.layers.len() > 0 {
724-
// Clear the z-buffer for each 3d render context
725-
// TODO(gw): Potential optimization here if there are no
726-
// layer intersections to disable z-buffering and
727-
// avoid clear.
728-
gl::clear(gl::DEPTH_BUFFER_BIT);
729-
730-
// TODO(gw): This is basically what FF does, which breaks badly
731-
// when there are intersecting polygons. Need to split polygons
732-
// to handle this case correctly (Blink uses a BSP tree).
733-
context.layers.sort_by(|a, b| {
734-
if a.z_center < b.z_center {
735-
return Ordering::Less;
736-
} else if a.z_center > b.z_center {
737-
return Ordering::Greater;
738-
} else if a.paint_order < b.paint_order {
739-
return Ordering::Less
740-
} else if a.paint_order > b.paint_order {
741-
return Ordering::Greater;
742-
} else {
743-
return Ordering::Equal;
744-
}
745-
});
762+
// Clear the z-buffer for each 3d render context
763+
// TODO(gw): Potential optimization here if there are no
764+
// layer intersections to disable z-buffering and
765+
// avoid clear.
766+
gl::clear(gl::DEPTH_BUFFER_BIT);
746767

747-
// Render child layers with z-testing.
748-
for render_layer in &context.layers {
768+
// Render child layers with z-testing.
769+
for child in &context.children {
770+
if let Some(ref layer) = child.layer {
749771
// TODO(gw): Disable clipping on 3d layers for now.
750772
// Need to implement proper polygon clipping to
751773
// make this work correctly.
752774
let clip_rect = context.clip_rect.and_then(|cr| {
753-
let m = render_layer.layer.transform_state.borrow().final_transform;
775+
let m = layer.transform_state.borrow().final_transform;
754776

755777
// See https://drafts.csswg.org/css-transforms/#2d-matrix
756778
let is_3d_transform = m.m31 != 0.0 || m.m32 != 0.0 ||
@@ -770,22 +792,22 @@ impl RenderContext {
770792
transform.m41, transform.m42);
771793
Some(xform_2d.transform_rect(&cr))
772794
}
773-
});
774795

775-
self.render_layer(render_layer.layer.clone(),
796+
});
797+
self.render_layer(layer.clone(),
776798
transform,
777799
projection,
778800
clip_rect,
779801
gfx_context);
780802
}
781-
}
782803

783-
// Now render child 3d contexts
784-
for child_context in &mut context.child_contexts {
785-
self.render_3d_context(child_context,
786-
transform,
787-
projection,
788-
gfx_context);
804+
if let Some(ref context) = child.context {
805+
self.render_3d_context(context,
806+
transform,
807+
projection,
808+
gfx_context);
809+
810+
}
789811
}
790812
}
791813
}
@@ -811,9 +833,7 @@ pub fn render_scene<T>(root_layer: Rc<Layer<T>>,
811833
let projection = create_ortho(&scene.viewport.size.to_untyped());
812834

813835
// Build the list of render items
814-
let mut root_3d_context = RenderContext3D::new(root_layer.clone(), None);
815-
root_layer.build(&mut root_3d_context);
816-
render_context.render_3d_context(&mut root_3d_context,
836+
render_context.render_3d_context(&RenderContext3D::new(root_layer.clone()),
817837
&transform,
818838
&projection,
819839
&render_context.compositing_display);

0 commit comments

Comments
 (0)