Use the same graphics device parameters across processes. (bug 1183910 part 7, r=mattwoodrow)

This commit is contained in:
David Anderson 2015-08-02 13:59:33 -07:00
parent 5e2bd8d78a
commit fa120e53db
13 changed files with 214 additions and 17 deletions

View File

@ -6,6 +6,7 @@ include protocol PBackground;
include protocol PBlob; // FIXME: bug 792908
include protocol PCache;
include protocol PCacheOp;
include protocol PCachePushStream;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;

View File

@ -763,6 +763,14 @@ ContentChild::AppendProcessId(nsACString& aName)
aName.Append(nsPrintfCString("(pid %u)", pid));
}
void
ContentChild::InitGraphicsDeviceData()
{
// Initialize the graphics platform. This may contact the parent process
// to read device preferences.
gfxPlatform::GetPlatform();
}
void
ContentChild::InitXPCOM()
{

View File

@ -76,6 +76,7 @@ public:
IPC::Channel* aChannel);
void InitProcessAttributes();
void InitXPCOM();
void InitGraphicsDeviceData();
static ContentChild* GetSingleton() {
return sSingleton;

View File

@ -5148,6 +5148,13 @@ ContentParent::RecvProfile(const nsCString& aProfile)
return true;
}
bool
ContentParent::RecvGetGraphicsDeviceInitData(DeviceInitData* aOut)
{
gfxPlatform::GetPlatform()->GetDeviceInitData(aOut);
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -862,6 +862,7 @@ private:
virtual bool RecvGamepadListenerAdded() override;
virtual bool RecvGamepadListenerRemoved() override;
virtual bool RecvProfile(const nsCString& aProfile) override;
virtual bool RecvGetGraphicsDeviceInitData(DeviceInitData* aOut) override;
// If you add strong pointers to cycle collected objects here, be sure to
// release these objects in ShutDownProcess. See the comment there for more

View File

@ -76,10 +76,11 @@ bool
ContentProcess::Init()
{
mContent.Init(IOThreadChild::message_loop(),
ParentPid(),
IOThreadChild::channel());
ParentPid(),
IOThreadChild::channel());
mXREEmbed.Start();
mContent.InitXPCOM();
mContent.InitGraphicsDeviceData();
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
SetUpSandboxEnvironment();

View File

@ -60,6 +60,7 @@ include PluginTypes;
include ProtocolTypes;
include PContentPermission;
include BrowserConfiguration;
include GraphicsMessages;
// Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
// are put into different UnifiedProtocolsXX.cpp files.
@ -1053,6 +1054,12 @@ parent:
async Profile(nsCString aProfile);
/**
* Request graphics initialization information from the parent.
*/
sync GetGraphicsDeviceInitData()
returns (DeviceInitData aData);
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal);

View File

@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace mozilla {
namespace gfx {
struct DeviceInitData
{
bool useAcceleration;
// Windows only.
bool useD3D11;
bool useD3D11WARP;
bool useD3D11ImageBridge;
bool d3d11TextureSharingWorks;
bool useD2D;
bool useD2D1;
};
} // namespace gfx
} // namespace mozilla

View File

@ -26,6 +26,10 @@ SOURCES += [
'SharedDIB.cpp',
]
IPDL_SOURCES = [
'GraphicsMessages.ipdlh',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -112,6 +112,7 @@ class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
#include "VsyncSource.h"
#include "SoftwareVsyncSource.h"
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
#include "mozilla/dom/ContentChild.h"
namespace mozilla {
namespace layers {
@ -2488,3 +2489,24 @@ gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
obsvc->NotifyObservers(nullptr, "compositor:created", nullptr);
}
}
void
gfxPlatform::GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut)
{
MOZ_ASSERT(XRE_IsParentProcess());
aOut->useAcceleration() = ShouldUseLayersAcceleration();
}
void
gfxPlatform::UpdateDeviceInitData()
{
if (XRE_IsParentProcess()) {
// The parent process figures out device initialization on its own.
return;
}
mozilla::gfx::DeviceInitData data;
mozilla::dom::ContentChild::GetSingleton()->SendGetGraphicsDeviceInitData(&data);
SetDeviceInitData(data);
}

View File

@ -49,6 +49,7 @@ class DataSourceSurface;
class ScaledFont;
class DrawEventRecorder;
class VsyncSource;
class DeviceInitData;
inline uint32_t
BackendTypeBit(BackendType b)
@ -485,7 +486,8 @@ public:
virtual bool CanUseHardwareVideoDecoding();
static bool CanUseDirect3D11ANGLE();
// Returns whether or not layers acceleration should be used.
// Returns whether or not layers acceleration should be used. This should
// only be called on the parent process.
bool ShouldUseLayersAcceleration();
// Returns a prioritized list of all available compositor backends.
@ -646,6 +648,10 @@ public:
virtual void TestDeviceReset(DeviceResetReason aReason)
{}
// Return information on how child processes should initialize graphics
// devices. Currently this is only used on Windows.
virtual void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut);
protected:
gfxPlatform();
virtual ~gfxPlatform();
@ -678,6 +684,17 @@ protected:
void InitBackendPrefs(uint32_t aCanvasBitmask, mozilla::gfx::BackendType aCanvasDefault,
uint32_t aContentBitmask, mozilla::gfx::BackendType aContentDefault);
/**
* If in a child process, triggers a refresh of device preferences.
*/
void UpdateDeviceInitData();
/**
* Called when new device preferences are available.
*/
virtual void SetDeviceInitData(mozilla::gfx::DeviceInitData& aData)
{}
/**
* returns the first backend named in the pref gfx.canvas.azure.backends
* which is a component of aBackendBitmask, a bitmask of backend types

View File

@ -373,6 +373,16 @@ public:
NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
// Device init data should only be used on child processes, so we protect it
// behind a getter here.
static DeviceInitData sDeviceInitDataDoNotUseDirectly;
static inline DeviceInitData&
GetParentDevicePrefs()
{
MOZ_ASSERT(XRE_IsContentProcess());
return sDeviceInitDataDoNotUseDirectly;
}
gfxWindowsPlatform::gfxWindowsPlatform()
: mRenderMode(RENDER_GDI)
, mIsWARP(false)
@ -403,6 +413,7 @@ gfxWindowsPlatform::gfxWindowsPlatform()
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
UpdateDeviceInitData();
InitializeDevices();
UpdateRenderMode();
@ -518,6 +529,9 @@ gfxWindowsPlatform::HandleDeviceReset()
imgLoader::Singleton()->ClearCache(false);
gfxAlphaBoxBlur::ShutdownBlurCache();
// Since we got a device reset, we must ask the parent process for an updated
// list of which devices to create.
UpdateDeviceInitData();
InitializeDevices();
return true;
}
@ -1900,6 +1914,12 @@ CanUseWARP()
return true;
}
// The child process can only use WARP if the parent process is also using
// WARP.
if (XRE_IsContentProcess()) {
return GetParentDevicePrefs().useD3D11WARP();
}
// It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
if (!IsWin8OrLater() ||
gfxPrefs::LayersD3D11DisableWARP() ||
@ -1918,6 +1938,14 @@ gfxWindowsPlatform::CheckD3D11Support(bool* aCanUseHardware)
return mD3D11Status;
}
if (XRE_IsContentProcess()) {
if (!GetParentDevicePrefs().useD3D11()) {
return FeatureStatus::Blocked;
}
*aCanUseHardware = !GetParentDevicePrefs().useD3D11WARP();
return FeatureStatus::Available;
}
if (gfxPrefs::LayersD3D11ForceWARP()) {
*aCanUseHardware = false;
return FeatureStatus::Available;
@ -1982,6 +2010,12 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation()
// Only test this when not using WARP since it can fail and cause
// GetDeviceRemovedReason to return weird values.
mDoesD3D11TextureSharingWork = ::DoesD3D11TextureSharingWork(mD3D11Device);
// Assert that the child and parent process both computed texture sharing
// properly.
MOZ_ASSERT_IF(XRE_IsContentProcess(),
mDoesD3D11TextureSharingWork == GetParentDevicePrefs().d3d11TextureSharingWorks());
mD3D11Device->SetExceptionMode(0);
mIsWARP = false;
}
@ -2078,31 +2112,31 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
}
}
void
gfxWindowsPlatform::SetDeviceInitData(mozilla::gfx::DeviceInitData& aData)
{
MOZ_ASSERT(XRE_IsContentProcess());
sDeviceInitDataDoNotUseDirectly = aData;
}
void
gfxWindowsPlatform::InitializeDevices()
{
// Don't retry acceleration if it failed earlier.
// If acceleration is disabled, we refuse to initialize anything.
mAcceleration = CheckAccelerationSupport();
if (IsFeatureStatusFailure(mAcceleration)) {
return;
}
// If we previously crashed initializing devices, or if we're in safe mode,
// bail out now.
// If we previously crashed initializing devices, bail out now. This is
// effectively a parent-process only check, since the content process
// cannot create a lock file.
DriverInitCrashDetection detectCrashes;
if (detectCrashes.DisableAcceleration() || InSafeMode()) {
if (detectCrashes.DisableAcceleration()) {
mAcceleration = FeatureStatus::Blocked;
return;
}
// If acceleration is disabled, we refuse to initialize anything.
if (!ShouldUseLayersAcceleration()) {
mAcceleration = FeatureStatus::Disabled;
return;
}
// At this point, as far as we know, we can probably accelerate.
mAcceleration = FeatureStatus::Available;
// If we're going to prefer D3D9, stop here. The rest of this function
// attempts to use D3D11 features.
if (gfxPrefs::LayersPreferD3D9()) {
@ -2117,6 +2151,38 @@ gfxWindowsPlatform::InitializeDevices()
}
}
FeatureStatus
gfxWindowsPlatform::CheckAccelerationSupport()
{
// Don't retry acceleration if it failed earlier.
if (IsFeatureStatusFailure(mAcceleration)) {
return mAcceleration;
}
if (XRE_IsContentProcess()) {
return GetParentDevicePrefs().useAcceleration()
? FeatureStatus::Available
: FeatureStatus::Blocked;
}
if (InSafeMode()) {
return FeatureStatus::Blocked;
}
if (!ShouldUseLayersAcceleration()) {
return FeatureStatus::Disabled;
}
return FeatureStatus::Available;
}
bool
gfxWindowsPlatform::CanUseD3D11ImageBridge()
{
if (XRE_IsContentProcess()) {
if (!GetParentDevicePrefs().useD3D11ImageBridge()) {
return false;
}
}
return !mIsWARP;
}
void
gfxWindowsPlatform::InitializeD3D11()
{
@ -2170,7 +2236,7 @@ gfxWindowsPlatform::InitializeD3D11()
mD3D11Status = FeatureStatus::Available;
MOZ_ASSERT(mD3D11Device);
if (!mIsWARP) {
if (CanUseD3D11ImageBridge()) {
AttemptD3D11ImageBridgeDeviceCreation();
}
@ -2206,6 +2272,12 @@ gfxWindowsPlatform::CheckD2DSupport()
return mD2DStatus;
}
if (XRE_IsContentProcess()) {
return GetParentDevicePrefs().useD2D()
? FeatureStatus::Available
: FeatureStatus::Blocked;
}
if (!gfxPrefs::Direct2DForceEnabled() && IsD2DBlacklisted()) {
return FeatureStatus::Blacklisted;
}
@ -2266,6 +2338,11 @@ gfxWindowsPlatform::CheckD2D1Support()
if (!Factory::SupportsD2D1()) {
return FeatureStatus::Unavailable;
}
if (XRE_IsContentProcess()) {
return GetParentDevicePrefs().useD2D1()
? FeatureStatus::Available
: FeatureStatus::Blocked;
}
if (!gfxPrefs::Direct2DUse1_1()) {
return FeatureStatus::Disabled;
}
@ -2609,3 +2686,24 @@ gfxWindowsPlatform::GetD3D11Version()
}
return device->GetFeatureLevel();
}
void
gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
{
// Check for device resets before giving back new graphics information.
UpdateRenderMode();
gfxPlatform::GetDeviceInitData(aOut);
// IPDL initializes each field to false for us so we can early return.
if (GetD3D11Status() != FeatureStatus::Available) {
return;
}
aOut->useD3D11() = true;
aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice;
aOut->d3d11TextureSharingWorks() = mDoesD3D11TextureSharingWork;
aOut->useD3D11WARP() = mIsWARP;
aOut->useD2D() = (GetD2DStatus() == FeatureStatus::Available);
aOut->useD2D1() = (GetD2D1Status() == FeatureStatus::Available);
}

View File

@ -283,12 +283,15 @@ public:
static mozilla::Atomic<size_t> sD3D9SurfaceImageUsed;
static mozilla::Atomic<size_t> sD3D9SharedTextureUsed;
void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut) override;
protected:
bool AccelerateLayersByDefault() override {
return true;
}
void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends);
virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
void SetDeviceInitData(mozilla::gfx::DeviceInitData& aData) override;
protected:
RenderMode mRenderMode;
@ -307,6 +310,7 @@ private:
void DisableD2D();
mozilla::gfx::FeatureStatus CheckAccelerationSupport();
mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware);
mozilla::gfx::FeatureStatus CheckD2DSupport();
mozilla::gfx::FeatureStatus CheckD2D1Support();
@ -314,6 +318,7 @@ private:
void AttemptWARPDeviceCreation();
void AttemptD3D11ImageBridgeDeviceCreation();
bool AttemptD3D11ContentDeviceCreation();
bool CanUseD3D11ImageBridge();
IDXGIAdapter1 *GetDXGIAdapter();
bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);