Bug 1662836 - Expose detailed initialization failure reason for WebRender. r=kvark

We don't know why we see initialization failures in the telemetry which
makes it hard to investigate why users aren't getting WebRender and
instead fallback to basic. Let's expose the detailed error message
WebRender already generates and puts in the critical log.

Differential Revision: https://phabricator.services.mozilla.com/D89185
This commit is contained in:
Andrew Osmond 2020-09-08 02:03:26 +00:00
Родитель 0acd64c691
Коммит c45c3ac881
14 изменённых файлов: 59 добавлений и 30 удалений

Просмотреть файл

@ -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<LayersBackend> ignored;

Просмотреть файл

@ -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() {

Просмотреть файл

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

Просмотреть файл

@ -1951,10 +1951,13 @@ PWebRenderBridgeParent* CompositorBridgeParent::AllocPWebRenderBridgeParent(
// Same, but for the OMTA sampler.
mOMTASampler->SetWebRenderWindowId(windowId);
}
nsCString error;
RefPtr<wr::WebRenderAPI> 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;
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -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<wr::WebRenderAPI> 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;

Просмотреть файл

@ -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.";

Просмотреть файл

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

Просмотреть файл

@ -63,7 +63,7 @@ class NewRenderer : public RendererEvent {
bool* aUseANGLE, bool* aUseDComp, bool* aUseTripleBuffering,
RefPtr<widget::CompositorWidget>&& 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> WebRenderAPI::Create(
layers::CompositorBridgeParent* aBridge,
RefPtr<widget::CompositorWidget>&& 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> 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<NewRenderer>(
&docHandle, aBridge, &maxTextureSize, &useANGLE, &useDComp,
&useTripleBuffering, std::move(aWidget), &task, aSize, &syncHandle);
auto event = MakeUnique<NewRenderer>(&docHandle, aBridge, &maxTextureSize,
&useANGLE, &useDComp,
&useTripleBuffering, std::move(aWidget),
&task, aSize, &syncHandle, &aError);
RenderThread::Get()->RunEvent(aWindowId, std::move(event));
task.Wait();

Просмотреть файл

@ -231,7 +231,8 @@ class WebRenderAPI final {
static already_AddRefed<WebRenderAPI> Create(
layers::CompositorBridgeParent* aBridge,
RefPtr<widget::CompositorWidget>&& aWidget,
const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize);
const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize,
nsACString& aError);
already_AddRefed<WebRenderAPI> Clone();

Просмотреть файл

@ -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);

Просмотреть файл

@ -1222,16 +1222,17 @@ already_AddRefed<LayerManager> 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();