@@ -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
338339pub 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
344344impl < 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
398437impl < 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