Bug 1542826 - Allow enabling/disabling the debug server at runtime. r=gw
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 25 Apr 2019 19:28:32 +0000
changeset 530179 59a08c05c327a26a92386a1f0da29f585994c1a3
parent 530178 e980a61a57d13ac9d17bf3de66fcd69bf21765ea
child 530180 459c9408935dee772b87c51edcf2eda470ad495c
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1542826
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1542826 - Allow enabling/disabling the debug server at runtime. r=gw This adds a RendererOption flag to control whether the debug server is enabled. This allows the debug server feature to be built without enabling the feature by default; it can then be enabled on a per-renderer basis via the RendererOption. Differential Revision: https://phabricator.services.mozilla.com/D28352
gfx/wr/webrender/src/debug_server.rs
gfx/wr/webrender/src/renderer.rs
--- a/gfx/wr/webrender/src/debug_server.rs
+++ b/gfx/wr/webrender/src/debug_server.rs
@@ -1,16 +1,17 @@
 /* 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 api::{ApiMsg, DebugCommand, DebugFlags};
 use api::channel::MsgSender;
 use api::units::DeviceIntSize;
 use print_tree::PrintTreePrinter;
+use renderer;
 use std::sync::mpsc::{channel, Receiver};
 use std::sync::mpsc::Sender;
 use std::thread;
 use ws;
 use base64::encode;
 use image_loader;
 
 // Messages that are sent from the render backend to the renderer
@@ -87,25 +88,25 @@ impl ws::Handler for Server {
         }
 
         Ok(())
     }
 }
 
 // Spawn a thread for a given renderer, and wait for
 // client connections.
-pub struct DebugServer {
+pub struct DebugServerImpl {
     join_handle: Option<thread::JoinHandle<()>>,
     broadcaster: ws::Sender,
     debug_rx: Receiver<DebugMsg>,
     senders: Vec<ws::Sender>,
 }
 
-impl DebugServer {
-    pub fn new(api_tx: MsgSender<ApiMsg>) -> DebugServer {
+impl DebugServerImpl {
+    pub fn new(api_tx: MsgSender<ApiMsg>) -> DebugServerImpl {
         let (debug_tx, debug_rx) = channel();
 
         let socket = ws::Builder::new()
             .build(move |out| {
                 Server {
                     ws: out,
                     debug_tx: debug_tx.clone(),
                     api_tx: api_tx.clone(),
@@ -119,25 +120,27 @@ impl DebugServer {
         let join_handle = Some(thread::spawn(move || {
             let address = "127.0.0.1:3583";
             debug!("WebRender debug server started: {}", address);
             if let Err(..) = socket.listen(address) {
                 error!("ERROR: Unable to bind debugger websocket (port may be in use).");
             }
         }));
 
-        DebugServer {
+        DebugServerImpl {
             join_handle,
             broadcaster,
             debug_rx,
             senders: Vec::new(),
         }
     }
+}
 
-    pub fn send(&mut self, message: String) {
+impl renderer::DebugServer for DebugServerImpl {
+    fn send(&mut self, message: String) {
         // Add any new connections that have been queued.
         while let Ok(msg) = self.debug_rx.try_recv() {
             match msg {
                 DebugMsg::AddSender(sender) => {
                     self.senders.push(sender);
                 }
                 DebugMsg::RemoveSender(token) => {
                     self.senders.retain(|sender| sender.token() != token);
@@ -161,17 +164,17 @@ impl DebugServer {
         // order so the indices are valid for the
         // entire loop.
         for i in disconnected_senders.iter().rev() {
             self.senders.remove(*i);
         }
     }
 }
 
-impl Drop for DebugServer {
+impl Drop for DebugServerImpl {
     fn drop(&mut self) {
         self.broadcaster.shutdown().ok();
         self.join_handle.take().unwrap().join().ok();
     }
 }
 
 // A serializable list of debug information about passes
 // that can be sent to the client.
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -29,26 +29,26 @@
 //!   - for rasterized primitives, the orthographics projection transforms
 //! the content rectangle to -1 to 1
 //!   - the viewport transformation is setup to map the whole range to
 //! the framebuffer rectangle provided by the document view, stored in `DrawTarget`
 //!   - all the direct framebuffer operations, like blitting, reading pixels, and setting
 //! up the scissor, are accepting already transformed coordinates, which we can get by
 //! calling `DrawTarget::to_framebuffer_rect`
 
-use api::{BlobImageHandler, ColorF, ColorU};
+use api::{ApiMsg, BlobImageHandler, ColorF, ColorU};
 use api::{DocumentId, Epoch, ExternalImageId};
 use api::{ExternalImageType, FontRenderMode, FrameMsg, ImageFormat, PipelineId};
 use api::{ImageRendering, Checkpoint, NotificationRequest};
 use api::{DebugCommand, MemoryReport, VoidPtrToSizeFn};
 use api::{RenderApiSender, RenderNotifier, TextureTarget};
 use api::channel;
 use api::units::*;
 pub use api::DebugFlags;
-use api::channel::PayloadReceiverHelperMethods;
+use api::channel::{MsgSender, PayloadReceiverHelperMethods};
 use batch::{BatchKind, BatchTextures, BrushBatchKind, ClipBatchList};
 #[cfg(any(feature = "capture", feature = "replay"))]
 use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
 use debug_colors;
 use debug_render::{DebugItem, DebugRenderer};
 use device::{DepthFunction, Device, GpuFrameId, Program, UploadMethod, Texture, PBO};
 use device::{DrawTarget, ExternalTexture, FBOId, ReadTarget, TextureSlot};
 use device::{ShaderError, TextureFilter, TextureFlags,
@@ -108,20 +108,17 @@ use tiling::{BlitJob, BlitJobSource, Ren
 use tiling::{Frame, RenderTarget, RenderTargetKind, TextureCacheRenderTarget};
 #[cfg(not(feature = "pathfinder"))]
 use tiling::GlyphJob;
 use time::precise_time_ns;
 
 cfg_if! {
     if #[cfg(feature = "debugger")] {
         use serde_json;
-        use debug_server::{self, DebugServer};
-    } else {
-        use api::ApiMsg;
-        use api::channel::MsgSender;
+        use debug_server;
     }
 }
 
 /// Is only false if no WR instances have ever been created.
 static HAS_BEEN_INITIALIZED: AtomicBool = AtomicBool::new(false);
 
 /// Returns true if a WR instance has ever been initialized in this process.
 pub fn wr_has_been_initialized() -> bool {
@@ -1846,17 +1843,17 @@ impl AsyncScreenshotGrabber {
 
 /// The renderer is responsible for submitting to the GPU the work prepared by the
 /// RenderBackend.
 ///
 /// We have a separate `Renderer` instance for each instance of WebRender (generally
 /// one per OS window), and all instances share the same thread.
 pub struct Renderer {
     result_rx: Receiver<ResultMsg>,
-    debug_server: DebugServer,
+    debug_server: Box<DebugServer>,
     pub device: Device,
     pending_texture_updates: Vec<TextureUpdateList>,
     pending_gpu_cache_updates: Vec<GpuCacheUpdateList>,
     pending_gpu_cache_clear: bool,
     pending_shader_updates: Vec<PathBuf>,
     active_documents: Vec<(DocumentId, RenderedDocument)>,
 
     shaders: Rc<RefCell<Shaders>>,
@@ -2003,17 +2000,17 @@ impl Renderer {
     ) -> Result<(Self, RenderApiSender), RendererError> {
         HAS_BEEN_INITIALIZED.store(true, Ordering::SeqCst);
 
         let (api_tx, api_rx) = channel::msg_channel()?;
         let (payload_tx, payload_rx) = channel::payload_channel()?;
         let (result_tx, result_rx) = channel();
         let gl_type = gl.get_type();
 
-        let debug_server = DebugServer::new(api_tx.clone());
+        let debug_server = new_debug_server(options.start_debug_server, api_tx.clone());
 
         let mut device = Device::new(
             gl,
             options.resource_override_path.clone(),
             options.upload_method.clone(),
             options.cached_programs.take(),
             options.allow_pixel_local_storage_support,
         );
@@ -5591,16 +5588,18 @@ pub struct RendererOptions {
     /// it is a performance win. The default is false, which tends to be best
     /// performance on lower end / integrated GPUs.
     pub gpu_supports_fast_clears: bool,
     /// If true, allow WR to use pixel local storage if the device supports it.
     /// For now, this defaults to false since the code is still experimental
     /// and not complete. This option will probably be removed once support is
     /// complete, and WR can implicitly choose whether to make use of PLS.
     pub allow_pixel_local_storage_support: bool,
+    /// Start the debug server for this renderer.
+    pub start_debug_server: bool,
 }
 
 impl Default for RendererOptions {
     fn default() -> Self {
         RendererOptions {
             device_pixel_ratio: 1.0,
             resource_override_path: None,
             enable_aa: true,
@@ -5631,30 +5630,53 @@ impl Default for RendererOptions {
             sampler: None,
             chase_primitive: ChasePrimitive::Nothing,
             support_low_priority_transactions: false,
             namespace_alloc_by_client: false,
             enable_picture_caching: false,
             testing: false,
             gpu_supports_fast_clears: false,
             allow_pixel_local_storage_support: false,
+            // For backwards compatibility we set this to true by default, so
+            // that if the debugger feature is enabled, the debug server will
+            // be started automatically. Users can explicitly disable this as
+            // needed.
+            start_debug_server: true,
         }
     }
 }
 
+pub trait DebugServer {
+    fn send(&mut self, _message: String);
+}
+
+struct NoopDebugServer;
+
+impl NoopDebugServer {
+    fn new(_: MsgSender<ApiMsg>) -> Self {
+        NoopDebugServer
+    }
+}
+
+impl DebugServer for NoopDebugServer {
+    fn send(&mut self, _: String) {}
+}
+
+#[cfg(feature = "debugger")]
+fn new_debug_server(enable: bool, api_tx: MsgSender<ApiMsg>) -> Box<DebugServer> {
+    if enable {
+        Box::new(debug_server::DebugServerImpl::new(api_tx))
+    } else {
+        Box::new(NoopDebugServer::new(api_tx))
+    }
+}
+
 #[cfg(not(feature = "debugger"))]
-pub struct DebugServer;
-
-#[cfg(not(feature = "debugger"))]
-impl DebugServer {
-    pub fn new(_: MsgSender<ApiMsg>) -> Self {
-        DebugServer
-    }
-
-    pub fn send(&mut self, _: String) {}
+fn new_debug_server(_enable: bool, api_tx: MsgSender<ApiMsg>) -> Box<DebugServer> {
+    Box::new(NoopDebugServer::new(api_tx))
 }
 
 /// Some basic statistics about the rendered scene, used in Gecko, as
 /// well as in wrench reftests to ensure that tests are batching and/or
 /// allocating on render targets as we expect them to.
 #[repr(C)]
 #[derive(Debug, Default)]
 pub struct RendererStats {