Bug 1449982 - Add the plumbing for scene builder thread interaction. r=nical
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 10 Apr 2018 12:29:55 -0400
changeset 412681 f14bce5630f5e7dd09727588ef06f88c121a6bfa
parent 412680 7b83f46b5fb38df3311a6b4659d32b6e75b9c275
child 412682 1c9e68c30a817cc840078999828d42d6dc713021
push id101981
push useraiakab@mozilla.com
push dateTue, 10 Apr 2018 22:18:59 +0000
treeherdermozilla-inbound@9ad2b8aabfae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1449982
milestone61.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 1449982 - Add the plumbing for scene builder thread interaction. r=nical This is all the (bidirectional) glue that connects the SceneBuilderHooks to the APZUpdater. MozReview-Commit-ID: JIqUaClVa57
gfx/layers/apz/src/APZUpdater.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -263,8 +263,36 @@ APZUpdater::RunOnControllerThread(alread
   RunOnUpdaterThread(NewRunnableFunction(
       "APZUpdater::RunOnControllerThread",
       &APZThreadUtils::RunOnControllerThread,
       Move(aTask)));
 }
 
 } // namespace layers
 } // namespace mozilla
+
+// Rust callback implementations
+
+void
+apz_register_updater(mozilla::wr::WrWindowId aWindowId)
+{
+}
+
+void
+apz_pre_scene_swap(mozilla::wr::WrWindowId aWindowId)
+{
+}
+
+void
+apz_post_scene_swap(mozilla::wr::WrWindowId aWindowId,
+                    mozilla::wr::WrPipelineInfo* aInfo)
+{
+}
+
+void
+apz_run_updater(mozilla::wr::WrWindowId aWindowId)
+{
+}
+
+void
+apz_deregister_updater(mozilla::wr::WrWindowId aWindowId)
+{
+}
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -502,16 +502,22 @@ WebRenderAPI::Resume()
     // implies that all frame data have been processed when the renderer runs this event.
     RunOnRenderThread(Move(event));
 
     task.Wait();
     return result;
 }
 
 void
+WebRenderAPI::WakeSceneBuilder()
+{
+    wr_api_wake_scene_builder(mDocHandle);
+}
+
+void
 WebRenderAPI::WaitFlushed()
 {
     class WaitFlushedEvent : public RendererEvent
     {
         public:
             explicit WaitFlushedEvent(layers::SynchronousTask* aTask)
                 : mTask(aTask)
             {
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -178,16 +178,18 @@ public:
 
   void RunOnRenderThread(UniquePtr<RendererEvent> aEvent);
 
   void Readback(gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize);
 
   void Pause();
   bool Resume();
 
+  void WakeSceneBuilder();
+
   wr::WrIdNamespace GetNamespace();
   uint32_t GetMaxTextureSize() const { return mMaxTextureSize; }
   bool GetUseANGLE() const { return mUseANGLE; }
   layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
 
   void Capture();
 
 protected:
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -7,16 +7,17 @@ use std::sync::Arc;
 use std::os::raw::{c_void, c_char, c_float};
 use gleam::gl;
 
 use webrender::api::*;
 use webrender::{ReadPixelsFormat, Renderer, RendererOptions, ThreadListener};
 use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use webrender::DebugFlags;
 use webrender::{ApiRecordingReceiver, BinaryRecorder};
+use webrender::{PipelineInfo, SceneBuilderHooks};
 use webrender::{ProgramCache, UploadMethod, VertexUsageHint};
 use thread_profiler::register_thread_with_profiler;
 use moz2d_renderer::Moz2dImageRenderer;
 use app_units::Au;
 use rayon;
 use euclid::SideOffsets2D;
 use log;
 
@@ -596,26 +597,29 @@ pub unsafe extern "C" fn wr_renderer_del
     // let renderer go out of scope and get dropped
 }
 
 pub struct WrPipelineInfo {
     epochs: Vec<(WrPipelineId, WrEpoch)>,
     removed_pipelines: Vec<PipelineId>,
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn wr_renderer_flush_pipeline_info(renderer: &mut Renderer) -> *mut WrPipelineInfo {
-    let info = renderer.flush_pipeline_info();
-    let pipeline_epochs = Box::new(
+impl WrPipelineInfo {
+    fn new(info: PipelineInfo) -> Self {
         WrPipelineInfo {
             epochs: info.epochs.into_iter().collect(),
             removed_pipelines: info.removed_pipelines,
         }
-    );
-    return Box::into_raw(pipeline_epochs);
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn wr_renderer_flush_pipeline_info(renderer: &mut Renderer) -> *mut WrPipelineInfo {
+    let info = renderer.flush_pipeline_info();
+    Box::into_raw(Box::new(WrPipelineInfo::new(info)))
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn wr_pipeline_info_next_epoch(
     info: &mut WrPipelineInfo,
     out_pipeline: &mut WrPipelineId,
     out_epoch: &mut WrEpoch
 ) -> bool {
@@ -640,16 +644,62 @@ pub unsafe extern "C" fn wr_pipeline_inf
 }
 
 /// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
 pub unsafe extern "C" fn wr_pipeline_info_delete(info: *mut WrPipelineInfo) {
     Box::from_raw(info);
 }
 
+#[allow(improper_ctypes)] // this is needed so that rustc doesn't complain about passing the *mut WrPipelineInfo to an extern function
+extern "C" {
+    fn apz_register_updater(window_id: WrWindowId);
+    fn apz_pre_scene_swap(window_id: WrWindowId);
+    // This function takes ownership of the pipeline_info and is responsible for
+    // freeing it via wr_pipeline_info_delete.
+    fn apz_post_scene_swap(window_id: WrWindowId, pipeline_info: *mut WrPipelineInfo);
+    fn apz_run_updater(window_id: WrWindowId);
+    fn apz_deregister_updater(window_id: WrWindowId);
+}
+
+struct APZCallbacks {
+    window_id: WrWindowId,
+}
+
+impl APZCallbacks {
+    pub fn new(window_id: WrWindowId) -> Self {
+        APZCallbacks {
+            window_id,
+        }
+    }
+}
+
+impl SceneBuilderHooks for APZCallbacks {
+    fn register(&self) {
+        unsafe { apz_register_updater(self.window_id) }
+    }
+
+    fn pre_scene_swap(&self) {
+        unsafe { apz_pre_scene_swap(self.window_id) }
+    }
+
+    fn post_scene_swap(&self, info: PipelineInfo) {
+        let info = Box::into_raw(Box::new(WrPipelineInfo::new(info)));
+        unsafe { apz_post_scene_swap(self.window_id, info) }
+    }
+
+    fn poke(&self) {
+        unsafe { apz_run_updater(self.window_id) }
+    }
+
+    fn deregister(&self) {
+        unsafe { apz_deregister_updater(self.window_id) }
+    }
+}
+
 extern "C" {
     fn gecko_profiler_register_thread(name: *const ::std::os::raw::c_char);
     fn gecko_profiler_unregister_thread();
 }
 
 struct GeckoProfilerThreadListener {}
 
 impl GeckoProfilerThreadListener {
@@ -779,16 +829,17 @@ pub extern "C" fn wr_window_new(window_i
                 match CStr::from_ptr(override_charptr).to_str() {
                     Ok(override_str) => Some(PathBuf::from(override_str)),
                     _ => None
                 }
             }
         },
         renderer_id: Some(window_id.0),
         upload_method,
+        scene_builder_hooks: Some(Box::new(APZCallbacks::new(window_id))),
         ..Default::default()
     };
 
     let notifier = Box::new(CppNotifier {
         window_id: window_id,
     });
     let (renderer, sender) = match Renderer::new(gl, notifier, opts) {
         Ok((renderer, sender)) => (renderer, sender),
@@ -1322,16 +1373,21 @@ pub extern "C" fn wr_resource_updates_de
     }
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn wr_api_get_namespace(dh: &mut DocumentHandle) -> WrIdNamespace {
     dh.api.get_namespace_id()
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn wr_api_wake_scene_builder(dh: &mut DocumentHandle) {
+    dh.api.wake_scene_builder();
+}
+
 // RenderThread WIP notes:
 // In order to separate the compositor thread (or ipc receiver) and the render
 // thread, some of the logic below needs to be rewritten. In particular
 // the WrWindowState and Notifier implementations aren't designed to work with
 // a separate render thread.
 // As part of that I am moving the bindings closer to WebRender's API boundary,
 // and moving more of the logic in C++ land.
 // This work is tracked by bug 1328602.
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -80,19 +80,28 @@ struct FontInstanceFlags {
     FONT_SMOOTHING    = 1 << 16,
 
     FORCE_AUTOHINT    = 1 << 16,
     NO_AUTOHINT       = 1 << 17,
     VERTICAL_LAYOUT   = 1 << 18
   };
 };
 
+struct WrWindowId;
+struct WrPipelineInfo;
+
 } // namespace wr
 } // namespace mozilla
 
+void apz_register_updater(mozilla::wr::WrWindowId aWindowId);
+void apz_pre_scene_swap(mozilla::wr::WrWindowId aWindowId);
+void apz_post_scene_swap(mozilla::wr::WrWindowId aWindowId, mozilla::wr::WrPipelineInfo* aInfo);
+void apz_run_updater(mozilla::wr::WrWindowId aWindowId);
+void apz_deregister_updater(mozilla::wr::WrWindowId aWindowId);
+
 } // extern "C"
 
 // Some useful defines to stub out webrender binding functions for when we
 // build gecko without webrender. We try to tell the compiler these functions
 // are unreachable in that case, but VC++ emits a warning if it finds any
 // unreachable functions invoked from destructors. That warning gets turned into
 // an error and causes the build to fail. So for wr_* functions called by
 // destructors in C++ classes, use WR_DESTRUCTOR_SAFE_FUNC instead, which omits
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -310,16 +310,30 @@ struct FontKey {
 };
 
 using WrFontKey = FontKey;
 
 using VecU8 = Vec<uint8_t>;
 
 using ArcVecU8 = Arc<VecU8>;
 
+struct WrWindowId {
+  uint64_t mHandle;
+
+  bool operator==(const WrWindowId& aOther) const {
+    return mHandle == aOther.mHandle;
+  }
+  bool operator<(const WrWindowId& aOther) const {
+    return mHandle < aOther.mHandle;
+  }
+  bool operator<=(const WrWindowId& aOther) const {
+    return mHandle <= aOther.mHandle;
+  }
+};
+
 template<typename T, typename U>
 struct TypedSize2D {
   T width;
   T height;
 
   bool operator==(const TypedSize2D& aOther) const {
     return width == aOther.width &&
            height == aOther.height;
@@ -740,30 +754,16 @@ struct MutByteSlice {
   uintptr_t len;
 
   bool operator==(const MutByteSlice& aOther) const {
     return buffer == aOther.buffer &&
            len == aOther.len;
   }
 };
 
-struct WrWindowId {
-  uint64_t mHandle;
-
-  bool operator==(const WrWindowId& aOther) const {
-    return mHandle == aOther.mHandle;
-  }
-  bool operator<(const WrWindowId& aOther) const {
-    return mHandle < aOther.mHandle;
-  }
-  bool operator<=(const WrWindowId& aOther) const {
-    return mHandle <= aOther.mHandle;
-  }
-};
-
 struct Epoch {
   uint32_t mHandle;
 
   bool operator==(const Epoch& aOther) const {
     return mHandle == aOther.mHandle;
   }
   bool operator<(const Epoch& aOther) const {
     return mHandle < aOther.mHandle;
@@ -942,16 +942,27 @@ extern void AddFontData(WrFontKey aKey,
                         const ArcVecU8 *aVec);
 
 extern void AddNativeFontHandle(WrFontKey aKey,
                                 void *aHandle,
                                 uint32_t aIndex);
 
 extern void DeleteFontData(WrFontKey aKey);
 
+extern void apz_deregister_updater(WrWindowId aWindowId);
+
+extern void apz_post_scene_swap(WrWindowId aWindowId,
+                                WrPipelineInfo *aPipelineInfo);
+
+extern void apz_pre_scene_swap(WrWindowId aWindowId);
+
+extern void apz_register_updater(WrWindowId aWindowId);
+
+extern void apz_run_updater(WrWindowId aWindowId);
+
 extern void gecko_printf_stderr_output(const char *aMsg);
 
 extern void gecko_profiler_register_thread(const char *aName);
 
 extern void gecko_profiler_unregister_thread();
 
 extern void gfx_critical_error(const char *aMsg);
 
@@ -1030,16 +1041,20 @@ void wr_api_send_transaction(DocumentHan
                              Transaction *aTransaction)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_shut_down(DocumentHandle *aDh)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE
+void wr_api_wake_scene_builder(DocumentHandle *aDh)
+WR_FUNC;
+
+WR_INLINE
 void wr_clear_item_tag(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
 void wr_dec_ref_arc(const VecU8 *aArc)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE