diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index ea4e141f1a2b..badc96f24890 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -2700,9 +2700,10 @@ bool BrowserChild::CreateRemoteLayerManager( success = mPuppetWidget->CreateRemoteLayerManager( [&](LayerManager* aLayerManager) -> bool { MOZ_ASSERT(aLayerManager->AsWebRenderLayerManager()); + nsCString error; return aLayerManager->AsWebRenderLayerManager()->Initialize( aCompositorChild, wr::AsPipelineId(mLayersId), - &mTextureFactoryIdentifier); + &mTextureFactoryIdentifier, error); }); } else { nsTArray ignored; diff --git a/gfx/ipc/GPUProcessManager.cpp b/gfx/ipc/GPUProcessManager.cpp index ebfc0773fc32..75ae993fc881 100644 --- a/gfx/ipc/GPUProcessManager.cpp +++ b/gfx/ipc/GPUProcessManager.cpp @@ -446,7 +446,8 @@ void GPUProcessManager::SimulateDeviceReset() { } } -void GPUProcessManager::DisableWebRender(wr::WebRenderError aError) { +void GPUProcessManager::DisableWebRender(wr::WebRenderError aError, + const nsCString& aMsg) { if (!gfx::gfxVars::UseWebRender()) { return; } @@ -454,8 +455,7 @@ void GPUProcessManager::DisableWebRender(wr::WebRenderError aError) { if (aError == wr::WebRenderError::INITIALIZE) { gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER) .ForceDisable(gfx::FeatureStatus::Unavailable, - "WebRender initialization failed", - "FEATURE_FAILURE_WEBRENDER_INITIALIZE"_ns); + "WebRender initialization failed", aMsg); } else if (aError == wr::WebRenderError::MAKE_CURRENT) { gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER) .ForceDisable(gfx::FeatureStatus::Unavailable, @@ -493,7 +493,7 @@ void GPUProcessManager::DisableWebRender(wr::WebRenderError aError) { } void GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError) { - DisableWebRender(aError); + DisableWebRender(aError, nsCString()); } void GPUProcessManager::OnInProcessDeviceReset() { diff --git a/gfx/ipc/GPUProcessManager.h b/gfx/ipc/GPUProcessManager.h index bbbadf1d0478..caa4da30938b 100644 --- a/gfx/ipc/GPUProcessManager.h +++ b/gfx/ipc/GPUProcessManager.h @@ -149,7 +149,7 @@ class GPUProcessManager final : public GPUProcessHost::Listener { void OnProcessLaunchComplete(GPUProcessHost* aHost) override; void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override; void SimulateDeviceReset(); - void DisableWebRender(wr::WebRenderError aError); + void DisableWebRender(wr::WebRenderError aError, const nsCString& aMsg); void NotifyWebRenderError(wr::WebRenderError aError); void OnInProcessDeviceReset(); void OnRemoteProcessDeviceReset(GPUProcessHost* aHost) override; diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index fc587520e030..81b03ad29f9e 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -1951,10 +1951,13 @@ PWebRenderBridgeParent* CompositorBridgeParent::AllocPWebRenderBridgeParent( // Same, but for the OMTA sampler. mOMTASampler->SetWebRenderWindowId(windowId); } + + nsCString error; RefPtr api = - wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize); + wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize, error); if (!api) { - mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId); + mWrBridge = + WebRenderBridgeParent::CreateDestroyed(aPipelineId, std::move(error)); mWrBridge.get()->AddRef(); // IPDL reference return mWrBridge; } diff --git a/gfx/layers/ipc/ContentCompositorBridgeParent.cpp b/gfx/layers/ipc/ContentCompositorBridgeParent.cpp index 37cad6d8c576..b56011b751f6 100644 --- a/gfx/layers/ipc/ContentCompositorBridgeParent.cpp +++ b/gfx/layers/ipc/ContentCompositorBridgeParent.cpp @@ -237,8 +237,9 @@ ContentCompositorBridgeParent::AllocPWebRenderBridgeParent( nsPrintfCString("Created child without a matching parent? root %p", root.get()) .get()); + nsCString error("NO_PARENT"); WebRenderBridgeParent* parent = - WebRenderBridgeParent::CreateDestroyed(aPipelineId); + WebRenderBridgeParent::CreateDestroyed(aPipelineId, std::move(error)); parent->AddRef(); // IPDL reference return parent; } diff --git a/gfx/layers/ipc/PWebRenderBridge.ipdl b/gfx/layers/ipc/PWebRenderBridge.ipdl index ce1525dbd0a4..f329cfcf3f21 100644 --- a/gfx/layers/ipc/PWebRenderBridge.ipdl +++ b/gfx/layers/ipc/PWebRenderBridge.ipdl @@ -41,7 +41,7 @@ sync protocol PWebRenderBridge parent: sync EnsureConnected() - returns (TextureFactoryIdentifier textureFactoryIdentifier, MaybeIdNamespace maybeIdNamespace); + returns (TextureFactoryIdentifier textureFactoryIdentifier, MaybeIdNamespace maybeIdNamespace, nsCString error); async NewCompositable(CompositableHandle handle, TextureInfo info); async ReleaseCompositable(CompositableHandle compositable); diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index f4198b85e6d3..06324c4b65e0 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -365,13 +365,15 @@ WebRenderBridgeParent::WebRenderBridgeParent( UpdateQualitySettings(); } -WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId) +WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId, + nsCString&& aError) : mCompositorBridge(nullptr), mPipelineId(aPipelineId), mChildLayersObserverEpoch{0}, mParentLayersObserverEpoch{0}, mWrEpoch{0}, mIdNamespace{0}, + mInitError(aError), mPaused(false), mDestroyed(true), mReceivedDisplayList(false), @@ -384,17 +386,18 @@ WebRenderBridgeParent::~WebRenderBridgeParent() {} /* static */ WebRenderBridgeParent* WebRenderBridgeParent::CreateDestroyed( - const wr::PipelineId& aPipelineId) { - return new WebRenderBridgeParent(aPipelineId); + const wr::PipelineId& aPipelineId, nsCString&& aError) { + return new WebRenderBridgeParent(aPipelineId, std::move(aError)); } mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEnsureConnected( TextureFactoryIdentifier* aTextureFactoryIdentifier, - MaybeIdNamespace* aMaybeIdNamespace) { + MaybeIdNamespace* aMaybeIdNamespace, nsCString* aError) { if (mDestroyed) { *aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE); *aMaybeIdNamespace = Nothing(); + *aError = std::move(mInitError); return IPC_OK(); } diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index a9f6b93b932d..e78dfc5cebe7 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -113,7 +113,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent, TimeDuration aVsyncRate); static WebRenderBridgeParent* CreateDestroyed( - const wr::PipelineId& aPipelineId); + const wr::PipelineId& aPipelineId, nsCString&& aError); wr::PipelineId PipelineId() { return mPipelineId; } already_AddRefed GetWebRenderAPI() { @@ -134,7 +134,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent, mozilla::ipc::IPCResult RecvEnsureConnected( TextureFactoryIdentifier* aTextureFactoryIdentifier, - MaybeIdNamespace* aMaybeIdNamespace) override; + MaybeIdNamespace* aMaybeIdNamespace, nsCString* aError) override; mozilla::ipc::IPCResult RecvNewCompositable( const CompositableHandle& aHandle, const TextureInfo& aInfo) override; @@ -335,7 +335,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent, private: class ScheduleSharedSurfaceRelease; - explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId); + WebRenderBridgeParent(const wr::PipelineId& aPipelineId, nsCString&& aError); virtual ~WebRenderBridgeParent(); bool ProcessEmptyTransactionUpdates(TransactionData& aData, @@ -507,6 +507,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent, wr::Epoch mWrEpoch; wr::IdNamespace mIdNamespace; CompositionOpportunityId mCompositionOpportunityId; + nsCString mInitError; VsyncId mSkippedCompositeId; TimeStamp mMostRecentComposite; diff --git a/gfx/layers/wr/WebRenderLayerManager.cpp b/gfx/layers/wr/WebRenderLayerManager.cpp index bc6bed341a50..d30c98915571 100644 --- a/gfx/layers/wr/WebRenderLayerManager.cpp +++ b/gfx/layers/wr/WebRenderLayerManager.cpp @@ -58,7 +58,7 @@ KnowsCompositor* WebRenderLayerManager::AsKnowsCompositor() { return mWrChild; } bool WebRenderLayerManager::Initialize( PCompositorBridgeChild* aCBChild, wr::PipelineId aLayersId, - TextureFactoryIdentifier* aTextureFactoryIdentifier) { + TextureFactoryIdentifier* aTextureFactoryIdentifier, nsCString& aError) { MOZ_ASSERT(mWrChild == nullptr); MOZ_ASSERT(aTextureFactoryIdentifier); @@ -71,13 +71,14 @@ bool WebRenderLayerManager::Initialize( // reinitialization. We can expect to be notified again to reinitialize // (which may or may not be using WebRender). gfxCriticalNote << "Failed to create WebRenderBridgeChild."; + aError.AssignLiteral("FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL"); return false; } TextureFactoryIdentifier textureFactoryIdentifier; wr::MaybeIdNamespace idNamespace; // Sync ipc - bridge->SendEnsureConnected(&textureFactoryIdentifier, &idNamespace); + bridge->SendEnsureConnected(&textureFactoryIdentifier, &idNamespace, &aError); if (textureFactoryIdentifier.mParentBackend == LayersBackend::LAYERS_NONE || idNamespace.isNothing()) { gfxCriticalNote << "Failed to connect WebRenderBridgeChild."; diff --git a/gfx/layers/wr/WebRenderLayerManager.h b/gfx/layers/wr/WebRenderLayerManager.h index 2b3ecd75500f..e2df09625bab 100644 --- a/gfx/layers/wr/WebRenderLayerManager.h +++ b/gfx/layers/wr/WebRenderLayerManager.h @@ -52,7 +52,8 @@ class WebRenderLayerManager final : public LayerManager { public: explicit WebRenderLayerManager(nsIWidget* aWidget); bool Initialize(PCompositorBridgeChild* aCBChild, wr::PipelineId aLayersId, - TextureFactoryIdentifier* aTextureFactoryIdentifier); + TextureFactoryIdentifier* aTextureFactoryIdentifier, + nsCString& aError); void Destroy() override; diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp index 178ffde22586..a9569e6bfc5d 100644 --- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -63,7 +63,7 @@ class NewRenderer : public RendererEvent { bool* aUseANGLE, bool* aUseDComp, bool* aUseTripleBuffering, RefPtr&& aWidget, layers::SynchronousTask* aTask, LayoutDeviceIntSize aSize, - layers::SyncHandle* aHandle) + layers::SyncHandle* aHandle, nsACString* aError) : mDocHandle(aDocHandle), mMaxTextureSize(aMaxTextureSize), mUseANGLE(aUseANGLE), @@ -73,7 +73,8 @@ class NewRenderer : public RendererEvent { mCompositorWidget(std::move(aWidget)), mTask(aTask), mSize(aSize), - mSyncHandle(aHandle) { + mSyncHandle(aHandle), + mError(aError) { MOZ_COUNT_CTOR(NewRenderer); } @@ -110,6 +111,7 @@ class NewRenderer : public RendererEvent { StaticPrefs::gfx_webrender_enable_low_priority_pool(); bool supportPictureCaching = isMainWindow; wr::Renderer* wrRenderer = nullptr; + char* errorMessage = nullptr; if (!wr_window_new( aWindowId, mSize.width, mSize.height, supportLowPriorityTransactions, supportLowPriorityThreadpool, @@ -138,10 +140,13 @@ class NewRenderer : public RendererEvent { compositor->GetMaxUpdateRects(), compositor->GetMaxPartialPresentRects(), compositor->ShouldDrawPreviousPartialPresentRegions(), mDocHandle, - &wrRenderer, mMaxTextureSize, + &wrRenderer, mMaxTextureSize, &errorMessage, StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(), panic_on_gl_error)) { // wr_window_new puts a message into gfxCriticalNote if it returns false + MOZ_ASSERT(errorMessage); + mError->AssignASCII(errorMessage); + wr_api_free_error_msg(errorMessage); return; } MOZ_ASSERT(wrRenderer); @@ -176,6 +181,7 @@ class NewRenderer : public RendererEvent { layers::SynchronousTask* mTask; LayoutDeviceIntSize mSize; layers::SyncHandle* mSyncHandle; + nsACString* mError; }; class RemoveRenderer : public RendererEvent { @@ -324,7 +330,7 @@ void TransactionWrapper::UpdateIsTransformAsyncZooming(uint64_t aAnimationId, already_AddRefed WebRenderAPI::Create( layers::CompositorBridgeParent* aBridge, RefPtr&& aWidget, const wr::WrWindowId& aWindowId, - LayoutDeviceIntSize aSize) { + LayoutDeviceIntSize aSize, nsACString& aError) { MOZ_ASSERT(aBridge); MOZ_ASSERT(aWidget); static_assert( @@ -342,9 +348,10 @@ already_AddRefed WebRenderAPI::Create( // created on the render thread. If need be we could delay waiting on this // task until the next time we need to access the DocumentHandle object. layers::SynchronousTask task("Create Renderer"); - auto event = MakeUnique( - &docHandle, aBridge, &maxTextureSize, &useANGLE, &useDComp, - &useTripleBuffering, std::move(aWidget), &task, aSize, &syncHandle); + auto event = MakeUnique(&docHandle, aBridge, &maxTextureSize, + &useANGLE, &useDComp, + &useTripleBuffering, std::move(aWidget), + &task, aSize, &syncHandle, &aError); RenderThread::Get()->RunEvent(aWindowId, std::move(event)); task.Wait(); diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h index 2a8e29fd2977..1b451931603a 100644 --- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -231,7 +231,8 @@ class WebRenderAPI final { static already_AddRefed Create( layers::CompositorBridgeParent* aBridge, RefPtr&& aWidget, - const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize); + const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize, + nsACString& aError); already_AddRefed Clone(); diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index f707f5f1e4a1..72a22f8c260f 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -1430,6 +1430,7 @@ pub extern "C" fn wr_window_new( out_handle: &mut *mut DocumentHandle, out_renderer: &mut *mut Renderer, out_max_texture_size: *mut i32, + out_err: &mut *mut c_char, enable_gpu_markers: bool, panic_on_gl_error: bool, ) -> bool { @@ -1578,6 +1579,7 @@ pub extern "C" fn wr_window_new( unsafe { gfx_critical_note(msg.as_ptr()); } + *out_err = msg.into_raw(); return false; } }; @@ -1598,6 +1600,13 @@ pub extern "C" fn wr_window_new( return true; } +#[no_mangle] +pub unsafe extern "C" fn wr_api_free_error_msg(msg: *mut c_char) { + if msg != ptr::null_mut() { + CString::from_raw(msg); + } +} + #[no_mangle] pub unsafe extern "C" fn wr_api_delete_document(dh: &mut DocumentHandle) { dh.api.delete_document(dh.document_id); diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 98ab3731c439..d4e8500d9b24 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1222,16 +1222,17 @@ already_AddRefed nsBaseWidget::CreateCompositorSession( if (lm->AsWebRenderLayerManager() && mCompositorSession) { TextureFactoryIdentifier textureFactoryIdentifier; + nsCString error; lm->AsWebRenderLayerManager()->Initialize( mCompositorSession->GetCompositorBridgeChild(), wr::AsPipelineId(mCompositorSession->RootLayerTreeId()), - &textureFactoryIdentifier); + &textureFactoryIdentifier, error); if (textureFactoryIdentifier.mParentBackend != LayersBackend::LAYERS_WR) { retry = true; DestroyCompositor(); // gfxVars::UseDoubleBufferingWithCompositor() is also disabled. gfx::GPUProcessManager::Get()->DisableWebRender( - wr::WebRenderError::INITIALIZE); + wr::WebRenderError::INITIALIZE, error); } } else if (lm->AsClientLayerManager() && mCompositorSession) { bool shouldAccelerate = ComputeShouldAccelerate();