Skip to content

Commit

Permalink
ports/cef: Implement accelerated compositing for the CEF port.
Browse files Browse the repository at this point in the history
  • Loading branch information
pcwalton committed Dec 7, 2014
1 parent a6768b6 commit 48c9881
Show file tree
Hide file tree
Showing 36 changed files with 1,342 additions and 256 deletions.
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -28,7 +28,7 @@ On Debian-based Linuxes:
sudo apt-get install curl freeglut3-dev \
libfreetype6-dev libgl1-mesa-dri libglib2.0-dev xorg-dev \
msttcorefonts gperf g++ cmake python-virtualenv \
libssl-dev libbz2-dev
libssl-dev
```

On Fedora:
Expand All @@ -37,7 +37,7 @@ On Fedora:
sudo yum install curl freeglut-devel libtool gcc-c++ libXi-devel \
freetype-devel mesa-libGL-devel glib2-devel libX11-devel libXrandr-devel gperf \
fontconfig-devel cabextract ttmkfdir python python-virtualenv expat-devel \
rpm-build openssl-devel cmake bzip2
rpm-build openssl-devel cmake
pushd .
cd /tmp
wget http://corefonts.sourceforge.net/msttcorefonts-2.5-1.spec
Expand All @@ -49,7 +49,7 @@ popd
On Arch Linux:

``` sh
sudo pacman -S base-devel git python2 python2-virtualenv mesa ttf-font cmake bzip2
sudo pacman -S base-devel git python2 python2-virtualenv mesa ttf-font cmake
```

Cross-compilation for Android:
Expand Down
102 changes: 79 additions & 23 deletions components/compositing/compositor.rs
Expand Up @@ -3,23 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use compositor_layer::{CompositorData, CompositorLayer, DoesntWantScrollEvents};
use compositor_layer::WantsScrollEvents;
use compositor_task::{ChangeReadyState, ChangeRenderState, CompositorEventListener};
use compositor_task::{CompositorProxy, CompositorReceiver, CompositorTask};
use compositor_task::{CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer, Exit};
use compositor_task::{FrameTreeUpdateMsg, GetGraphicsMetadata, LayerProperties};
use compositor_layer::{WantsScrollEvents};
use compositor_task::{ChangePageLoadData, ChangePageTitle, ChangeReadyState, ChangeRenderState};
use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver};
use compositor_task::{CompositorTask, CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer};
use compositor_task::{Exit, FrameTreeUpdateMsg, GetGraphicsMetadata, LayerProperties};
use compositor_task::{LoadComplete, Msg, Paint, RenderMsgDiscarded, ScrollFragmentPoint};
use compositor_task::{ScrollTimeout, SetIds, SetLayerOrigin, ShutdownComplete};
use constellation::{SendableFrameTree, FrameTreeDiff};
use constellation::{FrameId, FrameTreeDiff, SendableFrameTree};
use pipeline::CompositionPipeline;
use scrolling::ScrollingTimerProxy;
use windowing;
use windowing::{IdleWindowEvent, LoadUrlWindowEvent, MouseWindowClickEvent};
use windowing::{MouseWindowEvent, MouseWindowEventClass, MouseWindowMouseDownEvent};
use windowing::{MouseWindowMouseUpEvent, MouseWindowMoveEventClass, NavigationWindowEvent};
use windowing::{IdleWindowEvent, InitializeCompositingWindowEvent};
use windowing::{KeyEvent, LoadUrlWindowEvent, MouseWindowClickEvent, MouseWindowEvent};
use windowing::{MouseWindowEventClass, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
use windowing::{MouseWindowMoveEventClass, NavigationWindowEvent, PinchZoomWindowEvent};
use windowing::{QuitWindowEvent, RefreshWindowEvent, ResizeWindowEvent, ScrollWindowEvent};
use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
use windowing::{PinchZoomWindowEvent, KeyEvent};

use azure::azure_hl;
use std::cmp;
Expand All @@ -41,10 +41,10 @@ use gleam::gl;
use script_traits::{ViewportMsg, ScriptControlChan};
use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdleRenderState, LayerId};
use servo_msg::compositor_msg::{ReadyState, RenderingRenderState, RenderState, Scrollable};
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg};
use servo_msg::constellation_msg::{NavigateMsg, LoadData, PipelineId, ResizedWindowMsg};
use servo_msg::constellation_msg::{WindowSizeData, KeyState, Key, KeyModifiers};
use servo_msg::constellation_msg;
use servo_msg::constellation_msg::{mod, ConstellationChan, ExitMsg};
use servo_msg::constellation_msg::{GetPipelineTitleMsg, Key, KeyModifiers, KeyState, LoadData};
use servo_msg::constellation_msg::{LoadUrlMsg, NavigateMsg, PipelineId, ResizedWindowMsg};
use servo_msg::constellation_msg::{WindowSizeData};
use servo_util::geometry::{PagePx, ScreenPx, ViewportPx};
use servo_util::memory::MemoryProfilerChan;
use servo_util::opts;
Expand All @@ -58,15 +58,17 @@ use std::slice::bytes::copy_memory;
use time::{precise_time_ns, precise_time_s};
use url::Url;

/// NB: Never block on the constellation, because sometimes the constellation blocks on us.
pub struct IOCompositor<Window: WindowMethods> {
/// The application window.
window: Rc<Window>,

/// The port on which we receive messages.
port: Box<CompositorReceiver>,

/// The render context.
context: RenderContext,
/// The render context. This will be `None` if the windowing system has not yet sent us a
/// `PrepareRenderingEvent`.
context: Option<RenderContext>,

/// The root pipeline.
root_pipeline: Option<CompositionPipeline>,
Expand Down Expand Up @@ -177,13 +179,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// display list. This is only here because we don't have that logic in the renderer yet.
let window_size = window.framebuffer_size();
let hidpi_factor = window.hidpi_factor();
let context = CompositorTask::create_graphics_context(&window.native_metadata());

let show_debug_borders = opts::get().show_debug_borders;
IOCompositor {
window: window,
port: receiver,
context: rendergl::RenderContext::new(context, show_debug_borders),
context: None,
root_pipeline: None,
scene: Scene::new(Rect {
origin: Zero::zero(),
Expand Down Expand Up @@ -262,6 +261,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.change_render_state(pipeline_id, render_state);
}

(ChangePageTitle(pipeline_id, title), NotShuttingDown) => {
self.change_page_title(pipeline_id, title);
}

(ChangePageLoadData(frame_id, load_data), NotShuttingDown) => {
self.change_page_load_data(frame_id, load_data);
}

(RenderMsgDiscarded, NotShuttingDown) => {
self.remove_outstanding_render_msg();
}
Expand Down Expand Up @@ -305,13 +312,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.scroll_fragment_to_point(pipeline_id, layer_id, point);
}

(LoadComplete(..), NotShuttingDown) => {
(LoadComplete, NotShuttingDown) => {
self.got_load_complete_message = true;

// If we're rendering in headless mode, schedule a recomposite.
if opts::get().output_file.is_some() {
self.composite_if_necessary();
}

// Inform the embedder that the load has finished.
//
// TODO(pcwalton): Specify which frame's load completed.
self.window.load_end();
}

(ScrollTimeout(timestamp), NotShuttingDown) => {
Expand Down Expand Up @@ -371,6 +383,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.window.set_render_state(render_state);
}

fn change_page_title(&mut self, _: PipelineId, title: Option<String>) {
self.window.set_page_title(title);
}

fn change_page_load_data(&mut self, _: FrameId, load_data: LoadData) {
self.window.set_page_load_data(load_data);
}

fn all_pipelines_in_idle_render_state(&self) -> bool {
if self.ready_states.len() == 0 {
return false;
Expand Down Expand Up @@ -629,7 +649,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
IdleWindowEvent => {}

RefreshWindowEvent => {
self.composite_if_necessary()
self.composite();
}

InitializeCompositingWindowEvent => {
self.initialize_compositing();
}

ResizeWindowEvent(size) => {
Expand Down Expand Up @@ -678,6 +702,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}

fn on_resize_window_event(&mut self, new_size: TypedSize2D<DevicePixel, uint>) {
debug!("compositor resizing to {}", new_size.to_untyped());

// A size change could also mean a resolution change.
let new_hidpi_factor = self.window.hidpi_factor();
if self.hidpi_factor != new_hidpi_factor {
Expand Down Expand Up @@ -960,6 +986,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}

fn composite(&mut self) {
if !self.window.prepare_for_composite() {
return
}

let output_image = opts::get().output_file.is_some() &&
self.is_ready_to_render_image_output();

Expand Down Expand Up @@ -995,7 +1025,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// Render the scene.
match self.scene.root {
Some(ref layer) => {
rendergl::render_scene(layer.clone(), self.context, &self.scene);
match self.context {
None => {
debug!("compositor: not compositing because context not yet set up")
}
Some(context) => {
rendergl::render_scene(layer.clone(), context, &self.scene);
}
}
}
None => {}
}
Expand Down Expand Up @@ -1053,6 +1090,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}

fn initialize_compositing(&mut self) {
let context = CompositorTask::create_graphics_context(&self.window.native_metadata());
let show_debug_borders = opts::get().show_debug_borders;
self.context = Some(rendergl::RenderContext::new(context, show_debug_borders))
}

fn find_topmost_layer_at_point_for_layer(&self,
layer: Rc<Layer<CompositorData>>,
point: TypedPoint2D<LayerPixel, f32>)
Expand Down Expand Up @@ -1229,4 +1272,17 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind

self.scrolling_timer.shutdown();
}

fn pinch_zoom_level(&self) -> f32 {
self.viewport_zoom.get() as f32
}

fn get_title_for_main_frame(&self) {
let root_pipeline_id = match self.root_pipeline {
None => return,
Some(ref root_pipeline) => root_pipeline.id,
};
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(GetPipelineTitleMsg(root_pipeline_id));
}
}
18 changes: 16 additions & 2 deletions components/compositing/compositor_task.rs
Expand Up @@ -5,7 +5,7 @@
//! Communication with the compositor task.

pub use windowing;
pub use constellation::{SendableFrameTree, FrameTreeDiff};
pub use constellation::{FrameId, SendableFrameTree, FrameTreeDiff};

use compositor;
use headless;
Expand All @@ -19,7 +19,7 @@ use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphics
use layers::layers::LayerBufferSet;
use servo_msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState};
use servo_msg::compositor_msg::{RenderListener, RenderState, ScriptListener, ScrollPolicy};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
use servo_msg::constellation_msg::{ConstellationChan, LoadData, PipelineId};
use servo_util::memory::MemoryProfilerChan;
use servo_util::time::TimeProfilerChan;
use std::comm::{channel, Sender, Receiver};
Expand Down Expand Up @@ -81,8 +81,13 @@ impl ScriptListener for Box<CompositorProxy+'static+Send> {
fn dup(&mut self) -> Box<ScriptListener+'static> {
box self.clone_compositor_proxy() as Box<ScriptListener+'static>
}

fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
self.send(ChangePageTitle(pipeline_id, title))
}
}

/// Information about each layer that the compositor keeps.
pub struct LayerProperties {
pub pipeline_id: PipelineId,
pub epoch: Epoch,
Expand Down Expand Up @@ -184,6 +189,10 @@ pub enum Msg {
ChangeReadyState(PipelineId, ReadyState),
/// Alerts the compositor to the current status of rendering.
ChangeRenderState(PipelineId, RenderState),
/// 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 load data (including URL).
ChangePageLoadData(FrameId, LoadData),
/// Alerts the compositor that the RenderMsg has been discarded.
RenderMsgDiscarded,
/// Sets the channel to the current layout and render tasks, along with their id
Expand All @@ -210,6 +219,8 @@ impl Show for Msg {
Paint(..) => write!(f, "Paint"),
ChangeReadyState(..) => write!(f, "ChangeReadyState"),
ChangeRenderState(..) => write!(f, "ChangeRenderState"),
ChangePageTitle(..) => write!(f, "ChangePageTitle"),
ChangePageLoadData(..) => write!(f, "ChangePageLoadData"),
RenderMsgDiscarded(..) => write!(f, "RenderMsgDiscarded"),
SetIds(..) => write!(f, "SetIds"),
FrameTreeUpdateMsg(..) => write!(f, "FrameTreeUpdateMsg"),
Expand Down Expand Up @@ -269,5 +280,8 @@ pub trait CompositorEventListener {
fn handle_event(&mut self, event: WindowEvent) -> bool;
fn repaint_synchronously(&mut self);
fn shutdown(&mut self);
fn pinch_zoom_level(&self) -> f32;
/// Requests that the compositor send the title for the main frame as soon as possible.
fn get_title_for_main_frame(&self);
}

0 comments on commit 48c9881

Please sign in to comment.