Skip to content

Commit

Permalink
Bug 1544105 - Part 1. Expose new driver vendor field for the graphics…
Browse files Browse the repository at this point in the history
… blocklist. r=jrmuizel

This reunifies the behaviour changed in bug 1294232 to ensure that the
vendor ID of GfxInfo is the same between graphics hardware. Vendor ID
should always represent Intel, Nvidia, ATI, etc such that callers can
reason about the performance characteristics without being exposed to
the driver implementation for that platform. Now we split off the more
detailed driver information into the "driver vendor" which will contain
more information, such as what implementation is being used (e.g.
mesa/i965 for modern Intel graphics cards). This field is exposed to the
blocklist and will be useful for allowing different rules for different
driver implementations.

We also now provide a default implementation for
GfxInfoBase::FindMonitors for platforms missing support. This will just
list the primary screen size used without listing secondary monitors,
refresh rate, and such.

Differential Revision: https://phabricator.services.mozilla.com/D29471
  • Loading branch information
aosmond committed May 3, 2019
1 parent 864dcf0 commit c4dec73
Show file tree
Hide file tree
Showing 14 changed files with 309 additions and 85 deletions.
13 changes: 9 additions & 4 deletions gfx/thebes/gfxPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2595,8 +2595,7 @@ static FeatureState& WebRenderHardwareQualificationStatus(
}
#endif
#ifdef NIGHTLY_BUILD
} else if (adapterVendorID == u"0x8086" ||
adapterVendorID == u"mesa/i965") { // Intel
} else if (adapterVendorID == u"0x8086") { // Intel
const uint16_t supportedDevices[] = {
// skylake gt2+
0x1912,
Expand All @@ -2620,6 +2619,7 @@ static FeatureState& WebRenderHardwareQualificationStatus(
// kabylake gt2+
0x5912,
0x5916,
0x5917,
0x591a,
0x591b,
0x591c,
Expand Down Expand Up @@ -2669,7 +2669,11 @@ static FeatureState& WebRenderHardwareQualificationStatus(
featureWebRenderQualified.Disable(
FeatureStatus::Blocked, "Device too old",
NS_LITERAL_CSTRING("FEATURE_FAILURE_DEVICE_TOO_OLD"));
} else if (adapterVendorID == u"mesa/i965") {
}
# ifdef MOZ_WIDGET_GTK
else {
// Performance is not great on 4k screens with WebRender + Linux.
// Disable it for now if it is too large.
const int32_t maxPixels = 3440 * 1440; // UWQHD
int32_t pixels = aScreenSize.width * aScreenSize.height;
if (pixels > maxPixels) {
Expand All @@ -2682,7 +2686,8 @@ static FeatureState& WebRenderHardwareQualificationStatus(
NS_LITERAL_CSTRING("FEATURE_FAILURE_SCREEN_SIZE_UNKNOWN"));
}
}
#endif
# endif // MOZ_WIDGET_GTK
#endif // NIGHTLY_BUILD
} else {
featureWebRenderQualified.Disable(
FeatureStatus::Blocked, "Unsupported vendor",
Expand Down
40 changes: 34 additions & 6 deletions widget/GfxDriverInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ GfxDeviceFamily* const GfxDriverInfo::allDevices = nullptr;

GfxDeviceFamily* GfxDriverInfo::sDeviceFamilies[DeviceFamilyMax];
nsAString* GfxDriverInfo::sDeviceVendors[DeviceVendorMax];
nsAString* GfxDriverInfo::sDriverVendors[DriverVendorMax];

GfxDriverInfo::GfxDriverInfo()
: mOperatingSystem(OperatingSystem::Unknown),
mOperatingSystemVersion(0),
mAdapterVendor(GfxDriverInfo::GetDeviceVendor(VendorAll)),
mDriverVendor(GfxDriverInfo::GetDriverVendor(DriverVendorAll)),
mDevices(allDevices),
mDeleteDevices(false),
mFeature(allFeatures),
Expand All @@ -32,7 +34,8 @@ GfxDriverInfo::GfxDriverInfo()
mRuleId(nullptr),
mGpu2(false) {}

GfxDriverInfo::GfxDriverInfo(OperatingSystem os, nsAString& vendor,
GfxDriverInfo::GfxDriverInfo(OperatingSystem os, const nsAString& vendor,
const nsAString& driverVendor,
GfxDeviceFamily* devices, int32_t feature,
int32_t featureStatus, VersionComparisonOp op,
uint64_t driverVersion, const char* ruleId,
Expand All @@ -42,6 +45,7 @@ GfxDriverInfo::GfxDriverInfo(OperatingSystem os, nsAString& vendor,
: mOperatingSystem(os),
mOperatingSystemVersion(0),
mAdapterVendor(vendor),
mDriverVendor(driverVendor),
mDevices(devices),
mDeleteDevices(ownDevices),
mFeature(feature),
Expand All @@ -57,6 +61,7 @@ GfxDriverInfo::GfxDriverInfo(const GfxDriverInfo& aOrig)
: mOperatingSystem(aOrig.mOperatingSystem),
mOperatingSystemVersion(aOrig.mOperatingSystemVersion),
mAdapterVendor(aOrig.mAdapterVendor),
mDriverVendor(aOrig.mDriverVendor),
mFeature(aOrig.mFeature),
mFeatureStatus(aOrig.mFeatureStatus),
mComparisonOp(aOrig.mComparisonOp),
Expand Down Expand Up @@ -381,14 +386,37 @@ const nsAString& GfxDriverInfo::GetDeviceVendor(DeviceVendor id) {
// Choose an arbitrary Qualcomm PCI VENdor ID for now.
// TODO: This should be "QCOM" when Windows device ID parsing is reworked.
DECLARE_VENDOR_ID(VendorQualcomm, "0x5143");
DECLARE_VENDOR_ID(VendorMesaAll, "mesa/all");
DECLARE_VENDOR_ID(VendorMesaLLVMPipe, "mesa/llvmpipe");
DECLARE_VENDOR_ID(VendorMesaSoftPipe, "mesa/softpipe");
DECLARE_VENDOR_ID(VendorMesaSWRast, "mesa/swrast");
DECLARE_VENDOR_ID(VendorMesaUnknown, "mesa/unknown");
// Suppress a warning.
DECLARE_VENDOR_ID(DeviceVendorMax, "");
}

return *sDeviceVendors[id];
}

// Macro for assigning a driver vendor id to a string.
#define DECLARE_DRIVER_VENDOR_ID(name, driverVendorId) \
case name: \
sDriverVendors[id]->AssignLiteral(driverVendorId); \
break;

const nsAString& GfxDriverInfo::GetDriverVendor(DriverVendor id) {
NS_ASSERTION(id >= 0 && id < DriverVendorMax,
"DriverVendor id is out of range");

if (sDriverVendors[id]) return *sDriverVendors[id];

sDriverVendors[id] = new nsString();

switch (id) {
DECLARE_DRIVER_VENDOR_ID(DriverVendorAll, "");
DECLARE_DRIVER_VENDOR_ID(DriverMesaAll, "mesa/all");
DECLARE_DRIVER_VENDOR_ID(DriverMesaLLVMPipe, "mesa/llvmpipe");
DECLARE_DRIVER_VENDOR_ID(DriverMesaSoftPipe, "mesa/softpipe");
DECLARE_DRIVER_VENDOR_ID(DriverMesaSWRast, "mesa/swrast");
DECLARE_DRIVER_VENDOR_ID(DriverMesaUnknown, "mesa/unknown");
// Suppress a warning.
DECLARE_DRIVER_VENDOR_ID(DriverVendorMax, "");
}

return *sDriverVendors[id];
}
100 changes: 56 additions & 44 deletions widget/GfxDriverInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,47 @@
#include "nsString.h"

// Macros for adding a blocklist item to the static list.
#define APPEND_TO_DRIVER_BLOCKLIST(os, vendor, devices, feature, \
featureStatus, driverComparator, \
driverVersion, ruleId, suggestedVersion) \
sDriverInfo->AppendElement(GfxDriverInfo( \
os, vendor, devices, feature, featureStatus, driverComparator, \
driverVersion, ruleId, suggestedVersion))
#define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, devices, feature, \
featureStatus, driverComparator, \
driverVersion, ruleId) \
sDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, \
featureStatus, driverComparator, \
driverVersion, ruleId))

#define APPEND_TO_DRIVER_BLOCKLIST_RANGE( \
os, vendor, devices, feature, featureStatus, driverComparator, \
driverVersion, driverVersionMax, ruleId, suggestedVersion) \
do { \
MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
GfxDriverInfo info(os, vendor, devices, feature, featureStatus, \
driverComparator, driverVersion, ruleId, \
suggestedVersion); \
info.mDriverVersionMax = driverVersionMax; \
sDriverInfo->AppendElement(info); \
#define APPEND_TO_DRIVER_BLOCKLIST(os, vendor, driverVendor, devices, feature, \
featureStatus, driverComparator, \
driverVersion, ruleId, suggestedVersion) \
sDriverInfo->AppendElement(GfxDriverInfo( \
os, vendor, driverVendor, devices, feature, featureStatus, \
driverComparator, driverVersion, ruleId, suggestedVersion))
#define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, driverVendor, devices, \
feature, featureStatus, driverComparator, \
driverVersion, ruleId) \
sDriverInfo->AppendElement( \
GfxDriverInfo(os, vendor, driverVendor, devices, feature, featureStatus, \
driverComparator, driverVersion, ruleId))

#define APPEND_TO_DRIVER_BLOCKLIST_RANGE( \
os, vendor, driverVendor, devices, feature, featureStatus, \
driverComparator, driverVersion, driverVersionMax, ruleId, \
suggestedVersion) \
do { \
MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
GfxDriverInfo info(os, vendor, driverVendor, devices, feature, \
featureStatus, driverComparator, driverVersion, ruleId, \
suggestedVersion); \
info.mDriverVersionMax = driverVersionMax; \
sDriverInfo->AppendElement(info); \
} while (false)

#define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2( \
os, vendor, devices, feature, featureStatus, driverComparator, \
driverVersion, driverVersionMax, ruleId, suggestedVersion) \
do { \
MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
GfxDriverInfo info(os, vendor, devices, feature, featureStatus, \
driverComparator, driverVersion, ruleId, \
suggestedVersion, false, true); \
info.mDriverVersionMax = driverVersionMax; \
sDriverInfo->AppendElement(info); \
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2( \
os, vendor, driverVendor, devices, feature, featureStatus, \
driverComparator, driverVersion, driverVersionMax, ruleId, \
suggestedVersion) \
do { \
MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
GfxDriverInfo info(os, vendor, driverVendor, devices, feature, \
featureStatus, driverComparator, driverVersion, ruleId, \
suggestedVersion, false, true); \
info.mDriverVersionMax = driverVersionMax; \
sDriverInfo->AppendElement(info); \
} while (false)

namespace mozilla {
Expand Down Expand Up @@ -128,18 +130,23 @@ enum DeviceVendor {
VendorParallels,
VendorQualcomm,

DeviceVendorMax
};

enum DriverVendor {
DriverVendorAll, // There is an assumption that this is the first enum
// Wildcard for all Mesa drivers.
VendorMesaAll,
DriverMesaAll,
// Note that the following list of Mesa drivers is not comprehensive; we pull
// the DRI driver at runtime. These drivers are provided for convenience when
// populating the local blocklist.
VendorMesaLLVMPipe,
VendorMesaSoftPipe,
VendorMesaSWRast,
DriverMesaLLVMPipe,
DriverMesaSoftPipe,
DriverMesaSWRast,
// A generic ID to be provided when we can't determine the DRI driver on Mesa.
VendorMesaUnknown,
DriverMesaUnknown,

DeviceVendorMax
DriverVendorMax
};

/* Array of devices to match, or an empty array for all devices */
Expand All @@ -148,7 +155,8 @@ typedef nsTArray<nsString> GfxDeviceFamily;
struct GfxDriverInfo {
// If |ownDevices| is true, you are transferring ownership of the devices
// array, and it will be deleted when this GfxDriverInfo is destroyed.
GfxDriverInfo(OperatingSystem os, nsAString& vendor, GfxDeviceFamily* devices,
GfxDriverInfo(OperatingSystem os, const nsAString& vendor,
const nsAString& driverVendor, GfxDeviceFamily* devices,
int32_t feature, int32_t featureStatus, VersionComparisonOp op,
uint64_t driverVersion, const char* ruleId,
const char* suggestedVersion = nullptr, bool ownDevices = false,
Expand All @@ -162,6 +170,7 @@ struct GfxDriverInfo {
uint32_t mOperatingSystemVersion;

nsString mAdapterVendor;
nsString mDriverVendor;

static GfxDeviceFamily* const allDevices;
GfxDeviceFamily* mDevices;
Expand Down Expand Up @@ -193,6 +202,9 @@ struct GfxDriverInfo {
static const nsAString& GetDeviceVendor(DeviceVendor id);
static nsAString* sDeviceVendors[DeviceVendorMax];

static const nsAString& GetDriverVendor(DriverVendor id);
static nsAString* sDriverVendors[DriverVendorMax];

nsString mModel, mHardware, mProduct, mManufacturer;

bool mGpu2;
Expand Down
43 changes: 43 additions & 0 deletions widget/GfxInfoBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ static bool BlacklistEntryToDriverInfo(nsCString& aBlacklistEntry,
aDriverInfo.mOperatingSystemVersion = strtoul(value.get(), nullptr, 10);
} else if (key.EqualsLiteral("vendor")) {
aDriverInfo.mAdapterVendor = dataValue;
} else if (key.EqualsLiteral("driverVendor")) {
aDriverInfo.mDriverVendor = dataValue;
} else if (key.EqualsLiteral("feature")) {
aDriverInfo.mFeature = BlacklistFeatureToGfxFeature(dataValue);
if (aDriverInfo.mFeature < 0) {
Expand Down Expand Up @@ -679,16 +681,19 @@ int32_t GfxInfoBase::FindBlocklistedDeviceInList(
// Get the adapters once then reuse below
nsAutoString adapterVendorID[2];
nsAutoString adapterDeviceID[2];
nsAutoString adapterDriverVendor[2];
nsAutoString adapterDriverVersionString[2];
bool adapterInfoFailed[2];

adapterInfoFailed[0] =
(NS_FAILED(GetAdapterVendorID(adapterVendorID[0])) ||
NS_FAILED(GetAdapterDeviceID(adapterDeviceID[0])) ||
NS_FAILED(GetAdapterDriverVendor(adapterDriverVendor[0])) ||
NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString[0])));
adapterInfoFailed[1] =
(NS_FAILED(GetAdapterVendorID2(adapterVendorID[1])) ||
NS_FAILED(GetAdapterDeviceID2(adapterDeviceID[1])) ||
NS_FAILED(GetAdapterDriverVendor2(adapterDriverVendor[1])) ||
NS_FAILED(GetAdapterDriverVersion2(adapterDriverVersionString[1])));
// No point in going on if we don't have adapter info
if (adapterInfoFailed[0] && adapterInfoFailed[1]) {
Expand Down Expand Up @@ -732,6 +737,11 @@ int32_t GfxInfoBase::FindBlocklistedDeviceInList(
continue;
}

if (!DoesDriverVendorMatch(info[i].mDriverVendor,
adapterDriverVendor[infoIndex])) {
continue;
}

if (info[i].mDevices != GfxDriverInfo::allDevices &&
info[i].mDevices->Length()) {
bool deviceMatches = false;
Expand Down Expand Up @@ -887,6 +897,15 @@ bool GfxInfoBase::DoesVendorMatch(const nsAString& aBlocklistVendor,
nsCaseInsensitiveStringComparator());
}

bool GfxInfoBase::DoesDriverVendorMatch(const nsAString& aBlocklistVendor,
const nsAString& aDriverVendor) {
return aBlocklistVendor.Equals(aDriverVendor,
nsCaseInsensitiveStringComparator()) ||
aBlocklistVendor.Equals(
GfxDriverInfo::GetDriverVendor(DriverVendorAll),
nsCaseInsensitiveStringComparator());
}

nsresult GfxInfoBase::GetFeatureStatusImpl(
int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedVersion,
const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
Expand Down Expand Up @@ -1161,6 +1180,30 @@ void GfxInfoBase::RemoveCollector(GfxInfoCollectorBase* collector) {
}
}

nsresult GfxInfoBase::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
// If we have no platform specific implementation for detecting monitors, we
// can just get the screen size from gfxPlatform as the best guess.
if (!gfxPlatform::Initialized()) {
return NS_OK;
}

// If the screen size is empty, we are probably in xpcshell.
gfx::IntSize screenSize = gfxPlatform::GetPlatform()->GetScreenSize();

JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));

JS::Rooted<JS::Value> screenWidth(aCx, JS::Int32Value(screenSize.width));
JS_SetProperty(aCx, obj, "screenWidth", screenWidth);

JS::Rooted<JS::Value> screenHeight(aCx, JS::Int32Value(screenSize.height));
JS_SetProperty(aCx, obj, "screenHeight", screenHeight);

JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
JS_SetElement(aCx, aOutArray, 0, element);

return NS_OK;
}

NS_IMETHODIMP
GfxInfoBase::GetMonitors(JSContext* aCx, JS::MutableHandleValue aResult) {
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
Expand Down
11 changes: 6 additions & 5 deletions widget/GfxInfoBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ class GfxInfoBase : public nsIGfxInfo,
// Convenience to get the application version
static const nsCString& GetApplicationVersion();

virtual nsresult FindMonitors(JSContext* cx, JS::HandleObject array) {
return NS_ERROR_NOT_IMPLEMENTED;
}
virtual nsresult FindMonitors(JSContext* cx, JS::HandleObject array);

static void SetFeatureStatus(
const nsTArray<mozilla::dom::GfxInfoFeatureStatus>& aFS);
Expand All @@ -125,8 +123,11 @@ class GfxInfoBase : public nsIGfxInfo,

virtual void DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> obj);

virtual bool DoesVendorMatch(const nsAString& aBlocklistVendor,
const nsAString& aAdapterVendor);
bool DoesVendorMatch(const nsAString& aBlocklistVendor,
const nsAString& aAdapterVendor);

virtual bool DoesDriverVendorMatch(const nsAString& aBlocklistVendor,
const nsAString& aDriverVendor);

bool InitFeatureObject(JSContext* aCx, JS::Handle<JSObject*> aContainer,
const char* aName,
Expand Down
Loading

0 comments on commit c4dec73

Please sign in to comment.