mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Add WebRender integration to Servo.
WebRender is an experimental GPU accelerated rendering backend for Servo. The WebRender backend can be specified by running Servo with the -w option (otherwise the default rendering backend will be used). WebRender has many bugs, and missing features - but it is usable to browse most websites - please report any WebRender specific rendering bugs you encounter!
This commit is contained in:
parent
f7f0eea470
commit
c0531c312f
75 changed files with 2869 additions and 888 deletions
|
@ -6,7 +6,7 @@ use CompositorMsg as ConstellationMsg;
|
|||
use app_units::Au;
|
||||
use compositor_layer::{CompositorData, CompositorLayer, RcCompositorLayer, WantsScrollEventsFlag};
|
||||
use compositor_thread::{CompositorEventListener, CompositorProxy};
|
||||
use compositor_thread::{CompositorReceiver, InitialCompositorState, Msg};
|
||||
use compositor_thread::{CompositorReceiver, InitialCompositorState, Msg, RenderListener};
|
||||
use constellation::SendableFrameTree;
|
||||
use euclid::point::TypedPoint2D;
|
||||
use euclid::rect::TypedRect;
|
||||
|
@ -27,15 +27,15 @@ use layers::rendergl;
|
|||
use layers::rendergl::RenderContext;
|
||||
use layers::scene::Scene;
|
||||
use layout_traits::LayoutControlChan;
|
||||
use msg::constellation_msg::{Image, PixelFormat};
|
||||
use msg::constellation_msg::{ConvertPipelineIdFromWebRender, ConvertPipelineIdToWebRender, Image, PixelFormat};
|
||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
||||
use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData};
|
||||
use pipeline::CompositionPipeline;
|
||||
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_traits::CompositorEvent::{MouseMoveEvent, TouchEvent};
|
||||
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
|
||||
use script_traits::{AnimationState, ConstellationControlMsg, LayoutControlMsg};
|
||||
use script_traits::{MouseButton, TouchEventType, TouchId};
|
||||
use script_traits::{MouseButton, MouseEventType, TouchEventType, TouchId};
|
||||
use scrolling::ScrollingTimerProxy;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -51,6 +51,8 @@ use url::Url;
|
|||
use util::geometry::{PagePx, ScreenPx, ViewportPx};
|
||||
use util::opts;
|
||||
use util::print_tree::PrintTree;
|
||||
use webrender;
|
||||
use webrender_traits;
|
||||
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -192,6 +194,12 @@ pub struct IOCompositor<Window: WindowMethods> {
|
|||
|
||||
/// The id of the pipeline that was last sent a mouse move event, if any.
|
||||
last_mouse_move_recipient: Option<PipelineId>,
|
||||
|
||||
/// The webrender renderer, if enabled.
|
||||
webrender: Option<webrender::Renderer>,
|
||||
|
||||
/// The webrender interface, if enabled.
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
}
|
||||
|
||||
pub struct ScrollZoomEvent {
|
||||
|
@ -261,7 +269,23 @@ pub enum CompositeTarget {
|
|||
PngFile
|
||||
}
|
||||
|
||||
fn initialize_png(width: usize, height: usize) -> (Vec<gl::GLuint>, Vec<gl::GLuint>) {
|
||||
struct RenderTargetInfo {
|
||||
framebuffer_ids: Vec<gl::GLuint>,
|
||||
texture_ids: Vec<gl::GLuint>,
|
||||
renderbuffer_ids: Vec<gl::GLuint>,
|
||||
}
|
||||
|
||||
impl RenderTargetInfo {
|
||||
fn empty() -> RenderTargetInfo {
|
||||
RenderTargetInfo {
|
||||
framebuffer_ids: Vec::new(),
|
||||
texture_ids: Vec::new(),
|
||||
renderbuffer_ids: Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_png(width: usize, height: usize) -> RenderTargetInfo {
|
||||
let framebuffer_ids = gl::gen_framebuffers(1);
|
||||
gl::bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
|
||||
|
||||
|
@ -278,13 +302,64 @@ fn initialize_png(width: usize, height: usize) -> (Vec<gl::GLuint>, Vec<gl::GLui
|
|||
|
||||
gl::bind_texture(gl::TEXTURE_2D, 0);
|
||||
|
||||
(framebuffer_ids, texture_ids)
|
||||
let renderbuffer_ids = if opts::get().use_webrender {
|
||||
let renderbuffer_ids = gl::gen_renderbuffers(1);
|
||||
gl::bind_renderbuffer(gl::RENDERBUFFER, renderbuffer_ids[0]);
|
||||
gl::renderbuffer_storage(gl::RENDERBUFFER,
|
||||
gl::STENCIL_INDEX8,
|
||||
width as GLsizei,
|
||||
height as GLsizei);
|
||||
gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
|
||||
gl::STENCIL_ATTACHMENT,
|
||||
gl::RENDERBUFFER,
|
||||
renderbuffer_ids[0]);
|
||||
renderbuffer_ids
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
RenderTargetInfo {
|
||||
framebuffer_ids: framebuffer_ids,
|
||||
texture_ids: texture_ids,
|
||||
renderbuffer_ids: renderbuffer_ids
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reporter_name() -> String {
|
||||
"compositor-reporter".to_owned()
|
||||
}
|
||||
|
||||
struct RenderNotifier {
|
||||
compositor_proxy: Box<CompositorProxy>,
|
||||
constellation_chan: Sender<ConstellationMsg>,
|
||||
}
|
||||
|
||||
impl RenderNotifier {
|
||||
fn new(compositor_proxy: Box<CompositorProxy>,
|
||||
constellation_chan: Sender<ConstellationMsg>) -> RenderNotifier {
|
||||
RenderNotifier {
|
||||
compositor_proxy: compositor_proxy,
|
||||
constellation_chan: constellation_chan,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl webrender_traits::RenderNotifier for RenderNotifier {
|
||||
fn new_frame_ready(&mut self) {
|
||||
self.compositor_proxy.recomposite();
|
||||
}
|
||||
|
||||
fn pipeline_size_changed(&mut self,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
size: Option<Size2D<f32>>) {
|
||||
let pipeline_id = pipeline_id.from_webrender();
|
||||
let size = size.unwrap_or(Size2D::zero());
|
||||
|
||||
self.constellation_chan.send(ConstellationMsg::FrameSize(pipeline_id,
|
||||
size)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<Window: WindowMethods> IOCompositor<Window> {
|
||||
fn new(window: Rc<Window>, state: InitialCompositorState)
|
||||
-> IOCompositor<Window> {
|
||||
|
@ -306,6 +381,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
Some(_) => CompositeTarget::PngFile,
|
||||
None => CompositeTarget::Window
|
||||
};
|
||||
|
||||
let webrender_api = state.webrender_api_sender.map(|sender| {
|
||||
sender.create_api()
|
||||
});
|
||||
|
||||
let native_display = window.native_display();
|
||||
IOCompositor {
|
||||
window: window,
|
||||
|
@ -345,6 +425,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
surface_map: SurfaceMap::new(BUFFER_MAP_SIZE),
|
||||
pending_subpages: HashSet::new(),
|
||||
last_mouse_move_recipient: None,
|
||||
webrender: state.webrender,
|
||||
webrender_api: webrender_api,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +434,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
-> IOCompositor<Window> {
|
||||
let mut compositor = IOCompositor::new(window, state);
|
||||
|
||||
if let Some(ref mut webrender) = compositor.webrender {
|
||||
let compositor_proxy_for_webrender = compositor.channel_to_self
|
||||
.clone_compositor_proxy();
|
||||
let render_notifier = RenderNotifier::new(compositor_proxy_for_webrender,
|
||||
compositor.constellation_chan.clone());
|
||||
webrender.set_render_notifier(Box::new(render_notifier));
|
||||
}
|
||||
|
||||
// Set the size of the root layer.
|
||||
compositor.update_zoom_transform();
|
||||
|
||||
|
@ -674,6 +764,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
self.root_pipeline = Some(frame_tree.pipeline.clone());
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let pipeline_id = frame_tree.pipeline.id.to_webrender();
|
||||
webrender_api.set_root_pipeline(pipeline_id);
|
||||
}
|
||||
|
||||
// If we have an old root layer, release all old tiles before replacing it.
|
||||
let old_root_layer = self.scene.root.take();
|
||||
if let Some(ref old_root_layer) = old_root_layer {
|
||||
|
@ -1172,6 +1267,36 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
MouseWindowEvent::MouseDown(_, p) => p,
|
||||
MouseWindowEvent::MouseUp(_, p) => p,
|
||||
};
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let root_pipeline_id = match self.get_root_pipeline_id() {
|
||||
Some(root_pipeline_id) => root_pipeline_id,
|
||||
None => return,
|
||||
};
|
||||
let root_pipeline = match self.pipeline(root_pipeline_id) {
|
||||
Some(root_pipeline) => root_pipeline,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let translated_point =
|
||||
webrender_api.translate_point_to_layer_space(&point.to_untyped());
|
||||
let event_to_send = match mouse_window_event {
|
||||
MouseWindowEvent::Click(button, _) => {
|
||||
MouseButtonEvent(MouseEventType::Click, button, translated_point)
|
||||
}
|
||||
MouseWindowEvent::MouseDown(button, _) => {
|
||||
MouseButtonEvent(MouseEventType::MouseDown, button, translated_point)
|
||||
}
|
||||
MouseWindowEvent::MouseUp(button, _) => {
|
||||
MouseButtonEvent(MouseEventType::MouseUp, button, translated_point)
|
||||
}
|
||||
};
|
||||
root_pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(root_pipeline_id,
|
||||
event_to_send))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
match self.find_topmost_layer_at_point(point / self.scene.scale) {
|
||||
Some(result) => result.layer.send_mouse_event(self, mouse_window_event, result.point),
|
||||
None => {},
|
||||
|
@ -1184,6 +1309,25 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
return
|
||||
}
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let root_pipeline_id = match self.get_root_pipeline_id() {
|
||||
Some(root_pipeline_id) => root_pipeline_id,
|
||||
None => return,
|
||||
};
|
||||
let root_pipeline = match self.pipeline(root_pipeline_id) {
|
||||
Some(root_pipeline) => root_pipeline,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let translated_point =
|
||||
webrender_api.translate_point_to_layer_space(&cursor.to_untyped());
|
||||
let event_to_send = MouseMoveEvent(Some(translated_point));
|
||||
root_pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(root_pipeline_id,
|
||||
event_to_send))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
match self.find_topmost_layer_at_point(cursor / self.scene.scale) {
|
||||
Some(result) => {
|
||||
// In the case that the mouse was previously over a different layer,
|
||||
|
@ -1285,30 +1429,52 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
fn process_pending_scroll_events(&mut self) {
|
||||
let had_events = self.pending_scroll_zoom_events.len() > 0;
|
||||
for event in std_mem::replace(&mut self.pending_scroll_zoom_events,
|
||||
Vec::new()) {
|
||||
let delta = event.delta / self.scene.scale;
|
||||
let cursor = event.cursor.as_f32() / self.scene.scale;
|
||||
|
||||
if let Some(ref mut layer) = self.scene.root {
|
||||
layer.handle_scroll_event(delta, cursor);
|
||||
match self.webrender_api {
|
||||
Some(ref webrender_api) => {
|
||||
// Batch up all scroll events into one, or else we'll do way too much painting.
|
||||
let mut total_delta = None;
|
||||
let mut last_cursor = Point2D::zero();
|
||||
for scroll_event in self.pending_scroll_zoom_events.drain(..) {
|
||||
let this_delta = scroll_event.delta / self.scene.scale;
|
||||
last_cursor = scroll_event.cursor.as_f32() / self.scene.scale;
|
||||
match total_delta {
|
||||
None => total_delta = Some(this_delta),
|
||||
Some(ref mut total_delta) => *total_delta = *total_delta + this_delta,
|
||||
}
|
||||
}
|
||||
// TODO(gw): Support zoom (WR issue #28).
|
||||
if let Some(total_delta) = total_delta {
|
||||
webrender_api.scroll(total_delta.to_untyped(), last_cursor.to_untyped());
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for event in std_mem::replace(&mut self.pending_scroll_zoom_events,
|
||||
Vec::new()) {
|
||||
let delta = event.delta / self.scene.scale;
|
||||
let cursor = event.cursor.as_f32() / self.scene.scale;
|
||||
|
||||
if event.magnification != 1.0 {
|
||||
self.zoom_action = true;
|
||||
self.zoom_time = precise_time_s();
|
||||
self.viewport_zoom = ScaleFactor::new(
|
||||
(self.viewport_zoom.get() * event.magnification)
|
||||
.min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get))
|
||||
.max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get)));
|
||||
self.update_zoom_transform();
|
||||
if let Some(ref mut layer) = self.scene.root {
|
||||
layer.handle_scroll_event(delta, cursor);
|
||||
}
|
||||
|
||||
if event.magnification != 1.0 {
|
||||
self.zoom_action = true;
|
||||
self.zoom_time = precise_time_s();
|
||||
self.viewport_zoom = ScaleFactor::new(
|
||||
(self.viewport_zoom.get() * event.magnification)
|
||||
.min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get))
|
||||
.max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get)));
|
||||
self.update_zoom_transform();
|
||||
}
|
||||
|
||||
self.perform_updates_after_scroll();
|
||||
}
|
||||
|
||||
if had_events {
|
||||
self.send_viewport_rects_for_all_layers();
|
||||
}
|
||||
}
|
||||
|
||||
self.perform_updates_after_scroll();
|
||||
}
|
||||
|
||||
if had_events {
|
||||
self.send_viewport_rects_for_all_layers();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1542,6 +1708,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
/// Returns true if any buffer requests were sent or false otherwise.
|
||||
fn send_buffer_requests_for_all_layers(&mut self) -> bool {
|
||||
if self.webrender.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(ref root_layer) = self.scene.root {
|
||||
root_layer.update_transform_state(&Matrix4::identity(),
|
||||
&Matrix4::identity(),
|
||||
|
@ -1656,7 +1826,15 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
// frame tree.
|
||||
let mut pipeline_epochs = HashMap::new();
|
||||
for (id, details) in &self.pipeline_details {
|
||||
pipeline_epochs.insert(*id, details.current_epoch);
|
||||
if let Some(ref webrender) = self.webrender {
|
||||
let webrender_pipeline_id = id.to_webrender();
|
||||
if let Some(webrender_traits::Epoch(epoch)) = webrender.current_epoch(webrender_pipeline_id) {
|
||||
let epoch = Epoch(epoch);
|
||||
pipeline_epochs.insert(*id, epoch);
|
||||
}
|
||||
} else {
|
||||
pipeline_epochs.insert(*id, details.current_epoch);
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the pipeline/epoch states to the constellation and check
|
||||
|
@ -1707,7 +1885,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
/// is WindowAndPng Ok(Some(png::Image)) is returned.
|
||||
pub fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<Image>, UnableToComposite> {
|
||||
|
||||
if !self.context.is_some() {
|
||||
if self.context.is_none() && self.webrender.is_none() {
|
||||
return Err(UnableToComposite::NoContext)
|
||||
}
|
||||
let (width, height) =
|
||||
|
@ -1716,6 +1894,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
return Err(UnableToComposite::WindowUnprepared)
|
||||
}
|
||||
|
||||
if let Some(ref mut webrender) = self.webrender {
|
||||
assert!(self.context.is_none());
|
||||
webrender.update();
|
||||
}
|
||||
|
||||
let wait_for_stable_image = match target {
|
||||
CompositeTarget::WindowAndPng | CompositeTarget::PngFile => true,
|
||||
CompositeTarget::Window => opts::get().exit_after_load,
|
||||
|
@ -1738,8 +1921,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
let (framebuffer_ids, texture_ids) = match target {
|
||||
CompositeTarget::Window => (vec!(), vec!()),
|
||||
let render_target_info = match target {
|
||||
CompositeTarget::Window => RenderTargetInfo::empty(),
|
||||
_ => initialize_png(width, height)
|
||||
};
|
||||
|
||||
|
@ -1760,7 +1943,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
};
|
||||
|
||||
// Paint the scene.
|
||||
if let Some(ref layer) = self.scene.root {
|
||||
if let Some(ref mut webrender) = self.webrender {
|
||||
assert!(self.context.is_none());
|
||||
webrender.render(self.window_size.to_untyped());
|
||||
} else if let Some(ref layer) = self.scene.root {
|
||||
match self.context {
|
||||
Some(context) => {
|
||||
if let Some((point, size)) = self.viewport {
|
||||
|
@ -1790,16 +1976,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
let rv = match target {
|
||||
CompositeTarget::Window => None,
|
||||
CompositeTarget::WindowAndPng => {
|
||||
let img = self.draw_img(framebuffer_ids, texture_ids, width, height);
|
||||
let img = self.draw_img(render_target_info,
|
||||
width,
|
||||
height);
|
||||
Some(Image {
|
||||
width: img.width(),
|
||||
height: img.height(),
|
||||
format: PixelFormat::RGB8,
|
||||
bytes: IpcSharedMemory::from_bytes(&*img),
|
||||
id: None,
|
||||
})
|
||||
}
|
||||
CompositeTarget::PngFile => {
|
||||
let img = self.draw_img(framebuffer_ids, texture_ids, width, height);
|
||||
let img = self.draw_img(render_target_info,
|
||||
width,
|
||||
height);
|
||||
let path = opts::get().output_file.as_ref().unwrap();
|
||||
let mut file = File::create(path).unwrap();
|
||||
DynamicImage::ImageRgb8(img).save(&mut file, ImageFormat::PNG).unwrap();
|
||||
|
@ -1820,8 +2011,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
fn draw_img(&self,
|
||||
framebuffer_ids: Vec<gl::GLuint>,
|
||||
texture_ids: Vec<gl::GLuint>,
|
||||
render_target_info: RenderTargetInfo,
|
||||
width: usize,
|
||||
height: usize)
|
||||
-> RgbImage {
|
||||
|
@ -1832,8 +2022,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
gl::bind_framebuffer(gl::FRAMEBUFFER, 0);
|
||||
|
||||
gl::delete_buffers(&texture_ids);
|
||||
gl::delete_frame_buffers(&framebuffer_ids);
|
||||
gl::delete_buffers(&render_target_info.texture_ids);
|
||||
gl::delete_frame_buffers(&render_target_info.framebuffer_ids);
|
||||
if opts::get().use_webrender {
|
||||
gl::delete_renderbuffers(&render_target_info.renderbuffer_ids);
|
||||
}
|
||||
|
||||
// flip image vertically (texture is upside down)
|
||||
let orig_pixels = pixels.clone();
|
||||
|
@ -1859,10 +2052,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
fn initialize_compositing(&mut self) {
|
||||
let show_debug_borders = opts::get().show_debug_borders;
|
||||
self.context = Some(rendergl::RenderContext::new(self.native_display.clone(),
|
||||
show_debug_borders,
|
||||
opts::get().output_file.is_some()))
|
||||
if self.webrender.is_none() {
|
||||
let show_debug_borders = opts::get().show_debug_borders;
|
||||
self.context = Some(rendergl::RenderContext::new(self.native_display.clone(),
|
||||
show_debug_borders,
|
||||
opts::get().output_file.is_some()))
|
||||
}
|
||||
}
|
||||
|
||||
fn find_topmost_layer_at_point_for_layer(&self,
|
||||
|
@ -1951,6 +2146,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
self.surface_map.insert_surfaces(&self.native_display, surfaces);
|
||||
}
|
||||
|
||||
fn get_root_pipeline_id(&self) -> Option<PipelineId> {
|
||||
self.scene.root.as_ref().map(|root_layer| root_layer.extra_data.borrow().pipeline_id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn dump_layer_tree(&self) {
|
||||
if !opts::get().dump_layer_tree {
|
||||
|
@ -2076,19 +2275,37 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind
|
|||
///
|
||||
/// This is used when resizing the window.
|
||||
fn repaint_synchronously(&mut self) {
|
||||
while self.shutdown_state != ShutdownState::ShuttingDown {
|
||||
let msg = self.port.recv_compositor_msg();
|
||||
let received_new_buffers = match msg {
|
||||
Msg::AssignPaintedBuffers(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
let keep_going = self.handle_browser_message(msg);
|
||||
if received_new_buffers {
|
||||
self.composite();
|
||||
break
|
||||
if self.webrender.is_none() {
|
||||
while self.shutdown_state != ShutdownState::ShuttingDown {
|
||||
let msg = self.port.recv_compositor_msg();
|
||||
let received_new_buffers = match msg {
|
||||
Msg::AssignPaintedBuffers(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
let keep_going = self.handle_browser_message(msg);
|
||||
if received_new_buffers {
|
||||
self.composite();
|
||||
break
|
||||
}
|
||||
if !keep_going {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !keep_going {
|
||||
break
|
||||
} else {
|
||||
while self.shutdown_state != ShutdownState::ShuttingDown {
|
||||
let msg = self.port.recv_compositor_msg();
|
||||
let need_recomposite = match msg {
|
||||
Msg::RecompositeAfterScroll => true,
|
||||
_ => false,
|
||||
};
|
||||
let keep_going = self.handle_browser_message(msg);
|
||||
if need_recomposite {
|
||||
self.composite();
|
||||
break
|
||||
}
|
||||
if !keep_going {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue