aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCameron Zwarich <zwarich@mozilla.com>2014-07-28 20:51:39 -0700
committerCameron Zwarich <zwarich@mozilla.com>2014-07-28 20:51:39 -0700
commit1f04ce807dcfbea62524d4a33c8432fa2e6f018f (patch)
treed9871a3175ad0fc21eb6c37572a17bb6bd6f3cda /src
parent32740b3012928034dfbf964970c03d775b25fdea (diff)
parent2a612fd9c5b4b33e2728fb1ac3009742910aadef (diff)
downloadservo-1f04ce807dcfbea62524d4a33c8432fa2e6f018f.tar.gz
servo-1f04ce807dcfbea62524d4a33c8432fa2e6f018f.zip
Merge pull request #2945 from mrobinson/disentangle-scale
Untangle contents scale from rust-layers
Diffstat (limited to 'src')
-rw-r--r--src/components/compositing/compositor.rs96
-rw-r--r--src/components/compositing/compositor_data.rs71
-rw-r--r--src/components/compositing/events.rs29
m---------src/support/layers/rust-layers0
4 files changed, 123 insertions, 73 deletions
diff --git a/src/components/compositing/compositor.rs b/src/components/compositing/compositor.rs
index 8a357e059b4..11173d140f8 100644
--- a/src/components/compositing/compositor.rs
+++ b/src/components/compositing/compositor.rs
@@ -26,7 +26,7 @@ use geom::point::{Point2D, TypedPoint2D};
use geom::rect::Rect;
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
-use gfx::render_task::ReRenderMsg;
+use gfx::render_task::{RenderChan, ReRenderMsg, ReRenderRequest, UnusedBufferMsg};
use layers::layers::LayerBufferSet;
use layers::rendergl;
use layers::rendergl::RenderContext;
@@ -397,7 +397,15 @@ impl IOCompositor {
}
}
- fn create_or_update_root_layer(&mut self, layer_properties: LayerProperties) {
+ // rust-layers keeps everything in layer coordinates, so we must convert all rectangles
+ // from page coordinates into layer coordinates based on our current scale.
+ fn convert_page_rect_to_layer_coordinates(&self, page_rect: Rect<f32>) -> Rect<f32> {
+ page_rect * self.device_pixels_per_page_px().get()
+ }
+
+ fn create_or_update_root_layer(&mut self, mut layer_properties: LayerProperties) {
+ layer_properties.rect = self.convert_page_rect_to_layer_coordinates(layer_properties.rect);
+
let need_new_root_layer = !self.update_layer_if_exists(layer_properties);
if need_new_root_layer {
let root_pipeline = match self.root_pipeline {
@@ -433,7 +441,8 @@ impl IOCompositor {
self.ask_for_tiles();
}
- fn create_or_update_descendant_layer(&mut self, layer_properties: LayerProperties) {
+ fn create_or_update_descendant_layer(&mut self, mut layer_properties: LayerProperties) {
+ layer_properties.rect = self.convert_page_rect_to_layer_coordinates(layer_properties.rect);
if !self.update_layer_if_exists(layer_properties) {
self.create_descendant_layer(layer_properties);
}
@@ -483,6 +492,7 @@ impl IOCompositor {
pipeline_id: PipelineId,
layer_id: LayerId) {
let page_window = self.page_window();
+ let device_pixels_per_page_px = self.device_pixels_per_page_px();
let needs_recomposite = match self.scene.root {
Some(ref mut root_layer) => {
self.fragment_point.take().map_or(false, |fragment_point| {
@@ -490,7 +500,8 @@ impl IOCompositor {
pipeline_id,
layer_id,
fragment_point,
- page_window)
+ page_window,
+ device_pixels_per_page_px)
})
}
None => fail!("Compositor: Tried to scroll to fragment without root layer."),
@@ -502,14 +513,16 @@ impl IOCompositor {
fn set_layer_clip_rect(&mut self,
pipeline_id: PipelineId,
layer_id: LayerId,
- new_rect: Rect<f32>) {
+ new_rect_in_page_coordinates: Rect<f32>) {
+ let new_rect_in_layer_coordinates =
+ self.convert_page_rect_to_layer_coordinates(new_rect_in_page_coordinates);
let should_ask_for_tiles = match self.scene.root {
Some(ref root_layer) => {
match CompositorData::find_layer_with_pipeline_and_layer_id(root_layer.clone(),
pipeline_id,
layer_id) {
Some(ref layer) => {
- *layer.bounds.borrow_mut() = new_rect;
+ *layer.bounds.borrow_mut() = new_rect_in_layer_coordinates;
true
}
None => {
@@ -569,10 +582,16 @@ impl IOCompositor {
layer_id: LayerId,
point: Point2D<f32>) {
let page_window = self.page_window();
+ let device_pixels_per_page_px = self.device_pixels_per_page_px();
let (ask, move): (bool, bool) = match self.scene.root {
Some(ref layer) if layer.extra_data.borrow().pipeline.id == pipeline_id => {
(true,
- events::move(layer.clone(), pipeline_id, layer_id, point, page_window))
+ events::move(layer.clone(),
+ pipeline_id,
+ layer_id,
+ point,
+ page_window,
+ device_pixels_per_page_px))
}
Some(_) | None => {
self.fragment_point = Some(point);
@@ -704,12 +723,14 @@ impl IOCompositor {
let page_cursor = cursor.as_f32() / scale;
let page_window = self.page_window();
let mut scroll = false;
+ let device_pixels_per_page_px = self.device_pixels_per_page_px();
match self.scene.root {
Some(ref mut layer) => {
scroll = events::handle_scroll_event(layer.clone(),
page_delta,
page_cursor,
- page_window) || scroll;
+ page_window,
+ device_pixels_per_page_px) || scroll;
}
None => { }
}
@@ -761,12 +782,14 @@ impl IOCompositor {
let page_cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer
let page_window = self.page_window();
+ let device_pixels_per_page_px = self.device_pixels_per_page_px();
match self.scene.root {
Some(ref mut layer) => {
events::handle_scroll_event(layer.clone(),
page_delta,
page_cursor,
- page_window);
+ page_window,
+ device_pixels_per_page_px);
}
None => { }
}
@@ -786,22 +809,55 @@ impl IOCompositor {
/// Get BufferRequests from each layer.
fn ask_for_tiles(&mut self) {
let scale = self.device_pixels_per_page_px();
- let page_window = self.page_window();
let mut num_rerendermsgs_sent = 0;
+ let window_rect_in_device_pixels = Rect(Point2D(0f32, 0f32),
+ self.window_size.as_f32().to_untyped());
+
match self.scene.root {
- Some(ref layer) => {
- let rect = Rect(Point2D(0f32, 0f32), page_window.to_untyped());
- let mut request_map = HashMap::new();
- let recomposite =
- CompositorData::get_buffer_requests_recursively(&mut request_map,
- layer.clone(),
- rect,
- scale.get());
- for (_pipeline_id, (chan, requests)) in request_map.move_iter() {
+ Some(ref mut layer) => {
+ let mut layers_and_requests = Vec::new();
+ let mut unused_buffers = Vec::new();
+ CompositorData::get_buffer_requests_recursively(&mut layers_and_requests,
+ &mut unused_buffers,
+ layer.clone(),
+ window_rect_in_device_pixels);
+
+ // Return unused tiles first, so that they can be reused by any new BufferRequests.
+ let have_unused_buffers = unused_buffers.len() > 0;
+ self.recomposite = self.recomposite || have_unused_buffers;
+ if have_unused_buffers {
+ let message = UnusedBufferMsg(unused_buffers);
+ let _ = layer.extra_data.borrow().pipeline.render_chan.send_opt(message);
+ }
+
+ // We want to batch requests for each pipeline to avoid race conditions
+ // when handling the resulting BufferRequest responses.
+ let mut pipeline_requests:
+ HashMap<PipelineId, (RenderChan, Vec<ReRenderRequest>)> = HashMap::new();
+ for (layer, mut requests) in layers_and_requests.move_iter() {
+ let pipeline_id = layer.extra_data.borrow().pipeline.id;
+ let &(_, ref mut vec) = pipeline_requests.find_or_insert_with(pipeline_id, |_| {
+ (layer.extra_data.borrow().pipeline.render_chan.clone(), Vec::new())
+ });
+
+ // All the BufferRequests are in layer/device coordinates, but the render task
+ // wants to know the page coordinates. We scale them before sending them.
+ for request in requests.mut_iter() {
+ request.page_rect = request.page_rect / scale.get();
+ }
+
+ vec.push(ReRenderRequest {
+ buffer_requests: requests,
+ scale: scale.get(),
+ layer_id: layer.extra_data.borrow().id,
+ epoch: layer.extra_data.borrow().epoch,
+ });
+ }
+
+ for (_pipeline_id, (chan, requests)) in pipeline_requests.move_iter() {
num_rerendermsgs_sent += 1;
let _ = chan.send_opt(ReRenderMsg(requests));
}
- self.recomposite = self.recomposite || recomposite;
}
None => { }
}
diff --git a/src/components/compositing/compositor_data.rs b/src/components/compositing/compositor_data.rs
index 1432b1dd3d6..e08694443b9 100644
--- a/src/components/compositing/compositor_data.rs
+++ b/src/components/compositing/compositor_data.rs
@@ -9,15 +9,15 @@ use pipeline::CompositionPipeline;
use azure::azure_hl::Color;
use geom::point::TypedPoint2D;
use geom::rect::Rect;
+use geom::scale_factor::ScaleFactor;
use geom::size::{Size2D, TypedSize2D};
-use gfx::render_task::{ReRenderRequest, RenderChan, UnusedBufferMsg};
-use layers::layers::{Layer, LayerBufferSet};
+use gfx::render_task::UnusedBufferMsg;
+use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet};
use layers::platform::surface::NativeSurfaceMethods;
use servo_msg::compositor_msg::{Epoch, LayerId};
use servo_msg::compositor_msg::ScrollPolicy;
use servo_msg::constellation_msg::PipelineId;
use servo_util::geometry::PagePx;
-use std::collections::hashmap::HashMap;
use std::rc::Rc;
pub struct CompositorData {
@@ -83,40 +83,24 @@ impl CompositorData {
// Given the current window size, determine which tiles need to be (re-)rendered and sends them
// off the the appropriate renderer. Returns true if and only if the scene should be repainted.
- pub fn get_buffer_requests_recursively(requests: &mut HashMap<PipelineId,
- (RenderChan,
- Vec<ReRenderRequest>)>,
+ pub fn get_buffer_requests_recursively(requests: &mut Vec<(Rc<Layer<CompositorData>>,
+ Vec<BufferRequest>)>,
+ unused_buffers: &mut Vec<Box<LayerBuffer>>,
layer: Rc<Layer<CompositorData>>,
- window_rect: Rect<f32>,
- scale: f32)
- -> bool {
- let (request, unused) = layer.get_tile_rects_page(window_rect, scale);
- let redisplay = !unused.is_empty();
- if redisplay {
- // Send back unused tiles.
- let msg = UnusedBufferMsg(unused);
- let _ = layer.extra_data.borrow().pipeline.render_chan.send_opt(msg);
- }
+ window_rect_in_device_pixels: Rect<f32>) {
+ let (request, unused) = layer.get_tile_rects_page(window_rect_in_device_pixels);
+ unused_buffers.push_all_move(unused);
+
if !request.is_empty() {
- // Ask for tiles.
- let pipeline_id = layer.extra_data.borrow().pipeline.id;
- let msg = ReRenderRequest {
- buffer_requests: request,
- scale: scale,
- layer_id: layer.extra_data.borrow().id,
- epoch: layer.extra_data.borrow().epoch,
- };
- let &(_, ref mut vec) = requests.find_or_insert_with(pipeline_id, |_| {
- (layer.extra_data.borrow().pipeline.render_chan.clone(), Vec::new())
- });
- vec.push(msg);
+ requests.push((layer.clone(), request));
}
- let get_child_buffer_request = |kid: &Rc<Layer<CompositorData>>| -> bool {
- let mut new_rect = window_rect;
- let offset = kid.extra_data.borrow().scroll_offset.to_untyped();
- new_rect.origin.x = new_rect.origin.x - offset.x;
- new_rect.origin.y = new_rect.origin.y - offset.y;
+ for kid in layer.children().iter() {
+ let mut new_rect = window_rect_in_device_pixels;
+ let content_offset = kid.content_offset.borrow();
+ new_rect.origin.x = new_rect.origin.x - content_offset.x;
+ new_rect.origin.y = new_rect.origin.y - content_offset.y;
+
match new_rect.intersection(&*kid.bounds.borrow()) {
Some(new_rect) => {
// Child layers act as if they are rendered at (0,0), so we
@@ -125,17 +109,13 @@ impl CompositorData {
let child_rect = Rect(new_rect.origin.sub(&kid.bounds.borrow().origin),
new_rect.size);
CompositorData::get_buffer_requests_recursively(requests,
+ unused_buffers,
kid.clone(),
- child_rect,
- scale)
- }
- None => {
- false // Layer is offscreen
+ child_rect);
}
+ None => {}
}
};
-
- layer.children().iter().map(get_child_buffer_request).any(|b| b) || redisplay
}
pub fn update_layer(layer: Rc<Layer<CompositorData>>, layer_properties: LayerProperties) {
@@ -146,12 +126,15 @@ impl CompositorData {
layer.contents_changed();
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the
- // cursor position to make sure the scroll isn't propagated downwards.
+ // cursor position to make sure the scroll isn't propagated downwards. The
+ // scale factor does not matter here since we are scrolling to 0 offset and
+ // 0 * n == 0.
let size: TypedSize2D<PagePx, f32> = Size2D::from_untyped(&layer.bounds.borrow().size);
events::handle_scroll_event(layer.clone(),
- TypedPoint2D(0f32, 0f32),
- TypedPoint2D(-1f32, -1f32),
- size);
+ TypedPoint2D(0f32, 0f32),
+ TypedPoint2D(-1f32, -1f32),
+ size,
+ ScaleFactor(1.0));
}
pub fn find_layer_with_pipeline_and_layer_id(layer: Rc<Layer<CompositorData>>,
diff --git a/src/components/compositing/events.rs b/src/components/compositing/events.rs
index 5aa202d2bf0..8ded49a5477 100644
--- a/src/components/compositing/events.rs
+++ b/src/components/compositing/events.rs
@@ -10,13 +10,14 @@ use geom::length::Length;
use geom::matrix::identity;
use geom::point::{Point2D, TypedPoint2D};
use geom::rect::{Rect, TypedRect};
+use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use layers::layers::Layer;
use script::dom::event::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
use script::script_task::{ScriptChan, SendEventMsg};
use servo_msg::compositor_msg::{FixedPosition, LayerId};
use servo_msg::constellation_msg::PipelineId;
-use servo_util::geometry::PagePx;
+use servo_util::geometry::{DevicePixel, PagePx};
use std::rc::Rc;
trait Clampable {
@@ -44,7 +45,8 @@ impl Clampable for f32 {
pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
delta: TypedPoint2D<PagePx, f32>,
cursor: TypedPoint2D<PagePx, f32>,
- window_size: TypedSize2D<PagePx, f32>)
+ window_size: TypedSize2D<PagePx, f32>,
+ page_to_device_pixels_scale: ScaleFactor<PagePx, DevicePixel, f32>)
-> bool {
// If this layer doesn't want scroll events, neither it nor its children can handle scroll
// events.
@@ -60,7 +62,8 @@ pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
handle_scroll_event(child.clone(),
delta,
cursor - rect.origin,
- rect.size) {
+ rect.size,
+ page_to_device_pixels_scale) {
return true
}
}
@@ -86,13 +89,14 @@ pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
}
let offset = layer.extra_data.borrow().scroll_offset.clone();
- scroll(layer.clone(), offset)
+ scroll(layer.clone(), offset, page_to_device_pixels_scale)
}
/// Actually scrolls the descendants of a layer that scroll. This is called by
/// `handle_scroll_event` above when it determines that a layer wants to scroll.
fn scroll(layer: Rc<Layer<CompositorData>>,
- scroll_offset: TypedPoint2D<PagePx, f32>)
+ scroll_offset: TypedPoint2D<PagePx, f32>,
+ page_to_device_pixels_scale: ScaleFactor<PagePx, DevicePixel, f32>)
-> bool {
let mut result = false;
@@ -103,12 +107,13 @@ fn scroll(layer: Rc<Layer<CompositorData>>,
let scroll_offset = layer.extra_data.borrow().scroll_offset.clone();
*layer.transform.borrow_mut() = identity().translate(scroll_offset.x.get(), scroll_offset.y.get(), 0.0);
+ *layer.content_offset.borrow_mut() = (scroll_offset * page_to_device_pixels_scale).to_untyped();
result = true
}
for child in layer.children().iter() {
- result = scroll(child.clone(), scroll_offset) || result;
+ result = scroll(child.clone(), scroll_offset, page_to_device_pixels_scale) || result;
}
result
@@ -149,13 +154,19 @@ pub fn move(layer: Rc<Layer<CompositorData>>,
pipeline_id: PipelineId,
layer_id: LayerId,
origin: Point2D<f32>,
- window_size: TypedSize2D<PagePx, f32>)
+ window_size: TypedSize2D<PagePx, f32>,
+ page_to_device_pixels_scale: ScaleFactor<PagePx, DevicePixel, f32>)
-> bool {
// Search children for the right layer to move.
if layer.extra_data.borrow().pipeline.id != pipeline_id ||
layer.extra_data.borrow().id != layer_id {
return layer.children().iter().any(|kid| {
- move(kid.clone(), pipeline_id, layer_id, origin, window_size)
+ move(kid.clone(),
+ pipeline_id,
+ layer_id,
+ origin,
+ window_size,
+ page_to_device_pixels_scale)
});
}
@@ -183,5 +194,5 @@ pub fn move(layer: Rc<Layer<CompositorData>>,
}
let offset = layer.extra_data.borrow().scroll_offset.clone();
- scroll(layer.clone(), offset)
+ scroll(layer.clone(), offset, page_to_device_pixels_scale)
}
diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers
-Subproject 10e34dbdf9b9d4a437fedc412d37f13a42182e4
+Subproject 5f3dc4cc940c0f807171e26411e18ea1ee52836