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
--- 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