Bug 1591754 - Fix incorrect surface deletions when frames are skipped. r=nical
authorGlenn Watson <git@intuitionlibrary.com>
Fri, 15 Nov 2019 09:46:43 +0000
changeset 502218 b2abdbdb7ba238d751dd706d5f506fcb7556b797
parent 502217 0b2de590fde9951b3438f0c3681fe9907acc0f80
child 502219 dbc1778c0ebdfa4908d66c2c700daa798bd68209
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1591754
milestone72.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 1591754 - Fix incorrect surface deletions when frames are skipped. r=nical If the render backend is producing frames too quickly for the renderer thread to consume, old frames are dropped in favor of the most recent frame. When this occurs, we need to ensure that any native surface updates from the skipped frame are also applied. Otherwise, the state of the native surfaces list can get out of sync between the renderer and render backend threads. Differential Revision: https://phabricator.services.mozilla.com/D53122
gfx/wr/webrender/src/renderer.rs
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -2485,17 +2485,26 @@ impl Renderer {
                         Some(pos) => {
                             // If the document we are replacing must be drawn
                             // (in order to update the texture cache), issue
                             // a render just to off-screen targets.
                             if self.active_documents[pos].1.frame.must_be_drawn() {
                                 let device_size = self.device_size;
                                 self.render_impl(device_size).ok();
                             }
-                            self.active_documents[pos].1 = doc;
+
+                            let mut old_doc = mem::replace(
+                                &mut self.active_documents[pos].1,
+                                doc,
+                            );
+
+                            // If the document we are overwriting has any pending
+                            // native surface updates, ensure they are flushed
+                            // before replacing with the new document.
+                            self.update_native_surfaces(&mut old_doc.frame.composite_state);
                         }
                         None => self.active_documents.push((document_id, doc)),
                     }
 
                     // IMPORTANT: The pending texture cache updates must be applied
                     //            *after* the previous frame has been rendered above
                     //            (if neceessary for a texture cache update). For
                     //            an example of why this is required:
@@ -5003,21 +5012,21 @@ impl Renderer {
         );
 
         debug_assert!(self.texture_resolver.prev_pass_alpha.is_none());
         debug_assert!(self.texture_resolver.prev_pass_color.is_none());
     }
 
     fn update_native_surfaces(
         &mut self,
-        composite_state: &CompositeState,
+        composite_state: &mut CompositeState,
     ) {
         match self.compositor_config {
             CompositorConfig::Native { ref mut compositor, .. } => {
-                for op in &composite_state.native_surface_updates {
+                for op in composite_state.native_surface_updates.drain(..) {
                     match op.details {
                         NativeSurfaceOperationDetails::CreateSurface { size, is_opaque } => {
                             let _inserted = self.allocated_native_surfaces.insert(op.id);
                             debug_assert!(_inserted, "bug: creating existing surface");
 
                             compositor.create_surface(
                                 op.id,
                                 size,
@@ -5060,17 +5069,17 @@ impl Renderer {
             return;
         }
 
         self.device.disable_depth_write();
         self.set_blend(false, FramebufferKind::Other);
         self.device.disable_stencil();
 
         self.bind_frame_data(frame);
-        self.update_native_surfaces(&frame.composite_state);
+        self.update_native_surfaces(&mut frame.composite_state);
 
         for (_pass_index, pass) in frame.passes.iter_mut().enumerate() {
             #[cfg(not(target_os = "android"))]
             let _gm = self.gpu_profile.start_marker(&format!("pass {}", _pass_index));
 
             self.texture_resolver.bind(
                 &TextureSource::PrevPassAlpha,
                 TextureSampler::PrevPassAlpha,