mirror of
https://github.com/servo/servo.git
synced 2025-06-10 09:33:13 +00:00
Remove old rendering backend.
This removes paint threads, rust-layers dependency, and changes optional webrender types to be required. The use_webrender option has been removed, however I've left the "-w" command line option in place so that wpt runner can continue to pass that. Once it's removed from there we can also remove the -w option. Once this stage is complete, it should be fine to change the display list building code to generate webrender display lists directly and avoid the conversion step.
This commit is contained in:
parent
4af21e3ae1
commit
acfdfd2fa9
55 changed files with 422 additions and 3611 deletions
|
@ -58,8 +58,8 @@ pub struct CanvasPaintThread<'a> {
|
|||
path_builder: PathBuilder,
|
||||
state: CanvasPaintState<'a>,
|
||||
saved_states: Vec<CanvasPaintState<'a>>,
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
webrender_image_key: Option<webrender_traits::ImageKey>,
|
||||
webrender_api: webrender_traits::RenderApi,
|
||||
webrender_image_key: webrender_traits::ImageKey,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -100,12 +100,12 @@ impl<'a> CanvasPaintState<'a> {
|
|||
|
||||
impl<'a> CanvasPaintThread<'a> {
|
||||
fn new(size: Size2D<i32>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
antialias: bool) -> CanvasPaintThread<'a> {
|
||||
let draw_target = CanvasPaintThread::create(size);
|
||||
let path_builder = draw_target.create_path_builder();
|
||||
let webrender_api = webrender_api_sender.map(|wr| wr.create_api());
|
||||
let webrender_image_key = webrender_api.as_ref().map(|wr| wr.alloc_image());
|
||||
let webrender_api = webrender_api_sender.create_api();
|
||||
let webrender_image_key = webrender_api.alloc_image();
|
||||
CanvasPaintThread {
|
||||
drawtarget: draw_target,
|
||||
path_builder: path_builder,
|
||||
|
@ -119,7 +119,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
/// Creates a new `CanvasPaintThread` and returns an `IpcSender` to
|
||||
/// communicate with it.
|
||||
pub fn start(size: Size2D<i32>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
antialias: bool)
|
||||
-> IpcSender<CanvasMsg> {
|
||||
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
||||
|
@ -542,14 +542,12 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
|
||||
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
||||
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let size = self.drawtarget.get_size();
|
||||
webrender_api.update_image(self.webrender_image_key.unwrap(),
|
||||
self.webrender_api.update_image(self.webrender_image_key,
|
||||
size.width as u32,
|
||||
size.height as u32,
|
||||
webrender_traits::ImageFormat::RGBA8,
|
||||
element.into());
|
||||
}
|
||||
|
||||
let pixel_data = CanvasPixelData {
|
||||
image_data: IpcSharedMemory::from_bytes(element),
|
||||
|
@ -710,9 +708,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
|
||||
impl<'a> Drop for CanvasPaintThread<'a> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(ref mut wr) = self.webrender_api {
|
||||
wr.delete_image(self.webrender_image_key.unwrap());
|
||||
}
|
||||
self.webrender_api.delete_image(self.webrender_image_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ impl GLContextWrapper {
|
|||
|
||||
enum WebGLPaintTaskData {
|
||||
WebRender(webrender_traits::RenderApi, webrender_traits::WebGLContextId),
|
||||
Readback(GLContextWrapper, (Option<(webrender_traits::RenderApi, webrender_traits::ImageKey)>)),
|
||||
Readback(GLContextWrapper, webrender_traits::RenderApi, webrender_traits::ImageKey),
|
||||
}
|
||||
|
||||
pub struct WebGLPaintThread {
|
||||
|
@ -97,17 +97,14 @@ pub struct WebGLPaintThread {
|
|||
|
||||
fn create_readback_painter(size: Size2D<i32>,
|
||||
attrs: GLContextAttributes,
|
||||
webrender_api: Option<webrender_traits::RenderApi>)
|
||||
webrender_api: webrender_traits::RenderApi)
|
||||
-> Result<(WebGLPaintThread, GLLimits), String> {
|
||||
let context = try!(GLContextWrapper::new(size, attrs));
|
||||
let limits = context.get_limits();
|
||||
let webrender_api_and_image_key = webrender_api.map(|wr| {
|
||||
let key = wr.alloc_image();
|
||||
(wr, key)
|
||||
});
|
||||
let image_key = webrender_api.alloc_image();
|
||||
let painter = WebGLPaintThread {
|
||||
size: size,
|
||||
data: WebGLPaintTaskData::Readback(context, webrender_api_and_image_key)
|
||||
data: WebGLPaintTaskData::Readback(context, webrender_api, image_key)
|
||||
};
|
||||
|
||||
Ok((painter, limits))
|
||||
|
@ -116,10 +113,9 @@ fn create_readback_painter(size: Size2D<i32>,
|
|||
impl WebGLPaintThread {
|
||||
fn new(size: Size2D<i32>,
|
||||
attrs: GLContextAttributes,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||
webrender_api_sender: webrender_traits::RenderApiSender)
|
||||
-> Result<(WebGLPaintThread, GLLimits), String> {
|
||||
if let Some(sender) = webrender_api_sender {
|
||||
let wr_api = sender.create_api();
|
||||
let wr_api = webrender_api_sender.create_api();
|
||||
match wr_api.request_webgl_context(&size, attrs) {
|
||||
Ok((id, limits)) => {
|
||||
let painter = WebGLPaintThread {
|
||||
|
@ -130,12 +126,9 @@ impl WebGLPaintThread {
|
|||
},
|
||||
Err(msg) => {
|
||||
warn!("Initial context creation failed, falling back to readback: {}", msg);
|
||||
create_readback_painter(size, attrs, Some(wr_api))
|
||||
create_readback_painter(size, attrs, wr_api)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
create_readback_painter(size, attrs, None)
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) {
|
||||
|
@ -144,7 +137,7 @@ impl WebGLPaintThread {
|
|||
WebGLPaintTaskData::WebRender(ref api, id) => {
|
||||
api.send_webgl_command(id, message);
|
||||
}
|
||||
WebGLPaintTaskData::Readback(ref ctx, _) => {
|
||||
WebGLPaintTaskData::Readback(ref ctx, _, _) => {
|
||||
ctx.apply_command(message);
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +147,7 @@ impl WebGLPaintThread {
|
|||
/// communicate with it.
|
||||
pub fn start(size: Size2D<i32>,
|
||||
attrs: GLContextAttributes,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||
webrender_api_sender: webrender_traits::RenderApiSender)
|
||||
-> Result<(IpcSender<CanvasMsg>, GLLimits), String> {
|
||||
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
||||
let (result_chan, result_port) = channel();
|
||||
|
@ -196,7 +189,7 @@ impl WebGLPaintThread {
|
|||
|
||||
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
||||
match self.data {
|
||||
WebGLPaintTaskData::Readback(_, ref webrender_api_and_image_key) => {
|
||||
WebGLPaintTaskData::Readback(_, ref webrender_api, image_key) => {
|
||||
let width = self.size.width as usize;
|
||||
let height = self.size.height as usize;
|
||||
|
||||
|
@ -217,19 +210,17 @@ impl WebGLPaintThread {
|
|||
// rgba -> bgra
|
||||
byte_swap(&mut pixels);
|
||||
|
||||
if let Some((ref wr, wr_image_key)) = *webrender_api_and_image_key {
|
||||
// TODO: This shouldn't be a common path, but try to avoid
|
||||
// the spurious clone().
|
||||
wr.update_image(wr_image_key,
|
||||
webrender_api.update_image(image_key,
|
||||
width as u32,
|
||||
height as u32,
|
||||
webrender_traits::ImageFormat::RGBA8,
|
||||
pixels.clone());
|
||||
}
|
||||
|
||||
let pixel_data = CanvasPixelData {
|
||||
image_data: IpcSharedMemory::from_bytes(&pixels[..]),
|
||||
image_key: webrender_api_and_image_key.as_ref().map(|&(_, key)| key),
|
||||
image_key: image_key,
|
||||
};
|
||||
|
||||
chan.send(CanvasData::Pixels(pixel_data)).unwrap();
|
||||
|
@ -243,7 +234,7 @@ impl WebGLPaintThread {
|
|||
#[allow(unsafe_code)]
|
||||
fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> {
|
||||
match self.data {
|
||||
WebGLPaintTaskData::Readback(ref mut context, _) => {
|
||||
WebGLPaintTaskData::Readback(ref mut context, _, _) => {
|
||||
if size.width > self.size.width ||
|
||||
size.height > self.size.height {
|
||||
self.size = try!(context.resize(size));
|
||||
|
@ -261,7 +252,7 @@ impl WebGLPaintThread {
|
|||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
if let WebGLPaintTaskData::Readback(ref context, _) = self.data {
|
||||
if let WebGLPaintTaskData::Readback(ref context, _, _) = self.data {
|
||||
context.make_current();
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +260,7 @@ impl WebGLPaintThread {
|
|||
|
||||
impl Drop for WebGLPaintThread {
|
||||
fn drop(&mut self) {
|
||||
if let WebGLPaintTaskData::Readback(_, Some((ref mut wr, image_key))) = self.data {
|
||||
if let WebGLPaintTaskData::Readback(_, ref mut wr, image_key) = self.data {
|
||||
wr.delete_image(image_key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ pub enum CanvasData {
|
|||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct CanvasPixelData {
|
||||
pub image_data: IpcSharedMemory,
|
||||
pub image_key: Option<webrender_traits::ImageKey>,
|
||||
pub image_key: webrender_traits::ImageKey,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
|
|
|
@ -10,14 +10,11 @@ name = "compositing"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.3"
|
||||
azure = {git = "https://github.com/servo/rust-azure", features = ["plugins"]}
|
||||
euclid = "0.10.1"
|
||||
gfx_traits = {path = "../gfx_traits"}
|
||||
gleam = "0.2.8"
|
||||
image = "0.10"
|
||||
ipc-channel = "0.5"
|
||||
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
|
||||
log = "0.3.5"
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,542 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use azure::azure_hl;
|
||||
use compositor::IOCompositor;
|
||||
use euclid::point::TypedPoint2D;
|
||||
use euclid::rect::TypedRect;
|
||||
use euclid::size::TypedSize2D;
|
||||
use gfx_traits::{Epoch, LayerId, LayerProperties, ScrollPolicy};
|
||||
use layers::color::Color;
|
||||
use layers::geometry::LayerPixel;
|
||||
use layers::layers::{Layer, LayerBufferSet};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_traits::CompositorEvent;
|
||||
use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent, TouchpadPressureEvent};
|
||||
use script_traits::ConstellationControlMsg;
|
||||
use script_traits::MouseEventType;
|
||||
use script_traits::TouchpadPressurePhase;
|
||||
use std::rc::Rc;
|
||||
use windowing::{MouseWindowEvent, WindowMethods};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompositorData {
|
||||
/// This layer's pipeline id. The compositor can associate this id with an
|
||||
/// actual CompositionPipeline.
|
||||
pub pipeline_id: PipelineId,
|
||||
|
||||
/// The ID of this layer within the pipeline.
|
||||
pub id: LayerId,
|
||||
|
||||
/// The behavior of this layer when a scroll message is received.
|
||||
pub wants_scroll_events: WantsScrollEventsFlag,
|
||||
|
||||
/// Whether an ancestor layer that receives scroll events moves this layer.
|
||||
pub scroll_policy: ScrollPolicy,
|
||||
|
||||
/// The epoch that has been requested for this layer (via send_buffer_requests).
|
||||
pub requested_epoch: Epoch,
|
||||
|
||||
/// The last accepted painted buffer for this layer (via assign_pained_buffers).
|
||||
pub painted_epoch: Epoch,
|
||||
|
||||
/// The scroll offset originating from this scrolling root. This allows scrolling roots
|
||||
/// to track their current scroll position even while their content_offset does not change.
|
||||
pub scroll_offset: TypedPoint2D<f32, LayerPixel>,
|
||||
|
||||
/// The pipeline ID of this layer, if it represents a subpage.
|
||||
pub subpage_info: Option<PipelineId>,
|
||||
}
|
||||
|
||||
impl CompositorData {
|
||||
pub fn new_layer(pipeline_id: PipelineId,
|
||||
layer_properties: LayerProperties,
|
||||
wants_scroll_events: WantsScrollEventsFlag,
|
||||
tile_size: usize)
|
||||
-> Rc<Layer<CompositorData>> {
|
||||
let new_compositor_data = CompositorData {
|
||||
pipeline_id: pipeline_id,
|
||||
id: layer_properties.id,
|
||||
wants_scroll_events: wants_scroll_events,
|
||||
scroll_policy: layer_properties.scroll_policy,
|
||||
requested_epoch: Epoch(0),
|
||||
painted_epoch: Epoch(0),
|
||||
scroll_offset: TypedPoint2D::zero(),
|
||||
subpage_info: layer_properties.subpage_pipeline_id,
|
||||
};
|
||||
|
||||
Rc::new(Layer::new(TypedRect::from_untyped(&layer_properties.rect),
|
||||
tile_size,
|
||||
to_layers_color(&layer_properties.background_color),
|
||||
1.0,
|
||||
layer_properties.establishes_3d_context,
|
||||
new_compositor_data))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CompositorLayer {
|
||||
fn update_layer_except_bounds(&self, layer_properties: LayerProperties);
|
||||
|
||||
fn update_layer(&self, layer_properties: LayerProperties);
|
||||
|
||||
fn add_buffers<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
new_buffers: Box<LayerBufferSet>,
|
||||
epoch: Epoch)
|
||||
where Window: WindowMethods;
|
||||
|
||||
/// Destroys all layer tiles, sending the buffers back to the painter to be destroyed or
|
||||
/// reused.
|
||||
fn clear<Window>(&self, compositor: &mut IOCompositor<Window>) where Window: WindowMethods;
|
||||
|
||||
/// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
|
||||
/// painter to be destroyed or reused.
|
||||
fn clear_all_tiles<Window>(&self, compositor: &mut IOCompositor<Window>)
|
||||
where Window: WindowMethods;
|
||||
|
||||
/// Removes the root layer (and any children) for a given pipeline from the
|
||||
/// compositor. Buffers that the compositor is holding are returned to the
|
||||
/// owning paint thread.
|
||||
fn remove_root_layer_with_pipeline_id<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
pipeline_id: PipelineId)
|
||||
where Window: WindowMethods;
|
||||
|
||||
/// Destroys all tiles of all layers, including children, *without* sending them back to the
|
||||
/// painter. You must call this only when the paint thread is destined to be going down;
|
||||
/// otherwise, you will leak tiles.
|
||||
///
|
||||
/// This is used during shutdown, when we know the paint thread is going away.
|
||||
fn forget_all_tiles(&self);
|
||||
|
||||
/// Move the layer's descendants that don't want scroll events and scroll by a relative
|
||||
/// specified amount in page coordinates. This also takes in a cursor position to see if the
|
||||
/// mouse is over child layers first. If a layer successfully scrolled returns either
|
||||
/// ScrollPositionUnchanged or ScrollPositionChanged. If no layer was targeted by the event
|
||||
/// returns ScrollEventUnhandled.
|
||||
fn handle_scroll_event(&self,
|
||||
delta: TypedPoint2D<f32, LayerPixel>,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>)
|
||||
-> ScrollEventResult;
|
||||
|
||||
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
||||
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
||||
// client coordinates.
|
||||
fn send_mouse_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
event: MouseWindowEvent,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>)
|
||||
where Window: WindowMethods;
|
||||
|
||||
fn send_mouse_move_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>)
|
||||
where Window: WindowMethods;
|
||||
|
||||
fn send_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
event: CompositorEvent)
|
||||
where Window: WindowMethods;
|
||||
|
||||
fn send_touchpad_pressure_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>,
|
||||
pressure: f32,
|
||||
phase: TouchpadPressurePhase)
|
||||
where Window: WindowMethods;
|
||||
|
||||
fn clamp_scroll_offset_and_scroll_layer(&self,
|
||||
new_offset: TypedPoint2D<f32, LayerPixel>)
|
||||
-> ScrollEventResult;
|
||||
|
||||
fn scroll_layer_and_all_child_layers(&self,
|
||||
new_offset: TypedPoint2D<f32, LayerPixel>)
|
||||
-> bool;
|
||||
|
||||
/// Return a flag describing how this layer deals with scroll events.
|
||||
fn wants_scroll_events(&self) -> WantsScrollEventsFlag;
|
||||
|
||||
/// Return the pipeline id associated with this layer.
|
||||
fn pipeline_id(&self) -> PipelineId;
|
||||
}
|
||||
|
||||
pub trait RcCompositorLayer {
|
||||
/// Traverses the existing layer hierarchy and removes any layers that
|
||||
/// currently exist but which are no longer required.
|
||||
fn collect_old_layers<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
pipeline_id: PipelineId,
|
||||
new_layers: &[LayerProperties],
|
||||
pipelines_removed: &mut Vec<PipelineId>)
|
||||
where Window: WindowMethods;
|
||||
}
|
||||
|
||||
#[derive(Copy, PartialEq, Clone, Debug)]
|
||||
pub enum WantsScrollEventsFlag {
|
||||
WantsScrollEvents,
|
||||
DoesntWantScrollEvents,
|
||||
}
|
||||
|
||||
fn to_layers_color(color: &azure_hl::Color) -> Color {
|
||||
Color { r: color.r, g: color.g, b: color.b, a: color.a }
|
||||
}
|
||||
|
||||
trait Clampable {
|
||||
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
|
||||
}
|
||||
|
||||
impl Clampable for f32 {
|
||||
/// Returns the number constrained within the range `mn <= self <= mx`.
|
||||
/// If any of the numbers are `NAN` then `NAN` is returned.
|
||||
#[inline]
|
||||
fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
|
||||
match () {
|
||||
_ if self.is_nan() => *self,
|
||||
_ if !(*self <= *mx) => *mx,
|
||||
_ if !(*self >= *mn) => *mn,
|
||||
_ => *self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_content_size_for_layer(layer: &Layer<CompositorData>)
|
||||
-> TypedSize2D<f32, LayerPixel> {
|
||||
layer.children().iter().fold(TypedRect::zero(),
|
||||
|unioned_rect, child_rect| {
|
||||
unioned_rect.union(&*child_rect.bounds.borrow())
|
||||
}).size
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum ScrollEventResult {
|
||||
ScrollEventUnhandled,
|
||||
ScrollPositionChanged,
|
||||
ScrollPositionUnchanged,
|
||||
}
|
||||
|
||||
impl CompositorLayer for Layer<CompositorData> {
|
||||
fn update_layer_except_bounds(&self, layer_properties: LayerProperties) {
|
||||
self.extra_data.borrow_mut().scroll_policy = layer_properties.scroll_policy;
|
||||
self.extra_data.borrow_mut().subpage_info = layer_properties.subpage_pipeline_id;
|
||||
*self.transform.borrow_mut() = layer_properties.transform;
|
||||
*self.perspective.borrow_mut() = layer_properties.perspective;
|
||||
|
||||
*self.background_color.borrow_mut() = to_layers_color(&layer_properties.background_color);
|
||||
|
||||
self.contents_changed();
|
||||
}
|
||||
|
||||
fn update_layer(&self, layer_properties: LayerProperties) {
|
||||
*self.bounds.borrow_mut() = TypedRect::from_untyped(&layer_properties.rect);
|
||||
|
||||
// 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.
|
||||
self.handle_scroll_event(TypedPoint2D::zero(), TypedPoint2D::new(-1f32, -1f32));
|
||||
self.update_layer_except_bounds(layer_properties);
|
||||
}
|
||||
|
||||
// Add LayerBuffers to the specified layer. Returns the layer buffer set back if the layer that
|
||||
// matches the given pipeline ID was not found; otherwise returns None and consumes the layer
|
||||
// buffer set.
|
||||
//
|
||||
// If the epoch of the message does not match the layer's epoch, the message is ignored, the
|
||||
// layer buffer set is consumed, and None is returned.
|
||||
fn add_buffers<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
new_buffers: Box<LayerBufferSet>,
|
||||
epoch: Epoch)
|
||||
where Window: WindowMethods {
|
||||
self.extra_data.borrow_mut().painted_epoch = epoch;
|
||||
assert!(self.extra_data.borrow().painted_epoch == self.extra_data.borrow().requested_epoch);
|
||||
|
||||
for buffer in new_buffers.buffers.into_iter().rev() {
|
||||
self.add_buffer(buffer);
|
||||
}
|
||||
|
||||
compositor.cache_unused_buffers(self.collect_unused_buffers())
|
||||
}
|
||||
|
||||
fn clear<Window>(&self, compositor: &mut IOCompositor<Window>) where Window: WindowMethods {
|
||||
let buffers = self.collect_buffers();
|
||||
|
||||
if !buffers.is_empty() {
|
||||
compositor.cache_unused_buffers(buffers);
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
|
||||
/// painter to be destroyed or reused.
|
||||
fn clear_all_tiles<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>)
|
||||
where Window: WindowMethods {
|
||||
self.clear(compositor);
|
||||
for kid in &*self.children() {
|
||||
kid.clear_all_tiles(compositor);
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_root_layer_with_pipeline_id<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
pipeline_id: PipelineId)
|
||||
where Window: WindowMethods {
|
||||
// Find the child that is the root layer for this pipeline.
|
||||
let index = self.children().iter().position(|kid| {
|
||||
let extra_data = kid.extra_data.borrow();
|
||||
extra_data.pipeline_id == pipeline_id && extra_data.id == LayerId::null()
|
||||
});
|
||||
|
||||
match index {
|
||||
Some(index) => {
|
||||
// Remove the root layer, and return buffers to the paint thread
|
||||
let child = self.children().remove(index);
|
||||
child.clear_all_tiles(compositor);
|
||||
}
|
||||
None => {
|
||||
// Wasn't found, recurse into child layers
|
||||
for kid in &*self.children() {
|
||||
kid.remove_root_layer_with_pipeline_id(compositor, pipeline_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys all tiles of all layers, including children, *without* sending them back to the
|
||||
/// painter. You must call this only when the paint thread is destined to be going down;
|
||||
/// otherwise, you will leak tiles.
|
||||
///
|
||||
/// This is used during shutdown, when we know the paint thread is going away.
|
||||
fn forget_all_tiles(&self) {
|
||||
let tiles = self.collect_buffers();
|
||||
for tile in tiles {
|
||||
let mut tile = tile;
|
||||
tile.mark_wont_leak()
|
||||
}
|
||||
|
||||
for kid in &*self.children() {
|
||||
kid.forget_all_tiles();
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_scroll_event(&self,
|
||||
delta: TypedPoint2D<f32, LayerPixel>,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>)
|
||||
-> ScrollEventResult {
|
||||
// Allow children to scroll.
|
||||
let scroll_offset = self.extra_data.borrow().scroll_offset;
|
||||
let new_cursor = cursor - scroll_offset;
|
||||
for child in self.children().iter().rev() {
|
||||
let child_bounds = child.bounds.borrow();
|
||||
if child_bounds.contains(&new_cursor) {
|
||||
let result = child.handle_scroll_event(delta, new_cursor - child_bounds.origin);
|
||||
if result != ScrollEventResult::ScrollEventUnhandled {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this layer doesn't want scroll events, it can't handle scroll events.
|
||||
if self.wants_scroll_events() != WantsScrollEventsFlag::WantsScrollEvents {
|
||||
return ScrollEventResult::ScrollEventUnhandled;
|
||||
}
|
||||
|
||||
self.clamp_scroll_offset_and_scroll_layer(scroll_offset + delta)
|
||||
}
|
||||
|
||||
fn clamp_scroll_offset_and_scroll_layer(&self, new_offset: TypedPoint2D<f32, LayerPixel>)
|
||||
-> ScrollEventResult {
|
||||
let layer_size = self.bounds.borrow().size;
|
||||
let content_size = calculate_content_size_for_layer(self);
|
||||
let min_x = (layer_size.width - content_size.width).min(0.0);
|
||||
let min_y = (layer_size.height - content_size.height).min(0.0);
|
||||
let new_offset: TypedPoint2D<f32, LayerPixel> =
|
||||
TypedPoint2D::new(new_offset.x.clamp(&min_x, &0.0),
|
||||
new_offset.y.clamp(&min_y, &0.0));
|
||||
|
||||
if self.extra_data.borrow().scroll_offset == new_offset {
|
||||
return ScrollEventResult::ScrollPositionUnchanged;
|
||||
}
|
||||
|
||||
// The scroll offset is just a record of the scroll position of this scrolling root,
|
||||
// but scroll_layer_and_all_child_layers actually moves the child layers.
|
||||
self.extra_data.borrow_mut().scroll_offset = new_offset;
|
||||
|
||||
let mut result = false;
|
||||
for child in &*self.children() {
|
||||
result |= child.scroll_layer_and_all_child_layers(new_offset);
|
||||
}
|
||||
|
||||
if result {
|
||||
ScrollEventResult::ScrollPositionChanged
|
||||
} else {
|
||||
ScrollEventResult::ScrollPositionUnchanged
|
||||
}
|
||||
}
|
||||
|
||||
fn send_mouse_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
event: MouseWindowEvent,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>)
|
||||
where Window: WindowMethods {
|
||||
let event_point = cursor.to_untyped();
|
||||
let message = match event {
|
||||
MouseWindowEvent::Click(button, _) =>
|
||||
MouseButtonEvent(MouseEventType::Click, button, event_point),
|
||||
MouseWindowEvent::MouseDown(button, _) =>
|
||||
MouseButtonEvent(MouseEventType::MouseDown, button, event_point),
|
||||
MouseWindowEvent::MouseUp(button, _) =>
|
||||
MouseButtonEvent(MouseEventType::MouseUp, button, event_point),
|
||||
};
|
||||
self.send_event(compositor, message);
|
||||
}
|
||||
|
||||
fn send_mouse_move_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>)
|
||||
where Window: WindowMethods {
|
||||
self.send_event(compositor, MouseMoveEvent(Some(cursor.to_untyped())));
|
||||
}
|
||||
|
||||
fn send_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
event: CompositorEvent) where Window: WindowMethods {
|
||||
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
|
||||
let _ = pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), event));
|
||||
}
|
||||
}
|
||||
|
||||
fn send_touchpad_pressure_event<Window>(&self,
|
||||
compositor: &IOCompositor<Window>,
|
||||
cursor: TypedPoint2D<f32, LayerPixel>,
|
||||
pressure: f32,
|
||||
phase: TouchpadPressurePhase)
|
||||
where Window: WindowMethods {
|
||||
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
|
||||
let message = TouchpadPressureEvent(cursor.to_untyped(), pressure, phase);
|
||||
let _ = pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
|
||||
}
|
||||
}
|
||||
|
||||
fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<f32, LayerPixel>)
|
||||
-> bool {
|
||||
let mut result = false;
|
||||
|
||||
// Only scroll this layer if it's not fixed-positioned.
|
||||
if self.extra_data.borrow().scroll_policy != ScrollPolicy::FixedPosition {
|
||||
let new_offset = new_offset.to_untyped();
|
||||
*self.content_offset.borrow_mut() = TypedPoint2D::from_untyped(&new_offset);
|
||||
result = true
|
||||
}
|
||||
|
||||
let offset_for_children = new_offset + self.extra_data.borrow().scroll_offset;
|
||||
for child in &*self.children() {
|
||||
result |= child.scroll_layer_and_all_child_layers(offset_for_children);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn wants_scroll_events(&self) -> WantsScrollEventsFlag {
|
||||
self.extra_data.borrow().wants_scroll_events
|
||||
}
|
||||
|
||||
fn pipeline_id(&self) -> PipelineId {
|
||||
self.extra_data.borrow().pipeline_id
|
||||
}
|
||||
}
|
||||
|
||||
impl RcCompositorLayer for Rc<Layer<CompositorData>> {
|
||||
fn collect_old_layers<Window>(&self,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
pipeline_id: PipelineId,
|
||||
new_layers: &[LayerProperties],
|
||||
pipelines_removed: &mut Vec<PipelineId>)
|
||||
where Window: WindowMethods {
|
||||
fn find_root_layer_for_pipeline(layer: &Rc<Layer<CompositorData>>, pipeline_id: PipelineId)
|
||||
-> Option<Rc<Layer<CompositorData>>> {
|
||||
let extra_data = layer.extra_data.borrow();
|
||||
if extra_data.pipeline_id == pipeline_id {
|
||||
return Some((*layer).clone())
|
||||
}
|
||||
|
||||
for kid in &*layer.children() {
|
||||
if let Some(layer) = find_root_layer_for_pipeline(kid, pipeline_id) {
|
||||
return Some(layer.clone())
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn collect_old_layers_for_pipeline<Window>(
|
||||
layer: &Layer<CompositorData>,
|
||||
compositor: &mut IOCompositor<Window>,
|
||||
pipeline_id: PipelineId,
|
||||
new_layers: &[LayerProperties],
|
||||
pipelines_removed: &mut Vec<PipelineId>,
|
||||
layer_pipeline_id: Option<PipelineId>)
|
||||
where Window: WindowMethods {
|
||||
// Traverse children first so that layers are removed
|
||||
// bottom up - allowing each layer being removed to properly
|
||||
// clean up any tiles it owns.
|
||||
for kid in &*layer.children() {
|
||||
let extra_data = kid.extra_data.borrow();
|
||||
let layer_pipeline_id = extra_data.subpage_info.or(layer_pipeline_id);
|
||||
|
||||
collect_old_layers_for_pipeline(kid,
|
||||
compositor,
|
||||
pipeline_id,
|
||||
new_layers,
|
||||
pipelines_removed,
|
||||
layer_pipeline_id);
|
||||
}
|
||||
|
||||
// Retain child layers that also exist in the new layer list.
|
||||
layer.children().retain(|child| {
|
||||
let extra_data = child.extra_data.borrow();
|
||||
if pipeline_id == extra_data.pipeline_id {
|
||||
// Never remove our own root layer.
|
||||
if extra_data.id == LayerId::null() {
|
||||
return true
|
||||
}
|
||||
|
||||
// Keep this layer if it exists in the new layer list.
|
||||
if new_layers.iter().any(|properties| properties.id == extra_data.id) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(layer_pipeline_id) = layer_pipeline_id {
|
||||
for layer_properties in new_layers.iter() {
|
||||
// Keep this layer if a reference to it exists.
|
||||
if let Some(ref subpage_pipeline_id) = layer_properties.subpage_pipeline_id {
|
||||
if *subpage_pipeline_id == layer_pipeline_id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pipelines_removed.push(extra_data.pipeline_id);
|
||||
}
|
||||
|
||||
// When removing a layer, clear any tiles and surfaces associated with the layer.
|
||||
child.clear_all_tiles(compositor);
|
||||
false
|
||||
});
|
||||
}
|
||||
|
||||
// First, find the root layer with the given pipeline ID.
|
||||
let root_layer = match find_root_layer_for_pipeline(self, pipeline_id) {
|
||||
Some(root_layer) => root_layer,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Then collect all old layers underneath that layer.
|
||||
collect_old_layers_for_pipeline(&root_layer,
|
||||
compositor,
|
||||
pipeline_id,
|
||||
new_layers,
|
||||
pipelines_removed,
|
||||
None);
|
||||
}
|
||||
}
|
|
@ -8,16 +8,14 @@ use SendableFrameTree;
|
|||
use compositor::CompositingReason;
|
||||
use euclid::point::Point2D;
|
||||
use euclid::size::Size2D;
|
||||
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerProperties, PaintListener};
|
||||
use gfx_traits::LayerId;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use layers::layers::{BufferRequest, LayerBufferSet};
|
||||
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
||||
use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState, PipelineId};
|
||||
use profile_traits::mem;
|
||||
use profile_traits::time;
|
||||
use script_traits::{AnimationState, ConstellationMsg, EventResult};
|
||||
use std::fmt::{Debug, Error, Formatter};
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use style_traits::cursor::Cursor;
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use url::Url;
|
||||
|
@ -63,55 +61,6 @@ impl RenderListener for Box<CompositorProxy + 'static> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implementation of the abstract `PaintListener` interface.
|
||||
impl PaintListener for Box<CompositorProxy + 'static + Send> {
|
||||
fn native_display(&mut self) -> Option<NativeDisplay> {
|
||||
let (chan, port) = channel();
|
||||
self.send(Msg::GetNativeDisplay(chan));
|
||||
// If the compositor is shutting down when a paint thread
|
||||
// is being created, the compositor won't respond to
|
||||
// this message, resulting in an eventual panic. Instead,
|
||||
// just return None in this case, since the paint thread
|
||||
// will exit shortly and never actually be requested
|
||||
// to paint buffers by the compositor.
|
||||
port.recv().unwrap_or(None)
|
||||
}
|
||||
|
||||
fn assign_painted_buffers(&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
epoch: Epoch,
|
||||
replies: Vec<(LayerId, Box<LayerBufferSet>)>,
|
||||
frame_tree_id: FrameTreeId) {
|
||||
self.send(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id));
|
||||
}
|
||||
|
||||
fn ignore_buffer_requests(&mut self, buffer_requests: Vec<BufferRequest>) {
|
||||
let mut native_surfaces = Vec::new();
|
||||
for request in buffer_requests.into_iter() {
|
||||
if let Some(native_surface) = request.native_surface {
|
||||
native_surfaces.push(native_surface);
|
||||
}
|
||||
}
|
||||
if !native_surfaces.is_empty() {
|
||||
self.send(Msg::ReturnUnusedNativeSurfaces(native_surfaces));
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_layers_for_pipeline(&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
properties: Vec<LayerProperties>,
|
||||
epoch: Epoch) {
|
||||
// FIXME(#2004, pcwalton): This assumes that the first layer determines the page size, and
|
||||
// that all other layers are immediate children of it. This is sufficient to handle
|
||||
// `position: fixed` but will not be sufficient to handle `overflow: scroll` or transforms.
|
||||
self.send(Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties));
|
||||
}
|
||||
|
||||
fn notify_paint_thread_exiting(&mut self, pipeline_id: PipelineId) {
|
||||
self.send(Msg::PaintThreadExited(pipeline_id))
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages from the painting thread and the constellation thread to the compositor thread.
|
||||
pub enum Msg {
|
||||
/// Requests that the compositor shut down.
|
||||
|
@ -122,18 +71,8 @@ pub enum Msg {
|
|||
/// (e.g. SetFrameTree) at the time that we send it an ExitMsg.
|
||||
ShutdownComplete,
|
||||
|
||||
/// Requests the compositor's graphics metadata. Graphics metadata is what the painter needs
|
||||
/// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this
|
||||
/// is the pixel format.
|
||||
GetNativeDisplay(Sender<Option<NativeDisplay>>),
|
||||
|
||||
/// Tells the compositor to create or update the layers for a pipeline if necessary
|
||||
/// (i.e. if no layer with that ID exists).
|
||||
InitializeLayersForPipeline(PipelineId, Epoch, Vec<LayerProperties>),
|
||||
/// Scroll a page in a window
|
||||
ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool),
|
||||
/// Requests that the compositor assign the painted buffers to the given layers.
|
||||
AssignPaintedBuffers(PipelineId, Epoch, Vec<(LayerId, Box<LayerBufferSet>)>, FrameTreeId),
|
||||
/// Alerts the compositor that the current page has changed its title.
|
||||
ChangePageTitle(PipelineId, Option<String>),
|
||||
/// Alerts the compositor that the current page has changed its URL.
|
||||
|
@ -158,8 +97,6 @@ pub enum Msg {
|
|||
SetCursor(Cursor),
|
||||
/// Composite to a PNG file and return the Image over a passed channel.
|
||||
CreatePng(IpcSender<Option<Image>>),
|
||||
/// Informs the compositor that the paint thread for the given pipeline has exited.
|
||||
PaintThreadExited(PipelineId),
|
||||
/// Alerts the compositor that the viewport has been constrained in some manner
|
||||
ViewportConstrained(PipelineId, ViewportConstraints),
|
||||
/// A reply to the compositor asking if the output image is stable.
|
||||
|
@ -168,9 +105,6 @@ pub enum Msg {
|
|||
NewFavicon(Url),
|
||||
/// <head> tag finished parsing
|
||||
HeadParsed,
|
||||
/// Signal that the paint thread ignored the paint requests that carried
|
||||
/// these native surfaces, so that they can be re-added to the surface cache.
|
||||
ReturnUnusedNativeSurfaces(Vec<NativeSurface>),
|
||||
/// Collect memory reports and send them back to the given mem::ReportsChan.
|
||||
CollectMemoryReports(mem::ReportsChan),
|
||||
/// A status message to be displayed by the browser chrome.
|
||||
|
@ -181,8 +115,6 @@ pub enum Msg {
|
|||
MoveTo(Point2D<i32>),
|
||||
/// Resize the window to size
|
||||
ResizeTo(Size2D<u32>),
|
||||
/// Get scroll offset of a layer
|
||||
GetScrollOffset(PipelineId, LayerId, IpcSender<Point2D<f32>>),
|
||||
/// Pipeline visibility changed
|
||||
PipelineVisibilityChanged(PipelineId, bool),
|
||||
/// WebRender has successfully processed a scroll. The boolean specifies whether a composite is
|
||||
|
@ -201,10 +133,7 @@ impl Debug for Msg {
|
|||
match *self {
|
||||
Msg::Exit => write!(f, "Exit"),
|
||||
Msg::ShutdownComplete => write!(f, "ShutdownComplete"),
|
||||
Msg::GetNativeDisplay(..) => write!(f, "GetNativeDisplay"),
|
||||
Msg::InitializeLayersForPipeline(..) => write!(f, "InitializeLayersForPipeline"),
|
||||
Msg::ScrollFragmentPoint(..) => write!(f, "ScrollFragmentPoint"),
|
||||
Msg::AssignPaintedBuffers(..) => write!(f, "AssignPaintedBuffers"),
|
||||
Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"),
|
||||
Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
|
||||
Msg::ChangePageUrl(..) => write!(f, "ChangePageUrl"),
|
||||
|
@ -217,12 +146,10 @@ impl Debug for Msg {
|
|||
Msg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"),
|
||||
Msg::SetCursor(..) => write!(f, "SetCursor"),
|
||||
Msg::CreatePng(..) => write!(f, "CreatePng"),
|
||||
Msg::PaintThreadExited(..) => write!(f, "PaintThreadExited"),
|
||||
Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"),
|
||||
Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"),
|
||||
Msg::NewFavicon(..) => write!(f, "NewFavicon"),
|
||||
Msg::HeadParsed => write!(f, "HeadParsed"),
|
||||
Msg::ReturnUnusedNativeSurfaces(..) => write!(f, "ReturnUnusedNativeSurfaces"),
|
||||
Msg::CollectMemoryReports(..) => write!(f, "CollectMemoryReports"),
|
||||
Msg::Status(..) => write!(f, "Status"),
|
||||
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
|
||||
|
@ -230,7 +157,6 @@ impl Debug for Msg {
|
|||
Msg::ResizeTo(..) => write!(f, "ResizeTo"),
|
||||
Msg::PipelineVisibilityChanged(..) => write!(f, "PipelineVisibilityChanged"),
|
||||
Msg::PipelineExited(..) => write!(f, "PipelineExited"),
|
||||
Msg::GetScrollOffset(..) => write!(f, "GetScrollOffset"),
|
||||
Msg::NewScrollFrameReady(..) => write!(f, "NewScrollFrameReady"),
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +174,7 @@ pub struct InitialCompositorState {
|
|||
pub time_profiler_chan: time::ProfilerChan,
|
||||
/// A channel to the memory profiler thread.
|
||||
pub mem_profiler_chan: mem::ProfilerChan,
|
||||
/// Instance of webrender API if enabled
|
||||
pub webrender: Option<webrender::Renderer>,
|
||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
/// Instance of webrender API
|
||||
pub webrender: webrender::Renderer,
|
||||
pub webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
}
|
||||
|
|
|
@ -10,15 +10,11 @@
|
|||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
extern crate app_units;
|
||||
|
||||
extern crate azure;
|
||||
extern crate euclid;
|
||||
extern crate gfx_traits;
|
||||
extern crate gleam;
|
||||
extern crate image;
|
||||
extern crate ipc_channel;
|
||||
extern crate layers;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate msg;
|
||||
|
@ -39,18 +35,14 @@ extern crate webrender_traits;
|
|||
pub use compositor_thread::CompositorProxy;
|
||||
pub use compositor::IOCompositor;
|
||||
use euclid::size::TypedSize2D;
|
||||
use gfx_traits::ChromeToPaintMsg;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
|
||||
use std::sync::mpsc::Sender;
|
||||
use style_traits::PagePx;
|
||||
|
||||
mod compositor;
|
||||
mod compositor_layer;
|
||||
pub mod compositor_thread;
|
||||
mod delayed_composition;
|
||||
mod surface_map;
|
||||
mod touch;
|
||||
pub mod windowing;
|
||||
|
||||
|
@ -66,5 +58,4 @@ pub struct CompositionPipeline {
|
|||
pub id: PipelineId,
|
||||
pub script_chan: IpcSender<ConstellationControlMsg>,
|
||||
pub layout_chan: IpcSender<LayoutControlMsg>,
|
||||
pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||
}
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::size::Size2D;
|
||||
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// This is a struct used to store surfaces when they are not in use.
|
||||
/// The paint thread can quickly query for a particular size of surface when it
|
||||
/// needs it.
|
||||
pub struct SurfaceMap {
|
||||
/// A HashMap that stores the Buffers.
|
||||
map: HashMap<SurfaceKey, SurfaceValue>,
|
||||
/// The current amount of memory stored by the SurfaceMap's surfaces.
|
||||
mem: usize,
|
||||
/// The maximum allowed memory. Unused surfaces will be deleted
|
||||
/// when this threshold is exceeded.
|
||||
max_mem: usize,
|
||||
/// A monotonically increasing counter to track how recently tile sizes were used.
|
||||
counter: usize,
|
||||
}
|
||||
|
||||
/// A key with which to store surfaces. It is based on the size of the surface.
|
||||
#[derive(Eq, Copy, Clone)]
|
||||
struct SurfaceKey([i32; 2]);
|
||||
|
||||
impl Hash for SurfaceKey {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for SurfaceKey {
|
||||
fn eq(&self, other: &SurfaceKey) -> bool {
|
||||
let SurfaceKey(s) = *self;
|
||||
let SurfaceKey(o) = *other;
|
||||
s[0] == o[0] && s[1] == o[1]
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a key from a given size
|
||||
impl SurfaceKey {
|
||||
fn get(input: Size2D<i32>) -> SurfaceKey {
|
||||
SurfaceKey([input.width, input.height])
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper struct to keep track of surfaces in the HashMap
|
||||
struct SurfaceValue {
|
||||
/// An array of surfaces, all the same size
|
||||
surfaces: Vec<NativeSurface>,
|
||||
/// The counter when this size was last requested
|
||||
last_action: usize,
|
||||
}
|
||||
|
||||
impl SurfaceMap {
|
||||
// Creates a new SurfaceMap with a given surface limit.
|
||||
pub fn new(max_mem: usize) -> SurfaceMap {
|
||||
SurfaceMap {
|
||||
map: HashMap::new(),
|
||||
mem: 0,
|
||||
max_mem: max_mem,
|
||||
counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_surfaces<I>(&mut self, display: &NativeDisplay, surfaces: I)
|
||||
where I: IntoIterator<Item=NativeSurface>
|
||||
{
|
||||
for surface in surfaces {
|
||||
self.insert(display, surface);
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a new buffer into the map.
|
||||
pub fn insert(&mut self, display: &NativeDisplay, mut new_surface: NativeSurface) {
|
||||
let new_key = SurfaceKey::get(new_surface.get_size());
|
||||
|
||||
// If all our surfaces are the same size and we're already at our
|
||||
// memory limit, no need to store this new buffer; just let it drop.
|
||||
let new_total_memory_usage = self.mem + new_surface.get_memory_usage();
|
||||
if new_total_memory_usage > self.max_mem && self.map.len() == 1 &&
|
||||
self.map.contains_key(&new_key) {
|
||||
new_surface.destroy(display);
|
||||
return;
|
||||
}
|
||||
|
||||
self.mem = new_total_memory_usage;
|
||||
new_surface.mark_wont_leak();
|
||||
|
||||
// use lazy insertion function to prevent unnecessary allocation
|
||||
let counter = &self.counter;
|
||||
match self.map.entry(new_key) {
|
||||
Occupied(entry) => {
|
||||
entry.into_mut().surfaces.push(new_surface);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(SurfaceValue {
|
||||
surfaces: vec!(new_surface),
|
||||
last_action: *counter,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut opt_key: Option<SurfaceKey> = None;
|
||||
while self.mem > self.max_mem {
|
||||
let old_key = match opt_key {
|
||||
Some(key) => key,
|
||||
None => {
|
||||
match self.map.iter().min_by_key(|&(_, x)| x.last_action) {
|
||||
Some((k, _)) => *k,
|
||||
None => panic!("SurfaceMap: tried to delete with no elements in map"),
|
||||
}
|
||||
}
|
||||
};
|
||||
if {
|
||||
let list = &mut self.map.get_mut(&old_key).unwrap().surfaces;
|
||||
let mut condemned_surface = list.pop().take().unwrap();
|
||||
self.mem -= condemned_surface.get_memory_usage();
|
||||
condemned_surface.destroy(display);
|
||||
list.is_empty()
|
||||
}
|
||||
{ // then
|
||||
self.map.remove(&old_key); // Don't store empty vectors!
|
||||
opt_key = None;
|
||||
} else {
|
||||
opt_key = Some(old_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find a buffer for the given size.
|
||||
pub fn find(&mut self, size: Size2D<i32>) -> Option<NativeSurface> {
|
||||
let mut flag = false; // True if key needs to be popped after retrieval.
|
||||
let key = SurfaceKey::get(size);
|
||||
let ret = match self.map.get_mut(&key) {
|
||||
Some(ref mut surface_val) => {
|
||||
surface_val.last_action = self.counter;
|
||||
self.counter += 1;
|
||||
|
||||
let surface = surface_val.surfaces.pop().take().unwrap();
|
||||
self.mem -= surface.get_memory_usage();
|
||||
if surface_val.surfaces.is_empty() {
|
||||
flag = true;
|
||||
}
|
||||
Some(surface)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
if flag {
|
||||
self.map.remove(&key); // Don't store empty vectors!
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn mem(&self) -> usize {
|
||||
self.mem
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use euclid::point::TypedPoint2D;
|
||||
use euclid::scale_factor::ScaleFactor;
|
||||
use layers::geometry::DevicePixel;
|
||||
use gfx_traits::DevicePixel;
|
||||
use script_traits::{EventResult, TouchId};
|
||||
use self::TouchState::*;
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@ use euclid::{Point2D, Size2D};
|
|||
use euclid::point::TypedPoint2D;
|
||||
use euclid::scale_factor::ScaleFactor;
|
||||
use euclid::size::TypedSize2D;
|
||||
use layers::geometry::DevicePixel;
|
||||
use layers::platform::surface::NativeDisplay;
|
||||
use gfx_traits::DevicePixel;
|
||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
||||
use net_traits::net_error_list::NetError;
|
||||
use script_traits::{MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
|
||||
|
@ -139,9 +138,6 @@ pub trait WindowMethods {
|
|||
/// Returns the scale factor of the system (device pixels / screen pixels).
|
||||
fn scale_factor(&self) -> ScaleFactor<f32, ScreenPx, DevicePixel>;
|
||||
|
||||
/// Gets the OS native graphics display for this window.
|
||||
fn native_display(&self) -> NativeDisplay;
|
||||
|
||||
/// Creates a channel to the compositor. The dummy parameter is needed because we don't have
|
||||
/// UFCS in Rust yet.
|
||||
///
|
||||
|
|
|
@ -19,7 +19,6 @@ euclid = "0.10.1"
|
|||
gfx = {path = "../gfx"}
|
||||
gfx_traits = {path = "../gfx_traits"}
|
||||
ipc-channel = "0.5"
|
||||
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
|
||||
layout_traits = {path = "../layout_traits"}
|
||||
log = "0.3.5"
|
||||
msg = {path = "../msg"}
|
||||
|
|
|
@ -172,8 +172,8 @@ pub struct Constellation<Message, LTF, STF> {
|
|||
/// Document states for loaded pipelines (used only when writing screenshots).
|
||||
document_states: HashMap<PipelineId, DocumentState>,
|
||||
|
||||
// Webrender interface, if enabled.
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
// Webrender interface.
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
|
||||
/// Are we shutting down?
|
||||
shutting_down: bool,
|
||||
|
@ -209,8 +209,8 @@ pub struct InitialConstellationState {
|
|||
pub mem_profiler_chan: mem::ProfilerChan,
|
||||
/// Whether the constellation supports the clipboard.
|
||||
pub supports_clipboard: bool,
|
||||
/// Optional webrender API reference (if enabled).
|
||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
/// Webrender API.
|
||||
pub webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -971,9 +971,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
self.compositor_proxy.send(ToCompositorMsg::TouchEventProcessed(result))
|
||||
}
|
||||
|
||||
FromScriptMsg::GetScrollOffset(pid, lid, send) => {
|
||||
self.compositor_proxy.send(ToCompositorMsg::GetScrollOffset(pid, lid, send));
|
||||
}
|
||||
FromScriptMsg::RegisterServiceWorker(scope_things, scope) => {
|
||||
debug!("constellation got store registration scope message");
|
||||
self.handle_register_serviceworker(scope_things, scope);
|
||||
|
@ -1852,8 +1849,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
}
|
||||
|
||||
// Set paint permissions correctly for the compositor layers.
|
||||
self.revoke_paint_permission(prev_pipeline_id);
|
||||
self.send_frame_tree_and_grant_paint_permission();
|
||||
self.send_frame_tree();
|
||||
|
||||
// Update the owning iframe to point to the new pipeline id.
|
||||
// This makes things like contentDocument work correctly.
|
||||
|
@ -1910,12 +1906,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(old_pipeline_id) = frame_change.old_pipeline_id {
|
||||
// The new pipeline is replacing an old one.
|
||||
// Remove paint permissions for the pipeline being replaced.
|
||||
self.revoke_paint_permission(old_pipeline_id);
|
||||
};
|
||||
|
||||
if self.frames.contains_key(&frame_change.frame_id) {
|
||||
// Mature the new pipeline, and return frames evicted from history.
|
||||
if let Some(ref mut pipeline) = self.pipelines.get_mut(&frame_change.new_pipeline_id) {
|
||||
|
@ -1958,8 +1948,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
self.clear_joint_session_future(top_level_frame_id);
|
||||
}
|
||||
|
||||
// Build frame tree and send permission
|
||||
self.send_frame_tree_and_grant_paint_permission();
|
||||
// Build frame tree
|
||||
self.send_frame_tree();
|
||||
}
|
||||
|
||||
fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) {
|
||||
|
@ -2339,20 +2329,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
})
|
||||
}
|
||||
|
||||
// Revoke paint permission from a pipeline, and all children.
|
||||
fn revoke_paint_permission(&self, pipeline_id: PipelineId) {
|
||||
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
|
||||
for frame in self.current_frame_tree_iter(pipeline.frame_id) {
|
||||
if let Some(pipeline) = self.pipelines.get(&frame.current.pipeline_id) {
|
||||
pipeline.revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send the current frame tree to compositor, and grant paint
|
||||
// permission to each pipeline in the current frame tree.
|
||||
fn send_frame_tree_and_grant_paint_permission(&mut self) {
|
||||
// Send the current frame tree to compositor
|
||||
fn send_frame_tree(&mut self) {
|
||||
// Note that this function can panic, due to ipc-channel creation failure.
|
||||
// avoiding this panic would require a mechanism for dealing
|
||||
// with low-resource scenarios.
|
||||
|
@ -2365,10 +2343,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
return; // Our message has been discarded, probably shutting down.
|
||||
}
|
||||
}
|
||||
|
||||
for frame in self.current_frame_tree_iter(self.root_frame_id) {
|
||||
self.pipelines.get(&frame.current.pipeline_id).map(|pipeline| pipeline.grant_paint_permission());
|
||||
}
|
||||
}
|
||||
|
||||
/// For a given pipeline, determine the mozbrowser iframe that transitively contains
|
||||
|
|
|
@ -22,7 +22,6 @@ extern crate gaol;
|
|||
extern crate gfx;
|
||||
extern crate gfx_traits;
|
||||
extern crate ipc_channel;
|
||||
extern crate layers;
|
||||
extern crate layout_traits;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
|
|
@ -11,11 +11,9 @@ use euclid::size::TypedSize2D;
|
|||
#[cfg(not(target_os = "windows"))]
|
||||
use gaol;
|
||||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use gfx::paint_thread::{LayoutToPaintMsg, PaintThread};
|
||||
use gfx_traits::ChromeToPaintMsg;
|
||||
use gfx_traits::DevicePixel;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use layers::geometry::DevicePixel;
|
||||
use layout_traits::LayoutThreadFactory;
|
||||
use msg::constellation_msg::{FrameId, FrameType, LoadData, PipelineId, PipelineNamespaceId};
|
||||
use net_traits::{IpcSend, ResourceThreads};
|
||||
|
@ -31,11 +29,9 @@ use std::env;
|
|||
use std::ffi::OsStr;
|
||||
use std::io::Error as IOError;
|
||||
use std::process;
|
||||
use std::sync::mpsc::{Sender, channel};
|
||||
use std::sync::mpsc::Sender;
|
||||
use style_traits::{PagePx, ViewportPx};
|
||||
use url::Url;
|
||||
use util;
|
||||
use util::ipc::OptionalIpcSender;
|
||||
use util::opts::{self, Opts};
|
||||
use util::prefs::{PREFS, Pref};
|
||||
use webrender_traits;
|
||||
|
@ -58,7 +54,6 @@ pub struct Pipeline {
|
|||
pub layout_chan: IpcSender<LayoutControlMsg>,
|
||||
/// A channel to the compositor.
|
||||
pub compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
||||
pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||
/// URL corresponding to the most recently-loaded page.
|
||||
pub url: Url,
|
||||
/// The title of the most recently-loaded page.
|
||||
|
@ -127,8 +122,8 @@ pub struct InitialPipelineState {
|
|||
pub pipeline_namespace_id: PipelineNamespaceId,
|
||||
/// Pipeline visibility to be inherited
|
||||
pub prev_visibility: Option<bool>,
|
||||
/// Optional webrender api (if enabled).
|
||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
/// Webrender api.
|
||||
pub webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
/// Whether this pipeline is considered private.
|
||||
pub is_private: bool,
|
||||
}
|
||||
|
@ -143,8 +138,6 @@ impl Pipeline {
|
|||
{
|
||||
// Note: we allow channel creation to panic, since recovering from this
|
||||
// probably requires a general low-memory strategy.
|
||||
let (layout_to_paint_chan, layout_to_paint_port) = util::ipc::optional_ipc_channel();
|
||||
let (chrome_to_paint_chan, chrome_to_paint_port) = channel();
|
||||
let (pipeline_chan, pipeline_port) = ipc::channel()
|
||||
.expect("Pipeline main chan");;
|
||||
|
||||
|
@ -160,7 +153,6 @@ impl Pipeline {
|
|||
new_pipeline_id: state.id,
|
||||
frame_type: frame_type,
|
||||
load_data: state.load_data.clone(),
|
||||
paint_chan: layout_to_paint_chan.clone().to_opaque(),
|
||||
pipeline_port: pipeline_port,
|
||||
layout_to_constellation_chan: state.layout_to_constellation_chan.clone(),
|
||||
content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(),
|
||||
|
@ -178,16 +170,6 @@ impl Pipeline {
|
|||
}
|
||||
};
|
||||
|
||||
PaintThread::create(state.id,
|
||||
state.load_data.url.clone(),
|
||||
chrome_to_paint_chan.clone(),
|
||||
layout_to_paint_port,
|
||||
chrome_to_paint_port,
|
||||
state.compositor_proxy.clone_compositor_proxy(),
|
||||
state.font_cache_thread.clone(),
|
||||
state.time_profiler_chan.clone(),
|
||||
state.mem_profiler_chan.clone());
|
||||
|
||||
let mut child_process = None;
|
||||
if let Some((script_port, pipeline_port)) = content_ports {
|
||||
// Route messages coming from content to devtools as appropriate.
|
||||
|
@ -238,7 +220,6 @@ impl Pipeline {
|
|||
script_port: script_port,
|
||||
opts: (*opts::get()).clone(),
|
||||
prefs: PREFS.cloned(),
|
||||
layout_to_paint_chan: layout_to_paint_chan,
|
||||
pipeline_port: pipeline_port,
|
||||
pipeline_namespace_id: state.pipeline_namespace_id,
|
||||
layout_content_process_shutdown_chan: layout_content_process_shutdown_chan,
|
||||
|
@ -264,7 +245,6 @@ impl Pipeline {
|
|||
script_chan,
|
||||
pipeline_chan,
|
||||
state.compositor_proxy,
|
||||
chrome_to_paint_chan,
|
||||
state.is_private,
|
||||
state.load_data.url,
|
||||
state.window_size,
|
||||
|
@ -281,7 +261,6 @@ impl Pipeline {
|
|||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
layout_chan: IpcSender<LayoutControlMsg>,
|
||||
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
||||
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||
is_private: bool,
|
||||
url: Url,
|
||||
size: Option<TypedSize2D<f32, PagePx>>,
|
||||
|
@ -294,7 +273,6 @@ impl Pipeline {
|
|||
script_chan: script_chan,
|
||||
layout_chan: layout_chan,
|
||||
compositor_proxy: compositor_proxy,
|
||||
chrome_to_paint_chan: chrome_to_paint_chan,
|
||||
url: url,
|
||||
title: None,
|
||||
children: vec!(),
|
||||
|
@ -306,15 +284,6 @@ impl Pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn grant_paint_permission(&self) {
|
||||
let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionGranted);
|
||||
}
|
||||
|
||||
pub fn revoke_paint_permission(&self) {
|
||||
debug!("pipeline revoking paint channel paint permission");
|
||||
let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionRevoked);
|
||||
}
|
||||
|
||||
pub fn exit(&self) {
|
||||
debug!("pipeline {:?} exiting", self.id);
|
||||
|
||||
|
@ -353,9 +322,6 @@ impl Pipeline {
|
|||
if let Err(e) = self.script_chan.send(ConstellationControlMsg::ExitPipeline(self.id)) {
|
||||
warn!("Sending script exit message failed ({}).", e);
|
||||
}
|
||||
if let Err(e) = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit) {
|
||||
warn!("Sending paint exit message failed ({}).", e);
|
||||
}
|
||||
if let Err(e) = self.layout_chan.send(LayoutControlMsg::ExitNow) {
|
||||
warn!("Sending layout exit message failed ({}).", e);
|
||||
}
|
||||
|
@ -366,7 +332,6 @@ impl Pipeline {
|
|||
id: self.id.clone(),
|
||||
script_chan: self.script_chan.clone(),
|
||||
layout_chan: self.layout_chan.clone(),
|
||||
chrome_to_paint_chan: self.chrome_to_paint_chan.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,7 +395,6 @@ pub struct UnprivilegedPipelineContent {
|
|||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
load_data: LoadData,
|
||||
script_port: IpcReceiver<ConstellationControlMsg>,
|
||||
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||
opts: Opts,
|
||||
prefs: HashMap<String, Pref>,
|
||||
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||
|
@ -439,7 +403,7 @@ pub struct UnprivilegedPipelineContent {
|
|||
layout_content_process_shutdown_port: IpcReceiver<()>,
|
||||
script_content_process_shutdown_chan: IpcSender<()>,
|
||||
script_content_process_shutdown_port: IpcReceiver<()>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
}
|
||||
|
||||
impl UnprivilegedPipelineContent {
|
||||
|
@ -472,7 +436,6 @@ impl UnprivilegedPipelineContent {
|
|||
self.pipeline_port,
|
||||
self.layout_to_constellation_chan,
|
||||
self.script_chan,
|
||||
self.layout_to_paint_chan,
|
||||
self.image_cache_thread,
|
||||
self.font_cache_thread,
|
||||
self.time_profiler_chan,
|
||||
|
|
|
@ -22,7 +22,6 @@ harfbuzz-sys = "0.1"
|
|||
heapsize = "0.3.0"
|
||||
heapsize_plugin = "0.1.2"
|
||||
ipc-channel = "0.5"
|
||||
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2"
|
||||
log = "0.3.5"
|
||||
|
@ -31,8 +30,6 @@ msg = {path = "../msg"}
|
|||
net_traits = {path = "../net_traits"}
|
||||
ordered-float = "0.2.2"
|
||||
plugins = {path = "../plugins"}
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
rand = "0.3"
|
||||
range = {path = "../range"}
|
||||
rustc-serialize = "0.3"
|
||||
serde = "0.8"
|
||||
|
|
|
@ -112,7 +112,7 @@ pub struct Font {
|
|||
shaper: Option<Shaper>,
|
||||
shape_cache: RefCell<HashMap<ShapeCacheEntry, Arc<GlyphStore>>>,
|
||||
glyph_advance_cache: RefCell<HashMap<u32, FractionalPixel>>,
|
||||
pub font_key: Option<webrender_traits::FontKey>,
|
||||
pub font_key: webrender_traits::FontKey,
|
||||
}
|
||||
|
||||
impl Font {
|
||||
|
@ -121,7 +121,7 @@ impl Font {
|
|||
descriptor: FontTemplateDescriptor,
|
||||
requested_pt_size: Au,
|
||||
actual_pt_size: Au,
|
||||
font_key: Option<webrender_traits::FontKey>) -> Font {
|
||||
font_key: webrender_traits::FontKey) -> Font {
|
||||
let metrics = handle.metrics();
|
||||
Font {
|
||||
handle: handle,
|
||||
|
|
|
@ -349,16 +349,18 @@ impl FontCache {
|
|||
}
|
||||
|
||||
fn get_font_template_info(&mut self, template: Arc<FontTemplateData>) -> FontTemplateInfo {
|
||||
let mut font_key = None;
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let webrender_fonts = &mut self.webrender_fonts;
|
||||
let font_key = self.webrender_api.as_ref().map(|webrender_api| {
|
||||
*webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| {
|
||||
font_key = Some(*webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| {
|
||||
match (template.bytes_if_in_memory(), template.native_font()) {
|
||||
(Some(bytes), _) => webrender_api.add_raw_font(bytes),
|
||||
(None, Some(native_font)) => webrender_api.add_native_font(native_font),
|
||||
(None, None) => webrender_api.add_raw_font(template.bytes().clone()),
|
||||
}
|
||||
})
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
FontTemplateInfo {
|
||||
font_template: template,
|
||||
|
|
|
@ -109,7 +109,7 @@ impl FontContext {
|
|||
descriptor: FontTemplateDescriptor,
|
||||
pt_size: Au,
|
||||
variant: font_variant::T,
|
||||
font_key: Option<webrender_traits::FontKey>) -> Result<Font, ()> {
|
||||
font_key: webrender_traits::FontKey) -> Result<Font, ()> {
|
||||
// TODO: (Bug #3463): Currently we only support fake small-caps
|
||||
// painting. We should also support true small-caps (where the
|
||||
// font supports it) in the future.
|
||||
|
@ -197,7 +197,8 @@ impl FontContext {
|
|||
desc.clone(),
|
||||
style.font_size,
|
||||
style.font_variant,
|
||||
template_info.font_key);
|
||||
template_info.font_key
|
||||
.expect("No font key present!"));
|
||||
let font = match layout_font {
|
||||
Ok(layout_font) => {
|
||||
let layout_font = Rc::new(RefCell::new(layout_font));
|
||||
|
@ -242,7 +243,7 @@ impl FontContext {
|
|||
desc.clone(),
|
||||
style.font_size,
|
||||
style.font_variant,
|
||||
template_info.font_key);
|
||||
template_info.font_key.expect("No font key present!"));
|
||||
match layout_font {
|
||||
Ok(layout_font) => {
|
||||
let layout_font = Rc::new(RefCell::new(layout_font));
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(custom_derive)]
|
||||
#![feature(mpsc_select)]
|
||||
#![feature(plugin)]
|
||||
#![feature(proc_macro)]
|
||||
#![feature(range_contains)]
|
||||
|
@ -57,7 +56,6 @@ extern crate harfbuzz_sys as harfbuzz;
|
|||
|
||||
extern crate heapsize;
|
||||
extern crate ipc_channel;
|
||||
extern crate layers;
|
||||
#[allow(unused_extern_crates)]
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
@ -69,9 +67,6 @@ extern crate msg;
|
|||
extern crate net_traits;
|
||||
extern crate ordered_float;
|
||||
#[macro_use]
|
||||
extern crate profile_traits;
|
||||
extern crate rand;
|
||||
#[macro_use]
|
||||
extern crate range;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
|
@ -110,8 +105,6 @@ pub mod font_cache_thread;
|
|||
pub mod font_context;
|
||||
pub mod font_template;
|
||||
|
||||
pub mod paint_thread;
|
||||
|
||||
// Platform-specific implementations.
|
||||
#[allow(unsafe_code)]
|
||||
mod platform;
|
||||
|
|
|
@ -1,779 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! The thread that handles all painting.
|
||||
|
||||
use app_units::Au;
|
||||
use azure::AzFloat;
|
||||
use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat};
|
||||
use display_list::{DisplayItem, DisplayList, DisplayListTraversal};
|
||||
use display_list::{LayerInfo, StackingContext, StackingContextType};
|
||||
use euclid::Matrix4D;
|
||||
use euclid::point::Point2D;
|
||||
use euclid::rect::{Rect, TypedRect};
|
||||
use euclid::size::Size2D;
|
||||
use font_cache_thread::FontCacheThread;
|
||||
use font_context::FontContext;
|
||||
use gfx_traits::{ChromeToPaintMsg, Epoch, LayerId, LayerKind, LayerProperties};
|
||||
use gfx_traits::{PaintListener, PaintRequest, StackingContextId};
|
||||
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
|
||||
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use paint_context::PaintContext;
|
||||
use profile_traits::mem;
|
||||
use profile_traits::time;
|
||||
use rand::{self, Rng};
|
||||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::mem as std_mem;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use style::thread_state;
|
||||
use url::Url;
|
||||
use util::geometry::ExpandToPixelBoundaries;
|
||||
use util::opts;
|
||||
use util::thread;
|
||||
|
||||
#[derive(Clone, HeapSizeOf)]
|
||||
struct PaintLayer {
|
||||
/// The LayerProperties, which describe the layer in a way that the Compositor
|
||||
/// can consume.
|
||||
pub layer_properties: LayerProperties,
|
||||
|
||||
/// The StackingContextId of the StackingContext that is the immediate
|
||||
/// parent of this layer. This is used to ensure applying the proper transform
|
||||
/// when painting.
|
||||
pub starting_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The indices (in the DisplayList) to the first and last display item
|
||||
/// that are the contents of this layer.
|
||||
pub display_list_indices: Option<(usize, usize)>,
|
||||
|
||||
/// When painting, whether to draw the start by entering the surrounding StackingContext
|
||||
/// or simply to draw the single item this PaintLayer contains.
|
||||
pub single_item: bool,
|
||||
|
||||
/// The layer's bounds start at the overflow origin, but display items are
|
||||
/// positioned relative to the stacking context bounds, so we need to
|
||||
/// offset by the overflow rect (which will be in the coordinate system of
|
||||
/// the stacking context bounds).
|
||||
pub display_list_origin: Point2D<f32>
|
||||
}
|
||||
|
||||
impl PaintLayer {
|
||||
fn new_from_stacking_context(layer_info: &LayerInfo,
|
||||
stacking_context: &StackingContext,
|
||||
parent_origin: &Point2D<Au>,
|
||||
transform: &Matrix4D<f32>,
|
||||
perspective: &Matrix4D<f32>,
|
||||
parent_id: Option<LayerId>)
|
||||
-> PaintLayer {
|
||||
let bounds = Rect::new(stacking_context.bounds.origin + stacking_context.overflow.origin,
|
||||
stacking_context.overflow.size);
|
||||
let layer_boundaries = Rect::new(
|
||||
Point2D::new((parent_origin.x + bounds.min_x()).to_nearest_px() as f32,
|
||||
(parent_origin.y + bounds.min_y()).to_nearest_px() as f32),
|
||||
Size2D::new(bounds.size.width.to_nearest_px() as f32,
|
||||
bounds.size.height.to_nearest_px() as f32));
|
||||
|
||||
let transform = transform.pre_mul(&stacking_context.transform);
|
||||
let perspective = perspective.pre_mul(&stacking_context.perspective);
|
||||
let establishes_3d_context = stacking_context.establishes_3d_context;
|
||||
let scrolls_overflow_area = stacking_context.scrolls_overflow_area;
|
||||
|
||||
PaintLayer {
|
||||
layer_properties: LayerProperties {
|
||||
id: layer_info.layer_id,
|
||||
parent_id: parent_id,
|
||||
rect: layer_boundaries,
|
||||
background_color: layer_info.background_color,
|
||||
scroll_policy: layer_info.scroll_policy,
|
||||
transform: transform,
|
||||
perspective: perspective,
|
||||
establishes_3d_context: establishes_3d_context,
|
||||
scrolls_overflow_area: scrolls_overflow_area,
|
||||
subpage_pipeline_id: layer_info.subpage_pipeline_id,
|
||||
},
|
||||
starting_stacking_context_id: stacking_context.id,
|
||||
display_list_indices: None,
|
||||
single_item: false,
|
||||
display_list_origin: Point2D::new(stacking_context.overflow.origin.x.to_f32_px(),
|
||||
stacking_context.overflow.origin.y.to_f32_px()),
|
||||
}
|
||||
}
|
||||
|
||||
fn new_for_display_item(layer_info: &LayerInfo,
|
||||
item_bounds: &Rect<Au>,
|
||||
parent_origin: &Point2D<Au>,
|
||||
transform: &Matrix4D<f32>,
|
||||
perspective: &Matrix4D<f32>,
|
||||
parent_id: Option<LayerId>,
|
||||
stacking_context_id: StackingContextId,
|
||||
item_index: usize)
|
||||
-> PaintLayer {
|
||||
let bounds = item_bounds.expand_to_px_boundaries();
|
||||
let layer_boundaries = Rect::new(
|
||||
Point2D::new((parent_origin.x + bounds.min_x()).to_nearest_px() as f32,
|
||||
(parent_origin.y + bounds.min_y()).to_nearest_px() as f32),
|
||||
Size2D::new(bounds.size.width.to_nearest_px() as f32,
|
||||
bounds.size.height.to_nearest_px() as f32));
|
||||
|
||||
PaintLayer {
|
||||
layer_properties: LayerProperties {
|
||||
id: layer_info.layer_id,
|
||||
parent_id: parent_id,
|
||||
rect: layer_boundaries,
|
||||
background_color: layer_info.background_color,
|
||||
scroll_policy: layer_info.scroll_policy,
|
||||
transform: *transform,
|
||||
perspective: *perspective,
|
||||
establishes_3d_context: false,
|
||||
scrolls_overflow_area: false,
|
||||
subpage_pipeline_id: layer_info.subpage_pipeline_id,
|
||||
},
|
||||
starting_stacking_context_id: stacking_context_id,
|
||||
display_list_indices: Some((item_index, item_index)),
|
||||
single_item: true,
|
||||
display_list_origin: Point2D::new(bounds.origin.x.to_f32_px(),
|
||||
bounds.origin.y.to_f32_px()),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_item(&mut self, index: usize) {
|
||||
let indices = match self.display_list_indices {
|
||||
Some((first, _)) => (first, index),
|
||||
None => (index, index),
|
||||
};
|
||||
self.display_list_indices = Some(indices);
|
||||
}
|
||||
|
||||
fn make_companion_layer(&mut self) {
|
||||
self.layer_properties.id = self.layer_properties.id.companion_layer_id();
|
||||
self.display_list_indices = None;
|
||||
}
|
||||
}
|
||||
|
||||
struct LayerCreator {
|
||||
layers: Vec<PaintLayer>,
|
||||
layer_details_stack: Vec<PaintLayer>,
|
||||
current_layer: Option<PaintLayer>,
|
||||
}
|
||||
|
||||
impl LayerCreator {
|
||||
fn create_layers_with_display_list<'a>(display_list: &'a DisplayList) -> Vec<PaintLayer> {
|
||||
let mut layer_creator = LayerCreator {
|
||||
layers: Vec::new(),
|
||||
layer_details_stack: Vec::new(),
|
||||
current_layer: None,
|
||||
};
|
||||
let mut traversal = DisplayListTraversal::new(display_list);
|
||||
layer_creator.process_stacking_context_items(&mut traversal,
|
||||
&Point2D::zero(),
|
||||
&Matrix4D::identity(),
|
||||
&Matrix4D::identity());
|
||||
layer_creator.layers
|
||||
}
|
||||
|
||||
fn finalize_current_layer(&mut self) {
|
||||
if let Some(current_layer) = self.current_layer.take() {
|
||||
self.layers.push(current_layer);
|
||||
}
|
||||
}
|
||||
|
||||
fn current_parent_layer_id(&self) -> Option<LayerId> {
|
||||
self.layer_details_stack.last().as_ref().map(|layer|
|
||||
layer.layer_properties.id
|
||||
)
|
||||
}
|
||||
|
||||
fn current_parent_stacking_context_id(&self) -> StackingContextId {
|
||||
self.layer_details_stack.last().unwrap().starting_stacking_context_id
|
||||
}
|
||||
|
||||
fn create_layers_for_stacking_context<'a>(&mut self,
|
||||
stacking_context: &StackingContext,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
parent_origin: &Point2D<Au>,
|
||||
transform: &Matrix4D<f32>,
|
||||
perspective: &Matrix4D<f32>) {
|
||||
if let Some(ref layer_info) = stacking_context.layer_info {
|
||||
self.finalize_current_layer();
|
||||
let new_layer = PaintLayer::new_from_stacking_context(
|
||||
layer_info,
|
||||
stacking_context,
|
||||
parent_origin,
|
||||
transform,
|
||||
perspective,
|
||||
self.current_parent_layer_id());
|
||||
self.layer_details_stack.push(new_layer.clone());
|
||||
self.current_layer = Some(new_layer);
|
||||
|
||||
// When there is a new layer, the transforms and origin are handled by
|
||||
// the compositor, so the new transform and perspective matrices are
|
||||
// just the identity.
|
||||
//
|
||||
// The origin for child layers which might be somewhere other than the
|
||||
// layer origin, since layer boundaries are expanded to include overflow.
|
||||
self.process_stacking_context_items(traversal,
|
||||
&-stacking_context.overflow.origin,
|
||||
&Matrix4D::identity(),
|
||||
&Matrix4D::identity());
|
||||
self.finalize_current_layer();
|
||||
self.layer_details_stack.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
||||
self.process_stacking_context_items(traversal,
|
||||
&(stacking_context.bounds.origin + *parent_origin),
|
||||
&transform.pre_mul(&stacking_context.transform),
|
||||
&perspective.pre_mul(&stacking_context.perspective));
|
||||
}
|
||||
|
||||
fn process_stacking_context_items<'a>(&mut self,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
parent_origin: &Point2D<Au>,
|
||||
transform: &Matrix4D<f32>,
|
||||
perspective: &Matrix4D<f32>) {
|
||||
while let Some(item) = traversal.next() {
|
||||
match item {
|
||||
&DisplayItem::PushStackingContextClass(ref stacking_context_item) => {
|
||||
self.create_layers_for_stacking_context(&stacking_context_item.stacking_context,
|
||||
traversal,
|
||||
parent_origin,
|
||||
transform,
|
||||
perspective);
|
||||
}
|
||||
&DisplayItem::PopStackingContextClass(_) => return,
|
||||
_ => {
|
||||
self.create_layers_for_item(traversal.previous_item_id(),
|
||||
item,
|
||||
parent_origin,
|
||||
transform,
|
||||
perspective);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn create_layers_for_item<'a>(&mut self,
|
||||
current_item_index: usize,
|
||||
item: &DisplayItem,
|
||||
parent_origin: &Point2D<Au>,
|
||||
transform: &Matrix4D<f32>,
|
||||
perspective: &Matrix4D<f32>) {
|
||||
if let &DisplayItem::LayeredItemClass(ref layered_item) = item {
|
||||
// We need to finalize the last layer here before incrementing the item
|
||||
// index, otherwise this item will be placed into the parent layer.
|
||||
self.finalize_current_layer();
|
||||
let layer = PaintLayer::new_for_display_item(
|
||||
&layered_item.layer_info,
|
||||
&layered_item.item.bounds(),
|
||||
parent_origin,
|
||||
transform,
|
||||
perspective,
|
||||
self.current_parent_layer_id(),
|
||||
self.current_parent_stacking_context_id(),
|
||||
current_item_index);
|
||||
self.layers.push(layer);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have a current layer, we are an item that belonged to a
|
||||
// previous layer that was finalized by a child layer. We need to
|
||||
// resurrect a copy of the original ancestor layer to ensure that this
|
||||
// item is ordered on top of the child layers when painted.
|
||||
if self.current_layer.is_none() {
|
||||
let mut new_layer = self.layer_details_stack.pop().unwrap();
|
||||
new_layer.make_companion_layer();
|
||||
|
||||
if new_layer.layer_properties.parent_id == None {
|
||||
new_layer.layer_properties.parent_id =
|
||||
Some(new_layer.layer_properties.id.original());
|
||||
}
|
||||
|
||||
self.layer_details_stack.push(new_layer.clone());
|
||||
self.current_layer = Some(new_layer);
|
||||
}
|
||||
|
||||
if let Some(ref mut current_layer) = self.current_layer {
|
||||
current_layer.add_item(current_item_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
FromLayout(LayoutToPaintMsg),
|
||||
FromChrome(ChromeToPaintMsg),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum LayoutToPaintMsg {
|
||||
PaintInit(Epoch, Arc<DisplayList>),
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub struct PaintThread<C> {
|
||||
id: PipelineId,
|
||||
_url: Url,
|
||||
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
||||
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
||||
compositor: C,
|
||||
|
||||
/// A channel to the time profiler.
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
|
||||
/// The root paint layer sent to us by the layout thread.
|
||||
root_display_list: Option<Arc<DisplayList>>,
|
||||
|
||||
/// A map that associates LayerIds with their corresponding layers.
|
||||
layer_map: HashMap<LayerId, Arc<PaintLayer>>,
|
||||
|
||||
/// Permission to send paint messages to the compositor
|
||||
paint_permission: bool,
|
||||
|
||||
/// The current epoch counter is passed by the layout thread
|
||||
current_epoch: Option<Epoch>,
|
||||
|
||||
/// Communication handles to each of the worker threads.
|
||||
worker_threads: Vec<WorkerThreadProxy>,
|
||||
}
|
||||
|
||||
// If we implement this as a function, we get borrowck errors from borrowing
|
||||
// the whole PaintThread struct.
|
||||
macro_rules! native_display(
|
||||
($thread:expr) => (
|
||||
$thread.native_display.as_ref().expect("Need a graphics context to do painting")
|
||||
)
|
||||
);
|
||||
|
||||
impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
|
||||
pub fn create(id: PipelineId,
|
||||
url: Url,
|
||||
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
||||
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
||||
mut compositor: C,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan) {
|
||||
thread::spawn_named(format!("PaintThread {:?}", id), move || {
|
||||
thread_state::initialize(thread_state::PAINT);
|
||||
PipelineId::install(id);
|
||||
|
||||
let native_display = compositor.native_display();
|
||||
let worker_threads = WorkerThreadProxy::spawn(native_display,
|
||||
font_cache_thread,
|
||||
time_profiler_chan.clone());
|
||||
|
||||
let mut paint_thread = PaintThread {
|
||||
id: id,
|
||||
_url: url,
|
||||
layout_to_paint_port: layout_to_paint_port,
|
||||
chrome_to_paint_port: chrome_to_paint_port,
|
||||
compositor: compositor,
|
||||
time_profiler_chan: time_profiler_chan,
|
||||
root_display_list: None,
|
||||
layer_map: HashMap::new(),
|
||||
paint_permission: false,
|
||||
current_epoch: None,
|
||||
worker_threads: worker_threads,
|
||||
};
|
||||
|
||||
let reporter_name = format!("paint-reporter-{}", id);
|
||||
mem_profiler_chan.run_with_memory_reporting(|| {
|
||||
paint_thread.start();
|
||||
}, reporter_name, chrome_to_paint_chan, ChromeToPaintMsg::CollectReports);
|
||||
|
||||
// Tell all the worker threads to shut down.
|
||||
for worker_thread in &mut paint_thread.worker_threads {
|
||||
worker_thread.exit()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn start(&mut self) {
|
||||
debug!("PaintThread: beginning painting loop");
|
||||
|
||||
loop {
|
||||
let message = {
|
||||
let layout_to_paint = &self.layout_to_paint_port;
|
||||
let chrome_to_paint = &self.chrome_to_paint_port;
|
||||
select! {
|
||||
msg = layout_to_paint.recv() =>
|
||||
Msg::FromLayout(msg.expect("expected message from layout")),
|
||||
msg = chrome_to_paint.recv() =>
|
||||
Msg::FromChrome(msg.expect("expected message from chrome"))
|
||||
}
|
||||
};
|
||||
|
||||
match message {
|
||||
Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, display_list)) => {
|
||||
self.current_epoch = Some(epoch);
|
||||
self.root_display_list = Some(display_list);
|
||||
|
||||
if self.paint_permission {
|
||||
self.initialize_layers();
|
||||
}
|
||||
}
|
||||
Msg::FromChrome(ChromeToPaintMsg::Paint(requests, frame_tree_id)) => {
|
||||
if self.paint_permission && self.root_display_list.is_some() {
|
||||
let mut replies = Vec::new();
|
||||
for PaintRequest { buffer_requests, scale, layer_id, epoch, layer_kind }
|
||||
in requests {
|
||||
if self.current_epoch == Some(epoch) {
|
||||
self.paint(&mut replies, buffer_requests, scale, layer_id, layer_kind);
|
||||
} else {
|
||||
debug!("PaintThread: Ignoring requests with epoch mismatch: {:?} != {:?}",
|
||||
self.current_epoch,
|
||||
epoch);
|
||||
self.compositor.ignore_buffer_requests(buffer_requests);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("PaintThread: returning surfaces");
|
||||
self.compositor.assign_painted_buffers(self.id,
|
||||
self.current_epoch.unwrap(),
|
||||
replies,
|
||||
frame_tree_id);
|
||||
}
|
||||
}
|
||||
Msg::FromChrome(ChromeToPaintMsg::PaintPermissionGranted) => {
|
||||
self.paint_permission = true;
|
||||
|
||||
if self.root_display_list.is_some() {
|
||||
self.initialize_layers();
|
||||
}
|
||||
}
|
||||
Msg::FromChrome(ChromeToPaintMsg::PaintPermissionRevoked) => {
|
||||
self.paint_permission = false;
|
||||
}
|
||||
Msg::FromChrome(ChromeToPaintMsg::CollectReports(ref channel)) => {
|
||||
// FIXME(njn): should eventually measure the paint thread.
|
||||
channel.send(Vec::new())
|
||||
}
|
||||
Msg::FromLayout(LayoutToPaintMsg::Exit) => {
|
||||
// Ask the compositor to remove any layers it is holding for this paint thread.
|
||||
// FIXME(mrobinson): This can probably move back to the constellation now.
|
||||
debug!("PaintThread: Exiting.");
|
||||
self.compositor.notify_paint_thread_exiting(self.id);
|
||||
|
||||
break;
|
||||
}
|
||||
Msg::FromChrome(ChromeToPaintMsg::Exit) => {
|
||||
// Ask the compositor to remove any layers it is holding for this paint thread.
|
||||
// FIXME(mrobinson): This can probably move back to the constellation now.
|
||||
debug!("PaintThread: Exiting.");
|
||||
self.compositor.notify_paint_thread_exiting(self.id);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Paints one layer and places the painted tiles in `replies`.
|
||||
fn paint(&mut self,
|
||||
replies: &mut Vec<(LayerId, Box<LayerBufferSet>)>,
|
||||
mut tiles: Vec<BufferRequest>,
|
||||
scale: f32,
|
||||
layer_id: LayerId,
|
||||
layer_kind: LayerKind) {
|
||||
time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || {
|
||||
let display_list = match self.root_display_list {
|
||||
Some(ref display_list) => display_list.clone(),
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Bail out if there is no appropriate layer.
|
||||
let layer = match self.layer_map.get(&layer_id) {
|
||||
Some(layer) => layer.clone(),
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Divide up the layer into tiles and distribute them to workers via a simple round-
|
||||
// robin strategy.
|
||||
let tiles = std_mem::replace(&mut tiles, Vec::new());
|
||||
let tile_count = tiles.len();
|
||||
for (i, tile) in tiles.into_iter().enumerate() {
|
||||
let thread_id = i % self.worker_threads.len();
|
||||
self.worker_threads[thread_id].paint_tile(thread_id,
|
||||
tile,
|
||||
display_list.clone(),
|
||||
layer.clone(),
|
||||
scale,
|
||||
layer_kind);
|
||||
}
|
||||
let new_buffers = (0..tile_count).map(|i| {
|
||||
let thread_id = i % self.worker_threads.len();
|
||||
self.worker_threads[thread_id].painted_tile_buffer()
|
||||
}).collect();
|
||||
|
||||
let layer_buffer_set = box LayerBufferSet {
|
||||
buffers: new_buffers,
|
||||
};
|
||||
replies.push((layer_id, layer_buffer_set));
|
||||
})
|
||||
}
|
||||
|
||||
fn initialize_layers(&mut self) {
|
||||
let root_display_list = match self.root_display_list {
|
||||
None => return,
|
||||
Some(ref root_display_list) => root_display_list,
|
||||
};
|
||||
let layers = LayerCreator::create_layers_with_display_list(&root_display_list);
|
||||
let properties = layers.iter().map(|layer| layer.layer_properties.clone()).collect();
|
||||
self.compositor.initialize_layers_for_pipeline(self.id,
|
||||
properties,
|
||||
self.current_epoch.unwrap());
|
||||
self.layer_map.clear();
|
||||
for layer in layers.into_iter() {
|
||||
self.layer_map.insert(layer.layer_properties.id, Arc::new(layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkerThreadProxy {
|
||||
sender: Sender<MsgToWorkerThread>,
|
||||
receiver: Receiver<MsgFromWorkerThread>,
|
||||
}
|
||||
|
||||
impl WorkerThreadProxy {
|
||||
fn spawn(native_display: Option<NativeDisplay>,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan)
|
||||
-> Vec<WorkerThreadProxy> {
|
||||
// Don't make any paint threads if we're using WebRender. They're just a waste of
|
||||
// resources.
|
||||
if opts::get().use_webrender {
|
||||
return vec![]
|
||||
}
|
||||
|
||||
let thread_count = opts::get().paint_threads;
|
||||
(0..thread_count).map(|_| {
|
||||
let (from_worker_sender, from_worker_receiver) = channel();
|
||||
let (to_worker_sender, to_worker_receiver) = channel();
|
||||
let font_cache_thread = font_cache_thread.clone();
|
||||
let time_profiler_chan = time_profiler_chan.clone();
|
||||
thread::spawn_named("PaintWorker".to_owned(), move || {
|
||||
let mut worker_thread = WorkerThread::new(from_worker_sender,
|
||||
to_worker_receiver,
|
||||
native_display,
|
||||
font_cache_thread,
|
||||
time_profiler_chan);
|
||||
worker_thread.main();
|
||||
});
|
||||
WorkerThreadProxy {
|
||||
receiver: from_worker_receiver,
|
||||
sender: to_worker_sender,
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn paint_tile(&mut self,
|
||||
thread_id: usize,
|
||||
tile: BufferRequest,
|
||||
display_list: Arc<DisplayList>,
|
||||
paint_layer: Arc<PaintLayer>,
|
||||
scale: f32,
|
||||
layer_kind: LayerKind) {
|
||||
let msg = MsgToWorkerThread::PaintTile(thread_id,
|
||||
tile,
|
||||
display_list,
|
||||
paint_layer,
|
||||
scale,
|
||||
layer_kind);
|
||||
self.sender.send(msg).unwrap()
|
||||
}
|
||||
|
||||
fn painted_tile_buffer(&mut self) -> Box<LayerBuffer> {
|
||||
match self.receiver.recv().unwrap() {
|
||||
MsgFromWorkerThread::PaintedTile(layer_buffer) => layer_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
fn exit(&mut self) {
|
||||
self.sender.send(MsgToWorkerThread::Exit).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkerThread {
|
||||
sender: Sender<MsgFromWorkerThread>,
|
||||
receiver: Receiver<MsgToWorkerThread>,
|
||||
native_display: Option<NativeDisplay>,
|
||||
font_context: Box<FontContext>,
|
||||
time_profiler_sender: time::ProfilerChan,
|
||||
}
|
||||
|
||||
impl WorkerThread {
|
||||
fn new(sender: Sender<MsgFromWorkerThread>,
|
||||
receiver: Receiver<MsgToWorkerThread>,
|
||||
native_display: Option<NativeDisplay>,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_sender: time::ProfilerChan)
|
||||
-> WorkerThread {
|
||||
WorkerThread {
|
||||
sender: sender,
|
||||
receiver: receiver,
|
||||
native_display: native_display,
|
||||
font_context: box FontContext::new(font_cache_thread.clone()),
|
||||
time_profiler_sender: time_profiler_sender,
|
||||
}
|
||||
}
|
||||
|
||||
fn main(&mut self) {
|
||||
loop {
|
||||
match self.receiver.recv().unwrap() {
|
||||
MsgToWorkerThread::Exit => break,
|
||||
MsgToWorkerThread::PaintTile(thread_id,
|
||||
tile,
|
||||
display_list,
|
||||
paint_layer,
|
||||
scale,
|
||||
layer_kind) => {
|
||||
let buffer = self.optimize_and_paint_tile(thread_id,
|
||||
tile,
|
||||
display_list,
|
||||
paint_layer,
|
||||
scale,
|
||||
layer_kind);
|
||||
self.sender.send(MsgFromWorkerThread::PaintedTile(buffer)).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn optimize_and_paint_tile(&mut self,
|
||||
thread_id: usize,
|
||||
mut tile: BufferRequest,
|
||||
display_list: Arc<DisplayList>,
|
||||
paint_layer: Arc<PaintLayer>,
|
||||
scale: f32,
|
||||
layer_kind: LayerKind)
|
||||
-> Box<LayerBuffer> {
|
||||
let size = Size2D::new(tile.screen_rect.size.width as i32,
|
||||
tile.screen_rect.size.height as i32);
|
||||
let mut buffer = self.create_layer_buffer(&mut tile, scale);
|
||||
let draw_target = DrawTarget::new(BackendType::Skia, size, SurfaceFormat::B8G8R8A8);
|
||||
|
||||
{
|
||||
// Build the paint context.
|
||||
let mut paint_context = PaintContext {
|
||||
draw_target: draw_target.clone(),
|
||||
font_context: &mut self.font_context,
|
||||
page_rect: TypedRect::from_untyped(&tile.page_rect.translate(&paint_layer.display_list_origin)),
|
||||
screen_rect: TypedRect::from_untyped(&tile.screen_rect),
|
||||
clip_rect: None,
|
||||
transient_clip: None,
|
||||
layer_kind: layer_kind,
|
||||
subpixel_offset: Point2D::zero(),
|
||||
};
|
||||
|
||||
// Apply the translation to paint the tile we want.
|
||||
let matrix = Matrix4D::identity();
|
||||
let matrix = matrix.pre_scaled(scale as AzFloat, scale as AzFloat, 1.0);
|
||||
let tile_bounds = tile.page_rect.translate(&paint_layer.display_list_origin);
|
||||
let matrix = matrix.pre_translated(-tile_bounds.origin.x as AzFloat,
|
||||
-tile_bounds.origin.y as AzFloat,
|
||||
0.0);
|
||||
|
||||
// Clear the buffer.
|
||||
paint_context.clear();
|
||||
|
||||
// Draw the display list.
|
||||
time::profile(time::ProfilerCategory::PaintingPerTile,
|
||||
None,
|
||||
self.time_profiler_sender.clone(), || {
|
||||
if let Some((start, end)) = paint_layer.display_list_indices {
|
||||
if paint_layer.single_item {
|
||||
display_list.draw_item_at_index_into_context(
|
||||
&mut paint_context, &matrix, start);
|
||||
} else {
|
||||
display_list.draw_into_context(
|
||||
&mut paint_context,
|
||||
&matrix,
|
||||
paint_layer.starting_stacking_context_id,
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
paint_context.draw_target.flush();
|
||||
});
|
||||
|
||||
if opts::get().show_debug_parallel_paint {
|
||||
// Overlay a transparent solid color to identify the thread that
|
||||
// painted this tile.
|
||||
let color = THREAD_TINT_COLORS[thread_id % THREAD_TINT_COLORS.len()];
|
||||
paint_context.draw_solid_color(&Rect::new(Point2D::new(Au(0), Au(0)),
|
||||
Size2D::new(Au::from_px(size.width),
|
||||
Au::from_px(size.height))),
|
||||
color);
|
||||
}
|
||||
if opts::get().paint_flashing {
|
||||
// Overlay a random transparent color.
|
||||
let color = *rand::thread_rng().choose(&THREAD_TINT_COLORS[..]).unwrap();
|
||||
paint_context.draw_solid_color(&Rect::new(Point2D::new(Au(0), Au(0)),
|
||||
Size2D::new(Au::from_px(size.width),
|
||||
Au::from_px(size.height))),
|
||||
color);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the texture from the draw target and place it into its slot in the buffer.
|
||||
// Upload it first.
|
||||
draw_target.snapshot().get_data_surface().with_data(|data| {
|
||||
buffer.native_surface.upload(native_display!(self), data);
|
||||
debug!("painting worker thread uploading to native surface {}",
|
||||
buffer.native_surface.get_id());
|
||||
});
|
||||
|
||||
draw_target.finish();
|
||||
buffer
|
||||
}
|
||||
|
||||
fn create_layer_buffer(&mut self,
|
||||
tile: &mut BufferRequest,
|
||||
scale: f32)
|
||||
-> Box<LayerBuffer> {
|
||||
// Create an empty native surface. We mark it as not leaking
|
||||
// in case it dies in transit to the compositor thread.
|
||||
let width = tile.screen_rect.size.width;
|
||||
let height = tile.screen_rect.size.height;
|
||||
let mut native_surface = tile.native_surface.take().unwrap_or_else(|| {
|
||||
NativeSurface::new(native_display!(self), Size2D::new(width as i32, height as i32))
|
||||
});
|
||||
native_surface.mark_wont_leak();
|
||||
|
||||
box LayerBuffer {
|
||||
native_surface: native_surface,
|
||||
rect: tile.page_rect,
|
||||
screen_pos: tile.screen_rect,
|
||||
resolution: scale,
|
||||
painted_with_cpu: true,
|
||||
content_age: tile.content_age,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum MsgToWorkerThread {
|
||||
Exit,
|
||||
PaintTile(usize, BufferRequest, Arc<DisplayList>, Arc<PaintLayer>, f32, LayerKind),
|
||||
}
|
||||
|
||||
enum MsgFromWorkerThread {
|
||||
PaintedTile(Box<LayerBuffer>),
|
||||
}
|
||||
|
||||
pub static THREAD_TINT_COLORS: [Color; 8] = [
|
||||
Color { r: 6.0 / 255.0, g: 153.0 / 255.0, b: 198.0 / 255.0, a: 0.7 },
|
||||
Color { r: 255.0 / 255.0, g: 212.0 / 255.0, b: 83.0 / 255.0, a: 0.7 },
|
||||
Color { r: 116.0 / 255.0, g: 29.0 / 255.0, b: 109.0 / 255.0, a: 0.7 },
|
||||
Color { r: 204.0 / 255.0, g: 158.0 / 255.0, b: 199.0 / 255.0, a: 0.7 },
|
||||
Color { r: 242.0 / 255.0, g: 46.0 / 255.0, b: 121.0 / 255.0, a: 0.7 },
|
||||
Color { r: 116.0 / 255.0, g: 203.0 / 255.0, b: 196.0 / 255.0, a: 0.7 },
|
||||
Color { r: 255.0 / 255.0, g: 249.0 / 255.0, b: 201.0 / 255.0, a: 0.7 },
|
||||
Color { r: 137.0 / 255.0, g: 196.0 / 255.0, b: 78.0 / 255.0, a: 0.7 },
|
||||
];
|
|
@ -29,7 +29,7 @@ pub struct TextRun {
|
|||
pub font_template: Arc<FontTemplateData>,
|
||||
pub actual_pt_size: Au,
|
||||
pub font_metrics: FontMetrics,
|
||||
pub font_key: Option<webrender_traits::FontKey>,
|
||||
pub font_key: webrender_traits::FontKey,
|
||||
/// The glyph runs that make up this text run.
|
||||
pub glyphs: Arc<Vec<GlyphRun>>,
|
||||
pub bidi_level: u8,
|
||||
|
|
|
@ -11,13 +11,9 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
azure = {git = "https://github.com/servo/rust-azure", features = ["plugins"]}
|
||||
euclid = "0.10.1"
|
||||
heapsize = "0.3.0"
|
||||
heapsize_plugin = "0.1.2"
|
||||
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
|
||||
msg = {path = "../msg"}
|
||||
plugins = {path = "../plugins"}
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
range = {path = "../range"}
|
||||
rustc-serialize = "0.3"
|
||||
serde = "0.8"
|
||||
|
|
|
@ -11,11 +11,7 @@
|
|||
#![deny(unsafe_code)]
|
||||
|
||||
extern crate azure;
|
||||
extern crate euclid;
|
||||
extern crate heapsize;
|
||||
extern crate layers;
|
||||
extern crate msg;
|
||||
extern crate profile_traits;
|
||||
#[macro_use]
|
||||
extern crate range;
|
||||
extern crate rustc_serialize;
|
||||
|
@ -24,16 +20,8 @@ extern crate serde;
|
|||
extern crate serde_derive;
|
||||
|
||||
pub mod color;
|
||||
mod paint_listener;
|
||||
pub mod print_tree;
|
||||
|
||||
pub use paint_listener::PaintListener;
|
||||
use azure::azure_hl::Color;
|
||||
use euclid::Matrix4D;
|
||||
use euclid::rect::Rect;
|
||||
use layers::layers::BufferRequest;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use profile_traits::mem::ReportsChan;
|
||||
use range::RangeIndex;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
||||
|
@ -50,6 +38,20 @@ static NEXT_SPECIAL_STACKING_CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
|||
/// Note that we assume that the top 16 bits of the address space are unused on the platform.
|
||||
const SPECIAL_STACKING_CONTEXT_ID_MASK: usize = 0xffff;
|
||||
|
||||
// Units for use with euclid::length and euclid::scale_factor.
|
||||
|
||||
/// One hardware pixel.
|
||||
///
|
||||
/// This unit corresponds to the smallest addressable element of the display hardware.
|
||||
#[derive(Copy, Clone, RustcEncodable, Debug)]
|
||||
pub enum DevicePixel {}
|
||||
|
||||
/// One pixel in layer coordinate space.
|
||||
///
|
||||
/// This unit corresponds to a "pixel" in layer coordinate space, which after scaling and
|
||||
/// transformation becomes a device pixel.
|
||||
#[derive(Copy, Clone, RustcEncodable, Debug)]
|
||||
pub enum LayerPixel {}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum LayerKind {
|
||||
|
@ -128,33 +130,6 @@ impl LayerId {
|
|||
}
|
||||
}
|
||||
|
||||
/// All layer-specific information that the painting task sends to the compositor other than the
|
||||
/// buffer contents of the layer itself.
|
||||
#[derive(Copy, Clone, HeapSizeOf)]
|
||||
pub struct LayerProperties {
|
||||
/// An opaque ID. This is usually the address of the flow and index of the box within it.
|
||||
pub id: LayerId,
|
||||
/// The id of the parent layer.
|
||||
pub parent_id: Option<LayerId>,
|
||||
/// The position and size of the layer in pixels.
|
||||
pub rect: Rect<f32>,
|
||||
/// The background color of the layer.
|
||||
pub background_color: Color,
|
||||
/// The scrolling policy of this layer.
|
||||
pub scroll_policy: ScrollPolicy,
|
||||
/// The transform for this layer
|
||||
pub transform: Matrix4D<f32>,
|
||||
/// The perspective transform for this layer
|
||||
pub perspective: Matrix4D<f32>,
|
||||
/// The subpage that this layer represents. If this is `Some`, this layer represents an
|
||||
/// iframe.
|
||||
pub subpage_pipeline_id: Option<PipelineId>,
|
||||
/// Whether this layer establishes a new 3d rendering context.
|
||||
pub establishes_3d_context: bool,
|
||||
/// Whether this layer scrolls its overflow area.
|
||||
pub scrolls_overflow_area: bool,
|
||||
}
|
||||
|
||||
/// A newtype struct for denoting the age of messages; prevents race conditions.
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
pub struct Epoch(pub u32);
|
||||
|
@ -272,19 +247,3 @@ int_range_index! {
|
|||
#[derive(HeapSizeOf)]
|
||||
struct ByteIndex(isize)
|
||||
}
|
||||
|
||||
pub struct PaintRequest {
|
||||
pub buffer_requests: Vec<BufferRequest>,
|
||||
pub scale: f32,
|
||||
pub layer_id: LayerId,
|
||||
pub epoch: Epoch,
|
||||
pub layer_kind: LayerKind,
|
||||
}
|
||||
|
||||
pub enum ChromeToPaintMsg {
|
||||
Paint(Vec<PaintRequest>, FrameTreeId),
|
||||
PaintPermissionGranted,
|
||||
PaintPermissionRevoked,
|
||||
CollectReports(ReportsChan),
|
||||
Exit,
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use Epoch;
|
||||
use FrameTreeId;
|
||||
use LayerId;
|
||||
use LayerProperties;
|
||||
use layers::layers::{BufferRequest, LayerBufferSet};
|
||||
use layers::platform::surface::NativeDisplay;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
|
||||
/// The interface used by the painter to acquire draw targets for each paint frame and
|
||||
/// submit them to be drawn to the display.
|
||||
pub trait PaintListener {
|
||||
fn native_display(&mut self) -> Option<NativeDisplay>;
|
||||
|
||||
/// Informs the compositor of the layers for the given pipeline. The compositor responds by
|
||||
/// creating and/or destroying paint layers as necessary.
|
||||
fn initialize_layers_for_pipeline(&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
properties: Vec<LayerProperties>,
|
||||
epoch: Epoch);
|
||||
|
||||
/// Sends new buffers for the given layers to the compositor.
|
||||
fn assign_painted_buffers(&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
epoch: Epoch,
|
||||
replies: Vec<(LayerId, Box<LayerBufferSet>)>,
|
||||
frame_tree_id: FrameTreeId);
|
||||
|
||||
/// Inform the compositor that these buffer requests will be ignored.
|
||||
fn ignore_buffer_requests(&mut self, buffer_requests: Vec<BufferRequest>);
|
||||
|
||||
// Notification that the paint task wants to exit.
|
||||
fn notify_paint_thread_exiting(&mut self, pipeline_id: PipelineId);
|
||||
}
|
|
@ -31,7 +31,7 @@ use app_units::{Au, MAX_AU};
|
|||
use context::{LayoutContext, SharedLayoutContext};
|
||||
use display_list_builder::{BorderPaintingMode, DisplayListBuildState, FragmentDisplayListBuilding};
|
||||
use display_list_builder::BlockFlowDisplayListBuilding;
|
||||
use euclid::{Point2D, Rect, Size2D};
|
||||
use euclid::{Point2D, Size2D};
|
||||
use floats::{ClearType, FloatKind, Floats, PlacementInfo};
|
||||
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
|
||||
use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT};
|
||||
|
@ -64,10 +64,6 @@ use style::properties::ServoComputedValues;
|
|||
use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone};
|
||||
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use util::clamp;
|
||||
use util::geometry::max_rect;
|
||||
|
||||
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
||||
const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
|
||||
|
||||
/// Information specific to floated blocks.
|
||||
#[derive(Clone, RustcEncodable)]
|
||||
|
@ -1959,7 +1955,7 @@ impl Flow for BlockFlow {
|
|||
}
|
||||
}
|
||||
|
||||
fn compute_absolute_position(&mut self, layout_context: &SharedLayoutContext) {
|
||||
fn compute_absolute_position(&mut self, _layout_context: &SharedLayoutContext) {
|
||||
if self.base.flags.contains(NEEDS_LAYER) {
|
||||
self.fragment.flags.insert(HAS_LAYER)
|
||||
}
|
||||
|
@ -1970,7 +1966,6 @@ impl Flow for BlockFlow {
|
|||
|
||||
if self.is_root() {
|
||||
self.base.clip = ClippingRegion::max();
|
||||
self.base.stacking_relative_position_of_display_port = max_rect();
|
||||
}
|
||||
|
||||
let transform_style = self.fragment.style().get_used_transform_style();
|
||||
|
@ -1983,7 +1978,6 @@ impl Flow for BlockFlow {
|
|||
(overflow_x::T::auto, _) | (overflow_x::T::scroll, _) |
|
||||
(_, overflow_x::T::auto) | (_, overflow_x::T::scroll) => {
|
||||
self.base.clip = ClippingRegion::max();
|
||||
self.base.stacking_relative_position_of_display_port = max_rect();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -2085,25 +2079,6 @@ impl Flow for BlockFlow {
|
|||
self.base.stacking_relative_position + relative_offset
|
||||
};
|
||||
|
||||
let stacking_relative_position_of_display_port_for_children =
|
||||
if is_stacking_context || self.is_root() {
|
||||
let visible_rect =
|
||||
match layout_context.visible_rects.get(&self.layer_id()) {
|
||||
Some(visible_rect) => *visible_rect,
|
||||
None => Rect::new(Point2D::zero(), layout_context.style_context.viewport_size),
|
||||
};
|
||||
|
||||
let viewport_size = layout_context.style_context.viewport_size;
|
||||
visible_rect.inflate(viewport_size.width * DISPLAY_PORT_SIZE_FACTOR,
|
||||
viewport_size.height * DISPLAY_PORT_SIZE_FACTOR)
|
||||
} else if is_stacking_context {
|
||||
self.base
|
||||
.stacking_relative_position_of_display_port
|
||||
.translate(&-self.base.stacking_relative_position)
|
||||
} else {
|
||||
self.base.stacking_relative_position_of_display_port
|
||||
};
|
||||
|
||||
let stacking_relative_border_box =
|
||||
self.fragment
|
||||
.stacking_relative_border_box(&self.base.stacking_relative_position,
|
||||
|
@ -2168,8 +2143,6 @@ impl Flow for BlockFlow {
|
|||
|
||||
flow::mut_base(kid).late_absolute_position_info =
|
||||
late_absolute_position_info_for_children;
|
||||
flow::mut_base(kid).stacking_relative_position_of_display_port =
|
||||
stacking_relative_position_of_display_port_for_children;
|
||||
|
||||
// This clipping region is in our coordinate system. The child will fix it up to be in
|
||||
// its own coordinate system by itself if necessary.
|
||||
|
|
|
@ -15,7 +15,7 @@ use gfx::font_cache_thread::FontCacheThread;
|
|||
use gfx::font_context::FontContext;
|
||||
use gfx_traits::LayerId;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||
use ipc_channel::ipc;
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread, ImageResponse, ImageState};
|
||||
use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
|
@ -196,36 +196,27 @@ impl SharedLayoutContext {
|
|||
|
||||
pub fn get_webrender_image_for_url(&self,
|
||||
url: &Url,
|
||||
use_placeholder: UsePlaceholder,
|
||||
fetch_image_data_as_well: bool)
|
||||
-> Option<(WebRenderImageInfo, Option<IpcSharedMemory>)> {
|
||||
if !fetch_image_data_as_well {
|
||||
let webrender_image_cache = self.webrender_image_cache.read().unwrap();
|
||||
if let Some(existing_webrender_image) =
|
||||
webrender_image_cache.get(&((*url).clone(), use_placeholder)) {
|
||||
return Some(((*existing_webrender_image).clone(), None))
|
||||
}
|
||||
use_placeholder: UsePlaceholder)
|
||||
-> Option<WebRenderImageInfo> {
|
||||
if let Some(existing_webrender_image) = self.webrender_image_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&((*url).clone(), use_placeholder)) {
|
||||
return Some((*existing_webrender_image).clone())
|
||||
}
|
||||
|
||||
match self.get_or_request_image_or_meta((*url).clone(), use_placeholder) {
|
||||
Some(ImageOrMetadataAvailable::ImageAvailable(image)) => {
|
||||
let image_info = WebRenderImageInfo::from_image(&*image);
|
||||
if image_info.key.is_none() {
|
||||
let bytes = if !fetch_image_data_as_well {
|
||||
None
|
||||
Some(image_info)
|
||||
} else {
|
||||
Some(image.bytes.clone())
|
||||
};
|
||||
Some((image_info, bytes))
|
||||
} else if !fetch_image_data_as_well {
|
||||
let mut webrender_image_cache = self.webrender_image_cache
|
||||
.write()
|
||||
.unwrap();
|
||||
webrender_image_cache.insert(((*url).clone(), use_placeholder),
|
||||
image_info);
|
||||
Some((image_info, None))
|
||||
} else {
|
||||
Some((image_info, Some(image.bytes.clone())))
|
||||
Some(image_info)
|
||||
}
|
||||
}
|
||||
None | Some(ImageOrMetadataAvailable::MetadataAvailable(_)) => None,
|
||||
|
|
|
@ -25,10 +25,9 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayIte
|
|||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
|
||||
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem};
|
||||
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem};
|
||||
use gfx::display_list::{LayerInfo, LayeredItem, LineDisplayItem, OpaqueNode};
|
||||
use gfx::display_list::{LayerInfo, LineDisplayItem, OpaqueNode};
|
||||
use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType};
|
||||
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
|
||||
use gfx::paint_thread::THREAD_TINT_COLORS;
|
||||
use gfx_traits::{ScrollPolicy, StackingContextId, color};
|
||||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
||||
use ipc_channel::ipc;
|
||||
|
@ -60,6 +59,17 @@ use table_cell::CollapsedBordersForCell;
|
|||
use url::Url;
|
||||
use util::opts;
|
||||
|
||||
static THREAD_TINT_COLORS: [Color; 8] = [
|
||||
Color { r: 6.0 / 255.0, g: 153.0 / 255.0, b: 198.0 / 255.0, a: 0.7 },
|
||||
Color { r: 255.0 / 255.0, g: 212.0 / 255.0, b: 83.0 / 255.0, a: 0.7 },
|
||||
Color { r: 116.0 / 255.0, g: 29.0 / 255.0, b: 109.0 / 255.0, a: 0.7 },
|
||||
Color { r: 204.0 / 255.0, g: 158.0 / 255.0, b: 199.0 / 255.0, a: 0.7 },
|
||||
Color { r: 242.0 / 255.0, g: 46.0 / 255.0, b: 121.0 / 255.0, a: 0.7 },
|
||||
Color { r: 116.0 / 255.0, g: 203.0 / 255.0, b: 196.0 / 255.0, a: 0.7 },
|
||||
Color { r: 255.0 / 255.0, g: 249.0 / 255.0, b: 201.0 / 255.0, a: 0.7 },
|
||||
Color { r: 137.0 / 255.0, g: 196.0 / 255.0, b: 78.0 / 255.0, a: 0.7 },
|
||||
];
|
||||
|
||||
fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
|
||||
&arr[index % arr.len()]
|
||||
}
|
||||
|
@ -230,8 +240,6 @@ pub trait FragmentDisplayListBuilding {
|
|||
/// * `relative_containing_block_size`: The size of the containing block that
|
||||
/// `position: relative` makes use of.
|
||||
/// * `clip`: The region to clip the display items to.
|
||||
/// * `stacking_relative_display_port`: The position and size of the display port with respect
|
||||
/// to the nearest ancestor stacking context.
|
||||
fn build_display_list(&mut self,
|
||||
state: &mut DisplayListBuildState,
|
||||
stacking_relative_flow_origin: &Point2D<Au>,
|
||||
|
@ -239,8 +247,7 @@ pub trait FragmentDisplayListBuilding {
|
|||
relative_containing_block_mode: WritingMode,
|
||||
border_painting_mode: BorderPaintingMode,
|
||||
display_list_section: DisplayListSection,
|
||||
clip: &ClippingRegion,
|
||||
stacking_relative_display_port: &Rect<Au>);
|
||||
clip: &ClippingRegion);
|
||||
|
||||
/// Adjusts the clipping region for all descendants of this fragment as appropriate.
|
||||
fn adjust_clipping_region_for_children(&self,
|
||||
|
@ -497,13 +504,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
image_url: &Url,
|
||||
index: usize) {
|
||||
let background = style.get_background();
|
||||
let fetch_image_data_as_well = !opts::get().use_webrender;
|
||||
let webrender_image = state.shared_layout_context
|
||||
.get_webrender_image_for_url(image_url,
|
||||
UsePlaceholder::No,
|
||||
fetch_image_data_as_well);
|
||||
UsePlaceholder::No);
|
||||
|
||||
if let Some((webrender_image, image_data)) = webrender_image {
|
||||
if let Some(webrender_image) = webrender_image {
|
||||
debug!("(building display list) building background image");
|
||||
|
||||
// Use `background-size` to get the size.
|
||||
|
@ -633,7 +638,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
state.add_display_item(DisplayItem::ImageClass(box ImageDisplayItem {
|
||||
base: base,
|
||||
webrender_image: webrender_image,
|
||||
image_data: image_data.map(Arc::new),
|
||||
image_data: None,
|
||||
stretch_size: stretch_size,
|
||||
tile_spacing: tile_spacing,
|
||||
image_rendering: style.get_inheritedbox().image_rendering.clone(),
|
||||
|
@ -1080,8 +1085,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
relative_containing_block_mode: WritingMode,
|
||||
border_painting_mode: BorderPaintingMode,
|
||||
display_list_section: DisplayListSection,
|
||||
clip: &ClippingRegion,
|
||||
stacking_relative_display_port: &Rect<Au>) {
|
||||
clip: &ClippingRegion) {
|
||||
self.restyle_damage.remove(REPAINT);
|
||||
if self.style().get_inheritedbox().visibility != visibility::T::visible {
|
||||
return
|
||||
|
@ -1102,14 +1106,6 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
stacking_relative_flow_origin,
|
||||
self);
|
||||
|
||||
// webrender deals with all culling via aabb
|
||||
if !opts::get().use_webrender {
|
||||
if !stacking_relative_border_box.intersects(stacking_relative_display_port) {
|
||||
debug!("Fragment::build_display_list: outside display port");
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Check the clip rect. If there's nothing to render at all, don't even construct display
|
||||
// list items.
|
||||
let empty_rect = !clip.might_intersect_rect(&stacking_relative_border_box);
|
||||
|
@ -1270,17 +1266,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
iframe: fragment_info.pipeline_id,
|
||||
});
|
||||
|
||||
if opts::get().use_webrender {
|
||||
state.add_display_item(item);
|
||||
} else {
|
||||
state.add_display_item(DisplayItem::LayeredItemClass(box LayeredItem {
|
||||
item: item,
|
||||
layer_info: LayerInfo::new(self.layer_id(),
|
||||
ScrollPolicy::Scrollable,
|
||||
Some(fragment_info.pipeline_id),
|
||||
color::transparent()),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::Image(ref mut image_fragment) => {
|
||||
|
@ -1311,7 +1297,6 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
let computed_width = canvas_fragment_info.canvas_inline_size().to_px();
|
||||
let computed_height = canvas_fragment_info.canvas_block_size().to_px();
|
||||
|
||||
let layer_id = self.layer_id();
|
||||
let canvas_data = match canvas_fragment_info.ipc_renderer {
|
||||
Some(ref ipc_renderer) => {
|
||||
let ipc_renderer = ipc_renderer.lock().unwrap();
|
||||
|
@ -1338,7 +1323,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
width: computed_width as u32,
|
||||
height: computed_height as u32,
|
||||
format: PixelFormat::RGBA8,
|
||||
key: canvas_data.image_key,
|
||||
key: Some(canvas_data.image_key),
|
||||
},
|
||||
stretch_size: stacking_relative_content_box.size,
|
||||
tile_spacing: Size2D::zero(),
|
||||
|
@ -1353,17 +1338,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
};
|
||||
|
||||
if opts::get().use_webrender {
|
||||
state.add_display_item(display_item);
|
||||
} else {
|
||||
state.add_display_item(DisplayItem::LayeredItemClass(box LayeredItem {
|
||||
item: display_item,
|
||||
layer_info: LayerInfo::new(layer_id,
|
||||
ScrollPolicy::Scrollable,
|
||||
None,
|
||||
color::transparent()),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::UnscannedText(_) => {
|
||||
|
@ -1381,7 +1356,6 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
scroll_policy: ScrollPolicy,
|
||||
mode: StackingContextCreationMode)
|
||||
-> StackingContext {
|
||||
let use_webrender = opts::get().use_webrender;
|
||||
let border_box = match mode {
|
||||
StackingContextCreationMode::InnerScrollWrapper => {
|
||||
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
|
||||
|
@ -1396,10 +1370,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
};
|
||||
let overflow = match mode {
|
||||
StackingContextCreationMode::InnerScrollWrapper if !use_webrender => {
|
||||
Rect::new(Point2D::zero(), base_flow.overflow.paint.size)
|
||||
}
|
||||
StackingContextCreationMode::InnerScrollWrapper if use_webrender => {
|
||||
StackingContextCreationMode::InnerScrollWrapper => {
|
||||
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
|
||||
}
|
||||
StackingContextCreationMode::OuterScrollWrapper => {
|
||||
|
@ -1874,8 +1845,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
.relative_containing_block_mode,
|
||||
border_painting_mode,
|
||||
background_border_section,
|
||||
&self.base.clip,
|
||||
&self.base.stacking_relative_position_of_display_port);
|
||||
&self.base.clip);
|
||||
|
||||
self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
|
||||
}
|
||||
|
@ -1982,8 +1952,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
.relative_containing_block_mode,
|
||||
BorderPaintingMode::Separate,
|
||||
DisplayListSection::Content,
|
||||
&self.base.clip,
|
||||
&self.base.stacking_relative_position_of_display_port);
|
||||
&self.base.clip);
|
||||
}
|
||||
|
||||
fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState) {
|
||||
|
@ -2039,10 +2008,7 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
|
|||
.relative_containing_block_mode,
|
||||
BorderPaintingMode::Separate,
|
||||
DisplayListSection::Content,
|
||||
&self.block_flow.base.clip,
|
||||
&self.block_flow
|
||||
.base
|
||||
.stacking_relative_position_of_display_port);
|
||||
&self.block_flow.base.clip);
|
||||
}
|
||||
|
||||
// Draw the rest of the block.
|
||||
|
|
|
@ -29,7 +29,7 @@ use app_units::Au;
|
|||
use block::{BlockFlow, FormattingContextType};
|
||||
use context::{LayoutContext, SharedLayoutContext};
|
||||
use display_list_builder::DisplayListBuildState;
|
||||
use euclid::{Point2D, Rect, Size2D};
|
||||
use euclid::{Point2D, Size2D};
|
||||
use floats::{Floats, SpeculatedFloatPlacement};
|
||||
use flow_list::{FlowList, MutFlowListIterator};
|
||||
use flow_ref::{self, FlowRef, WeakFlowRef};
|
||||
|
@ -940,12 +940,6 @@ pub struct BaseFlow {
|
|||
/// this is in the flow's own coordinate system.
|
||||
pub clip: ClippingRegion,
|
||||
|
||||
/// The stacking-relative position of the display port.
|
||||
///
|
||||
/// FIXME(pcwalton): This might be faster as an Arc, since this varies only
|
||||
/// per-stacking-context.
|
||||
pub stacking_relative_position_of_display_port: Rect<Au>,
|
||||
|
||||
/// The writing mode for this flow.
|
||||
pub writing_mode: WritingMode,
|
||||
|
||||
|
@ -1124,7 +1118,6 @@ impl BaseFlow {
|
|||
early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
|
||||
late_absolute_position_info: LateAbsolutePositionInfo::new(),
|
||||
clip: ClippingRegion::max(),
|
||||
stacking_relative_position_of_display_port: Rect::zero(),
|
||||
flags: flags,
|
||||
writing_mode: writing_mode,
|
||||
thread_id: 0,
|
||||
|
|
|
@ -1566,8 +1566,6 @@ impl Flow for InlineFlow {
|
|||
|
||||
block_flow.base.stacking_relative_position =
|
||||
stacking_relative_content_box.origin;
|
||||
block_flow.base.stacking_relative_position_of_display_port =
|
||||
self.base.stacking_relative_position_of_display_port;
|
||||
|
||||
// Write the clip in our coordinate system into the child flow. (The kid will
|
||||
// fix it up to be in its own coordinate system if necessary.)
|
||||
|
@ -1581,8 +1579,6 @@ impl Flow for InlineFlow {
|
|||
|
||||
block_flow.base.stacking_relative_position =
|
||||
stacking_relative_border_box.origin;
|
||||
block_flow.base.stacking_relative_position_of_display_port =
|
||||
self.base.stacking_relative_position_of_display_port;
|
||||
|
||||
// As above, this is in our coordinate system for now.
|
||||
block_flow.base.clip = self.base.clip.clone()
|
||||
|
@ -1602,8 +1598,6 @@ impl Flow for InlineFlow {
|
|||
|
||||
block_flow.base.stacking_relative_position =
|
||||
stacking_relative_border_box.origin;
|
||||
block_flow.base.stacking_relative_position_of_display_port =
|
||||
self.base.stacking_relative_position_of_display_port;
|
||||
|
||||
// As above, this is in our coordinate system for now.
|
||||
block_flow.base.clip = self.base.clip.clone()
|
||||
|
|
|
@ -411,7 +411,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
builder.push_text(item.base.bounds.to_rectf(),
|
||||
item.base.clip.to_clip_region(frame_builder),
|
||||
glyphs,
|
||||
item.text_run.font_key.expect("Font not added to webrender!"),
|
||||
item.text_run.font_key,
|
||||
item.text_color.to_colorf(),
|
||||
item.text_run.actual_pt_size,
|
||||
item.blur_radius,
|
||||
|
|
|
@ -56,7 +56,6 @@ use gfx::display_list::{StackingContext, StackingContextType, WebRenderImageInfo
|
|||
use gfx::font;
|
||||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use gfx::font_context;
|
||||
use gfx::paint_thread::LayoutToPaintMsg;
|
||||
use gfx_traits::{Epoch, FragmentType, LayerId, ScrollPolicy, StackingContextId, color};
|
||||
use heapsize::HeapSizeOf;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
|
@ -120,7 +119,6 @@ use style::timer::Timer;
|
|||
use style::workqueue::WorkQueue;
|
||||
use url::Url;
|
||||
use util::geometry::max_rect;
|
||||
use util::ipc::OptionalIpcSender;
|
||||
use util::opts;
|
||||
use util::prefs::PREFS;
|
||||
use util::resource_files::read_resource_file;
|
||||
|
@ -164,9 +162,6 @@ pub struct LayoutThread {
|
|||
/// The channel on which messages can be sent to the script thread.
|
||||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
|
||||
/// The channel on which messages can be sent to the painting thread.
|
||||
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||
|
||||
/// The channel on which messages can be sent to the time profiler.
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
|
||||
|
@ -232,8 +227,8 @@ pub struct LayoutThread {
|
|||
WebRenderImageInfo,
|
||||
BuildHasherDefault<FnvHasher>>>>,
|
||||
|
||||
// Webrender interface, if enabled.
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
// Webrender interface.
|
||||
webrender_api: webrender_traits::RenderApi,
|
||||
|
||||
/// The timer object to control the timing of the animations. This should
|
||||
/// only be a test-mode timer during testing for animations.
|
||||
|
@ -255,13 +250,12 @@ impl LayoutThreadFactory for LayoutThread {
|
|||
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||
constellation_chan: IpcSender<ConstellationMsg>,
|
||||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||
image_cache_thread: ImageCacheThread,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
content_process_shutdown_chan: IpcSender<()>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
layout_threads: usize) {
|
||||
thread::spawn_named(format!("LayoutThread {:?}", id),
|
||||
move || {
|
||||
|
@ -276,7 +270,6 @@ impl LayoutThreadFactory for LayoutThread {
|
|||
pipeline_port,
|
||||
constellation_chan,
|
||||
script_chan,
|
||||
paint_chan,
|
||||
image_cache_thread,
|
||||
font_cache_thread,
|
||||
time_profiler_chan,
|
||||
|
@ -388,12 +381,11 @@ impl LayoutThread {
|
|||
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||
constellation_chan: IpcSender<ConstellationMsg>,
|
||||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||
image_cache_thread: ImageCacheThread,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
layout_threads: usize)
|
||||
-> LayoutThread {
|
||||
let device = Device::new(
|
||||
|
@ -439,7 +431,6 @@ impl LayoutThread {
|
|||
pipeline_port: pipeline_receiver,
|
||||
script_chan: script_chan.clone(),
|
||||
constellation_chan: constellation_chan.clone(),
|
||||
paint_chan: paint_chan,
|
||||
time_profiler_chan: time_profiler_chan,
|
||||
mem_profiler_chan: mem_profiler_chan,
|
||||
image_cache_thread: image_cache_thread,
|
||||
|
@ -460,7 +451,7 @@ impl LayoutThread {
|
|||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
epoch: Epoch(0),
|
||||
viewport_size: Size2D::new(Au(0), Au(0)),
|
||||
webrender_api: webrender_api_sender.map(|wr| wr.create_api()),
|
||||
webrender_api: webrender_api_sender.create_api(),
|
||||
rw_data: Arc::new(Mutex::new(
|
||||
LayoutThreadData {
|
||||
constellation_chan: constellation_chan,
|
||||
|
@ -763,13 +754,12 @@ impl LayoutThread {
|
|||
info.pipeline_port,
|
||||
info.constellation_chan,
|
||||
info.script_chan.clone(),
|
||||
info.paint_chan.to::<LayoutToPaintMsg>(),
|
||||
self.image_cache_thread.clone(),
|
||||
self.font_cache_thread.clone(),
|
||||
self.time_profiler_chan.clone(),
|
||||
self.mem_profiler_chan.clone(),
|
||||
info.content_process_shutdown_chan,
|
||||
self.webrender_api.as_ref().map(|wr| wr.clone_sender()),
|
||||
self.webrender_api.clone_sender(),
|
||||
info.layout_threads);
|
||||
}
|
||||
|
||||
|
@ -805,8 +795,6 @@ impl LayoutThread {
|
|||
if let Some(ref mut traversal) = self.parallel_traversal {
|
||||
traversal.shutdown()
|
||||
}
|
||||
|
||||
let _ = self.paint_chan.send(LayoutToPaintMsg::Exit);
|
||||
}
|
||||
|
||||
fn handle_add_stylesheet<'a, 'b>(&self,
|
||||
|
@ -1009,7 +997,6 @@ impl LayoutThread {
|
|||
|
||||
self.epoch.next();
|
||||
|
||||
if let Some(ref mut webrender_api) = self.webrender_api {
|
||||
// TODO: Avoid the temporary conversion and build webrender sc/dl directly!
|
||||
let Epoch(epoch_number) = self.epoch;
|
||||
let epoch = webrender_traits::Epoch(epoch_number);
|
||||
|
@ -1019,7 +1006,7 @@ impl LayoutThread {
|
|||
let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id);
|
||||
let root_scroll_layer_id = frame_builder.next_scroll_layer_id();
|
||||
let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender(
|
||||
webrender_api,
|
||||
&mut self.webrender_api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
Some(root_scroll_layer_id),
|
||||
|
@ -1034,8 +1021,7 @@ impl LayoutThread {
|
|||
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
|
||||
self.viewport_size.height.to_f32_px());
|
||||
|
||||
webrender_api.set_root_stacking_context(
|
||||
sc_id,
|
||||
self.webrender_api.set_root_stacking_context(sc_id,
|
||||
root_background_color,
|
||||
epoch,
|
||||
pipeline_id,
|
||||
|
@ -1043,11 +1029,6 @@ impl LayoutThread {
|
|||
frame_builder.stacking_contexts,
|
||||
frame_builder.display_lists,
|
||||
frame_builder.auxiliary_lists_builder.finalize());
|
||||
} else {
|
||||
self.paint_chan
|
||||
.send(LayoutToPaintMsg::PaintInit(self.epoch, display_list))
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ script_traits = {path = "../script_traits"}
|
|||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
util = {path = "../util"}
|
||||
ipc-channel = "0.5"
|
||||
url = {version = "1.2", features = ["heap_size"]}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ extern crate net_traits;
|
|||
extern crate profile_traits;
|
||||
extern crate script_traits;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
// This module contains traits in layout used generically
|
||||
|
@ -20,7 +19,6 @@ extern crate webrender_traits;
|
|||
// that these modules won't have to depend on layout.
|
||||
|
||||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use gfx::paint_thread::LayoutToPaintMsg;
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image_cache_thread::ImageCacheThread;
|
||||
|
@ -29,7 +27,6 @@ use script_traits::{ConstellationControlMsg, LayoutControlMsg};
|
|||
use script_traits::LayoutMsg as ConstellationMsg;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use url::Url;
|
||||
use util::ipc::OptionalIpcSender;
|
||||
|
||||
// A static method creating a layout thread
|
||||
// Here to remove the compositor -> layout dependency
|
||||
|
@ -42,12 +39,11 @@ pub trait LayoutThreadFactory {
|
|||
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||
constellation_chan: IpcSender<ConstellationMsg>,
|
||||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||
image_cache_thread: ImageCacheThread,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
content_process_shutdown_chan: IpcSender<()>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
webrender_api_sender: webrender_traits::RenderApiSender,
|
||||
layout_threads: usize);
|
||||
}
|
||||
|
|
|
@ -252,8 +252,8 @@ struct ImageCache {
|
|||
// The placeholder image used when an image fails to load
|
||||
placeholder_image: Option<Arc<Image>>,
|
||||
|
||||
// Webrender API instance, if enabled.
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
// Webrender API instance.
|
||||
webrender_api: webrender_traits::RenderApi,
|
||||
}
|
||||
|
||||
/// Message that the decoder worker threads send to main image cache thread.
|
||||
|
@ -318,24 +318,23 @@ impl LoadOrigin for ImageCacheOrigin {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_placeholder_image(webrender_api: &Option<webrender_traits::RenderApi>) -> io::Result<Arc<Image>> {
|
||||
fn get_placeholder_image(webrender_api: &webrender_traits::RenderApi) -> io::Result<Arc<Image>> {
|
||||
let mut placeholder_path = try!(resources_dir_path());
|
||||
placeholder_path.push("rippy.png");
|
||||
let mut file = try!(File::open(&placeholder_path));
|
||||
let mut image_data = vec![];
|
||||
try!(file.read_to_end(&mut image_data));
|
||||
let mut image = load_from_memory(&image_data).unwrap();
|
||||
if let Some(ref webrender_api) = *webrender_api {
|
||||
let format = convert_format(image.format);
|
||||
let mut bytes = Vec::new();
|
||||
bytes.extend_from_slice(&*image.bytes);
|
||||
image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes));
|
||||
}
|
||||
Ok(Arc::new(image))
|
||||
}
|
||||
|
||||
impl ImageCache {
|
||||
fn run(core_resource_thread: CoreResourceThread,
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
webrender_api: webrender_traits::RenderApi,
|
||||
ipc_command_receiver: IpcReceiver<ImageCacheCommand>) {
|
||||
// Preload the placeholder image, used when images fail to load.
|
||||
let placeholder_image = get_placeholder_image(&webrender_api).ok();
|
||||
|
@ -479,17 +478,15 @@ impl ImageCache {
|
|||
fn complete_load(&mut self, key: LoadKey, mut load_result: LoadResult) {
|
||||
let pending_load = self.pending_loads.remove(&key).unwrap();
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
match load_result {
|
||||
LoadResult::Loaded(ref mut image) => {
|
||||
let format = convert_format(image.format);
|
||||
let mut bytes = Vec::new();
|
||||
bytes.extend_from_slice(&*image.bytes);
|
||||
image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes));
|
||||
image.id = Some(self.webrender_api.add_image(image.width, image.height, format, bytes));
|
||||
}
|
||||
LoadResult::PlaceholderLoaded(..) | LoadResult::None => {}
|
||||
}
|
||||
}
|
||||
|
||||
let image_response = match load_result {
|
||||
LoadResult::Loaded(image) => ImageResponse::Loaded(Arc::new(image)),
|
||||
|
@ -627,7 +624,7 @@ impl ImageCache {
|
|||
|
||||
/// Create a new image cache.
|
||||
pub fn new_image_cache_thread(core_resource_thread: CoreResourceThread,
|
||||
webrender_api: Option<webrender_traits::RenderApi>) -> ImageCacheThread {
|
||||
webrender_api: webrender_traits::RenderApi) -> ImageCacheThread {
|
||||
let (ipc_command_sender, ipc_command_receiver) = ipc::channel().unwrap();
|
||||
|
||||
spawn_named("ImageCacheThread".to_owned(), move || {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
use ipc_channel::ipc::IpcSharedMemory;
|
||||
use piston_image::{self, DynamicImage, ImageFormat};
|
||||
use util::opts;
|
||||
|
||||
pub use msg::constellation_msg::{Image, PixelFormat};
|
||||
|
||||
|
@ -21,26 +20,16 @@ pub struct ImageMetadata {
|
|||
fn byte_swap_and_premultiply(data: &mut [u8]) {
|
||||
let length = data.len();
|
||||
|
||||
// No need to pre-multiply alpha when using direct GPU rendering.
|
||||
let premultiply_alpha = !opts::get().use_webrender;
|
||||
|
||||
for i in (0..length).step_by(4) {
|
||||
let r = data[i + 2];
|
||||
let g = data[i + 1];
|
||||
let b = data[i + 0];
|
||||
let a = data[i + 3];
|
||||
|
||||
if premultiply_alpha {
|
||||
data[i + 0] = ((r as u32) * (a as u32) / 255) as u8;
|
||||
data[i + 1] = ((g as u32) * (a as u32) / 255) as u8;
|
||||
data[i + 2] = ((b as u32) * (a as u32) / 255) as u8;
|
||||
} else {
|
||||
data[i + 0] = r;
|
||||
data[i + 1] = g;
|
||||
data[i + 2] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
||||
if buffer.is_empty() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg};
|
||||
use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
|
||||
use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
|
||||
use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap, byte_swap_and_premultiply};
|
||||
use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
|
||||
use cssparser::{Parser, RGBA};
|
||||
use cssparser::Color as CSSColor;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
|
@ -47,7 +47,6 @@ use std::cell::Cell;
|
|||
use std::str::FromStr;
|
||||
use unpremultiplytable::UNPREMULTIPLY_TABLE;
|
||||
use url::Url;
|
||||
use util::opts;
|
||||
|
||||
#[must_root]
|
||||
#[derive(JSTraceable, Clone, HeapSizeOf)]
|
||||
|
@ -297,14 +296,7 @@ impl CanvasRenderingContext2D {
|
|||
Some((mut data, size)) => {
|
||||
// Pixels come from cache in BGRA order and drawImage expects RGBA so we
|
||||
// have to swap the color values
|
||||
if opts::get().use_webrender {
|
||||
// Webrender doesn't pre-multiply alpha when decoding
|
||||
// images, but canvas expects the images to be
|
||||
// pre-multiplied alpha.
|
||||
byte_swap_and_premultiply(&mut data);
|
||||
} else {
|
||||
byte_swap(&mut data);
|
||||
}
|
||||
let size = Size2D::new(size.width as f64, size.height as f64);
|
||||
(data, size)
|
||||
},
|
||||
|
|
|
@ -1220,10 +1220,6 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn scroll_offset_query(&self, node: &Node) -> Point2D<f32> {
|
||||
// WebRender always keeps the scroll offsets up to date and stored here in the window. So,
|
||||
// if WR is in use, all we need to do is to check our list of scroll offsets and return the
|
||||
// result.
|
||||
if opts::get().use_webrender {
|
||||
let mut node = Root::from_ref(node);
|
||||
loop {
|
||||
if let Some(scroll_offset) = self.scroll_offsets
|
||||
|
@ -1237,25 +1233,7 @@ impl Window {
|
|||
}
|
||||
}
|
||||
let offset = self.current_viewport.get().origin;
|
||||
return Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px())
|
||||
}
|
||||
|
||||
let node = node.to_trusted_node_address();
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::NodeLayerIdQuery(node),
|
||||
ReflowReason::Query) {
|
||||
return Point2D::zero();
|
||||
}
|
||||
|
||||
let layer_id = self.layout_rpc.node_layer_id().layer_id;
|
||||
|
||||
let (send, recv) = ipc::channel::<Point2D<f32>>().unwrap();
|
||||
let global_scope = self.upcast::<GlobalScope>();
|
||||
global_scope
|
||||
.constellation_chan()
|
||||
.send(ConstellationMsg::GetScrollOffset(global_scope.pipeline_id(), layer_id, send))
|
||||
.unwrap();
|
||||
recv.recv().unwrap_or(Point2D::zero())
|
||||
Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px())
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-scroll
|
||||
|
|
|
@ -1143,7 +1143,6 @@ impl ScriptThread {
|
|||
new_pipeline_id,
|
||||
frame_type,
|
||||
load_data,
|
||||
paint_chan,
|
||||
pipeline_port,
|
||||
layout_to_constellation_chan,
|
||||
content_process_shutdown_chan,
|
||||
|
@ -1160,7 +1159,6 @@ impl ScriptThread {
|
|||
layout_pair: layout_pair,
|
||||
pipeline_port: pipeline_port,
|
||||
constellation_chan: layout_to_constellation_chan,
|
||||
paint_chan: paint_chan,
|
||||
script_chan: self.control_chan.clone(),
|
||||
image_cache_thread: self.image_cache_thread.clone(),
|
||||
content_process_shutdown_chan: content_process_shutdown_chan,
|
||||
|
|
|
@ -31,4 +31,3 @@ selectors = "0.13"
|
|||
string_cache = {version = "0.2.26", features = ["heap_size"]}
|
||||
style = {path = "../style"}
|
||||
url = {version = "1.2", features = ["heap_size"]}
|
||||
util = {path = "../util"}
|
||||
|
|
|
@ -39,7 +39,6 @@ extern crate selectors;
|
|||
extern crate string_cache;
|
||||
extern crate style;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
|
||||
pub mod message;
|
||||
pub mod reporter;
|
||||
|
|
|
@ -21,7 +21,6 @@ use style::context::ReflowGoal;
|
|||
use style::selector_impl::PseudoElement;
|
||||
use style::stylesheets::Stylesheet;
|
||||
use url::Url;
|
||||
use util::ipc::OptionalOpaqueIpcSender;
|
||||
|
||||
/// Asynchronous messages that script can send to layout.
|
||||
pub enum Msg {
|
||||
|
@ -148,7 +147,6 @@ pub struct NewLayoutThreadInfo {
|
|||
pub constellation_chan: IpcSender<ConstellationMsg>,
|
||||
pub script_chan: IpcSender<ConstellationControlMsg>,
|
||||
pub image_cache_thread: ImageCacheThread,
|
||||
pub paint_chan: OptionalOpaqueIpcSender,
|
||||
pub content_process_shutdown_chan: IpcSender<()>,
|
||||
pub layout_threads: usize,
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ heapsize = "0.3.0"
|
|||
heapsize_plugin = "0.1.2"
|
||||
hyper_serde = "0.1.4"
|
||||
ipc-channel = "0.5"
|
||||
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
|
||||
libc = "0.2"
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
|
@ -33,4 +32,3 @@ serde_derive = "0.8"
|
|||
style_traits = {path = "../style_traits", features = ["servo"]}
|
||||
time = "0.1.12"
|
||||
url = {version = "1.2", features = ["heap_size"]}
|
||||
util = {path = "../util"}
|
||||
|
|
|
@ -20,7 +20,6 @@ extern crate gfx_traits;
|
|||
extern crate heapsize;
|
||||
extern crate hyper_serde;
|
||||
extern crate ipc_channel;
|
||||
extern crate layers;
|
||||
extern crate libc;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
|
@ -33,7 +32,6 @@ extern crate serde_derive;
|
|||
extern crate style_traits;
|
||||
extern crate time;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
|
||||
mod script_msg;
|
||||
pub mod webdriver_msg;
|
||||
|
@ -46,12 +44,12 @@ use euclid::point::Point2D;
|
|||
use euclid::rect::Rect;
|
||||
use euclid::scale_factor::ScaleFactor;
|
||||
use euclid::size::TypedSize2D;
|
||||
use gfx_traits::DevicePixel;
|
||||
use gfx_traits::Epoch;
|
||||
use gfx_traits::LayerId;
|
||||
use gfx_traits::StackingContextId;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use layers::geometry::DevicePixel;
|
||||
use libc::c_void;
|
||||
use msg::constellation_msg::{FrameId, FrameType, Image, Key, KeyModifiers, KeyState, LoadData};
|
||||
use msg::constellation_msg::{PipelineId, PipelineNamespaceId, ReferrerPolicy};
|
||||
|
@ -68,7 +66,6 @@ use std::fmt;
|
|||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use style_traits::{PagePx, UnsafeNode, ViewportPx};
|
||||
use url::Url;
|
||||
use util::ipc::OptionalOpaqueIpcSender;
|
||||
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
||||
|
||||
pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
|
||||
|
@ -138,9 +135,6 @@ pub struct NewLayoutInfo {
|
|||
pub frame_type: FrameType,
|
||||
/// Network request data which will be initiated by the script thread.
|
||||
pub load_data: LoadData,
|
||||
/// The paint channel, cast to `OptionalOpaqueIpcSender`. This is really an
|
||||
/// `Sender<LayoutToPaintMsg>`.
|
||||
pub paint_chan: OptionalOpaqueIpcSender,
|
||||
/// A port on which layout can receive messages from the pipeline.
|
||||
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||
/// A sender for the layout thread to communicate to the constellation.
|
||||
|
|
|
@ -128,8 +128,6 @@ pub enum ScriptMsg {
|
|||
ResizeTo(Size2D<u32>),
|
||||
/// Script has handled a touch event, and either prevented or allowed default actions.
|
||||
TouchEventProcessed(EventResult),
|
||||
/// Get Scroll Offset
|
||||
GetScrollOffset(PipelineId, LayerId, IpcSender<Point2D<f32>>),
|
||||
/// A log entry, with the pipeline id and thread name
|
||||
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
||||
/// Notifies the constellation that this pipeline has exited.
|
||||
|
|
38
components/servo/Cargo.lock
generated
38
components/servo/Cargo.lock
generated
|
@ -321,14 +321,11 @@ dependencies = [
|
|||
name = "compositing"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"azure 0.9.0 (git+https://github.com/servo/rust-azure)",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -359,7 +356,6 @@ dependencies = [
|
|||
"gfx 0.0.1",
|
||||
"gfx_traits 0.0.1",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"layout_traits 0.0.1",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
|
@ -797,7 +793,6 @@ dependencies = [
|
|||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -806,8 +801,6 @@ dependencies = [
|
|||
"net_traits 0.0.1",
|
||||
"ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plugins 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"range 0.0.1",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -841,13 +834,9 @@ name = "gfx_traits"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"azure 0.9.0 (git+https://github.com/servo/rust-azure)",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"msg 0.0.1",
|
||||
"plugins 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"range 0.0.1",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -894,8 +883,8 @@ dependencies = [
|
|||
"compositing 0.0.1",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -1141,26 +1130,6 @@ name = "language-tags"
|
|||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "layers"
|
||||
version = "0.5.3"
|
||||
source = "git+https://github.com/servo/rust-layers#b064de859b2cf3f4e07b29ee11a34543f1671ac0"
|
||||
dependencies = [
|
||||
"cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"io-surface 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-skia 0.20130412.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "layout"
|
||||
version = "0.0.1"
|
||||
|
@ -1251,7 +1220,6 @@ dependencies = [
|
|||
"profile_traits 0.0.1",
|
||||
"script_traits 0.0.1",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.6.0 (git+https://github.com/servo/webrender)",
|
||||
]
|
||||
|
||||
|
@ -2050,7 +2018,6 @@ dependencies = [
|
|||
"string_cache 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style 0.0.1",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2077,7 +2044,6 @@ dependencies = [
|
|||
"heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -2090,7 +2056,6 @@ dependencies = [
|
|||
"style_traits 0.0.1",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2917,7 +2882,6 @@ dependencies = [
|
|||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum layers 0.5.3 (git+https://github.com/servo/rust-layers)" = "<none>"
|
||||
"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
||||
"checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73"
|
||||
|
|
|
@ -133,10 +133,10 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
|
|||
devtools::start_server(port)
|
||||
});
|
||||
|
||||
let (webrender, webrender_api_sender) = if opts::get().use_webrender {
|
||||
if let Ok(mut resource_path) = resources_dir_path() {
|
||||
let mut resource_path = resources_dir_path().unwrap();
|
||||
resource_path.push("shaders");
|
||||
|
||||
let (webrender, webrender_api_sender) = {
|
||||
// TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
|
||||
let scale_factor = window.scale_factor().get();
|
||||
let device_pixel_ratio = match opts.device_pixels_per_px {
|
||||
|
@ -153,7 +153,6 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
|
|||
webrender_traits::RendererKind::Native
|
||||
};
|
||||
|
||||
let (webrender, webrender_sender) =
|
||||
webrender::Renderer::new(webrender::RendererOptions {
|
||||
device_pixel_ratio: device_pixel_ratio,
|
||||
resource_path: resource_path,
|
||||
|
@ -165,13 +164,7 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
|
|||
precache_shaders: opts.precache_shaders,
|
||||
enable_scrollbars: opts.output_file.is_none(),
|
||||
renderer_kind: renderer_kind,
|
||||
});
|
||||
(Some(webrender), Some(webrender_sender))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
} else {
|
||||
(None, None)
|
||||
})
|
||||
};
|
||||
|
||||
// Create the constellation, which maintains the engine
|
||||
|
@ -247,7 +240,7 @@ fn create_constellation(opts: opts::Opts,
|
|||
mem_profiler_chan: mem::ProfilerChan,
|
||||
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
|
||||
supports_clipboard: bool,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||
webrender_api_sender: webrender_traits::RenderApiSender)
|
||||
-> (Sender<ConstellationMsg>, SWManagerSenders) {
|
||||
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
|
||||
|
||||
|
@ -257,9 +250,9 @@ fn create_constellation(opts: opts::Opts,
|
|||
time_profiler_chan.clone(),
|
||||
opts.config_dir.map(Into::into));
|
||||
let image_cache_thread = new_image_cache_thread(public_resource_threads.sender(),
|
||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||
webrender_api_sender.create_api());
|
||||
let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
|
||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||
Some(webrender_api_sender.create_api()));
|
||||
|
||||
let resource_sender = public_resource_threads.sender();
|
||||
|
||||
|
|
|
@ -192,9 +192,6 @@ pub struct Opts {
|
|||
/// Enable vsync in the compositor
|
||||
pub enable_vsync: bool,
|
||||
|
||||
/// True to enable the webrender painting/compositing backend.
|
||||
pub use_webrender: bool,
|
||||
|
||||
/// True to show webrender profiling stats on screen.
|
||||
pub webrender_stats: bool,
|
||||
|
||||
|
@ -212,9 +209,6 @@ pub struct Opts {
|
|||
/// Directory for a default config directory
|
||||
pub config_dir: Option<String>,
|
||||
|
||||
// Which rendering API to use.
|
||||
pub render_api: RenderApi,
|
||||
|
||||
// don't skip any backtraces on panic
|
||||
pub full_backtraces: bool,
|
||||
|
||||
|
@ -452,15 +446,6 @@ enum UserAgent {
|
|||
Android,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
pub enum RenderApi {
|
||||
GL,
|
||||
ES2,
|
||||
}
|
||||
|
||||
const DEFAULT_RENDER_API: RenderApi = RenderApi::GL;
|
||||
|
||||
fn default_user_agent_string(agent: UserAgent) -> &'static str {
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
const DESKTOP_UA_STRING: &'static str =
|
||||
|
@ -549,10 +534,8 @@ pub fn default_opts() -> Opts {
|
|||
exit_after_load: false,
|
||||
no_native_titlebar: false,
|
||||
enable_vsync: true,
|
||||
use_webrender: true,
|
||||
webrender_stats: false,
|
||||
use_msaa: false,
|
||||
render_api: DEFAULT_RENDER_API,
|
||||
config_dir: None,
|
||||
full_backtraces: false,
|
||||
is_printing_version: false,
|
||||
|
@ -800,15 +783,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
opt_match.opt_present("b") ||
|
||||
!PREFS.get("shell.native-titlebar.enabled").as_boolean().unwrap();
|
||||
|
||||
let use_webrender = !opt_match.opt_present("c");
|
||||
|
||||
let render_api = match opt_match.opt_str("G") {
|
||||
Some(ref ga) if ga == "gl" => RenderApi::GL,
|
||||
Some(ref ga) if ga == "es2" => RenderApi::ES2,
|
||||
None => DEFAULT_RENDER_API,
|
||||
_ => args_fail(&format!("error: graphics option must be gl or es2:")),
|
||||
};
|
||||
|
||||
let is_printing_version = opt_match.opt_present("v") || opt_match.opt_present("version");
|
||||
|
||||
let opts = Opts {
|
||||
|
@ -842,7 +816,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
sandbox: opt_match.opt_present("S"),
|
||||
random_pipeline_closure_probability: random_pipeline_closure_probability,
|
||||
random_pipeline_closure_seed: random_pipeline_closure_seed,
|
||||
render_api: render_api,
|
||||
show_debug_borders: debug_options.show_compositor_borders,
|
||||
show_debug_fragment_borders: debug_options.show_fragment_borders,
|
||||
show_debug_parallel_paint: debug_options.show_parallel_paint,
|
||||
|
@ -862,7 +835,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
exit_after_load: opt_match.opt_present("x"),
|
||||
no_native_titlebar: do_not_use_native_titlebar,
|
||||
enable_vsync: !debug_options.disable_vsync,
|
||||
use_webrender: use_webrender,
|
||||
webrender_stats: debug_options.webrender_stats,
|
||||
use_msaa: debug_options.use_msaa,
|
||||
config_dir: opt_match.opt_str("config-dir"),
|
||||
|
|
40
ports/cef/Cargo.lock
generated
40
ports/cef/Cargo.lock
generated
|
@ -6,9 +6,9 @@ dependencies = [
|
|||
"compositing 0.0.1",
|
||||
"devtools 0.0.1",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin_app 0.0.1",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
|
@ -278,14 +278,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "compositing"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"azure 0.9.0 (git+https://github.com/servo/rust-azure)",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -316,7 +313,6 @@ dependencies = [
|
|||
"gfx 0.0.1",
|
||||
"gfx_traits 0.0.1",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"layout_traits 0.0.1",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
|
@ -713,7 +709,6 @@ dependencies = [
|
|||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -722,8 +717,6 @@ dependencies = [
|
|||
"net_traits 0.0.1",
|
||||
"ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plugins 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"range 0.0.1",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -748,13 +741,9 @@ name = "gfx_traits"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"azure 0.9.0 (git+https://github.com/servo/rust-azure)",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"msg 0.0.1",
|
||||
"plugins 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"range 0.0.1",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -801,8 +790,8 @@ dependencies = [
|
|||
"compositing 0.0.1",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -1048,26 +1037,6 @@ name = "language-tags"
|
|||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "layers"
|
||||
version = "0.5.3"
|
||||
source = "git+https://github.com/servo/rust-layers#b064de859b2cf3f4e07b29ee11a34543f1671ac0"
|
||||
dependencies = [
|
||||
"cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"io-surface 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-skia 0.20130412.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "layout"
|
||||
version = "0.0.1"
|
||||
|
@ -1151,7 +1120,6 @@ dependencies = [
|
|||
"profile_traits 0.0.1",
|
||||
"script_traits 0.0.1",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.6.0 (git+https://github.com/servo/webrender)",
|
||||
]
|
||||
|
||||
|
@ -1901,7 +1869,6 @@ dependencies = [
|
|||
"string_cache 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style 0.0.1",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1918,7 +1885,6 @@ dependencies = [
|
|||
"heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.5.3 (git+https://github.com/servo/rust-layers)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -1931,7 +1897,6 @@ dependencies = [
|
|||
"style_traits 0.0.1",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2769,7 +2734,6 @@ dependencies = [
|
|||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum layers 0.5.3 (git+https://github.com/servo/rust-layers)" = "<none>"
|
||||
"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
||||
"checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73"
|
||||
|
|
|
@ -18,9 +18,9 @@ opt-level = 3
|
|||
compositing = {path = "../../components/compositing"}
|
||||
devtools = {path = "../../components/devtools"}
|
||||
euclid = "0.10.1"
|
||||
gfx_traits = {path = "../../components/gfx_traits"}
|
||||
gleam = "0.2.8"
|
||||
glutin_app = {path = "../glutin"}
|
||||
layers = {git = "https://github.com/servo/rust-layers"}
|
||||
libc = "0.2"
|
||||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
msg = {path = "../../components/msg"}
|
||||
|
|
|
@ -19,9 +19,9 @@ extern crate servo;
|
|||
extern crate compositing;
|
||||
|
||||
extern crate euclid;
|
||||
extern crate gfx_traits;
|
||||
extern crate gleam;
|
||||
extern crate glutin_app;
|
||||
extern crate layers;
|
||||
extern crate rustc_unicode;
|
||||
extern crate script_traits;
|
||||
|
||||
|
|
|
@ -23,9 +23,8 @@ use compositing::windowing::{WindowEvent, WindowMethods};
|
|||
use euclid::point::Point2D;
|
||||
use euclid::scale_factor::ScaleFactor;
|
||||
use euclid::size::{Size2D, TypedSize2D};
|
||||
use gfx_traits::DevicePixel;
|
||||
use gleam::gl;
|
||||
use layers::geometry::DevicePixel;
|
||||
use layers::platform::surface::NativeDisplay;
|
||||
use msg::constellation_msg::{Key, KeyModifiers};
|
||||
use net_traits::net_error_list::NetError;
|
||||
use std::cell::RefCell;
|
||||
|
@ -284,19 +283,6 @@ impl WindowMethods for Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
fn native_display(&self) -> NativeDisplay {
|
||||
use x11::xlib;
|
||||
unsafe {
|
||||
NativeDisplay::new(DISPLAY as *mut xlib::Display)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os="linux"))]
|
||||
fn native_display(&self) -> NativeDisplay {
|
||||
NativeDisplay::new()
|
||||
}
|
||||
|
||||
fn create_compositor_channel(&self)
|
||||
-> (Box<CompositorProxy+Send>, Box<CompositorReceiver>) {
|
||||
let (sender, receiver) = channel();
|
||||
|
|
|
@ -12,8 +12,8 @@ path = "lib.rs"
|
|||
bitflags = "0.7"
|
||||
compositing = {path = "../../components/compositing"}
|
||||
euclid = "0.10.1"
|
||||
gfx_traits = {path = "../../components/gfx_traits"}
|
||||
gleam = "0.2.8"
|
||||
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
|
||||
log = "0.3.5"
|
||||
msg = {path = "../../components/msg"}
|
||||
net_traits = {path = "../../components/net_traits"}
|
||||
|
|
|
@ -11,9 +11,9 @@ extern crate compositing;
|
|||
#[allow(unused_extern_crates)]
|
||||
#[cfg(target_os = "android")] extern crate egl;
|
||||
extern crate euclid;
|
||||
extern crate gfx_traits;
|
||||
extern crate gleam;
|
||||
extern crate glutin;
|
||||
extern crate layers;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
|
@ -22,7 +22,6 @@ extern crate script_traits;
|
|||
extern crate style_traits;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
#[cfg(target_os = "linux")] extern crate x11;
|
||||
#[cfg(target_os = "windows")] extern crate winapi;
|
||||
#[cfg(target_os = "windows")] extern crate user32;
|
||||
#[cfg(target_os = "windows")] extern crate gdi32;
|
||||
|
|
|
@ -13,14 +13,13 @@ use euclid::scale_factor::ScaleFactor;
|
|||
use euclid::size::TypedSize2D;
|
||||
#[cfg(target_os = "windows")]
|
||||
use gdi32;
|
||||
use gfx_traits::DevicePixel;
|
||||
use gleam::gl;
|
||||
use glutin;
|
||||
use glutin::{Api, ElementState, Event, GlRequest, MouseButton, MouseScrollDelta, VirtualKeyCode};
|
||||
use glutin::{ScanCode, TouchPhase};
|
||||
#[cfg(target_os = "macos")]
|
||||
use glutin::os::macos::{ActivationPolicy, WindowBuilderExt};
|
||||
use layers::geometry::DevicePixel;
|
||||
use layers::platform::surface::NativeDisplay;
|
||||
use msg::constellation_msg::{self, Key};
|
||||
use msg::constellation_msg::{ALT, CONTROL, KeyState, NONE, SHIFT, SUPER};
|
||||
use net_traits::net_error_list::NetError;
|
||||
|
@ -42,8 +41,6 @@ use url::Url;
|
|||
use user32;
|
||||
use util::geometry::ScreenPx;
|
||||
use util::opts;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use util::opts::RenderApi;
|
||||
use util::prefs::PREFS;
|
||||
use util::resource_files;
|
||||
#[cfg(target_os = "windows")]
|
||||
|
@ -318,18 +315,8 @@ impl Window {
|
|||
|
||||
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
|
||||
fn gl_version() -> GlRequest {
|
||||
if opts::get().use_webrender {
|
||||
return GlRequest::Specific(Api::OpenGl, (3, 2));
|
||||
}
|
||||
match opts::get().render_api {
|
||||
RenderApi::GL => {
|
||||
GlRequest::Specific(Api::OpenGl, (2, 1))
|
||||
}
|
||||
RenderApi::ES2 => {
|
||||
GlRequest::Specific(Api::OpenGlEs, (2, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||
fn gl_version() -> GlRequest {
|
||||
|
@ -558,13 +545,6 @@ impl Window {
|
|||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn handle_next_event(&self) -> bool {
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
// WebRender can use the normal blocking event check and proper vsync,
|
||||
// because it doesn't call X11 functions from another thread, so doesn't
|
||||
// hit the same issues explained below.
|
||||
if opts::get().use_webrender {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window) => {
|
||||
let event = match window.wait_events().next() {
|
||||
|
@ -589,43 +569,6 @@ impl Window {
|
|||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO(gw): This is an awful hack to work around the
|
||||
// broken way we currently call X11 from multiple threads.
|
||||
//
|
||||
// On some (most?) X11 implementations, blocking here
|
||||
// with XPeekEvent results in the paint thread getting stuck
|
||||
// in XGetGeometry randomly. When this happens the result
|
||||
// is that until you trigger the XPeekEvent to return
|
||||
// (by moving the mouse over the window) the paint thread
|
||||
// never completes and you don't see the most recent
|
||||
// results.
|
||||
//
|
||||
// For now, poll events and sleep for ~1 frame if there
|
||||
// are no events. This means we don't spin the CPU at
|
||||
// 100% usage, but is far from ideal!
|
||||
//
|
||||
// See https://github.com/servo/servo/issues/5780
|
||||
//
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window) => {
|
||||
let first_event = window.poll_events().next();
|
||||
|
||||
match first_event {
|
||||
Some(event) => {
|
||||
self.handle_window_event(event)
|
||||
}
|
||||
None => {
|
||||
thread::sleep(Duration::from_millis(16));
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowKind::Headless(..) => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wait_events(&self) -> Vec<WindowEvent> {
|
||||
|
@ -1031,33 +974,6 @@ impl WindowMethods for Window {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn native_display(&self) -> NativeDisplay {
|
||||
use x11::xlib;
|
||||
unsafe {
|
||||
match opts::get().render_api {
|
||||
RenderApi::GL => {
|
||||
match self.kind {
|
||||
WindowKind::Window(ref window) => {
|
||||
NativeDisplay::new(window.platform_display() as *mut xlib::Display)
|
||||
}
|
||||
WindowKind::Headless(..) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
},
|
||||
RenderApi::ES2 => {
|
||||
NativeDisplay::new_egl_display()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn native_display(&self) -> NativeDisplay {
|
||||
NativeDisplay::new()
|
||||
}
|
||||
|
||||
/// Helper function to handle keyboard events.
|
||||
fn handle_key(&self, ch: Option<char>, key: Key, mods: constellation_msg::KeyModifiers) {
|
||||
match (mods, ch, key) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue