From 5b15c3352373a3cc39f630e2286054a8749146a3 Mon Sep 17 00:00:00 2001 From: JerryShih Date: Mon, 30 Oct 2017 11:31:38 +0800 Subject: [PATCH] Bug 1399389 - redirect the warn/error message to gfx_critical_error/note in WR. r=kvark MozReview-Commit-ID: Fxkz3Fq96Tb --- gfx/layers/wr/WebRenderBridgeParent.cpp | 10 ++++ gfx/thebes/gfxPlatform.cpp | 7 +++ gfx/webrender_bindings/Cargo.toml | 1 + gfx/webrender_bindings/cbindgen.toml | 2 +- gfx/webrender_bindings/src/bindings.rs | 72 ++++++++++++++++++++++++- gfx/webrender_bindings/src/lib.rs | 1 + gfx/webrender_bindings/webrender_ffi.h | 2 + 7 files changed, 93 insertions(+), 2 deletions(-) diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index de7b19d9e221..d78a196887c4 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -78,6 +78,16 @@ void gfx_critical_note(const char* msg) gfxCriticalNote << msg; } +void gfx_critical_error(const char* msg) +{ + gfxCriticalError() << msg; +} + +void gecko_printf_stderr_output(const char* msg) +{ + printf_stderr("%s\n", msg); +} + void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname) { MOZ_ASSERT(glcontext_ptr); diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 2496550dade1..a1d52a4f7137 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -8,6 +8,7 @@ #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter #include "mozilla/webrender/RenderThread.h" +#include "mozilla/webrender/webrender_ffi.h" #include "mozilla/layers/PaintThread.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/GPUProcessManager.h" @@ -1015,6 +1016,8 @@ gfxPlatform::Shutdown() gfxConfig::Shutdown(); + mozilla::wr::wr_shutdown_external_log_handler(); + gPlatform->WillShutdown(); delete gPlatform; @@ -2563,6 +2566,10 @@ gfxPlatform::InitWebRenderConfig() Preferences::RegisterPrefixCallbackAndCall(WebRenderDebugPrefChangeCallback, WR_DEBUG_PREF); } + + // Redirect the webrender's log to gecko's log system. + // The current log level is "warning". + mozilla::wr::wr_init_external_log_handler(wr::LogLevelFilter::Warn); } } diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index c853a03ae2cd..4994910d4076 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -12,6 +12,7 @@ thread_profiler = "0.1.1" euclid = "0.15" app_units = "0.5.6" gleam = "0.4" +log = "0.3" [dependencies.webrender] path = "../webrender" diff --git a/gfx/webrender_bindings/cbindgen.toml b/gfx/webrender_bindings/cbindgen.toml index 39fb31336392..ff860408ddb7 100644 --- a/gfx/webrender_bindings/cbindgen.toml +++ b/gfx/webrender_bindings/cbindgen.toml @@ -16,7 +16,7 @@ namespaces = ["mozilla", "wr"] [parse] parse_deps = true -include = ["webrender", "webrender_api"] +include = ["log", "webrender", "webrender_api"] expand = ["euclid"] [fn] diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 329f9dfe47f4..717f0e72658d 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -17,6 +17,7 @@ use app_units::Au; use rayon; use euclid::SideOffsets2D; use bincode; +use log::{set_logger, shutdown_logger, LogLevelFilter, Log, LogLevel, LogMetadata, LogRecord}; extern crate webrender_api; @@ -43,6 +44,8 @@ pub type WrFontKey = FontKey; type WrFontInstanceKey = FontInstanceKey; /// cbindgen:field-names=[mNamespace, mHandle] type WrYuvColorSpace = YuvColorSpace; +/// cbindgen:field-names=[mNamespace, mHandle] +type WrLogLevelFilter = LogLevelFilter; fn make_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] { if ptr.is_null() { @@ -400,7 +403,13 @@ extern "C" { // by commenting out the path that adds an external image ID fn gfx_use_wrench() -> bool; fn gfx_wr_resource_path_override() -> *const c_char; + // TODO: make gfx_critical_error() work. + // We still have problem to pass the error message from render/render_backend + // thread to main thread now. + #[allow(dead_code)] + fn gfx_critical_error(msg: *const c_char); fn gfx_critical_note(msg: *const c_char); + fn gecko_printf_stderr_output(msg: *const c_char); } struct CppNotifier { @@ -477,7 +486,7 @@ pub extern "C" fn wr_renderer_render(renderer: &mut Renderer, let msg = CString::new(format!("wr_renderer_render: {:?}", e)).unwrap(); unsafe { gfx_critical_note(msg.as_ptr()); - } + } } false }, @@ -1814,3 +1823,64 @@ extern "C" { output: MutByteSlice) -> bool; } + +type ExternalMessageHandler = unsafe extern "C" fn(msg: *const c_char); + +struct WrExternalLogHandler { + error_msg: ExternalMessageHandler, + warn_msg: ExternalMessageHandler, + info_msg: ExternalMessageHandler, + debug_msg: ExternalMessageHandler, + trace_msg: ExternalMessageHandler, + log_level: LogLevel, +} + +impl WrExternalLogHandler { + fn new(log_level: LogLevel) -> WrExternalLogHandler { + WrExternalLogHandler { + error_msg: gfx_critical_note, + warn_msg: gfx_critical_note, + info_msg: gecko_printf_stderr_output, + debug_msg: gecko_printf_stderr_output, + trace_msg: gecko_printf_stderr_output, + log_level: log_level, + } + } +} + +impl Log for WrExternalLogHandler { + fn enabled(&self, metadata : &LogMetadata) -> bool { + metadata.level() <= self.log_level + } + + fn log(&self, record: &LogRecord) { + if self.enabled(record.metadata()) { + // For file path and line, please check the record.location(). + let msg = CString::new(format!("WR: {}", + record.args())).unwrap(); + unsafe { + match record.level() { + LogLevel::Error => (self.error_msg)(msg.as_ptr()), + LogLevel::Warn => (self.warn_msg)(msg.as_ptr()), + LogLevel::Info => (self.info_msg)(msg.as_ptr()), + LogLevel::Debug => (self.debug_msg)(msg.as_ptr()), + LogLevel::Trace => (self.trace_msg)(msg.as_ptr()), + } + } + } + } +} + +#[no_mangle] +pub extern "C" fn wr_init_external_log_handler(log_filter: WrLogLevelFilter) { + let _ = set_logger(|max_log_level| { + max_log_level.set(log_filter); + Box::new(WrExternalLogHandler::new(log_filter.to_log_level() + .unwrap_or(LogLevel::Error))) + }); +} + +#[no_mangle] +pub extern "C" fn wr_shutdown_external_log_handler() { + let _ = shutdown_logger(); +} diff --git a/gfx/webrender_bindings/src/lib.rs b/gfx/webrender_bindings/src/lib.rs index 90d328128a32..1f1ddf258276 100644 --- a/gfx/webrender_bindings/src/lib.rs +++ b/gfx/webrender_bindings/src/lib.rs @@ -12,6 +12,7 @@ extern crate gleam; extern crate rayon; extern crate thread_profiler; extern crate bincode; +extern crate log; #[allow(non_snake_case)] pub mod bindings; diff --git a/gfx/webrender_bindings/webrender_ffi.h b/gfx/webrender_bindings/webrender_ffi.h index 6f668ce72132..0c6b27e4e468 100644 --- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -23,6 +23,8 @@ bool is_glcontext_egl(void* glcontext_ptr); bool gfx_use_wrench(); const char* gfx_wr_resource_path_override(); void gfx_critical_note(const char* msg); +void gfx_critical_error(const char* msg); +void gecko_printf_stderr_output(const char* msg); void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname); } // extern "C"