Bug 1687522 - Use a 'gecko' feature instead of having a ThreadListener trait. r=kvark

Previously, we've taken the strategy of exposing any gecko specific hooks
as traits. The disadvantage of this approach is that it requires plumbing
a boxed trait through to any places that need to use it.

With this approach, we add global functions that don't do anything when
compiled without the 'gecko' feature. This makes it easier to add hooks
and avoids the plumbing which should reduce friction in the process
of moving more stuff out of gecko and into webrender.

Differential Revision: https://phabricator.services.mozilla.com/D102334
This commit is contained in:
Jeff Muizelaar 2021-02-03 16:19:20 +00:00
parent ba4f83d4d6
commit 69eeb000ea
7 changed files with 51 additions and 79 deletions

View File

@ -28,7 +28,7 @@ wr_malloc_size_of = { path = "../wr/wr_malloc_size_of" }
path = "../wr/webrender"
version = "0.61.0"
default-features = false
features = ["capture", "serialize_program"]
features = ["capture", "serialize_program", "gecko"]
[target.'cfg(target_os = "windows")'.dependencies]
dwrote = "0.11"

View File

@ -38,7 +38,7 @@ use webrender::{
CompositorCapabilities, CompositorConfig, CompositorSurfaceTransform, DebugFlags, Device, NativeSurfaceId,
NativeSurfaceInfo, NativeTileId, PartialPresentCompositor, PipelineInfo, ProfilerHooks, RecordedFrameHandle,
Renderer, RendererOptions, RendererStats, SceneBuilderHooks, ShaderPrecacheFlags, Shaders, SharedShaders,
TextureCacheConfig, ThreadListener, UploadMethod, ONE_TIME_USAGE_HINT,
TextureCacheConfig, UploadMethod, ONE_TIME_USAGE_HINT, host_utils::{thread_started, thread_stopped}
};
use wr_malloc_size_of::MallocSizeOfOps;
@ -1058,35 +1058,9 @@ impl AsyncPropertySampler for SamplerCallback {
}
extern "C" {
fn gecko_profiler_register_thread(name: *const ::std::os::raw::c_char);
fn gecko_profiler_unregister_thread();
fn wr_register_thread_local_arena();
}
pub struct GeckoProfilerThreadListener {}
impl GeckoProfilerThreadListener {
pub fn new() -> GeckoProfilerThreadListener {
GeckoProfilerThreadListener {}
}
}
impl ThreadListener for GeckoProfilerThreadListener {
fn thread_started(&self, thread_name: &str) {
let name = CString::new(thread_name).unwrap();
unsafe {
// gecko_profiler_register_thread copies the passed name here.
gecko_profiler_register_thread(name.as_ptr());
}
}
fn thread_stopped(&self, _: &str) {
unsafe {
gecko_profiler_unregister_thread();
}
}
}
pub struct WrThreadPool(Arc<rayon::ThreadPool>);
#[no_mangle]
@ -1101,15 +1075,14 @@ pub extern "C" fn wr_thread_pool_new(low_priority: bool) -> *mut WrThreadPool {
let worker = rayon::ThreadPoolBuilder::new()
.thread_name(move |idx| format!("WRWorker{}#{}", priority_tag, idx))
.num_threads(num_threads)
.start_handler(move |idx| unsafe {
wr_register_thread_local_arena();
.start_handler(move |idx| {
unsafe { wr_register_thread_local_arena(); }
let name = format!("WRWorker{}#{}", priority_tag, idx);
register_thread_with_profiler(name.clone());
let name = CString::new(name).unwrap();
gecko_profiler_register_thread(name.as_ptr());
thread_started(&name);
})
.exit_handler(|_idx| unsafe {
gecko_profiler_unregister_thread();
.exit_handler(|_idx| {
thread_stopped();
})
.build();
@ -1633,7 +1606,6 @@ pub extern "C" fn wr_window_new(
))),
crash_annotator: Some(Box::new(MozCrashAnnotator)),
workers: Some(workers),
thread_listener: Some(Box::new(GeckoProfilerThreadListener::new())),
size_of_op: Some(size_of_op),
enclosing_size_of_op: Some(enclosing_size_of_op),
cached_programs,

View File

@ -2,7 +2,7 @@
* 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 bindings::{GeckoProfilerThreadListener, WrCompositor};
use bindings::WrCompositor;
use gleam::{gl, gl::GLenum, gl::Gl};
use std::cell::{Cell, UnsafeCell};
use std::collections::{hash_map::HashMap, VecDeque};
@ -16,7 +16,7 @@ use std::thread;
use webrender::{
api::units::*, api::ColorDepth, api::ExternalImageId, api::ImageRendering, api::YuvColorSpace, Compositor,
CompositorCapabilities, CompositorSurfaceTransform, NativeSurfaceId, NativeSurfaceInfo, NativeTileId,
ThreadListener,
host_utils::{thread_started, thread_stopped}
};
#[no_mangle]
@ -730,15 +730,14 @@ impl SwCompositeThread {
// overhead.
.stack_size(32 * 1024)
.spawn(move || {
let thread_listener = GeckoProfilerThreadListener::new();
thread_listener.thread_started(thread_name);
thread_started(thread_name);
// Process any available jobs. This will return a non-Ok
// result when the job queue is dropped, causing the thread
// to eventually exit.
while let Some((job, band)) = info.take_job(true) {
info.process_job(job, band);
}
thread_listener.thread_stopped(thread_name);
thread_stopped();
})
.expect("Failed creating SwComposite thread");
result

View File

@ -19,6 +19,7 @@ display_list_stats = ["api/display_list_stats"]
serialize_program = ["serde", "webrender_build/serialize_program"]
no_static_freetype = []
leak_checks = []
gecko = []
[build-dependencies]
build-parallel = "0.1.2"

View File

@ -0,0 +1,26 @@
#[cfg(feature = "gecko")]
mod utils {
use std::ffi::CString;
extern "C" {
fn gecko_profiler_register_thread(name: *const ::std::os::raw::c_char);
fn gecko_profiler_unregister_thread();
}
pub fn thread_started(thread_name: &str) {
let name = CString::new(thread_name).unwrap();
unsafe {
// gecko_profiler_register_thread copies the passed name here.
gecko_profiler_register_thread(name.as_ptr());
}
}
pub fn thread_stopped() {
unsafe { gecko_profiler_unregister_thread(); }
}
}
#[cfg(not(feature = "gecko"))]
mod utils {
pub fn thread_started(_: &str) { }
pub fn thread_stopped() { }
}
pub use utils::*;

View File

@ -132,6 +132,8 @@ mod util;
mod visibility;
mod api_resources;
mod image_tiling;
pub mod host_utils;
///
pub mod intern;
///
@ -219,7 +221,7 @@ pub use crate::profiler::{ProfilerHooks, set_profiler_hooks};
pub use crate::renderer::{
AsyncPropertySampler, CpuProfile, DebugFlags, GpuProfile, GraphicsApi,
GraphicsApiInfo, PipelineInfo, Renderer, RendererError, RendererOptions, RenderResults,
RendererStats, SceneBuilderHooks, Shaders, SharedShaders, ThreadListener, ShaderPrecacheFlags,
RendererStats, SceneBuilderHooks, Shaders, SharedShaders, ShaderPrecacheFlags,
MAX_VERTEX_TEXTURE_WIDTH, ONE_TIME_USAGE_HINT,
};
pub use crate::hit_test::SharedHitTester;

View File

@ -94,6 +94,7 @@ use crate::render_target::{RenderTargetKind, BlitJob, BlitJobSource};
use crate::texture_cache::{TextureCache, TextureCacheConfig};
use crate::tile_cache::PictureCacheDebugInfo;
use crate::util::drain_filter;
use crate::host_utils::{thread_started, thread_stopped};
use upload::{upload_to_texture_cache, UploadTexturePool};
use euclid::{rect, Transform3D, Scale, default};
@ -1118,9 +1119,6 @@ impl Renderer {
let enclosing_size_of_op = options.enclosing_size_of_op;
let make_size_of_ops =
move || size_of_op.map(|o| MallocSizeOfOps::new(o, enclosing_size_of_op));
let thread_listener = Arc::new(options.thread_listener);
let thread_listener_for_rayon_start = thread_listener.clone();
let thread_listener_for_rayon_end = thread_listener.clone();
let workers = options
.workers
.take()
@ -1129,14 +1127,10 @@ impl Renderer {
.thread_name(|idx|{ format!("WRWorker#{}", idx) })
.start_handler(move |idx| {
register_thread_with_profiler(format!("WRWorker#{}", idx));
if let Some(ref thread_listener) = *thread_listener_for_rayon_start {
thread_listener.thread_started(&format!("WRWorker#{}", idx));
}
thread_started(&format!("WRWorker#{}", idx));
})
.exit_handler(move |idx| {
if let Some(ref thread_listener) = *thread_listener_for_rayon_end {
thread_listener.thread_stopped(&format!("WRWorker#{}", idx));
}
.exit_handler(move |_idx| {
thread_stopped();
})
.build();
Arc::new(worker.unwrap())
@ -1147,9 +1141,6 @@ impl Renderer {
let font_instances = SharedFontInstanceMap::new();
let blob_image_handler = options.blob_image_handler.take();
let thread_listener_for_render_backend = thread_listener.clone();
let thread_listener_for_scene_builder = thread_listener.clone();
let thread_listener_for_lp_scene_builder = thread_listener.clone();
let scene_builder_hooks = options.scene_builder_hooks;
let rb_thread_name = format!("WRRenderBackend#{}", options.renderer_id.unwrap_or(0));
let scene_thread_name = format!("WRSceneBuilder#{}", options.renderer_id.unwrap_or(0));
@ -1163,9 +1154,7 @@ impl Renderer {
thread::Builder::new().name(scene_thread_name.clone()).spawn(move || {
register_thread_with_profiler(scene_thread_name.clone());
if let Some(ref thread_listener) = *thread_listener_for_scene_builder {
thread_listener.thread_started(&scene_thread_name);
}
thread_started(&scene_thread_name);
let mut scene_builder = SceneBuilderThread::new(
config,
@ -1177,9 +1166,7 @@ impl Renderer {
);
scene_builder.run();
if let Some(ref thread_listener) = *thread_listener_for_scene_builder {
thread_listener.thread_stopped(&scene_thread_name);
}
thread_stopped();
})?;
let low_priority_scene_tx = if options.support_low_priority_transactions {
@ -1192,16 +1179,12 @@ impl Renderer {
thread::Builder::new().name(lp_scene_thread_name.clone()).spawn(move || {
register_thread_with_profiler(lp_scene_thread_name.clone());
if let Some(ref thread_listener) = *thread_listener_for_lp_scene_builder {
thread_listener.thread_started(&lp_scene_thread_name);
}
thread_started(&lp_scene_thread_name);
let mut scene_builder = lp_builder;
scene_builder.run();
if let Some(ref thread_listener) = *thread_listener_for_lp_scene_builder {
thread_listener.thread_stopped(&lp_scene_thread_name);
}
thread_stopped();
})?;
low_priority_scene_tx
@ -1225,9 +1208,7 @@ impl Renderer {
let enable_multithreading = options.enable_multithreading;
thread::Builder::new().name(rb_thread_name.clone()).spawn(move || {
register_thread_with_profiler(rb_thread_name.clone());
if let Some(ref thread_listener) = *thread_listener_for_render_backend {
thread_listener.thread_started(&rb_thread_name);
}
thread_started(&rb_thread_name);
let texture_cache = TextureCache::new(
max_texture_size,
@ -1264,9 +1245,7 @@ impl Renderer {
namespace_alloc_by_client,
);
backend.run();
if let Some(ref thread_listener) = *thread_listener_for_render_backend {
thread_listener.thread_stopped(&rb_thread_name);
}
thread_stopped();
})?;
let debug_method = if !options.enable_gpu_markers {
@ -5176,11 +5155,6 @@ impl Renderer {
}
}
pub trait ThreadListener {
fn thread_started(&self, thread_name: &str);
fn thread_stopped(&self, thread_name: &str);
}
/// Allows callers to hook in at certain points of the async scene build. These
/// functions are all called from the scene builder thread.
pub trait SceneBuilderHooks {
@ -5268,7 +5242,6 @@ pub struct RendererOptions {
pub enable_multithreading: bool,
pub blob_image_handler: Option<Box<dyn BlobImageHandler>>,
pub crash_annotator: Option<Box<dyn CrashAnnotator>>,
pub thread_listener: Option<Box<dyn ThreadListener + Send + Sync>>,
pub size_of_op: Option<VoidPtrToSizeFn>,
pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
pub cached_programs: Option<Rc<ProgramCache>>,
@ -5356,7 +5329,6 @@ impl Default for RendererOptions {
enable_multithreading: true,
blob_image_handler: None,
crash_annotator: None,
thread_listener: None,
size_of_op: None,
enclosing_size_of_op: None,
renderer_id: None,