From 3622d66a9069ee6b0bd695de6691989c65586d3d Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 20 Oct 2017 15:50:11 -0400 Subject: [PATCH 1/2] Pass in notifier at renderer creation. --- webrender/examples/common/boilerplate.rs | 6 ++-- webrender/src/render_backend.rs | 18 ++++-------- webrender/src/renderer.rs | 19 ++----------- wrench/src/main.rs | 36 +++++++++++++++++++++--- wrench/src/perf.rs | 20 ++----------- wrench/src/png.rs | 18 ++---------- wrench/src/rawtest.rs | 19 ++----------- wrench/src/reftest.rs | 19 ++----------- wrench/src/wrench.rs | 12 ++++---- 9 files changed, 57 insertions(+), 110 deletions(-) diff --git a/webrender/examples/common/boilerplate.rs b/webrender/examples/common/boilerplate.rs index 785f38d8d8..3dfece4345 100644 --- a/webrender/examples/common/boilerplate.rs +++ b/webrender/examples/common/boilerplate.rs @@ -125,13 +125,11 @@ pub fn main_wrapper(example: &mut Example, options: Option, - notifier: Arc>>>, + notifier: Arc>>, recorder: Option>, enable_render_on_scroll: bool, @@ -160,7 +160,7 @@ impl RenderBackend { default_device_pixel_ratio: f32, texture_cache: TextureCache, workers: Arc, - notifier: Arc>>>, + notifier: Arc>>, frame_config: FrameBuilderConfig, recorder: Option>, blob_image_renderer: Option>, @@ -445,7 +445,7 @@ impl RenderBackend { } Err(..) => { let notifier = self.notifier.lock(); - notifier.unwrap().as_mut().unwrap().shut_down(); + notifier.unwrap().shut_down(); break; } }; @@ -512,7 +512,7 @@ impl RenderBackend { } ApiMsg::ExternalEvent(evt) => { let notifier = self.notifier.lock(); - notifier.unwrap().as_mut().unwrap().external_event(evt); + notifier.unwrap().external_event(evt); } ApiMsg::ClearNamespace(namespace_id) => { self.resource_cache.clear_namespace(namespace_id); @@ -540,8 +540,6 @@ impl RenderBackend { self.notifier .lock() .unwrap() - .as_mut() - .unwrap() .new_frame_ready(); } ApiMsg::DebugCommand(option) => { @@ -558,11 +556,11 @@ impl RenderBackend { }; self.result_tx.send(msg).unwrap(); let notifier = self.notifier.lock(); - notifier.unwrap().as_mut().unwrap().new_frame_ready(); + notifier.unwrap().new_frame_ready(); } ApiMsg::ShutDown => { let notifier = self.notifier.lock(); - notifier.unwrap().as_mut().unwrap().shut_down(); + notifier.unwrap().shut_down(); break; } } @@ -595,8 +593,6 @@ impl RenderBackend { // cleaner way to do this, or use the OnceMutex on crates.io? let mut notifier = self.notifier.lock(); notifier - .as_mut() - .unwrap() .as_mut() .unwrap() .new_frame_ready(); @@ -609,8 +605,6 @@ impl RenderBackend { // cleaner way to do this, or use the OnceMutex on crates.io? let mut notifier = self.notifier.lock(); notifier - .as_mut() - .unwrap() .as_mut() .unwrap() .new_scroll_frame_ready(composite_needed); diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 0c4fbc41f8..7b4a3d35bb 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -930,7 +930,7 @@ struct PrimitiveShader { } struct FileWatcher { - notifier: Arc>>>, + notifier: Arc>>, result_tx: Sender, } @@ -939,8 +939,6 @@ impl FileWatcherHandler for FileWatcher { self.result_tx.send(ResultMsg::RefreshShader(path)).ok(); let mut notifier = self.notifier.lock(); notifier - .as_mut() - .unwrap() .as_mut() .unwrap() .new_frame_ready(); @@ -1137,8 +1135,6 @@ pub struct Renderer { ps_split_composite: LazilyCompiledShader, ps_composite: LazilyCompiledShader, - notifier: Arc>>>, - max_texture_size: u32, max_recorded_profiles: usize, @@ -1234,6 +1230,7 @@ impl Renderer { /// [rendereroptions]: struct.RendererOptions.html pub fn new( gl: Rc, + notifier: Box, mut options: RendererOptions, ) -> Result<(Renderer, RenderApiSender), RendererError> { let (api_tx, api_rx) = try!{ channel::msg_channel() }; @@ -1241,7 +1238,7 @@ impl Renderer { let (result_tx, result_rx) = channel(); let gl_type = gl.get_type(); - let notifier = Arc::new(Mutex::new(None)); + let notifier = Arc::new(Mutex::new(notifier)); let debug_server = DebugServer::new(api_tx.clone()); let file_watch_handler = FileWatcher { @@ -1740,7 +1737,6 @@ impl Renderer { ps_split_composite, ps_composite, ps_line, - notifier, debug: debug_renderer, debug_flags, enable_batcher: options.enable_batcher, @@ -1799,15 +1795,6 @@ impl Renderer { (color_space as usize) } - /// Sets the new RenderNotifier. - /// - /// The RenderNotifier will be called when processing e.g. of a (scrolling) frame is done, - /// and therefore the screen should be updated. - pub fn set_render_notifier(&self, notifier: Box) { - let mut notifier_arc = self.notifier.lock().unwrap(); - *notifier_arc = Some(notifier); - } - /// Returns the Epoch of the current frame in a pipeline. pub fn current_epoch(&self, pipeline_id: PipelineId) -> Option { self.pipeline_epoch_map.get(&pipeline_id).cloned() diff --git a/wrench/src/main.rs b/wrench/src/main.rs index b80aa5f474..43b72d1371 100644 --- a/wrench/src/main.rs +++ b/wrench/src/main.rs @@ -63,6 +63,7 @@ use std::os::raw::c_void; use std::path::{Path, PathBuf}; use std::ptr; use std::rc::Rc; +use std::sync::mpsc::{channel, Sender, Receiver}; use webrender::api::*; use wrench::{Wrench, WrenchThing}; use yaml_frame_reader::YamlFrameReader; @@ -278,6 +279,21 @@ fn make_window( wrapper } +fn create_notifier() -> (Box, Receiver<()>) { + // setup a notifier so we can wait for frames to be finished + struct Notifier { + tx: Sender<()>, + }; + impl RenderNotifier for Notifier { + fn new_frame_ready(&mut self) { + self.tx.send(()).unwrap(); + } + fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {} + } + let (tx, rx) = channel(); + (Box::new(Notifier { tx: tx }), rx) +} + fn main() { #[cfg(feature = "logging")] env_logger::init().unwrap(); @@ -321,6 +337,17 @@ fn main() { let dp_ratio = dp_ratio.unwrap_or(window.hidpi_factor()); let (width, height) = window.get_inner_size_pixels(); let dim = DeviceUintSize::new(width, height); + + let needs_frame_notifier = ["perf", "reftest", "png", "rawtest"] + .iter() + .any(|s| args.subcommand_matches(s).is_some()); + let (notifier, rx) = if needs_frame_notifier { + let (notifier, rx) = create_notifier(); + (Some(notifier), Some(rx)) + } else { + (None, None) + }; + let mut wrench = Wrench::new( &mut window, res_path, @@ -333,6 +360,7 @@ fn main() { args.is_present("verbose"), args.is_present("no_scissor"), args.is_present("no_batch"), + notifier, ); let mut thing = if let Some(subargs) = args.subcommand_matches("show") { @@ -341,12 +369,12 @@ fn main() { Box::new(BinaryFrameReader::new_from_args(subargs)) as Box } else if let Some(subargs) = args.subcommand_matches("png") { let reader = YamlFrameReader::new_from_args(subargs); - png::png(&mut wrench, &mut window, reader); + png::png(&mut wrench, &mut window, reader, rx.unwrap()); wrench.renderer.deinit(); return; } else if let Some(subargs) = args.subcommand_matches("reftest") { let (w, h) = window.get_inner_size_pixels(); - let harness = ReftestHarness::new(&mut wrench, &mut window); + let harness = ReftestHarness::new(&mut wrench, &mut window, rx.unwrap()); let base_manifest = Path::new("reftests/reftest.list"); let specific_reftest = subargs.value_of("REFTEST").map(|x| Path::new(x)); let mut reftest_options = ReftestOptions::default(); @@ -358,7 +386,7 @@ fn main() { return; } else if let Some(_) = args.subcommand_matches("rawtest") { { - let harness = RawtestHarness::new(&mut wrench, &mut window); + let harness = RawtestHarness::new(&mut wrench, &mut window, rx.unwrap()); harness.run(); } wrench.renderer.deinit(); @@ -367,7 +395,7 @@ fn main() { // Perf mode wants to benchmark the total cost of drawing // a new displaty list each frame. wrench.rebuild_display_lists = true; - let harness = PerfHarness::new(&mut wrench, &mut window); + let harness = PerfHarness::new(&mut wrench, &mut window, rx.unwrap()); let base_manifest = Path::new("benchmarks/benchmarks.list"); let filename = subargs.value_of("filename").unwrap(); harness.run(base_manifest, filename); diff --git a/wrench/src/perf.rs b/wrench/src/perf.rs index 8de1a7bc1f..be17dc270a 100644 --- a/wrench/src/perf.rs +++ b/wrench/src/perf.rs @@ -9,8 +9,7 @@ use std::fs::File; use std::io::{BufRead, BufReader}; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; -use std::sync::mpsc::{channel, Receiver, Sender}; -use webrender::api::*; +use std::sync::mpsc::Receiver; use wrench::{Wrench, WrenchThing}; use yaml_frame_reader::YamlFrameReader; @@ -128,22 +127,7 @@ pub struct PerfHarness<'a> { } impl<'a> PerfHarness<'a> { - pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper) -> PerfHarness<'a> { - // setup a notifier so we can wait for frames to be finished - struct Notifier { - tx: Sender<()>, - }; - impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { - self.tx.send(()).unwrap(); - } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {} - } - let (tx, rx) = channel(); - wrench - .renderer - .set_render_notifier(Box::new(Notifier { tx: tx })); - + pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper, rx: Receiver<()>) -> PerfHarness<'a> { PerfHarness { wrench, window, rx } } diff --git a/wrench/src/png.rs b/wrench/src/png.rs index 446cbdfbb7..c267b3ed75 100644 --- a/wrench/src/png.rs +++ b/wrench/src/png.rs @@ -7,7 +7,7 @@ use image::ColorType; use image::png::PNGEncoder; use std::fs::File; use std::path::Path; -use std::sync::mpsc::{channel, Sender}; +use std::sync::mpsc::Receiver; use webrender::api::*; use wrench::{Wrench, WrenchThing}; use yaml_frame_reader::YamlFrameReader; @@ -29,21 +29,7 @@ pub fn save_flipped>(path: P, orig_pixels: &[u8], size: DeviceUin .expect("Unable to encode PNG!"); } -pub fn png(wrench: &mut Wrench, window: &mut WindowWrapper, mut reader: YamlFrameReader) { - // setup a notifier so we can wait for frames to be finished - struct Notifier { - tx: Sender<()>, - }; - impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { - self.tx.send(()).unwrap(); - } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {} - } - let (tx, rx) = channel(); - wrench - .renderer - .set_render_notifier(Box::new(Notifier { tx: tx })); +pub fn png(wrench: &mut Wrench, window: &mut WindowWrapper, mut reader: YamlFrameReader, rx: Receiver<()>) { reader.do_frame(wrench); // wait for the frame diff --git a/wrench/src/rawtest.rs b/wrench/src/rawtest.rs index 8f74f02072..6c62c654cf 100644 --- a/wrench/src/rawtest.rs +++ b/wrench/src/rawtest.rs @@ -4,7 +4,7 @@ use WindowWrapper; use blob; -use std::sync::mpsc::{channel, Receiver, Sender}; +use std::sync::mpsc::Receiver; use webrender::api::*; use wrench::Wrench; @@ -15,22 +15,7 @@ pub struct RawtestHarness<'a> { } impl<'a> RawtestHarness<'a> { - pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper) -> RawtestHarness<'a> { - // setup a notifier so we can wait for frames to be finished - struct Notifier { - tx: Sender<()>, - }; - impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { - self.tx.send(()).unwrap(); - } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {} - } - let (tx, rx) = channel(); - wrench - .renderer - .set_render_notifier(Box::new(Notifier { tx: tx })); - + pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper, rx: Receiver<()>) -> RawtestHarness<'a> { RawtestHarness { wrench: wrench, rx: rx, diff --git a/wrench/src/reftest.rs b/wrench/src/reftest.rs index 4ad6870369..d32b842f2b 100644 --- a/wrench/src/reftest.rs +++ b/wrench/src/reftest.rs @@ -14,7 +14,7 @@ use std::fmt::{Display, Error, Formatter}; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; -use std::sync::mpsc::{channel, Receiver, Sender}; +use std::sync::mpsc::Receiver; use webrender::api::*; use wrench::{Wrench, WrenchThing}; use yaml_frame_reader::YamlFrameReader; @@ -259,22 +259,7 @@ pub struct ReftestHarness<'a> { rx: Receiver<()>, } impl<'a> ReftestHarness<'a> { - pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper) -> ReftestHarness<'a> { - // setup a notifier so we can wait for frames to be finished - struct Notifier { - tx: Sender<()>, - }; - impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { - self.tx.send(()).unwrap(); - } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {} - } - let (tx, rx) = channel(); - wrench - .renderer - .set_render_notifier(Box::new(Notifier { tx: tx })); - + pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper, rx: Receiver<()>) -> ReftestHarness<'a> { ReftestHarness { wrench, window, rx } } diff --git a/wrench/src/wrench.rs b/wrench/src/wrench.rs index 5d8e79e6b5..38fa68486c 100644 --- a/wrench/src/wrench.rs +++ b/wrench/src/wrench.rs @@ -138,6 +138,7 @@ impl Wrench { verbose: bool, no_scissor: bool, no_batch: bool, + notifier: Option>, ) -> Wrench { println!("Shader override path: {:?}", shader_override_path); @@ -167,10 +168,6 @@ impl Wrench { ..Default::default() }; - let (renderer, sender) = webrender::Renderer::new(window.clone_gl(), opts).unwrap(); - let api = sender.create_api(); - let document_id = api.add_document(size); - let proxy = window.create_window_proxy(); // put an Awakened event into the queue to kick off the first frame if let Some(ref wp) = proxy { @@ -179,8 +176,11 @@ impl Wrench { } let (timing_sender, timing_receiver) = chase_lev::deque(); - let notifier = Box::new(Notifier::new(proxy, timing_receiver, verbose)); - renderer.set_render_notifier(notifier); + let notifier = notifier.unwrap_or_else(|| Box::new(Notifier::new(proxy, timing_receiver, verbose))); + + let (renderer, sender) = webrender::Renderer::new(window.clone_gl(), notifier, opts).unwrap(); + let api = sender.create_api(); + let document_id = api.add_document(size); let graphics_api = renderer.get_graphics_api_info(); From 78fd025236e141ee4bd76e9158c1b9cfac735ab8 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 20 Oct 2017 16:22:42 -0400 Subject: [PATCH 2/2] Require threadsafe, cloneable render notifier. --- Cargo.lock | 8 ++--- webrender/Cargo.toml | 2 +- webrender/examples/common/boilerplate.rs | 10 ++++-- webrender/src/render_backend.rs | 45 ++++++------------------ webrender/src/renderer.rs | 15 +++----- webrender_api/Cargo.toml | 2 +- webrender_api/src/api.rs | 9 ++--- wrench/src/main.rs | 28 +++++++++------ wrench/src/wrench.rs | 39 +++++++++++++------- 9 files changed, 79 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d842c65bc..e5ac3a23cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "servo-glutin 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.52.1", + "webrender 0.53.0", "yaml-rust 0.3.4 (git+https://github.com/vvuk/yaml-rust)", ] @@ -1050,7 +1050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "webrender" -version = "0.52.1" +version = "0.53.0" dependencies = [ "angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)", "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1079,13 +1079,13 @@ dependencies = [ "servo-glutin 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.52.1", + "webrender_api 0.53.0", "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webrender_api" -version = "0.52.1" +version = "0.53.0" dependencies = [ "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index e88b7a24f2..2989c5cd2a 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.52.1" +version = "0.53.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender/examples/common/boilerplate.rs b/webrender/examples/common/boilerplate.rs index 3dfece4345..2822c0c8c5 100644 --- a/webrender/examples/common/boilerplate.rs +++ b/webrender/examples/common/boilerplate.rs @@ -22,12 +22,18 @@ impl Notifier { } impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { + fn clone(&self) -> Box { + Box::new(Notifier { + window_proxy: self.window_proxy.clone(), + }) + } + + fn new_frame_ready(&self) { #[cfg(not(target_os = "android"))] self.window_proxy.wakeup_event_loop(); } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) { + fn new_scroll_frame_ready(&self, _composite_needed: bool) { #[cfg(not(target_os = "android"))] self.window_proxy.wakeup_event_loop(); } diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index 5daab8c213..c2d684f5f5 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -23,7 +23,7 @@ use scene::Scene; #[cfg(feature = "debugger")] use serde_json; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::sync::mpsc::Sender; use std::u32; use texture_cache::TextureCache; @@ -145,7 +145,7 @@ pub struct RenderBackend { frame_config: FrameBuilderConfig, documents: FastHashMap, - notifier: Arc>>, + notifier: Box, recorder: Option>, enable_render_on_scroll: bool, @@ -160,7 +160,7 @@ impl RenderBackend { default_device_pixel_ratio: f32, texture_cache: TextureCache, workers: Arc, - notifier: Arc>>, + notifier: Box, frame_config: FrameBuilderConfig, recorder: Option>, blob_image_renderer: Option>, @@ -444,8 +444,7 @@ impl RenderBackend { msg } Err(..) => { - let notifier = self.notifier.lock(); - notifier.unwrap().shut_down(); + self.notifier.shut_down(); break; } }; @@ -511,8 +510,7 @@ impl RenderBackend { self.documents.remove(&document_id); } ApiMsg::ExternalEvent(evt) => { - let notifier = self.notifier.lock(); - notifier.unwrap().external_event(evt); + self.notifier.external_event(evt); } ApiMsg::ClearNamespace(namespace_id) => { self.resource_cache.clear_namespace(namespace_id); @@ -537,10 +535,7 @@ impl RenderBackend { // We use new_frame_ready to wake up the renderer and get the // resource updates processed, but the UpdateResources message // will cancel rendering the frame. - self.notifier - .lock() - .unwrap() - .new_frame_ready(); + self.notifier.new_frame_ready(); } ApiMsg::DebugCommand(option) => { let msg = match option { @@ -555,12 +550,10 @@ impl RenderBackend { _ => ResultMsg::DebugCommand(option), }; self.result_tx.send(msg).unwrap(); - let notifier = self.notifier.lock(); - notifier.unwrap().new_frame_ready(); + self.notifier.new_frame_ready(); } ApiMsg::ShutDown => { - let notifier = self.notifier.lock(); - notifier.unwrap().shut_down(); + self.notifier.shut_down(); break; } } @@ -587,27 +580,11 @@ impl RenderBackend { ) { self.publish_frame(document_id, frame, profile_counters); - // TODO(gw): This is kindof bogus to have to lock the notifier - // each time it's used. This is due to some nastiness - // in initialization order for Servo. Perhaps find a - // cleaner way to do this, or use the OnceMutex on crates.io? - let mut notifier = self.notifier.lock(); - notifier - .as_mut() - .unwrap() - .new_frame_ready(); + self.notifier.new_frame_ready(); } - fn notify_compositor_of_new_scroll_frame(&mut self, composite_needed: bool) { - // TODO(gw): This is kindof bogus to have to lock the notifier - // each time it's used. This is due to some nastiness - // in initialization order for Servo. Perhaps find a - // cleaner way to do this, or use the OnceMutex on crates.io? - let mut notifier = self.notifier.lock(); - notifier - .as_mut() - .unwrap() - .new_scroll_frame_ready(composite_needed); + fn notify_compositor_of_new_scroll_frame(&self, composite_needed: bool) { + self.notifier.new_scroll_frame_ready(composite_needed); } diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 7b4a3d35bb..24a785987a 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -55,7 +55,7 @@ use std::f32; use std::mem; use std::path::PathBuf; use std::rc::Rc; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread; use texture_cache::TextureCache; @@ -930,18 +930,14 @@ struct PrimitiveShader { } struct FileWatcher { - notifier: Arc>>, + notifier: Box, result_tx: Sender, } impl FileWatcherHandler for FileWatcher { fn file_changed(&self, path: PathBuf) { self.result_tx.send(ResultMsg::RefreshShader(path)).ok(); - let mut notifier = self.notifier.lock(); - notifier - .as_mut() - .unwrap() - .new_frame_ready(); + self.notifier.new_frame_ready(); } } @@ -1238,12 +1234,11 @@ impl Renderer { let (result_tx, result_rx) = channel(); let gl_type = gl.get_type(); - let notifier = Arc::new(Mutex::new(notifier)); let debug_server = DebugServer::new(api_tx.clone()); let file_watch_handler = FileWatcher { result_tx: result_tx.clone(), - notifier: Arc::clone(¬ifier), + notifier: notifier.clone(), }; let mut device = Device::new( @@ -1654,7 +1649,7 @@ impl Renderer { device.end_frame(); - let backend_notifier = Arc::clone(¬ifier); + let backend_notifier = notifier.clone(); let default_font_render_mode = match (options.enable_aa, options.enable_subpixel_aa) { (true, true) => FontRenderMode::Subpixel, diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index 115ed55629..20f526a206 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_api" -version = "0.52.1" +version = "0.53.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index 9f01274fbf..91b07972fd 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -873,10 +873,11 @@ pub struct DynamicProperties { } pub trait RenderNotifier: Send { - fn new_frame_ready(&mut self); - fn new_scroll_frame_ready(&mut self, composite_needed: bool); - fn external_event(&mut self, _evt: ExternalEvent) { + fn clone(&self) -> Box; + fn new_frame_ready(&self); + fn new_scroll_frame_ready(&self, composite_needed: bool); + fn external_event(&self, _evt: ExternalEvent) { unimplemented!() } - fn shut_down(&mut self) {} + fn shut_down(&self) {} } diff --git a/wrench/src/main.rs b/wrench/src/main.rs index 43b72d1371..5077869435 100644 --- a/wrench/src/main.rs +++ b/wrench/src/main.rs @@ -279,17 +279,25 @@ fn make_window( wrapper } -fn create_notifier() -> (Box, Receiver<()>) { - // setup a notifier so we can wait for frames to be finished - struct Notifier { - tx: Sender<()>, - }; - impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { - self.tx.send(()).unwrap(); - } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {} +struct Notifier { + tx: Sender<()>, +} + +// setup a notifier so we can wait for frames to be finished +impl RenderNotifier for Notifier { + fn clone(&self) -> Box { + Box::new(Notifier { + tx: self.tx.clone(), + }) } + + fn new_frame_ready(&self) { + self.tx.send(()).unwrap(); + } + fn new_scroll_frame_ready(&self, _composite_needed: bool) {} +} + +fn create_notifier() -> (Box, Receiver<()>) { let (tx, rx) = channel(); (Box::new(Notifier { tx: tx }), rx) } diff --git a/wrench/src/wrench.rs b/wrench/src/wrench.rs index 38fa68486c..d43cc6571c 100644 --- a/wrench/src/wrench.rs +++ b/wrench/src/wrench.rs @@ -15,6 +15,7 @@ use json_frame_writer::JsonFrameWriter; use ron_frame_writer::RonFrameWriter; use std::collections::HashMap; use std::path::PathBuf; +use std::sync::{Arc, Mutex}; use time; use webrender; use webrender::api::*; @@ -43,20 +44,20 @@ pub enum SaveType { Binary, } -struct Notifier { +struct NotifierData { window_proxy: Option, frames_notified: u32, timing_receiver: chase_lev::Stealer, verbose: bool, } -impl Notifier { +impl NotifierData { fn new( window_proxy: Option, timing_receiver: chase_lev::Stealer, verbose: bool, - ) -> Notifier { - Notifier { + ) -> NotifierData { + NotifierData { window_proxy, frames_notified: 0, timing_receiver, @@ -65,32 +66,41 @@ impl Notifier { } } +struct Notifier(Arc>); + impl RenderNotifier for Notifier { - fn new_frame_ready(&mut self) { - match self.timing_receiver.steal() { + fn clone(&self) -> Box { + Box::new(Notifier(self.0.clone())) + } + + fn new_frame_ready(&self) { + let mut data = self.0.lock(); + let data = data.as_mut().unwrap(); + match data.timing_receiver.steal() { chase_lev::Steal::Data(last_timing) => { - self.frames_notified += 1; - if self.verbose && self.frames_notified == 600 { + data.frames_notified += 1; + if data.verbose && data.frames_notified == 600 { let elapsed = time::SteadyTime::now() - last_timing; println!( "frame latency (consider queue depth here): {:3.6} ms", elapsed.num_microseconds().unwrap() as f64 / 1000. ); - self.frames_notified = 0; + data.frames_notified = 0; } } _ => { println!("Notified of frame, but no frame was ready?"); } } - if let Some(ref window_proxy) = self.window_proxy { + if let Some(ref window_proxy) = data.window_proxy { #[cfg(not(target_os = "android"))] window_proxy.wakeup_event_loop(); } } - fn new_scroll_frame_ready(&mut self, _composite_needed: bool) { - if let Some(ref window_proxy) = self.window_proxy { + fn new_scroll_frame_ready(&self, _composite_needed: bool) { + let data = self.0.lock(); + if let Some(ref window_proxy) = data.unwrap().window_proxy { #[cfg(not(target_os = "android"))] window_proxy.wakeup_event_loop(); } @@ -176,7 +186,10 @@ impl Wrench { } let (timing_sender, timing_receiver) = chase_lev::deque(); - let notifier = notifier.unwrap_or_else(|| Box::new(Notifier::new(proxy, timing_receiver, verbose))); + let notifier = notifier.unwrap_or_else(|| { + let data = Arc::new(Mutex::new(NotifierData::new(proxy, timing_receiver, verbose))); + Box::new(Notifier(data)) + }); let (renderer, sender) = webrender::Renderer::new(window.clone_gl(), notifier, opts).unwrap(); let api = sender.create_api();