@@ -329,25 +329,69 @@ impl SolidColorProgram {
329
329
}
330
330
}
331
331
332
- struct RenderLayer < T > {
332
+ struct RenderContextChild < T > {
333
+ layer : Option < Rc < Layer < T > > > ,
334
+ context : Option < RenderContext3D < T > > ,
333
335
paint_order : usize ,
334
336
z_center : f32 ,
335
- layer : Rc < Layer < T > > ,
336
337
}
337
338
338
339
pub struct RenderContext3D < T > {
339
- layers : Vec < RenderLayer < T > > ,
340
- child_contexts : Vec < RenderContext3D < T > > ,
340
+ children : Vec < RenderContextChild < T > > ,
341
341
clip_rect : Option < Rect < f32 > > ,
342
342
}
343
343
344
344
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
+ }
350
363
}
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
+ } ) ;
351
395
}
352
396
353
397
fn calculate_context_clip ( layer : Rc < Layer < T > > ,
@@ -372,22 +416,17 @@ impl<T> RenderContext3D<T> {
372
416
}
373
417
}
374
418
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 > > ,
377
422
z_center : f32 ) {
378
- let render_layer = RenderLayer {
423
+ let paint_order = self . children . len ( ) ;
424
+ self . children . push ( RenderContextChild {
379
425
layer : layer,
426
+ context : child_context,
380
427
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
+ } ) ;
391
430
}
392
431
}
393
432
@@ -397,28 +436,27 @@ pub trait RenderContext3DBuilder<T> {
397
436
398
437
impl < T > RenderContext3DBuilder < T > for Rc < Layer < T > > {
399
438
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
+ } ;
409
443
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) ;
413
449
return ;
414
450
}
415
-
416
- current_context. child_contexts . push ( new_context) ;
417
- current_context. child_contexts . last_mut ( ) . unwrap ( )
418
- } else {
419
- current_context
420
451
} ;
421
452
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
+
422
460
for child in self . children ( ) . iter ( ) {
423
461
child. build ( current_context) ;
424
462
}
@@ -713,44 +751,28 @@ impl RenderContext {
713
751
}
714
752
715
753
fn render_3d_context < T > ( & self ,
716
- context : & mut RenderContext3D < T > ,
754
+ context : & RenderContext3D < T > ,
717
755
transform : & Matrix4 ,
718
756
projection : & Matrix4 ,
719
757
gfx_context : & NativeDisplay ) {
758
+ if context. children . is_empty ( ) {
759
+ return ;
760
+ }
720
761
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 ) ;
746
767
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 {
749
771
// TODO(gw): Disable clipping on 3d layers for now.
750
772
// Need to implement proper polygon clipping to
751
773
// make this work correctly.
752
774
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 ;
754
776
755
777
// See https://drafts.csswg.org/css-transforms/#2d-matrix
756
778
let is_3d_transform = m. m31 != 0.0 || m. m32 != 0.0 ||
@@ -770,22 +792,22 @@ impl RenderContext {
770
792
transform. m41 , transform. m42 ) ;
771
793
Some ( xform_2d. transform_rect ( & cr) )
772
794
}
773
- } ) ;
774
795
775
- self . render_layer ( render_layer. layer . clone ( ) ,
796
+ } ) ;
797
+ self . render_layer ( layer. clone ( ) ,
776
798
transform,
777
799
projection,
778
800
clip_rect,
779
801
gfx_context) ;
780
802
}
781
- }
782
803
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
+ }
789
811
}
790
812
}
791
813
}
@@ -811,9 +833,7 @@ pub fn render_scene<T>(root_layer: Rc<Layer<T>>,
811
833
let projection = create_ortho ( & scene. viewport . size . to_untyped ( ) ) ;
812
834
813
835
// 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 ( ) ) ,
817
837
& transform,
818
838
& projection,
819
839
& render_context. compositing_display ) ;
0 commit comments