Bug 1390138 - Add render() error handling to gecko. r=jrmuizel
authorSotaro Ikeda <sikeda@mozilla.com>
Fri, 01 Sep 2017 09:39:28 -0400
changeset 428500 5ca9c4d3658cda11a748e7e8722f3fc51fc80b5d
parent 428499 c084a72939ccdcb66605ec39fe493d48bdbac705
child 428501 f64e2b4dcf5eec0b4ad456c149680a67b7c26dc4
child 428601 19a399059c8b9309e54928e8b268638bc4707c44
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1390138
milestone57.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 1390138 - Add render() error handling to gecko. r=jrmuizel
gfx/ipc/GPUProcessManager.cpp
gfx/webrender_bindings/RendererOGL.cpp
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -430,28 +430,32 @@ GPUProcessManager::SimulateDeviceReset()
 }
 
 void
 GPUProcessManager::DisableWebRender(wr::WebRenderError aError)
 {
   if (!gfx::gfxVars::UseWebRender()) {
     return;
   }
+  // Disable WebRender
   if (aError == wr::WebRenderError::INITIALIZE) {
-    // Disable WebRender
     gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
       gfx::FeatureStatus::Unavailable,
       "WebRender initialization failed",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_INITIALIZE"));
   } else if (aError == wr::WebRenderError::MAKE_CURRENT) {
-    // Disable WebRender
     gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
       gfx::FeatureStatus::Unavailable,
       "Failed to make render context current",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_MAKE_CURRENT"));
+  } else if (aError == wr::WebRenderError::RENDER) {
+    gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
+      gfx::FeatureStatus::Unavailable,
+      "Failed to render WebRender",
+      NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_RENDER"));
   } else {
     MOZ_ASSERT_UNREACHABLE("Invalid value");
   }
   gfx::gfxVars::SetUseWebRender(false);
 
   if (mProcess) {
     OnRemoteProcessDeviceReset(mProcess);
   } else {
--- a/gfx/webrender_bindings/RendererOGL.cpp
+++ b/gfx/webrender_bindings/RendererOGL.cpp
@@ -169,17 +169,19 @@ RendererOGL::Render()
 
   auto size = mWidget->GetClientSize();
 
   if (mSyncObject) {
     // XXX: if the synchronization is failed, we should handle the device reset.
     mSyncObject->Synchronize();
   }
 
-  wr_renderer_render(mRenderer, size.width, size.height);
+  if (!wr_renderer_render(mRenderer, size.width, size.height)) {
+    NotifyWebRenderError(WebRenderError::RENDER);
+  }
 
   mGL->SwapBuffers();
   mWidget->PostRender(&widgetContext);
 
 #if defined(ENABLE_FRAME_LATENCY_LOG)
   if (mFrameStartTime) {
     uint32_t latencyMs = round((TimeStamp::Now() - mFrameStartTime).ToMilliseconds());
     printf_stderr("generate frame latencyMs latencyMs %d\n", latencyMs);
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -698,16 +698,17 @@ struct WrClipId {
   }
 };
 
 typedef Variant<layers::FrameMetrics::ViewID, WrClipId> ScrollOrClipId;
 
 enum class WebRenderError : int8_t {
   INITIALIZE = 0,
   MAKE_CURRENT,
+  RENDER,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
 } // namespace wr
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERTYPES_H */
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -438,18 +438,30 @@ pub extern "C" fn wr_renderer_set_extern
 #[no_mangle]
 pub extern "C" fn wr_renderer_update(renderer: &mut Renderer) {
     renderer.update();
 }
 
 #[no_mangle]
 pub extern "C" fn wr_renderer_render(renderer: &mut Renderer,
                                      width: u32,
-                                     height: u32) {
-    renderer.render(DeviceUintSize::new(width, height));
+                                     height: u32) -> bool {
+    match renderer.render(DeviceUintSize::new(width, height)) {
+        Ok(()) => true,
+        Err(errors) => {
+            for e in errors {
+                println!(" Failed to render: {:?}", e);
+                let msg = CString::new(format!("wr_renderer_render: {:?}", e)).unwrap();
+                unsafe {
+                    gfx_critical_note(msg.as_ptr());
+               }
+            }
+            false
+        },
+    }
 }
 
 // Call wr_renderer_render() before calling this function.
 #[no_mangle]
 pub unsafe extern "C" fn wr_renderer_readback(renderer: &mut Renderer,
                                               width: u32,
                                               height: u32,
                                               dst_buffer: *mut u8,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1140,17 +1140,17 @@ WR_INLINE
 void wr_renderer_readback(Renderer *aRenderer,
                           uint32_t aWidth,
                           uint32_t aHeight,
                           uint8_t *aDstBuffer,
                           size_t aBufferSize)
 WR_FUNC;
 
 WR_INLINE
-void wr_renderer_render(Renderer *aRenderer,
+bool wr_renderer_render(Renderer *aRenderer,
                         uint32_t aWidth,
                         uint32_t aHeight)
 WR_FUNC;
 
 WR_INLINE
 void wr_renderer_set_debug_flags(Renderer *aRenderer,
                                  WrDebugFlags aFlags)
 WR_FUNC;