Bug 1515654 - Update webrender to commit 6bdd0d26afe3fc5a24f10c19d4ca8569d0182a37 (WR PR #3440). r=kats
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Fri, 21 Dec 2018 21:12:36 +0000
changeset 451764 7610d5c01d9ab148a3e573e11145e9c47efe1d4f
parent 451763 ce0f2042c1e2239e065275769969574077a02516
child 451765 a3e192395bf8c9e202fa26dc10ba1abaaef0079c
push id35253
push userccoroiu@mozilla.com
push dateSat, 22 Dec 2018 04:12:04 +0000
treeherdermozilla-central@d30b4fd63e17 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1515654
milestone66.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 1515654 - Update webrender to commit 6bdd0d26afe3fc5a24f10c19d4ca8569d0182a37 (WR PR #3440). r=kats https://github.com/servo/webrender/pull/3440 Differential Revision: https://phabricator.services.mozilla.com/D15224
gfx/webrender_bindings/revision.txt
gfx/wr/examples/common/boilerplate.rs
gfx/wr/examples/multiwindow.rs
gfx/wr/webrender/src/debug_server.rs
gfx/wr/webrender/src/gpu_cache.rs
gfx/wr/webrender/src/render_backend.rs
gfx/wr/webrender/src/renderer.rs
gfx/wr/webrender/src/scene_builder.rs
gfx/wr/webrender_api/src/api.rs
gfx/wr/wrench/src/main.rs
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-57379d1fec269ea70cbab28d4353614fd9c58122
+6bdd0d26afe3fc5a24f10c19d4ca8569d0182a37
--- a/gfx/wr/examples/common/boilerplate.rs
+++ b/gfx/wr/examples/common/boilerplate.rs
@@ -6,16 +6,17 @@ extern crate env_logger;
 extern crate euclid;
 
 use gleam::gl;
 use glutin::{self, GlContext};
 use std::env;
 use std::path::PathBuf;
 use webrender;
 use winit;
+use webrender::DebugFlags;
 use webrender::ShaderPrecacheFlags;
 use webrender::api::*;
 
 struct Notifier {
     events_proxy: winit::EventsLoopProxy,
 }
 
 impl Notifier {
@@ -142,23 +143,24 @@ pub fn main_wrapper<E: Example>(
     };
 
     println!("OpenGL version {}", gl.get_string(gl::VERSION));
     println!("Shader resource path: {:?}", res_path);
     let device_pixel_ratio = window.get_hidpi_factor() as f32;
     println!("Device pixel ratio: {}", device_pixel_ratio);
 
     println!("Loading shaders...");
+    let mut debug_flags = DebugFlags::ECHO_DRIVER_MESSAGES | DebugFlags::TEXTURE_CACHE_DBG;
     let opts = webrender::RendererOptions {
         resource_override_path: res_path,
         precache_flags: E::PRECACHE_SHADER_FLAGS,
         device_pixel_ratio,
         clear_color: Some(ColorF::new(0.3, 0.0, 0.0, 1.0)),
         //scatter_gpu_cache_updates: false,
-        debug_flags: webrender::DebugFlags::ECHO_DRIVER_MESSAGES,
+        debug_flags,
         ..options.unwrap_or(webrender::RendererOptions::default())
     };
 
     let framebuffer_size = {
         let size = window
             .get_inner_size()
             .unwrap()
             .to_physical(device_pixel_ratio as f64);
@@ -174,18 +176,16 @@ pub fn main_wrapper<E: Example>(
     if let Some(output_image_handler) = output {
         renderer.set_output_image_handler(output_image_handler);
     }
 
     if let Some(external_image_handler) = external {
         renderer.set_external_image_handler(external_image_handler);
     }
 
-    renderer.toggle_debug_flags(webrender::DebugFlags::TEXTURE_CACHE_DBG);
-
     let epoch = Epoch(0);
     let pipeline_id = PipelineId(0, 0);
     let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
     let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
     let mut txn = Transaction::new();
 
     example.render(
         &api,
@@ -206,16 +206,17 @@ pub fn main_wrapper<E: Example>(
     txn.generate_frame();
     api.send_transaction(document_id, txn);
 
     println!("Entering event loop");
     events_loop.run_forever(|global_event| {
         let mut txn = Transaction::new();
         let mut custom_event = true;
 
+        let old_flags = debug_flags;
         match global_event {
             winit::Event::WindowEvent {
                 event: winit::WindowEvent::CloseRequested,
                 ..
             } => return winit::ControlFlow::Break,
             winit::Event::WindowEvent {
                 event: winit::WindowEvent::KeyboardInput {
                     input: winit::KeyboardInput {
@@ -223,32 +224,27 @@ pub fn main_wrapper<E: Example>(
                         virtual_keycode: Some(key),
                         ..
                     },
                     ..
                 },
                 ..
             } => match key {
                 winit::VirtualKeyCode::Escape => return winit::ControlFlow::Break,
-                winit::VirtualKeyCode::P => renderer.toggle_debug_flags(webrender::DebugFlags::PROFILER_DBG),
-                winit::VirtualKeyCode::O => renderer.toggle_debug_flags(webrender::DebugFlags::RENDER_TARGET_DBG),
-                winit::VirtualKeyCode::I => renderer.toggle_debug_flags(webrender::DebugFlags::TEXTURE_CACHE_DBG),
-                winit::VirtualKeyCode::S => renderer.toggle_debug_flags(webrender::DebugFlags::COMPACT_PROFILER),
-                winit::VirtualKeyCode::Q => renderer.toggle_debug_flags(
-                    webrender::DebugFlags::GPU_TIME_QUERIES | webrender::DebugFlags::GPU_SAMPLE_QUERIES
+                winit::VirtualKeyCode::P => debug_flags.toggle(DebugFlags::PROFILER_DBG),
+                winit::VirtualKeyCode::O => debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG),
+                winit::VirtualKeyCode::I => debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG),
+                winit::VirtualKeyCode::S => debug_flags.toggle(DebugFlags::COMPACT_PROFILER),
+                winit::VirtualKeyCode::Q => debug_flags.toggle(
+                    DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES
                 ),
-                winit::VirtualKeyCode::F => renderer.toggle_debug_flags(
-                    webrender::DebugFlags::NEW_FRAME_INDICATOR | webrender::DebugFlags::NEW_SCENE_INDICATOR
+                winit::VirtualKeyCode::F => debug_flags.toggle(
+                    DebugFlags::NEW_FRAME_INDICATOR | DebugFlags::NEW_SCENE_INDICATOR
                 ),
-                winit::VirtualKeyCode::G => api.send_debug_cmd(
-                    // go through the API so that we reach the render backend
-                    DebugCommand::EnableGpuCacheDebug(
-                        !renderer.get_debug_flags().contains(webrender::DebugFlags::GPU_CACHE_DBG)
-                    ),
-                ),
+                winit::VirtualKeyCode::G => debug_flags.toggle(DebugFlags::GPU_CACHE_DBG),
                 winit::VirtualKeyCode::Key1 => txn.set_window_parameters(
                     framebuffer_size,
                     DeviceIntRect::new(DeviceIntPoint::zero(), framebuffer_size),
                     1.0
                 ),
                 winit::VirtualKeyCode::Key2 => txn.set_window_parameters(
                     framebuffer_size,
                     DeviceIntRect::new(DeviceIntPoint::zero(), framebuffer_size),
@@ -277,16 +273,20 @@ pub fn main_wrapper<E: Example>(
             winit::Event::WindowEvent { event, .. } => custom_event = example.on_event(
                 event,
                 &api,
                 document_id,
             ),
             _ => return winit::ControlFlow::Continue,
         };
 
+        if debug_flags != old_flags {
+            api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
+        }
+
         if custom_event {
             let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
 
             example.render(
                 &api,
                 &mut builder,
                 &mut txn,
                 framebuffer_size,
--- a/gfx/wr/examples/multiwindow.rs
+++ b/gfx/wr/examples/multiwindow.rs
@@ -10,16 +10,17 @@ extern crate webrender;
 extern crate winit;
 
 use app_units::Au;
 use gleam::gl;
 use glutin::GlContext;
 use std::fs::File;
 use std::io::Read;
 use webrender::api::*;
+use webrender::DebugFlags;
 use winit::dpi::LogicalSize;
 
 struct Notifier {
     events_proxy: winit::EventsLoopProxy,
 }
 
 impl Notifier {
     fn new(events_proxy: winit::EventsLoopProxy) -> Notifier {
@@ -137,16 +138,17 @@ impl Window {
 
     fn tick(&mut self) -> bool {
         unsafe {
             self.window.make_current().ok();
         }
         let mut do_exit = false;
         let my_name = &self.name;
         let renderer = &mut self.renderer;
+        let api = &mut self.api;
 
         self.events_loop.poll_events(|global_event| match global_event {
             winit::Event::WindowEvent { event, .. } => match event {
                 winit::WindowEvent::CloseRequested |
                 winit::WindowEvent::KeyboardInput {
                     input: winit::KeyboardInput {
                         virtual_keycode: Some(winit::VirtualKeyCode::Escape),
                         ..
@@ -158,18 +160,18 @@ impl Window {
                 winit::WindowEvent::KeyboardInput {
                     input: winit::KeyboardInput {
                         state: winit::ElementState::Pressed,
                         virtual_keycode: Some(winit::VirtualKeyCode::P),
                         ..
                     },
                     ..
                 } => {
-                    println!("toggle flags {}", my_name);
-                    renderer.toggle_debug_flags(webrender::DebugFlags::PROFILER_DBG);
+                    println!("set flags {}", my_name);
+                    api.send_debug_cmd(DebugCommand::SetFlags(DebugFlags::PROFILER_DBG))
                 }
                 _ => {}
             }
             _ => {}
         });
         if do_exit {
             return true
         }
@@ -273,17 +275,17 @@ impl Window {
             self.epoch,
             None,
             layout_size,
             builder.finalize(),
             true,
         );
         txn.set_root_pipeline(self.pipeline_id);
         txn.generate_frame();
-        self.api.send_transaction(self.document_id, txn);
+        api.send_transaction(self.document_id, txn);
 
         renderer.update();
         renderer.render(framebuffer_size).unwrap();
         self.window.swap_buffers().ok();
 
         false
     }
 
--- a/gfx/wr/webrender/src/debug_server.rs
+++ b/gfx/wr/webrender/src/debug_server.rs
@@ -1,13 +1,13 @@
 /* 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, DeviceIntSize};
+use api::{ApiMsg, DebugCommand, DebugFlags, DeviceIntSize};
 use api::channel::MsgSender;
 use print_tree::PrintTreePrinter;
 use std::sync::mpsc::{channel, Receiver};
 use std::sync::mpsc::Sender;
 use std::thread;
 use ws;
 use base64::encode;
 use image_loader;
@@ -21,16 +21,17 @@ enum DebugMsg {
     RemoveSender(ws::util::Token),
 }
 
 // Represents a connection to a client.
 struct Server {
     ws: ws::Sender,
     debug_tx: Sender<DebugMsg>,
     api_tx: MsgSender<ApiMsg>,
+    debug_flags: DebugFlags,
 }
 
 impl ws::Handler for Server {
     fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
         self.debug_tx
             .send(DebugMsg::AddSender(self.ws.clone()))
             .ok();
 
@@ -41,35 +42,45 @@ impl ws::Handler for Server {
         self.debug_tx
             .send(DebugMsg::RemoveSender(self.ws.token()))
             .ok();
     }
 
     fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
         match msg {
             ws::Message::Text(string) => {
-                let cmd = match string.as_str() {
-                    "enable_profiler" => DebugCommand::EnableProfiler(true),
-                    "disable_profiler" => DebugCommand::EnableProfiler(false),
-                    "enable_texture_cache_debug" => DebugCommand::EnableTextureCacheDebug(true),
-                    "disable_texture_cache_debug" => DebugCommand::EnableTextureCacheDebug(false),
-                    "enable_render_target_debug" => DebugCommand::EnableRenderTargetDebug(true),
-                    "disable_render_target_debug" => DebugCommand::EnableRenderTargetDebug(false),
-                    "enable_gpu_time_queries" => DebugCommand::EnableGpuTimeQueries(true),
-                    "disable_gpu_time_queries" => DebugCommand::EnableGpuTimeQueries(false),
-                    "enable_gpu_sample_queries" => DebugCommand::EnableGpuSampleQueries(true),
-                    "disable_gpu_sample_queries" => DebugCommand::EnableGpuSampleQueries(false),
-                    "fetch_passes" => DebugCommand::FetchPasses,
-                    "fetch_screenshot" => DebugCommand::FetchScreenshot,
-                    "fetch_documents" => DebugCommand::FetchDocuments,
-                    "fetch_clip_scroll_tree" => DebugCommand::FetchClipScrollTree,
-                    "fetch_render_tasks" => DebugCommand::FetchRenderTasks,
-                    msg => {
-                        error!("unknown msg {}", msg);
-                        return Ok(());
+                // First, check for flag change commands.
+                let mut set_flags = true;
+                match string.as_str() {
+                    "enable_profiler" => self.debug_flags.insert(DebugFlags::PROFILER_DBG),
+                    "disable_profiler" => self.debug_flags.remove(DebugFlags::PROFILER_DBG),
+                    "enable_texture_cache_debug" => self.debug_flags.insert(DebugFlags::TEXTURE_CACHE_DBG),
+                    "disable_texture_cache_debug" => self.debug_flags.remove(DebugFlags::TEXTURE_CACHE_DBG),
+                    "enable_render_target_debug" => self.debug_flags.insert(DebugFlags::RENDER_TARGET_DBG),
+                    "disable_render_target_debug" => self.debug_flags.remove(DebugFlags::RENDER_TARGET_DBG),
+                    "enable_gpu_time_queries" => self.debug_flags.insert(DebugFlags::GPU_TIME_QUERIES),
+                    "disable_gpu_time_queries" => self.debug_flags.remove(DebugFlags::GPU_TIME_QUERIES),
+                    "enable_gpu_sample_queries" => self.debug_flags.insert(DebugFlags::GPU_SAMPLE_QUERIES),
+                    "disable_gpu_sample_queries" => self.debug_flags.remove(DebugFlags::GPU_SAMPLE_QUERIES),
+                    _ => set_flags = false,
+                };
+
+                let cmd = if set_flags {
+                    DebugCommand::SetFlags(self.debug_flags)
+                } else {
+                    match string.as_str() {
+                        "fetch_passes" => DebugCommand::FetchPasses,
+                        "fetch_screenshot" => DebugCommand::FetchScreenshot,
+                        "fetch_documents" => DebugCommand::FetchDocuments,
+                        "fetch_clip_scroll_tree" => DebugCommand::FetchClipScrollTree,
+                        "fetch_render_tasks" => DebugCommand::FetchRenderTasks,
+                        msg => {
+                            error!("unknown msg {}", msg);
+                            return Ok(());
+                        }
                     }
                 };
 
                 let msg = ApiMsg::DebugCommand(cmd);
                 self.api_tx.send(msg).unwrap();
             }
             ws::Message::Binary(..) => {}
         }
@@ -92,16 +103,17 @@ impl DebugServer {
         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(),
+                    debug_flags: DebugFlags::empty(),
                 }
             })
             .unwrap();
 
         let broadcaster = socket.broadcaster();
 
         let join_handle = Some(thread::spawn(move || {
             let address = "127.0.0.1:3583";
--- a/gfx/wr/webrender/src/gpu_cache.rs
+++ b/gfx/wr/webrender/src/gpu_cache.rs
@@ -19,17 +19,17 @@
 //! data is not in the cache, the user provided closure
 //! will be invoked to build the data.
 //!
 //! After ```end_frame``` has occurred, callers can
 //! use the ```get_address``` API to get the allocated
 //! address in the GPU cache of a given resource slot
 //! for this frame.
 
-use api::{PremultipliedColorF, TexelRect};
+use api::{DebugFlags, PremultipliedColorF, TexelRect};
 use api::{VoidPtrToSizeFn};
 use euclid::TypedRect;
 use profiler::GpuCacheProfileCounters;
 use render_backend::FrameId;
 use renderer::MAX_VERTEX_TEXTURE_WIDTH;
 use std::{mem, u16, u32};
 use std::ops::Add;
 use std::os::raw::c_void;
@@ -229,17 +229,16 @@ pub enum GpuCacheUpdate {
         block_index: usize,
         block_count: usize,
         address: GpuCacheAddress,
     },
 }
 
 pub struct GpuDebugChunk {
     pub address: GpuCacheAddress,
-    pub fresh: bool,
     pub tag: u8,
     pub size: u16,
 }
 
 #[must_use]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct GpuCacheUpdateList {
@@ -536,28 +535,27 @@ impl<'a> Drop for GpuDataRequest<'a> {
 pub struct GpuCache {
     /// Current frame ID.
     frame_id: FrameId,
     /// CPU-side texture allocator.
     texture: Texture,
     /// Number of blocks requested this frame that don't
     /// need to be re-uploaded.
     saved_block_count: usize,
-    /// True if the Renderer expects to receive the metadata
-    /// about GPU blocks with on each update.
-    in_debug: bool,
+    /// The current debug flags for the system.
+    debug_flags: DebugFlags,
 }
 
 impl GpuCache {
     pub fn new() -> Self {
         GpuCache {
             frame_id: FrameId::INVALID,
             texture: Texture::new(),
             saved_block_count: 0,
-            in_debug: false,
+            debug_flags: DebugFlags::empty(),
         }
     }
 
     /// Begin a new frame.
     pub fn begin_frame(&mut self, frame_id: FrameId) {
         debug_assert!(self.texture.pending_blocks.is_empty());
         self.frame_id = frame_id;
         self.texture.evict_old_blocks(self.frame_id);
@@ -648,39 +646,38 @@ impl GpuCache {
         self.frame_id
     }
 
     /// Extract the pending updates from the cache.
     pub fn extract_updates(&mut self) -> GpuCacheUpdateList {
         GpuCacheUpdateList {
             frame_id: self.frame_id,
             height: self.texture.height,
-            debug_chunks: if self.in_debug {
+            debug_chunks: if self.debug_flags.contains(DebugFlags::GPU_CACHE_DBG) {
                 self.texture.updates
                     .iter()
                     .map(|update| match *update {
-                        GpuCacheUpdate::Copy { address, block_index, block_count } => GpuDebugChunk {
+                        GpuCacheUpdate::Copy { address, block_index: _, block_count } => GpuDebugChunk {
                             address,
-                            fresh: self.frame_id == self.texture.blocks[block_index].last_access_time,
                             tag: 0, //TODO
                             size: block_count.min(0xFFFF) as u16,
                         }
                     })
                     .collect()
             } else {
                 Vec::new()
             },
             updates: mem::replace(&mut self.texture.updates, Vec::new()),
             blocks: mem::replace(&mut self.texture.pending_blocks, Vec::new()),
         }
     }
 
-    /// Enable GPU block debugging.
-    pub fn set_debug(&mut self, enable: bool) {
-        self.in_debug = enable;
+    /// Sets the current debug flags for the system.
+    pub fn set_debug_flags(&mut self, flags: DebugFlags) {
+        self.debug_flags = flags;
     }
 
     /// Get the actual GPU address in the texture for a given slot ID.
     /// It's assumed at this point that the given slot has been requested
     /// and built for this frame. Attempting to get the address for a
     /// freed or pending slot will panic!
     pub fn get_address(&self, id: &GpuCacheHandle) -> GpuCacheAddress {
         let location = id.location.expect("handle not requested or allocated!");
--- a/gfx/wr/webrender/src/render_backend.rs
+++ b/gfx/wr/webrender/src/render_backend.rs
@@ -12,17 +12,17 @@ use api::{ApiMsg, BuiltDisplayList, Clea
 #[cfg(feature = "debugger")]
 use api::{BuiltDisplayListIter, SpecificDisplayItem};
 use api::{DevicePixelScale, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
 use api::{DocumentId, DocumentLayer, ExternalScrollId, FrameMsg, HitTestFlags, HitTestResult};
 use api::{IdNamespace, LayoutPoint, PipelineId, RenderNotifier, SceneMsg, ScrollClamping};
 use api::{MemoryReport, VoidPtrToSizeFn};
 use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, BlobImageKey};
 use api::{NotificationRequest, Checkpoint};
-use api::channel::{MsgReceiver, Payload};
+use api::channel::{MsgReceiver, MsgSender, Payload};
 #[cfg(feature = "capture")]
 use api::CaptureBits;
 #[cfg(feature = "replay")]
 use api::CapturedDocument;
 use clip::ClipDataStore;
 use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
 #[cfg(feature = "debugger")]
 use debug_server;
@@ -1026,20 +1026,16 @@ impl RenderBackend {
 
                         self.low_priority_scene_tx.send(SceneBuilderRequest::SetFrameBuilderConfig(
                             self.frame_config.clone()
                         )).unwrap();
 
                         // We don't want to forward this message to the renderer.
                         return true;
                     }
-                    DebugCommand::EnableGpuCacheDebug(enable) => {
-                        self.gpu_cache.set_debug(enable);
-                        ResultMsg::DebugCommand(option)
-                    }
                     DebugCommand::FetchDocuments => {
                         let json = self.get_docs_for_debugger();
                         ResultMsg::DebugOutput(DebugOutput::FetchDocuments(json))
                     }
                     DebugCommand::FetchClipScrollTree => {
                         let json = self.get_clip_scroll_tree_for_debugger();
                         ResultMsg::DebugOutput(DebugOutput::FetchClipScrollTree(json))
                     }
@@ -1102,16 +1098,17 @@ impl RenderBackend {
                     DebugCommand::SimulateLongLowPrioritySceneBuild(time_ms) => {
                         self.low_priority_scene_tx.send(
                             SceneBuilderRequest::SimulateLongLowPrioritySceneBuild(time_ms)
                         ).unwrap();
                         return true;
                     }
                     DebugCommand::SetFlags(flags) => {
                         self.resource_cache.set_debug_flags(flags);
+                        self.gpu_cache.set_debug_flags(flags);
                         ResultMsg::DebugCommand(option)
                     }
                     _ => ResultMsg::DebugCommand(option),
                 };
                 self.result_tx.send(msg).unwrap();
                 self.notifier.wake_up();
             }
             ApiMsg::ShutDown => {
@@ -1497,17 +1494,17 @@ impl RenderBackend {
             doc.clip_scroll_tree.print_with(&mut builder);
 
             debug_root.add(builder.build());
         }
 
         serde_json::to_string(&debug_root).unwrap()
     }
 
-    fn report_memory(&self, tx: ::api::channel::MsgSender<MemoryReport>) {
+    fn report_memory(&self, tx: MsgSender<MemoryReport>) {
         let mut report = MemoryReport::default();
         let op = self.size_of_op.unwrap();
         report.gpu_cache_metadata = self.gpu_cache.malloc_size_of(op);
         for (_id, doc) in &self.documents {
             if let Some(ref fb) = doc.frame_builder {
                 report.clip_stores += fb.clip_store.malloc_size_of(op);
             }
             report.hit_testers +=
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -2379,43 +2379,16 @@ impl Renderer {
             debug_root.add(builder.build());
         }
 
         serde_json::to_string(&debug_root).unwrap()
     }
 
     fn handle_debug_command(&mut self, command: DebugCommand) {
         match command {
-            DebugCommand::EnableProfiler(enable) => {
-                self.set_debug_flag(DebugFlags::PROFILER_DBG, enable);
-            }
-            DebugCommand::EnableTextureCacheDebug(enable) => {
-                self.set_debug_flag(DebugFlags::TEXTURE_CACHE_DBG, enable);
-            }
-            DebugCommand::EnableRenderTargetDebug(enable) => {
-                self.set_debug_flag(DebugFlags::RENDER_TARGET_DBG, enable);
-            }
-            DebugCommand::EnableGpuCacheDebug(enable) => {
-                self.set_debug_flag(DebugFlags::GPU_CACHE_DBG, enable);
-            }
-            DebugCommand::EnableGpuTimeQueries(enable) => {
-                self.set_debug_flag(DebugFlags::GPU_TIME_QUERIES, enable);
-            }
-            DebugCommand::EnableGpuSampleQueries(enable) => {
-                self.set_debug_flag(DebugFlags::GPU_SAMPLE_QUERIES, enable);
-            }
-            DebugCommand::EnableNewFrameIndicator(enable) => {
-                self.set_debug_flag(DebugFlags::NEW_FRAME_INDICATOR, enable);
-            }
-            DebugCommand::EnableNewSceneIndicator(enable) => {
-                self.set_debug_flag(DebugFlags::NEW_SCENE_INDICATOR, enable);
-            }
-            DebugCommand::EnableShowOverdraw(enable) => {
-                self.set_debug_flag(DebugFlags::SHOW_OVERDRAW, enable);
-            }
             DebugCommand::EnableDualSourceBlending(_) => {
                 panic!("Should be handled by render backend");
             }
             DebugCommand::FetchDocuments |
             DebugCommand::FetchClipScrollTree => {}
             DebugCommand::FetchRenderTasks => {
                 let json = self.get_render_tasks_for_debugger();
                 self.debug_server.send(json);
@@ -4252,28 +4225,16 @@ impl Renderer {
             } else {
                 self.gpu_profile.disable_samplers();
             }
         }
 
         self.debug_flags = flags;
     }
 
-    pub fn set_debug_flag(&mut self, flag: DebugFlags, enabled: bool) {
-        let mut new_flags = self.debug_flags;
-        new_flags.set(flag, enabled);
-        self.set_debug_flags(new_flags);
-    }
-
-    pub fn toggle_debug_flags(&mut self, toggle: DebugFlags) {
-        let mut new_flags = self.debug_flags;
-        new_flags.toggle(toggle);
-        self.set_debug_flags(new_flags);
-    }
-
     pub fn save_cpu_profile(&self, filename: &str) {
         write_profile(filename);
     }
 
     #[cfg(feature = "debug_renderer")]
     fn draw_render_target_debug(&mut self, framebuffer_size: DeviceIntSize) {
         if !self.debug_flags.contains(DebugFlags::RENDER_TARGET_DBG) {
             return;
--- a/gfx/wr/webrender/src/scene_builder.rs
+++ b/gfx/wr/webrender/src/scene_builder.rs
@@ -164,17 +164,17 @@ pub enum SceneBuilderRequest {
     DeleteDocument(DocumentId),
     WakeUp,
     Flush(MsgSender<()>),
     ClearNamespace(IdNamespace),
     SetFrameBuilderConfig(FrameBuilderConfig),
     SimulateLongSceneBuild(u32),
     SimulateLongLowPrioritySceneBuild(u32),
     Stop,
-    ReportMemory(MemoryReport, ::api::channel::MsgSender<MemoryReport>),
+    ReportMemory(MemoryReport, MsgSender<MemoryReport>),
     #[cfg(feature = "capture")]
     SaveScene(CaptureConfig),
     #[cfg(feature = "replay")]
     LoadScenes(Vec<LoadScene>),
 }
 
 // Message from scene builder to render backend.
 pub enum SceneBuilderResult {
--- a/gfx/wr/webrender_api/src/api.rs
+++ b/gfx/wr/webrender_api/src/api.rs
@@ -675,36 +675,20 @@ bitflags!{
 pub struct CapturedDocument {
     pub document_id: DocumentId,
     pub root_pipeline_id: Option<PipelineId>,
     pub window_size: DeviceIntSize,
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum DebugCommand {
-    /// Display the frame profiler on screen.
-    EnableProfiler(bool),
-    /// Display all texture cache pages on screen.
-    EnableTextureCacheDebug(bool),
-    /// Display intermediate render targets on screen.
-    EnableRenderTargetDebug(bool),
-    /// Display the contents of GPU cache.
-    EnableGpuCacheDebug(bool),
-    /// Display GPU timing results.
-    EnableGpuTimeQueries(bool),
-    /// Display GPU overdraw results
-    EnableGpuSampleQueries(bool),
+    /// Sets the provided debug flags.
+    SetFlags(DebugFlags),
     /// Configure if dual-source blending is used, if available.
     EnableDualSourceBlending(bool),
-    /// Show an indicator that moves every time a frame is rendered.
-    EnableNewFrameIndicator(bool),
-    /// Show an indicator that moves every time a scene is built.
-    EnableNewSceneIndicator(bool),
-    /// Show an overlay displaying overdraw amount.
-    EnableShowOverdraw(bool),
     /// Fetch current documents and display lists.
     FetchDocuments,
     /// Fetch current passes and batches.
     FetchPasses,
     /// Fetch clip-scroll tree.
     FetchClipScrollTree,
     /// Fetch render tasks.
     FetchRenderTasks,
@@ -719,19 +703,16 @@ pub enum DebugCommand {
     /// Invalidate GPU cache, forcing the update from the CPU mirror.
     InvalidateGpuCache,
     /// Causes the scene builder to pause for a given amount of miliseconds each time it
     /// processes a transaction.
     SimulateLongSceneBuild(u32),
     /// Causes the low priority scene builder to pause for a given amount of miliseconds
     /// each time it processes a transaction.
     SimulateLongLowPrioritySceneBuild(u32),
-    /// Sets the provided debug flags. This may overlap with some of the functionality
-    /// above.
-    SetFlags(DebugFlags),
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum ApiMsg {
     /// Add/remove/update images and fonts.
     UpdateResources(Vec<ResourceUpdate>),
     /// Gets the glyph dimensions
     GetGlyphDimensions(
@@ -975,28 +956,36 @@ impl RenderApiSender {
             next_id: Cell::new(ResourceId(0)),
         }
     }
 }
 
 bitflags! {
     #[derive(Default, Deserialize, Serialize)]
     pub struct DebugFlags: u32 {
+        /// Display the frame profiler on screen.
         const PROFILER_DBG          = 1 << 0;
+        /// Display intermediate render targets on screen.
         const RENDER_TARGET_DBG     = 1 << 1;
+        /// Display all texture cache pages on screen.
         const TEXTURE_CACHE_DBG     = 1 << 2;
+        /// Display GPU timing results.
         const GPU_TIME_QUERIES      = 1 << 3;
         const GPU_SAMPLE_QUERIES    = 1 << 4;
         const DISABLE_BATCHING      = 1 << 5;
         const EPOCHS                = 1 << 6;
         const COMPACT_PROFILER      = 1 << 7;
         const ECHO_DRIVER_MESSAGES  = 1 << 8;
+        /// Show an indicator that moves every time a frame is rendered.
         const NEW_FRAME_INDICATOR   = 1 << 9;
+        /// Show an indicator that moves every time a scene is built.
         const NEW_SCENE_INDICATOR   = 1 << 10;
+        /// Show an overlay displaying overdraw amount.
         const SHOW_OVERDRAW         = 1 << 11;
+        /// Display the contents of GPU cache.
         const GPU_CACHE_DBG         = 1 << 12;
         const SLOW_FRAME_INDICATOR  = 1 << 13;
         const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 14;
     }
 }
 
 pub struct RenderApi {
     api_sender: MsgSender<ApiMsg>,
--- a/gfx/wr/wrench/src/main.rs
+++ b/gfx/wr/wrench/src/main.rs
@@ -560,16 +560,17 @@ fn render<'a>(
     let mut do_loop = false;
     let mut cpu_profile_index = 0;
     let mut cursor_position = WorldPoint::zero();
 
     let dim = window.get_inner_size();
     wrench.update(dim);
     thing.do_frame(wrench);
 
+    let mut debug_flags = DebugFlags::empty();
     let mut body = |wrench: &mut Wrench, global_event: winit::Event| {
         let mut do_frame = false;
         let mut do_render = false;
 
         match global_event {
             winit::Event::Awakened => {
                 do_render = true;
             }
@@ -592,46 +593,49 @@ fn render<'a>(
                         ..
                     },
                     ..
                 } => match vk {
                     VirtualKeyCode::Escape => {
                         return winit::ControlFlow::Break;
                     }
                     VirtualKeyCode::P => {
-                        wrench.renderer.toggle_debug_flags(DebugFlags::PROFILER_DBG);
+                        debug_flags.toggle(DebugFlags::PROFILER_DBG);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
                         do_render = true;
                     }
                     VirtualKeyCode::O => {
-                        wrench.renderer.toggle_debug_flags(DebugFlags::RENDER_TARGET_DBG);
+                        debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
                         do_render = true;
                     }
                     VirtualKeyCode::I => {
-                        wrench.renderer.toggle_debug_flags(DebugFlags::TEXTURE_CACHE_DBG);
+                        debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
                         do_render = true;
                     }
                     VirtualKeyCode::S => {
-                        wrench.renderer.toggle_debug_flags(DebugFlags::COMPACT_PROFILER);
+                        debug_flags.toggle(DebugFlags::COMPACT_PROFILER);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
                         do_render = true;
                     }
                     VirtualKeyCode::Q => {
-                        wrench.renderer.toggle_debug_flags(
-                            DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES
-                        );
+                        debug_flags.toggle(DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
                         do_render = true;
                     }
                     VirtualKeyCode::V => {
-                        wrench.renderer.toggle_debug_flags(DebugFlags::SHOW_OVERDRAW);
+                        debug_flags.toggle(DebugFlags::SHOW_OVERDRAW);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
                         do_render = true;
                     }
                     VirtualKeyCode::G => {
-                        // go through the API so that we reach the render backend
-                        wrench.api.send_debug_cmd(DebugCommand::EnableGpuCacheDebug(
-                            !wrench.renderer.get_debug_flags().contains(webrender::DebugFlags::GPU_CACHE_DBG)
-                        ));
+                        debug_flags.toggle(DebugFlags::GPU_CACHE_DBG);
+                        wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
+
                         // force scene rebuild to see the full set of used GPU cache entries
                         let mut txn = Transaction::new();
                         txn.set_root_pipeline(wrench.root_pipeline_id);
                         wrench.api.send_transaction(wrench.document_id, txn);
 
                         do_frame = true;
                     }
                     VirtualKeyCode::R => {