Bug 1273691 - Implement 'media.wmf.disable-d3d11-for-dlls' pref - r=cpearce

Format:
"dll1.dll: 1.2.3.4[, more versions...][; more dlls...]"
I.e., DLLs are separated by semicolons, a DLL and all its versions are
separated by a single colon, and versions are separated by commas.
Whitespace between names&numbers is ignored.

Seeding pref with blacklistings from bug 1268905, bug 1269204, and bug 1273406.

MozReview-Commit-ID: 8auw4GPNyb9

--HG--
extra : rebase_source : 56c093abce3dcfbf4ddad9384a7e14fd4be6ae51
This commit is contained in:
Gerald Squelart 2016-05-18 15:44:42 +10:00
Родитель 79f1a7b3bc
Коммит 8be5775f6c
2 изменённых файлов: 103 добавлений и 82 удалений

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

@ -18,6 +18,7 @@
#include "MediaInfo.h"
#include "MediaPrefs.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "nsWindowsHelpers.h"
#include "gfx2DGlue.h"
#include "gfxWindowsPlatform.h"
@ -26,6 +27,7 @@
#include "mozilla/Telemetry.h"
#include "nsPrintfCString.h"
#include "MediaTelemetryConstants.h"
#include "GMPUtils.h" // For SplitAt. TODO: Move SplitAt to a central place.
extern mozilla::LogModule* GetPDMLog();
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
@ -151,91 +153,112 @@ WMFVideoMFTManager::GetMediaSubtypeGUID()
};
}
struct BlacklistedD3D11DLL
{
constexpr
BlacklistedD3D11DLL(LPCWSTR aName, DWORD a, DWORD b, DWORD c, DWORD d)
: name(aName), ms((a << 16) | b), ls((c << 16) | d)
{}
LPCWSTR name;
DWORD ms;
DWORD ls;
};
static constexpr BlacklistedD3D11DLL sBlacklistedD3D11DLL[] =
{
// Keep same DLL names together.
BlacklistedD3D11DLL(L"igd10umd32.dll", 9,17,10,2857),
BlacklistedD3D11DLL(L"isonyvideoprocessor.dll", 4,1,2247,8090),
BlacklistedD3D11DLL(L"isonyvideoprocessor.dll", 4,1,2153,6200),
BlacklistedD3D11DLL(L"tosqep.dll", 1,2,15,526),
BlacklistedD3D11DLL(L"tosqep.dll", 1,1,12,201),
BlacklistedD3D11DLL(L"tosqep.dll", 1,0,11,318),
BlacklistedD3D11DLL(L"tosqep.dll", 1,0,11,215),
BlacklistedD3D11DLL(L"tosqep64.dll", 1,1,12,201),
BlacklistedD3D11DLL(L"tosqep64.dll", 1,0,11,215),
// Keep this last.
BlacklistedD3D11DLL(nullptr, 0,0,0,0)
};
// If a blacklisted DLL is found, return its information, otherwise nullptr.
static const BlacklistedD3D11DLL*
// If a blacklisted DLL is found, return its information, otherwise "".
static const nsACString&
IsD3D11DLLBlacklisted()
{
NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
// Cache the result, so we only check DLLs once per browser run.
static const BlacklistedD3D11DLL* sAlreadySearched = nullptr;
if (sAlreadySearched) {
// If we point at the last empty entry, there's no actual blacklisting.
return sAlreadySearched->name ? sAlreadySearched : nullptr;
// Result is cached as long as pref doesn't change.
static nsCString sBlacklistedDLL;
nsAdoptingCString blacklist =
Preferences::GetCString("media.wmf.disable-d3d11-for-dlls");
if (blacklist.IsEmpty()) {
// Empty blacklist -> No blacklisting.
sBlacklistedDLL.SetLength(0);
return sBlacklistedDLL;
}
WCHAR systemPath[MAX_PATH + 1];
LPCWSTR previousDLLName = L"";
VS_FIXEDFILEINFO *vInfo = nullptr;
// vInfo is a pointer into infoData, that's why we keep it outside of the loop.
UniquePtr<unsigned char[]> infoData;
// Remember pref between calls, to detect changes.
static nsCString sBlacklistPref;
if (sBlacklistPref.Equals(blacklist)) {
// Same blacklist -> Return same result (i.e., don't check DLLs again).
return sBlacklistedDLL;
}
// Adopt new pref now, so we don't work on it again.
sBlacklistPref = blacklist;
for (const BlacklistedD3D11DLL* dll = sBlacklistedD3D11DLL; ; ++dll) {
if (!dll->name) {
// End of list, no blacklisting.
sAlreadySearched = dll;
return nullptr;
}
// Check if we need to check another DLL (compare by pointer to name string)
if (wcscmp(previousDLLName, dll->name) != 0) {
previousDLLName = dll->name;
vInfo = nullptr;
infoData = nullptr;
if (!ConstructSystem32Path(dll->name, systemPath, MAX_PATH + 1)) {
// Cannot build path -> Assume it's not the blacklisted DLL.
continue;
}
DWORD zero;
DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero);
if (infoSize == 0) {
// Can't get file info -> Assume we don't have the blacklisted DLL.
continue;
}
infoData = MakeUnique<unsigned char[]>(infoSize);
UINT vInfoLen;
if (!GetFileVersionInfoW(systemPath, 0, infoSize, infoData.get())
|| !VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)) {
// Can't find version -> Assume it's not blacklisted.
vInfo = nullptr;
infoData = nullptr;
continue;
}
// media.wmf.disable-d3d11-for-dlls format: (whitespace is trimmed)
// "dll1.dll: 1.2.3.4[, more versions...][; more dlls...]"
nsTArray<nsCString> dlls;
SplitAt(";", blacklist, dlls);
for (const auto& dll : dlls) {
nsTArray<nsCString> nameAndVersions;
SplitAt(":", dll, nameAndVersions);
if (nameAndVersions.Length() != 2) {
NS_WARNING("Skipping incorrect 'media.wmf.disable-d3d11-for-dlls' dll:versions format");
continue;
}
if (vInfo
&& vInfo->dwFileVersionMS == dll->ms
&& vInfo->dwFileVersionLS == dll->ls) {
// Blacklisted! Keep pointer to bad DLL.
sAlreadySearched = dll;
return dll;
nameAndVersions[0].CompressWhitespace();
NS_ConvertUTF8toUTF16 name(nameAndVersions[0]);
WCHAR systemPath[MAX_PATH + 1];
if (!ConstructSystem32Path(name.get(), systemPath, MAX_PATH + 1)) {
// Cannot build path -> Assume it's not the blacklisted DLL.
continue;
}
DWORD zero;
DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero);
if (infoSize == 0) {
// Can't get file info -> Assume we don't have the blacklisted DLL.
continue;
}
// vInfo is a pointer into infoData, that's why we keep it outside of the loop.
auto infoData = MakeUnique<unsigned char[]>(infoSize);
VS_FIXEDFILEINFO *vInfo;
UINT vInfoLen;
if (!GetFileVersionInfoW(systemPath, 0, infoSize, infoData.get())
|| !VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)
|| !vInfo) {
// Can't find version -> Assume it's not blacklisted.
continue;
}
nsTArray<nsCString> versions;
SplitAt(",", nameAndVersions[1], versions);
for (const auto& version : versions) {
nsTArray<nsCString> numberStrings;
SplitAt(".", version, numberStrings);
if (numberStrings.Length() != 4) {
NS_WARNING("Skipping incorrect 'media.wmf.disable-d3d11-for-dlls' a.b.c.d version format");
continue;
}
DWORD numbers[4];
nsresult errorCode = NS_OK;
for (int i = 0; i < 4; ++i) {
numberStrings[i].CompressWhitespace();
numbers[i] = DWORD(numberStrings[i].ToInteger(&errorCode));
if (NS_FAILED(errorCode)) {
break;
}
if (numbers[i] > UINT16_MAX) {
errorCode = NS_ERROR_FAILURE;
break;
}
}
if (NS_FAILED(errorCode)) {
NS_WARNING("Skipping incorrect 'media.wmf.disable-d3d11-for-dlls' a.b.c.d version format");
continue;
}
if (vInfo->dwFileVersionMS == ((numbers[0] << 16) | numbers[1])
&& vInfo->dwFileVersionLS == ((numbers[2] << 16) | numbers[3])) {
// Blacklisted! Record bad DLL.
sBlacklistedDLL.SetLength(0);
sBlacklistedDLL.AppendPrintf(
"%s (%lu.%lu.%lu.%lu)",
nameAndVersions[0].get(), numbers[0], numbers[1], numbers[2], numbers[3]);
return sBlacklistedDLL;
}
}
}
// No blacklisted DLL.
sBlacklistedDLL.SetLength(0);
return sBlacklistedDLL;
}
class CreateDXVAManagerEvent : public Runnable {
@ -251,13 +274,10 @@ public:
nsCString secondFailureReason;
if (mBackend == LayersBackend::LAYERS_D3D11 &&
MediaPrefs::PDMWMFAllowD3D11() && IsWin8OrLater()) {
const BlacklistedD3D11DLL* blacklistedDLL = IsD3D11DLLBlacklisted();
if (blacklistedDLL) {
failureReason->AppendPrintf(
"D3D11 blacklisted with DLL %s (%u.%u.%u.%u)",
blacklistedDLL->name,
blacklistedDLL->ms >> 16, blacklistedDLL->ms & 0xFFu,
blacklistedDLL->ls >> 16, blacklistedDLL->ls & 0xFFu);
const nsACString& blacklistedDLL = IsD3D11DLLBlacklisted();
if (!blacklistedDLL.IsEmpty()) {
failureReason->AppendPrintf("D3D11 blacklisted with DLL %s",
blacklistedDLL);
} else {
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(*failureReason);
if (mDXVA2Manager) {

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

@ -318,6 +318,7 @@ pref("media.wmf.decoder.thread-count", -1);
pref("media.wmf.low-latency.enabled", false);
pref("media.wmf.skip-blacklist", false);
pref("media.windows-media-foundation.allow-d3d11-dxva", true);
pref("media.wmf.disable-d3d11-for-dlls", "igd10umd32.dll: 9.17.10.2857; isonyvideoprocessor.dll: 4.1.2247.8090, 4.1.2153.6200; tosqep.dll: 1.2.15.526, 1.1.12.201, 1.0.11.318, 1.0.11.215; tosqep64.dll: 1.1.12.201, 1.0.11.215");
#endif
#if defined(MOZ_FFMPEG)
#if defined(XP_MACOSX)