diff options
Diffstat (limited to 'components/gfx')
-rw-r--r-- | components/gfx/display_list/mod.rs | 74 | ||||
-rw-r--r-- | components/gfx/paint_context.rs | 3 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 117 |
3 files changed, 147 insertions, 47 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 22ca879b417..93a11d6b605 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -32,7 +32,7 @@ use euclid::approxeq::ApproxEq; use euclid::num::Zero; use libc::uintptr_t; use paint_task::PaintLayer; -use msg::compositor_msg::LayerId; +use msg::compositor_msg::{LayerId, LayerKind}; use net_traits::image::base::Image; use util::opts; use util::cursor::Cursor; @@ -246,6 +246,12 @@ pub struct StackingContext { /// A transform to be applied to this stacking context. pub transform: Matrix4, + + /// The perspective matrix to be applied to children. + pub perspective: Matrix4, + + /// Whether this stacking context creates a new 3d rendering context. + pub establishes_3d_context: bool, } impl StackingContext { @@ -255,30 +261,40 @@ impl StackingContext { bounds: &Rect<Au>, overflow: &Rect<Au>, z_index: i32, - transform: &Matrix4, filters: filter::T, blend_mode: mix_blend_mode::T, - layer: Option<Arc<PaintLayer>>) + layer: Option<Arc<PaintLayer>>, + transform: Matrix4, + perspective: Matrix4, + establishes_3d_context: bool) -> StackingContext { StackingContext { display_list: display_list, - layer: layer, bounds: *bounds, overflow: *overflow, z_index: z_index, - transform: *transform, filters: filters, blend_mode: blend_mode, + layer: layer, + transform: transform, + perspective: perspective, + establishes_3d_context: establishes_3d_context, } } /// Draws the stacking context in the proper order according to the steps in CSS 2.1 § E.2. - pub fn optimize_and_draw_into_context(&self, - paint_context: &mut PaintContext, - tile_bounds: &Rect<AzFloat>, - transform: &Matrix4, - clip_rect: Option<&Rect<Au>>) { - let transform = transform.mul(&self.transform); + pub fn draw_into_context(&self, + display_list: &DisplayList, + paint_context: &mut PaintContext, + tile_bounds: &Rect<AzFloat>, + transform: &Matrix4, + clip_rect: Option<&Rect<Au>>) { + // If a layer is being used, the transform for this layer + // will be handled by the compositor. + let transform = match self.layer { + Some(..) => *transform, + None => transform.mul(&self.transform), + }; let temporary_draw_target = paint_context.get_or_create_temporary_draw_target(&self.filters, self.blend_mode); { @@ -289,12 +305,9 @@ impl StackingContext { screen_rect: paint_context.screen_rect, clip_rect: clip_rect.map(|clip_rect| *clip_rect), transient_clip: None, + layer_kind: paint_context.layer_kind, }; - // Optimize the display list to throw out out-of-bounds display items and so forth. - let display_list = - DisplayListOptimizer::new(tile_bounds).optimize(&*self.display_list); - if opts::get().dump_display_list_optimized { println!("**** optimized display list. Tile bounds: {:?}", tile_bounds); display_list.print_items("*".to_owned()); @@ -409,6 +422,35 @@ impl StackingContext { paint_context.draw_temporary_draw_target_if_necessary(&temporary_draw_target, &self.filters, self.blend_mode) + + } + + /// Optionally optimize and then draws the stacking context. + pub fn optimize_and_draw_into_context(&self, + paint_context: &mut PaintContext, + tile_bounds: &Rect<AzFloat>, + transform: &Matrix4, + clip_rect: Option<&Rect<Au>>) { + // TODO(gw): This is a hack to avoid running the DL optimizer + // on 3d transformed tiles. We should have a better solution + // than just disabling the opts here. + if paint_context.layer_kind == LayerKind::Layer3D { + self.draw_into_context(&self.display_list, + paint_context, + tile_bounds, + transform, + clip_rect); + + } else { + // Optimize the display list to throw out out-of-bounds display items and so forth. + let display_list = DisplayListOptimizer::new(tile_bounds).optimize(&*self.display_list); + + self.draw_into_context(&display_list, + paint_context, + tile_bounds, + transform, + clip_rect); + } } /// Translate the given tile rect into the coordinate system of a child stacking context. @@ -1005,7 +1047,7 @@ impl<'a> Iterator for DisplayItemIterator<'a> { impl DisplayItem { /// Paints this display item into the given painting context. fn draw_into_context(&self, paint_context: &mut PaintContext) { - { + if paint_context.layer_kind == LayerKind::Layer2D { let this_clip = &self.base().clip; match paint_context.transient_clip { Some(ref transient_clip) if transient_clip == this_clip => {} diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs index 2098b5c9c19..57b6b1feba2 100644 --- a/components/gfx/paint_context.rs +++ b/components/gfx/paint_context.rs @@ -29,6 +29,7 @@ use euclid::rect::Rect; use euclid::side_offsets::SideOffsets2D; use euclid::size::Size2D; use libc::types::common::c99::uint32_t; +use msg::compositor_msg::LayerKind; use net_traits::image::base::Image; use png::PixelsByColorType; use std::default::Default; @@ -54,6 +55,8 @@ pub struct PaintContext<'a> { /// clipping region used by the last display item. We cache the last value so that we avoid /// pushing and popping clipping regions unnecessarily. pub transient_clip: Option<ClippingRegion>, + /// A temporary hack to disable clipping optimizations on 3d layers. + pub layer_kind: LayerKind, } #[derive(Copy, Clone)] diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index b711b14e98e..1d02c153f78 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -21,7 +21,7 @@ use layers::platform::surface::NativeSurface; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers; use canvas_traits::CanvasMsg; -use msg::compositor_msg::{Epoch, FrameTreeId, LayerId}; +use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind}; use msg::compositor_msg::{LayerProperties, PaintListener, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; @@ -69,6 +69,7 @@ pub struct PaintRequest { pub scale: f32, pub layer_id: LayerId, pub epoch: Epoch, + pub layer_kind: LayerKind, } pub enum Msg { @@ -272,10 +273,10 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { } let mut replies = Vec::new(); - for PaintRequest { buffer_requests, scale, layer_id, epoch } + for PaintRequest { buffer_requests, scale, layer_id, epoch, layer_kind } in requests.into_iter() { if self.current_epoch == Some(epoch) { - self.paint(&mut replies, buffer_requests, scale, layer_id); + self.paint(&mut replies, buffer_requests, scale, layer_id, layer_kind); } else { debug!("painter epoch mismatch: {:?} != {:?}", self.current_epoch, epoch); } @@ -405,7 +406,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { replies: &mut Vec<(LayerId, Box<LayerBufferSet>)>, mut tiles: Vec<BufferRequest>, scale: f32, - layer_id: LayerId) { + layer_id: LayerId, + layer_kind: LayerKind) { time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || { // Bail out if there is no appropriate stacking context. let stacking_context = if let Some(ref stacking_context) = self.root_stacking_context { @@ -429,7 +431,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { tile, layer_buffer, stacking_context.clone(), - scale); + scale, + layer_kind); } let new_buffers = (0..tile_count).map(|i| { let thread_id = i % self.worker_threads.len(); @@ -450,32 +453,72 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { }; let mut properties = Vec::new(); - build(&mut properties, &**root_stacking_context, &ZERO_POINT); + build(&mut properties, + &**root_stacking_context, + &ZERO_POINT, + &Matrix4::identity(), + &Matrix4::identity(), + None); self.compositor.initialize_layers_for_pipeline(self.id, properties, self.current_epoch.unwrap()); fn build(properties: &mut Vec<LayerProperties>, stacking_context: &StackingContext, - page_position: &Point2D<Au>) { - let page_position = stacking_context.bounds.origin + *page_position; - if let Some(ref paint_layer) = stacking_context.layer { - // Layers start at the top left of their overflow rect, as far as the info we give to - // the compositor is concerned. - let overflow_relative_page_position = page_position + stacking_context.overflow.origin; - let layer_position = - Rect::new(Point2D::new(overflow_relative_page_position.x.to_nearest_px() as f32, - overflow_relative_page_position.y.to_nearest_px() as f32), - Size2D::new(stacking_context.overflow.size.width.to_nearest_px() as f32, - stacking_context.overflow.size.height.to_nearest_px() as f32)); - properties.push(LayerProperties { - id: paint_layer.id, - rect: layer_position, - background_color: paint_layer.background_color, - scroll_policy: paint_layer.scroll_policy, - }) - } + page_position: &Point2D<Au>, + transform: &Matrix4, + perspective: &Matrix4, + parent_id: Option<LayerId>) { + + let transform = transform.mul(&stacking_context.transform); + let perspective = perspective.mul(&stacking_context.perspective); + + let (next_parent_id, page_position, transform, perspective) = match stacking_context.layer { + Some(ref paint_layer) => { + // Layers start at the top left of their overflow rect, as far as the info we give to + // the compositor is concerned. + let overflow_relative_page_position = *page_position + + stacking_context.bounds.origin + + stacking_context.overflow.origin; + let layer_position = + Rect::new(Point2D::new(overflow_relative_page_position.x.to_nearest_px() as f32, + overflow_relative_page_position.y.to_nearest_px() as f32), + Size2D::new(stacking_context.overflow.size.width.to_nearest_px() as f32, + stacking_context.overflow.size.height.to_nearest_px() as f32)); + + let establishes_3d_context = stacking_context.establishes_3d_context; + + properties.push(LayerProperties { + id: paint_layer.id, + parent_id: parent_id, + rect: layer_position, + background_color: paint_layer.background_color, + scroll_policy: paint_layer.scroll_policy, + transform: transform, + perspective: perspective, + establishes_3d_context: establishes_3d_context, + }); + + // When there is a new layer, the transforms and origin + // are handled by the compositor. + (Some(paint_layer.id), + Point2D::zero(), + Matrix4::identity(), + Matrix4::identity()) + } + None => { + (parent_id, + stacking_context.bounds.origin + *page_position, + transform, + perspective) + } + }; for kid in stacking_context.display_list.children.iter() { - build(properties, &**kid, &page_position) + build(properties, + &**kid, + &page_position, + &transform, + &perspective, + next_parent_id); } } } @@ -522,8 +565,14 @@ impl WorkerThreadProxy { tile: BufferRequest, layer_buffer: Option<Box<LayerBuffer>>, stacking_context: Arc<StackingContext>, - scale: f32) { - let msg = MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale); + scale: f32, + layer_kind: LayerKind) { + let msg = MsgToWorkerThread::PaintTile(thread_id, + tile, + layer_buffer, + stacking_context, + scale, + layer_kind); self.sender.send(msg).unwrap() } @@ -568,8 +617,12 @@ impl WorkerThread { loop { match self.receiver.recv().unwrap() { MsgToWorkerThread::Exit => break, - MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale) => { - let draw_target = self.optimize_and_paint_tile(thread_id, &tile, stacking_context, scale); + MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale, layer_kind) => { + let draw_target = self.optimize_and_paint_tile(thread_id, + &tile, + stacking_context, + scale, + layer_kind); let buffer = self.create_layer_buffer_for_painted_tile(&tile, layer_buffer, draw_target, @@ -584,7 +637,8 @@ impl WorkerThread { thread_id: usize, tile: &BufferRequest, stacking_context: Arc<StackingContext>, - scale: f32) + scale: f32, + layer_kind: LayerKind) -> DrawTarget { let size = Size2D::new(tile.screen_rect.size.width as i32, tile.screen_rect.size.height as i32); let draw_target = if !opts::get().gpu_painting { @@ -612,6 +666,7 @@ impl WorkerThread { screen_rect: tile.screen_rect, clip_rect: None, transient_clip: None, + layer_kind: layer_kind, }; // Apply a translation to start at the boundaries of the stacking context, since the @@ -708,7 +763,7 @@ impl WorkerThread { enum MsgToWorkerThread { Exit, - PaintTile(usize, BufferRequest, Option<Box<LayerBuffer>>, Arc<StackingContext>, f32), + PaintTile(usize, BufferRequest, Option<Box<LayerBuffer>>, Arc<StackingContext>, f32, LayerKind), } enum MsgFromWorkerThread { |