Bug 1381095 - Fallback correctly to non-WebRender if the GPU process/WebRender are disabled when creating a remote compositor session. r=dvander

This commit is contained in:
Andrew Osmond 2017-07-20 09:20:22 -04:00
parent ccbd885da6
commit 69da7c2120
4 changed files with 81 additions and 35 deletions

View File

@ -187,6 +187,11 @@ GPUProcessManager::DisableGPUProcess(const char* aMessage)
// correctly. We cannot re-enter DisableGPUProcess from this call because we
// know that it is disabled in the config above.
EnsureProtocolsReady();
// If we disable the GPU process during reinitialization after a previous
// crash, then we need to tell the content processes again, because they
// need to rebind to the UI process.
HandleProcessLost();
}
bool
@ -481,12 +486,12 @@ GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
mDecodeVideoOnGpuProcess = false;
Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
uint32_t(FallbackType::DECODINGDISABLED));
HandleProcessLost();
} else {
Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
uint32_t(FallbackType::NONE));
HandleProcessLost();
}
HandleProcessLost();
}
void
@ -666,14 +671,17 @@ GPUProcessManager::DestroyProcess()
#endif
}
RefPtr<CompositorSession>
already_AddRefed<CompositorSession>
GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
LayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
const CompositorOptions& aOptions,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize)
const gfx::IntSize& aSurfaceSize,
bool* aRetryOut)
{
MOZ_ASSERT(aRetryOut);
uint64_t layerTreeId = AllocateLayerTreeId();
EnsureProtocolsReady();
@ -692,10 +700,10 @@ GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
if (!session) {
// We couldn't create a remote compositor, so abort the process.
DisableGPUProcess("Failed to create remote compositor");
*aRetryOut = true;
return nullptr;
}
}
if (!session) {
} else {
session = InProcessCompositorSession::Create(
aWidget,
aLayerManager,
@ -715,7 +723,8 @@ GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
}
#endif // defined(MOZ_WIDGET_ANDROID)
return session;
*aRetryOut = false;
return session.forget();
}
RefPtr<CompositorSession>

View File

@ -89,13 +89,14 @@ public:
// Otherwise it blocks until the GPU process has finished launching.
bool EnsureGPUReady();
RefPtr<CompositorSession> CreateTopLevelCompositor(
already_AddRefed<CompositorSession> CreateTopLevelCompositor(
nsBaseWidget* aWidget,
LayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
const CompositorOptions& aOptions,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
const gfx::IntSize& aSurfaceSize,
bool* aRetry);
bool CreateContentBridges(
base::ProcessId aOtherProcess,

View File

@ -1247,6 +1247,56 @@ nsBaseWidget::GetCompositorVsyncDispatcher()
return mCompositorVsyncDispatcher;
}
already_AddRefed<LayerManager>
nsBaseWidget::CreateCompositorSession(int aWidth,
int aHeight,
CompositorOptions* aOptionsOut)
{
MOZ_ASSERT(aOptionsOut);
do {
CreateCompositorVsyncDispatcher();
bool enableWR = gfx::gfxVars::UseWebRender();
if (enableWR && !WidgetTypeSupportsAcceleration()) {
// fall back to basic
break;
}
bool enableAPZ = UseAPZ();
CompositorOptions options(enableAPZ, enableWR);
bool enableAL = gfx::gfxConfig::IsEnabled(gfx::Feature::ADVANCED_LAYERS);
options.SetUseAdvancedLayers(enableAL);
RefPtr<LayerManager> lm;
if (options.UseWebRender()) {
lm = new WebRenderLayerManager(this);
} else {
lm = new ClientLayerManager(this);
}
bool retry = false;
gfx::GPUProcessManager* gpu = gfx::GPUProcessManager::Get();
mCompositorSession = gpu->CreateTopLevelCompositor(
this,
lm,
GetDefaultScale(),
options,
UseExternalCompositingSurface(),
gfx::IntSize(aWidth, aHeight),
&retry);
// We need to retry in a loop because the act of failing to create the
// compositor can change our state (e.g. disable WebRender).
if (mCompositorSession || !retry) {
*aOptionsOut = options;
return lm.forget();
}
} while (true);
return nullptr;
}
void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
{
// This makes sure that gfxPlatforms gets initialized if it hasn't by now.
@ -1271,34 +1321,14 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
return;
}
CreateCompositorVsyncDispatcher();
bool enableWR = gfx::gfxVars::UseWebRender();
if (enableWR && !WidgetTypeSupportsAcceleration()) {
// fall back to basic
CompositorOptions options;
RefPtr<LayerManager> lm =
CreateCompositorSession(aWidth, aHeight, &options);
if (!lm) {
return;
}
bool enableAPZ = UseAPZ();
CompositorOptions options(enableAPZ, enableWR);
bool enableAL = gfx::gfxConfig::IsEnabled(gfx::Feature::ADVANCED_LAYERS);
options.SetUseAdvancedLayers(enableAL);
RefPtr<LayerManager> lm;
if (options.UseWebRender()) {
lm = new WebRenderLayerManager(this);
} else {
lm = new ClientLayerManager(this);
}
gfx::GPUProcessManager* gpu = gfx::GPUProcessManager::Get();
mCompositorSession = gpu->CreateTopLevelCompositor(
this,
lm,
GetDefaultScale(),
options,
UseExternalCompositingSurface(),
gfx::IntSize(aWidth, aHeight));
MOZ_ASSERT(mCompositorSession);
mCompositorBridgeChild = mCompositorSession->GetCompositorBridgeChild();
mCompositorWidgetDelegate = mCompositorSession->GetCompositorWidgetDelegate();

View File

@ -11,6 +11,7 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/WidgetUtils.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/CompositorOptions.h"
#include "nsRect.h"
#include "nsIWidget.h"
#include "nsWidgetsCID.h"
@ -743,6 +744,11 @@ protected:
static bool debug_GetCachedBoolPref(const char* aPrefName);
#endif
private:
already_AddRefed<LayerManager>
CreateCompositorSession(int aWidth, int aHeight,
mozilla::layers::CompositorOptions* aOptionsOut);
};
#endif // nsBaseWidget_h__