mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Auto merge of #13711 - glennw:remove-old-renderer, r=larsbergstrom
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 for now 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. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13711) <!-- Reviewable:end -->
This commit is contained in:
commit
f96718d03d
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,25 +20,15 @@ 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> {
|
||||
|
|
|
@ -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",
|
||||
|
@ -1140,26 +1129,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"
|
||||
|
@ -1250,7 +1219,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)",
|
||||
]
|
||||
|
||||
|
@ -2049,7 +2017,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]]
|
||||
|
@ -2076,7 +2043,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",
|
||||
|
@ -2089,7 +2055,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]]
|
||||
|
@ -2916,7 +2881,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",
|
||||
|
@ -1047,26 +1036,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"
|
||||
|
@ -1150,7 +1119,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)",
|
||||
]
|
||||
|
||||
|
@ -1900,7 +1868,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]]
|
||||
|
@ -1917,7 +1884,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",
|
||||
|
@ -1930,7 +1896,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]]
|
||||
|
@ -2768,7 +2733,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