new file mode 100644
--- /dev/null
+++ b/gfx/src/gfxTelemetry.cpp
@@ -0,0 +1,36 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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/. */
+#include "gfxTelemetry.h"
+
+namespace mozilla {
+namespace gfx {
+
+const char*
+FeatureStatusToString(FeatureStatus aStatus)
+{
+ switch (aStatus) {
+ case FeatureStatus::Unused:
+ return "unused";
+ case FeatureStatus::Unavailable:
+ return "unavailable";
+ case FeatureStatus::Blocked:
+ return "blocked";
+ case FeatureStatus::Blacklisted:
+ return "blacklisted";
+ case FeatureStatus::Failed:
+ return "failed";
+ case FeatureStatus::Disabled:
+ return "disabled";
+ case FeatureStatus::Available:
+ return "available";
+ default:
+ MOZ_ASSERT_UNREACHABLE("missing status case");
+ return "unknown";
+ }
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/src/gfxTelemetry.h
@@ -0,0 +1,46 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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/. */
+#ifndef gfx_src_gfxTelemetry_h__
+#define gfx_src_gfxTelemetry_h__
+
+namespace mozilla {
+namespace gfx {
+
+// Describes the status of a graphics feature, in terms of whether or not we've
+// attempted to initialize the feature, and if so, whether or not it succeeded
+// (and if not, why).
+enum class FeatureStatus
+{
+ // This feature has not been requested.
+ Unused,
+
+ // This feature is unavailable due to Safe Mode or not being included with
+ // the operating system.
+ Unavailable,
+
+ // This feature was blocked for reasons outside the blacklist, such as a
+ // runtime test failing.
+ Blocked,
+
+ // This feature has been blocked by the graphics blacklist.
+ Blacklisted,
+
+ // This feature was attempted but failed to activate.
+ Failed,
+
+ // This feature was explicitly disabled by the user.
+ Disabled,
+
+ // This feature is available for use.
+ Available
+};
+
+const char* FeatureStatusToString(FeatureStatus aStatus);
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // gfx_src_gfxTelemetry_h__
--- a/gfx/src/moz.build
+++ b/gfx/src/moz.build
@@ -13,16 +13,17 @@ XPIDL_MODULE = 'gfx'
DEFINES['MOZ_APP_VERSION'] = '"%s"' % CONFIG['MOZ_APP_VERSION']
EXPORTS += [
'DriverInitCrashDetection.h',
'FilterSupport.h',
'gfxCore.h',
'gfxCrashReporterUtils.h',
+ 'gfxTelemetry.h',
'nsBoundingMetrics.h',
'nsColor.h',
'nsColorNameList.h',
'nsColorNames.h',
'nsCoord.h',
'nsDeviceContext.h',
'nsFont.h',
'nsFontMetrics.h',
@@ -51,16 +52,17 @@ if CONFIG['MOZ_X11']:
SOURCES += [
'X11Util.cpp',
]
UNIFIED_SOURCES += [
'DriverInitCrashDetection.cpp',
'FilterSupport.cpp',
'gfxCrashReporterUtils.cpp',
+ 'gfxTelemetry.cpp',
'nsColor.cpp',
'nsFont.cpp',
'nsFontMetrics.cpp',
'nsRect.cpp',
'nsRegion.cpp',
'nsRenderingContext.cpp',
'nsScriptableRegion.cpp',
'nsThebesFontEnumerator.cpp',
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -374,16 +374,17 @@ static nsIAtom* PrefLangToLangGroups(uin
: nsGkAtoms::Unicode;
}
gfxPlatform::gfxPlatform()
: mTileWidth(-1)
, mTileHeight(-1)
, mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
, mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo)
+ , mCompositorBackend(layers::LayersBackend::LAYERS_NONE)
{
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
mFallbackUsesCmaps = UNINITIALIZED_VALUE;
mWordCacheCharLimit = UNINITIALIZED_VALUE;
mWordCacheMaxEntries = UNINITIALIZED_VALUE;
mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
@@ -405,16 +406,22 @@ gfxPlatform*
gfxPlatform::GetPlatform()
{
if (!gPlatform) {
Init();
}
return gPlatform;
}
+bool
+gfxPlatform::Initialized()
+{
+ return !!gPlatform;
+}
+
void RecordingPrefChanged(const char *aPrefName, void *aClosure)
{
if (Preferences::GetBool("gfx.2d.recording", false)) {
nsAutoCString fileName;
nsAdoptingString prefFileName = Preferences::GetString("gfx.2d.recordingfile");
if (prefFileName) {
fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
@@ -2439,8 +2446,26 @@ gfxPlatform::GetCompositorBackends(bool
{
if (useAcceleration) {
GetAcceleratedCompositorBackends(aBackends);
}
if (SupportsBasicCompositor()) {
aBackends.AppendElement(LayersBackend::LAYERS_BASIC);
}
}
+
+void
+gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
+{
+ if (mCompositorBackend == aBackend) {
+ return;
+ }
+
+ NS_ASSERTION(mCompositorBackend == LayersBackend::LAYERS_NONE, "Compositor backend changed.");
+
+ // Set the backend before we notify so it's available immediately.
+ mCompositorBackend = aBackend;
+
+ // Notify that we created a compositor, so telemetry can update.
+ if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
+ obsvc->NotifyObservers(nullptr, "compositor:created", nullptr);
+ }
+}
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -154,16 +154,22 @@ public:
/**
* Return a pointer to the current active platform.
* This is a singleton; it contains mostly convenience
* functions to obtain platform-specific objects.
*/
static gfxPlatform *GetPlatform();
+ /**
+ * Returns whether or not graphics has been initialized yet. This is
+ * intended for Telemetry where we don't necessarily want to initialize
+ * graphics just to observe its state.
+ */
+ static bool Initialized();
/**
* Shut down Thebes.
* Init() arranges for this to be called at an appropriate time.
*/
static void Shutdown();
static void InitLayersIPC();
@@ -626,16 +632,21 @@ public:
mozilla::gfx::SurfaceFormat aFormat);
/**
* Wrapper around gfxPrefs::PerfWarnings().
* Extracted into a function to avoid including gfxPrefs.h from this file.
*/
static bool PerfWarnings();
+ void NotifyCompositorCreated(mozilla::layers::LayersBackend aBackend);
+ mozilla::layers::LayersBackend GetCompositorBackend() const {
+ return mCompositorBackend;
+ }
+
protected:
gfxPlatform();
virtual ~gfxPlatform();
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
/**
@@ -746,11 +757,15 @@ private:
int mTileWidth;
int mTileHeight;
mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
mozilla::widget::GfxInfoCollector<gfxPlatform> mApzSupportCollector;
mozilla::RefPtr<mozilla::gfx::DrawEventRecorder> mRecorder;
mozilla::RefPtr<mozilla::gl::SkiaGLGlue> mSkiaGlue;
+
+ // Backend that we are compositing with. NONE, if no compositor has been
+ // created yet.
+ mozilla::layers::LayersBackend mCompositorBackend;
};
#endif /* GFX_PLATFORM_H */
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -372,16 +372,18 @@ public:
NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
gfxWindowsPlatform::gfxWindowsPlatform()
: mD3D11DeviceInitialized(false)
, mIsWARP(false)
, mHasDeviceReset(false)
, mDoesD3D11TextureSharingWork(false)
+ , mD3D11Status(FeatureStatus::Unused)
+ , mD2DStatus(FeatureStatus::Unused)
{
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
mUseClearTypeAlways = UNINITIALIZED_VALUE;
mUsingGDIFonts = false;
/*
* Initialize COM
@@ -431,17 +433,17 @@ bool
gfxWindowsPlatform::CanUseHardwareVideoDecoding()
{
if (!gfxPrefs::LayersPreferD3D9() && !mDoesD3D11TextureSharingWork) {
return false;
}
return !IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
}
-void
+FeatureStatus
gfxWindowsPlatform::InitD2DSupport()
{
#ifdef CAIRO_HAS_D2D_SURFACE
bool d2dBlocked = false;
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
if (gfxInfo) {
int32_t status;
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT2D, &status))) {
@@ -453,40 +455,51 @@ gfxWindowsPlatform::InitD2DSupport()
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
d2dBlocked = true;
}
}
}
// If D2D is blocked or D3D9 is prefered, and D2D is not force-enabled, then
// we don't attempt to use D2D.
- if ((d2dBlocked || gfxPrefs::LayersPreferD3D9()) && !gfxPrefs::Direct2DForceEnabled()) {
- return;
+ if (!gfxPrefs::Direct2DForceEnabled()) {
+ if (d2dBlocked) {
+ return FeatureStatus::Blacklisted;
+ }
+ if (gfxPrefs::LayersPreferD3D9()) {
+ return FeatureStatus::Disabled;
+ }
}
// Do not ever try to use D2D if it's explicitly disabled or if we're not
// using DWrite fonts.
if (gfxPrefs::Direct2DDisabled() || mUsingGDIFonts) {
- return;
+ return FeatureStatus::Disabled;
}
- ID3D11Device* device = GetD3D11Device();
- if (IsVistaOrLater() &&
- !InSafeMode() &&
- device &&
- mDoesD3D11TextureSharingWork)
- {
- VerifyD2DDevice(gfxPrefs::Direct2DForceEnabled());
- if (mD3D10Device && GetD3D11Device()) {
- mRenderMode = RENDER_DIRECT2D;
- mUseDirectWrite = true;
- }
- } else {
- mD3D10Device = nullptr;
+ if (!IsVistaOrLater() || !GetD3D11Device()) {
+ return FeatureStatus::Unavailable;
+ }
+ if (!mDoesD3D11TextureSharingWork) {
+ return FeatureStatus::Failed;
+ }
+ if (InSafeMode()) {
+ return FeatureStatus::Blocked;
}
+
+ VerifyD2DDevice(gfxPrefs::Direct2DForceEnabled());
+ if (!mD3D10Device || !GetD3D11Device()) {
+ return FeatureStatus::Failed;
+ }
+
+ mRenderMode = RENDER_DIRECT2D;
+ mUseDirectWrite = true;
+ return FeatureStatus::Available;
+#else
+ return FeatureStatus::Unavailable;
#endif
}
void
gfxWindowsPlatform::InitDWriteSupport()
{
#ifdef CAIRO_HAS_DWRITE_FONT
// Enable when it's preffed on -and- we're using Vista or higher. Or when
@@ -547,17 +560,17 @@ gfxWindowsPlatform::UpdateRenderMode()
Factory::SetDirect3D11Device(nullptr);
didReset = true;
}
mRenderMode = RENDER_GDI;
mUseDirectWrite = gfxPrefs::DirectWriteFontRenderingEnabled();
- InitD2DSupport();
+ mD2DStatus = InitD2DSupport();
InitDWriteSupport();
uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
BackendType defaultBackend = BackendType::CAIRO;
if (mRenderMode == RENDER_DIRECT2D) {
canvasMask |= BackendTypeBit(BackendType::DIRECT2D);
contentMask |= BackendTypeBit(BackendType::DIRECT2D);
@@ -2051,34 +2064,37 @@ gfxWindowsPlatform::InitD3D11Devices()
// is not blacklisted for D3D11 layers. This will first attempt to create a
// hardware accelerated device. If this creation fails or the hardware is
// blacklisted, then this function will abort if WARP is disabled, causing us
// to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
// a WARP device which should always be available on Windows 7 and higher.
mD3D11DeviceInitialized = true;
mDoesD3D11TextureSharingWork = false;
- MOZ_ASSERT(!mD3D11Device);
+ MOZ_ASSERT(!mD3D11Device);
DriverInitCrashDetection detectCrashes;
if (InSafeMode() || detectCrashes.DisableAcceleration()) {
+ mD3D11Status = FeatureStatus::Blocked;
return;
}
D3D11Status status = CheckD3D11Support();
if (status == D3D11Status::Blocked) {
+ mD3D11Status = FeatureStatus::Blacklisted;
return;
}
nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
sD3D11CreateDeviceFn =
(decltype(D3D11CreateDevice)*)GetProcAddress(d3d11Module, "D3D11CreateDevice");
if (!sD3D11CreateDeviceFn) {
// We should just be on Windows Vista or XP in this case.
+ mD3D11Status = FeatureStatus::Unavailable;
return;
}
nsTArray<D3D_FEATURE_LEVEL> featureLevels;
if (IsWin8OrLater()) {
featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
}
featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
@@ -2092,24 +2108,26 @@ gfxWindowsPlatform::InitD3D11Devices()
}
}
if (IsWin8OrLater() &&
!gfxPrefs::LayersD3D11DisableWARP() &&
(status == D3D11Status::TryWARP || status == D3D11Status::ForceWARP))
{
AttemptWARPDeviceCreation(featureLevels);
+ mD3D11Status = FeatureStatus::Failed;
}
if (!mD3D11Device) {
// We could not get a D3D11 compositor, and there's nothing more we can try.
return;
}
mD3D11Device->SetExceptionMode(0);
+ mD3D11Status = FeatureStatus::Available;
// We create our device for D2D content drawing here. Normally we don't use
// D2D content drawing when using WARP. However when WARP is forced by
// default we will let Direct2D use WARP as well.
if (Factory::SupportsD2D1() && (!mIsWARP || (status == D3D11Status::ForceWARP))) {
if (!AttemptD3D11ContentDeviceCreation(featureLevels)) {
mD3D11ContentDevice = nullptr;
d3d11Module.disown();
@@ -2404,8 +2422,37 @@ gfxWindowsPlatform::GetAcceleratedCompos
// We don't want D3D9 except on Windows XP
if (gfxPlatform::CanUseDirect3D9()) {
aBackends.AppendElement(LayersBackend::LAYERS_D3D9);
} else {
NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
}
}
}
+
+FeatureStatus
+gfxWindowsPlatform::GetD2D1Status()
+{
+ if (GetD2DStatus() != FeatureStatus::Available ||
+ !Factory::SupportsD2D1())
+ {
+ return FeatureStatus::Unavailable;
+ }
+
+ if (!GetD3D11ContentDevice()) {
+ return FeatureStatus::Failed;
+ }
+
+ if (!gfxPrefs::Direct2DUse1_1()) {
+ return FeatureStatus::Disabled;
+ }
+ return FeatureStatus::Available;
+}
+
+unsigned
+gfxWindowsPlatform::GetD3D11Version()
+{
+ ID3D11Device* device = GetD3D11Device();
+ if (!device) {
+ return 0;
+ }
+ return device->GetFeatureLevel();
+}
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -15,16 +15,17 @@
#include "gfxFontUtils.h"
#include "gfxWindowsSurface.h"
#include "gfxFont.h"
#ifdef CAIRO_HAS_DWRITE_FONT
#include "gfxDWriteFonts.h"
#endif
#include "gfxPlatform.h"
+#include "gfxTelemetry.h"
#include "gfxTypes.h"
#include "mozilla/Attributes.h"
#include "mozilla/Atomics.h"
#include "nsTArray.h"
#include "nsDataHashtable.h"
#include "mozilla/RefPtr.h"
@@ -256,16 +257,28 @@ public:
bool IsWARP() { return mIsWARP; }
bool DoesD3D11TextureSharingWork() { return mDoesD3D11TextureSharingWork; }
bool SupportsApzWheelInput() const override {
return true;
}
bool SupportsApzTouchInput() const override;
+ // Return the diagnostic status of DirectX initialization. If
+ // initialization has not been attempted, this returns
+ // FeatureStatus::Unused.
+ mozilla::gfx::FeatureStatus GetD3D11Status() const {
+ return mD3D11Status;
+ }
+ mozilla::gfx::FeatureStatus GetD2DStatus() const {
+ return mD2DStatus;
+ }
+ unsigned GetD3D11Version();
+ mozilla::gfx::FeatureStatus GetD2D1Status();
+
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
static mozilla::Atomic<size_t> sD3D11MemoryUsed;
static mozilla::Atomic<size_t> sD3D9MemoryUsed;
static mozilla::Atomic<size_t> sD3D9SurfaceImageUsed;
static mozilla::Atomic<size_t> sD3D9SharedTextureUsed;
protected:
bool AccelerateLayersByDefault() override {
@@ -293,17 +306,17 @@ private:
};
D3D11Status CheckD3D11Support();
bool AttemptD3D11DeviceCreation(const nsTArray<D3D_FEATURE_LEVEL>& aFeatureLevels);
bool AttemptWARPDeviceCreation(const nsTArray<D3D_FEATURE_LEVEL>& aFeatureLevels);
bool AttemptD3D11ImageBridgeDeviceCreation(const nsTArray<D3D_FEATURE_LEVEL>& aFeatureLevels);
bool AttemptD3D11ContentDeviceCreation(const nsTArray<D3D_FEATURE_LEVEL>& aFeatureLevels);
// Used by UpdateRenderMode().
- void InitD2DSupport();
+ mozilla::gfx::FeatureStatus InitD2DSupport();
void InitDWriteSupport();
IDXGIAdapter1 *GetDXGIAdapter();
bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
bool mUseDirectWrite;
bool mUsingGDIFonts;
@@ -321,12 +334,15 @@ private:
mozilla::RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
bool mD3D11DeviceInitialized;
mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
bool mIsWARP;
bool mHasDeviceReset;
bool mDoesD3D11TextureSharingWork;
DeviceResetReason mDeviceResetReason;
+ mozilla::gfx::FeatureStatus mD3D11Status;
+ mozilla::gfx::FeatureStatus mD2DStatus;
+
virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
};
#endif /* GFX_WINDOWS_PLATFORM_H */
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -28,16 +28,17 @@
#include "nsTArray.h"
#include "nsXULAppAPI.h"
#include "nsIXULAppInfo.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Logging.h"
#include "gfxPrefs.h"
+#include "gfxPlatform.h"
#if defined(MOZ_CRASHREPORTER)
#include "nsExceptionHandler.h"
#endif
using namespace mozilla::widget;
using namespace mozilla;
using mozilla::MutexAutoLock;
@@ -1174,16 +1175,100 @@ GfxInfoBase::GetMonitors(JSContext* aCx,
if (NS_FAILED(rv)) {
return rv;
}
aResult.setObject(*array);
return NS_OK;
}
+static const char*
+GetLayersBackendName(layers::LayersBackend aBackend)
+{
+ switch (aBackend) {
+ case layers::LayersBackend::LAYERS_NONE:
+ return "none";
+ case layers::LayersBackend::LAYERS_OPENGL:
+ return "opengl";
+ case layers::LayersBackend::LAYERS_D3D9:
+ return "d3d9";
+ case layers::LayersBackend::LAYERS_D3D11:
+ return "d3d11";
+ case layers::LayersBackend::LAYERS_CLIENT:
+ return "client";
+ default:
+ MOZ_ASSERT_UNREACHABLE("unknown layers backend");
+ return "unknown";
+ }
+}
+
+nsresult
+GfxInfoBase::GetFeatures(JSContext* aCx, JS::MutableHandle<JS::Value> aOut)
+{
+ JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
+ if (!obj) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ aOut.setObject(*obj);
+
+ layers::LayersBackend backend = gfxPlatform::Initialized()
+ ? gfxPlatform::GetPlatform()->GetCompositorBackend()
+ : layers::LayersBackend::LAYERS_NONE;
+ const char* backendName = GetLayersBackendName(backend);
+ {
+ JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, backendName));
+ JS::Rooted<JS::Value> val(aCx, StringValue(str));
+ JS_SetProperty(aCx, obj, "compositor", val);
+ }
+
+ // If graphics isn't initialized yet, just stop now.
+ if (!gfxPlatform::Initialized()) {
+ return NS_OK;
+ }
+
+ DescribeFeatures(aCx, obj);
+ return NS_OK;
+}
+
+void
+GfxInfoBase::DescribeFeatures(JSContext* cx, JS::Handle<JSObject*> aOut)
+{
+}
+
+bool
+GfxInfoBase::InitFeatureObject(JSContext* aCx,
+ JS::Handle<JSObject*> aContainer,
+ const char* aName,
+ mozilla::gfx::FeatureStatus aFeatureStatus,
+ JS::MutableHandle<JSObject*> aOutObj)
+{
+ JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
+ if (!obj) {
+ return false;
+ }
+
+ const char* status = FeatureStatusToString(aFeatureStatus);
+
+ // Set "status".
+ {
+ JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, status));
+ JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
+ JS_SetProperty(aCx, obj, "status", val);
+ }
+
+ // Add the feature object to the container.
+ {
+ JS::Rooted<JS::Value> val(aCx, JS::ObjectValue(*obj));
+ JS_SetProperty(aCx, aContainer, aName, val);
+ }
+
+ aOutObj.set(obj);
+ return true;
+}
+
GfxInfoCollectorBase::GfxInfoCollectorBase()
{
GfxInfoBase::AddCollector(this);
}
GfxInfoCollectorBase::~GfxInfoCollectorBase()
{
GfxInfoBase::RemoveCollector(this);
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -14,16 +14,17 @@
#endif
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "GfxDriverInfo.h"
#include "nsTArray.h"
#include "nsString.h"
#include "GfxInfoCollector.h"
+#include "gfxTelemetry.h"
#include "nsIGfxInfoDebug.h"
#include "mozilla/Mutex.h"
#include "js/Value.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace widget {
@@ -53,16 +54,17 @@ public:
NS_IMETHOD GetFeatureStatus(int32_t aFeature, int32_t *_retval) override;
NS_IMETHOD GetFeatureSuggestedDriverVersion(int32_t aFeature, nsAString & _retval) override;
NS_IMETHOD GetWebGLParameter(const nsAString & aParam, nsAString & _retval) override;
NS_IMETHOD GetMonitors(JSContext* cx, JS::MutableHandleValue _retval) override;
NS_IMETHOD GetFailures(uint32_t *failureCount, int32_t** indices, char ***failures) override;
NS_IMETHOD_(void) LogFailure(const nsACString &failure) override;
NS_IMETHOD GetInfo(JSContext*, JS::MutableHandle<JS::Value>) override;
+ NS_IMETHOD GetFeatures(JSContext*, JS::MutableHandle<JS::Value>) override;
// Initialization function. If you override this, you must call this class's
// version of Init first.
// We need Init to be called separately from the constructor so we can
// register as an observer after all derived classes have been constructed
// and we know we have a non-zero refcount.
// Ideally, Init() would be void-return, but the rules of
// NS_GENERIC_FACTORY_CONSTRUCTOR_INIT require it be nsresult return.
@@ -98,16 +100,24 @@ protected:
nsAString& aSuggestedDriverVersion,
const nsTArray<GfxDriverInfo>& aDriverInfo,
OperatingSystem* aOS = nullptr);
// Gets the driver info table. Used by GfxInfoBase to check for general cases
// (while subclasses check for more specific ones).
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() = 0;
+ virtual void DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> obj);
+ bool InitFeatureObject(
+ JSContext* aCx,
+ JS::Handle<JSObject*> aContainer,
+ const char* aName,
+ mozilla::gfx::FeatureStatus aFeatureStatus,
+ JS::MutableHandle<JSObject*> aOutObj);
+
private:
virtual int32_t FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& aDriverInfo,
nsAString& aSuggestedVersion,
int32_t aFeature,
OperatingSystem os);
void EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo);
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1126,16 +1126,18 @@ void nsBaseWidget::CreateCompositor(int
}
lf->SetShadowManager(shadowManager);
lf->IdentifyTextureHost(textureFactoryIdentifier);
ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
WindowUsesOMTC();
mLayerManager = lm.forget();
+
+ gfxPlatform::GetPlatform()->NotifyCompositorCreated(mLayerManager->GetCompositorBackendType());
}
bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
{
return gfxPlatform::UsesOffMainThreadCompositing();
}
LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -3,17 +3,17 @@
* 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/. */
#include "nsISupports.idl"
/* NOTE: this interface is completely undesigned, not stable and likely to change */
-[scriptable, uuid(47eedfa0-f7cb-445b-b5cf-a2ca83600560)]
+[scriptable, uuid(98690931-c9a5-4675-9ab4-90932ec32bf2)]
interface nsIGfxInfo : nsISupports
{
/*
* These are win32-specific
*/
readonly attribute boolean D2DEnabled;
readonly attribute boolean DWriteEnabled;
readonly attribute DOMString DWriteVersion;
@@ -142,10 +142,36 @@ interface nsIGfxInfo : nsISupports
*/
DOMString getWebGLParameter(in DOMString aParam);
// only useful on X11
[noscript, notxpcom] void GetData();
[implicit_jscontext]
jsval getInfo();
+
+ // Returns an object containing information about graphics features. It is
+ // intended to be directly included into the Telemetry environment.
+ //
+ // "layers":
+ // {
+ // "compositor": "d3d9", "d3d11", "opengl", "basic", or "none"
+ // // ("none" indicates no compositors have been created)
+ // // Feature is one of "d3d9", "d3d11", "opengl", "basic", or "d2d".
+ // "<feature>": {
+ // // Each backend can have one of the following statuses:
+ // // "unused" - This feature has not been requested.
+ // // "unavailable" - OS version or restriction prevents use.
+ // // "blocked" - An internal condition (such as safe mode) prevents use.
+ // // "blacklisted" - Blocked due to a blacklist restriction.
+ // // "disabled" - User explicitly disabled this default feature.
+ // // "failed" - Feature failed to initialize.
+ // // "available" - User has this feature available by default.
+ // "status": "<status>",
+ // "version": "<version>",
+ // "warp": true|false, // D3D11 only.
+ // "textureSharing": true|false, // D3D11 only.
+ // }
+ // }
+ [implicit_jscontext]
+ jsval getFeatures();
};
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1250,16 +1250,52 @@ GfxInfo::FindMonitors(JSContext* aCx, JS
JS_SetProperty(aCx, obj, "pseudoDisplay", pseudoDisplay);
JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
JS_SetElement(aCx, aOutArray, deviceCount++, element);
}
return NS_OK;
}
+void
+GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj)
+{
+ JS::Rooted<JSObject*> obj(aCx);
+
+ gfxWindowsPlatform* platform = gfxWindowsPlatform::GetPlatform();
+
+ gfx::FeatureStatus d3d11 = platform->GetD3D11Status();
+ if (!InitFeatureObject(aCx, aObj, "d3d11", d3d11, &obj)) {
+ return;
+ }
+ if (d3d11 == gfx::FeatureStatus::Available) {
+ JS::Rooted<JS::Value> val(aCx, JS::Int32Value(platform->GetD3D11Version()));
+ JS_SetProperty(aCx, obj, "version", val);
+
+ val = JS::BooleanValue(platform->IsWARP());
+ JS_SetProperty(aCx, obj, "warp", val);
+
+ val = JS::BooleanValue(platform->DoesD3D11TextureSharingWork());
+ JS_SetProperty(aCx, obj, "textureSharing", val);
+ }
+
+ gfx::FeatureStatus d2d = platform->GetD2DStatus();
+ if (!InitFeatureObject(aCx, aObj, "d2d", d2d, &obj)) {
+ return;
+ }
+ {
+ const char* version = "1.0";
+ if (platform->GetD2D1Status() == gfx::FeatureStatus::Available)
+ version = "1.1";
+ JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, version));
+ JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
+ JS_SetProperty(aCx, obj, "version", val);
+ }
+}
+
#ifdef DEBUG
// Implement nsIGfxInfoDebug
/* void spoofVendorID (in DOMString aVendorID); */
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
{
mAdapterVendorID = aVendorID;
--- a/widget/windows/GfxInfo.h
+++ b/widget/windows/GfxInfo.h
@@ -63,16 +63,18 @@ protected:
virtual nsresult GetFeatureStatusImpl(int32_t aFeature,
int32_t *aStatus,
nsAString & aSuggestedDriverVersion,
const nsTArray<GfxDriverInfo>& aDriverInfo,
OperatingSystem* aOS = nullptr);
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo();
+ void DescribeFeatures(JSContext* cx, JS::Handle<JSObject*> aOut) override;
+
private:
void AddCrashReportAnnotations();
void GetCountryCode();
nsString mCountryCode;
nsString mDeviceString;
nsString mDeviceID;