зеркало из https://github.com/mozilla/gecko-dev.git
Move D3D11 checking logic out of gfxWindowsPlatform. (bug 1282364 part 2, r=mattwoodrow)
--HG-- extra : rebase_source : df247cc5d03a111075eb4b201618dd957213d76f
This commit is contained in:
Родитель
b7855c4ee9
Коммит
572069e3e9
|
@ -0,0 +1,394 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "D3D11Checks.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "GfxDriverInfo.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include <dxgi.h>
|
||||
#include <d3d10_1.h>
|
||||
#include <d3d11.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::DoesRenderTargetViewNeedRecreating(ID3D11Device *aDevice)
|
||||
{
|
||||
bool result = false;
|
||||
// CreateTexture2D is known to crash on lower feature levels, see bugs
|
||||
// 1170211 and 1089413.
|
||||
if (aDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> deviceContext;
|
||||
aDevice->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||
int backbufferWidth = 32; int backbufferHeight = 32;
|
||||
RefPtr<ID3D11Texture2D> offscreenTexture;
|
||||
RefPtr<IDXGIKeyedMutex> keyedMutex;
|
||||
|
||||
D3D11_TEXTURE2D_DESC offscreenTextureDesc = { 0 };
|
||||
offscreenTextureDesc.Width = backbufferWidth;
|
||||
offscreenTextureDesc.Height = backbufferHeight;
|
||||
offscreenTextureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
offscreenTextureDesc.MipLevels = 0;
|
||||
offscreenTextureDesc.ArraySize = 1;
|
||||
offscreenTextureDesc.SampleDesc.Count = 1;
|
||||
offscreenTextureDesc.SampleDesc.Quality = 0;
|
||||
offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
offscreenTextureDesc.CPUAccessFlags = 0;
|
||||
offscreenTextureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
|
||||
HRESULT hr = aDevice->CreateTexture2D(&offscreenTextureDesc, NULL, getter_AddRefs(offscreenTexture));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingCreateTexture2DFail";
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = offscreenTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(keyedMutex));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingKeyedMutexFailed";
|
||||
return false;
|
||||
}
|
||||
D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
|
||||
offscreenRTVDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
offscreenRTVDesc.Texture2D.MipSlice = 0;
|
||||
|
||||
RefPtr<ID3D11RenderTargetView> offscreenRTView;
|
||||
hr = aDevice->CreateRenderTargetView(offscreenTexture, &offscreenRTVDesc, getter_AddRefs(offscreenRTView));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingCreateRenderTargetViewFailed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Acquire and clear
|
||||
keyedMutex->AcquireSync(0, INFINITE);
|
||||
FLOAT color1[4] = { 1, 1, 0.5, 1 };
|
||||
deviceContext->ClearRenderTargetView(offscreenRTView, color1);
|
||||
keyedMutex->ReleaseSync(0);
|
||||
|
||||
|
||||
keyedMutex->AcquireSync(0, INFINITE);
|
||||
FLOAT color2[4] = { 1, 1, 0, 1 };
|
||||
|
||||
deviceContext->ClearRenderTargetView(offscreenRTView, color2);
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
offscreenTexture->GetDesc(&desc);
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
desc.BindFlags = 0;
|
||||
ID3D11Texture2D* cpuTexture;
|
||||
hr = aDevice->CreateTexture2D(&desc, NULL, &cpuTexture);
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingCreateCPUTextureFailed";
|
||||
return false;
|
||||
}
|
||||
|
||||
deviceContext->CopyResource(cpuTexture, offscreenTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
hr = deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped);
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingMapFailed " << hexa(hr);
|
||||
return false;
|
||||
}
|
||||
int resultColor = *(int*)mapped.pData;
|
||||
deviceContext->Unmap(cpuTexture, 0);
|
||||
cpuTexture->Release();
|
||||
|
||||
// XXX on some drivers resultColor will not have changed to
|
||||
// match the clear
|
||||
if (resultColor != 0xffffff00) {
|
||||
gfxCriticalNote << "RenderTargetViewNeedsRecreating";
|
||||
result = true;
|
||||
}
|
||||
|
||||
keyedMutex->ReleaseSync(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::DoesD3D11DeviceWork()
|
||||
{
|
||||
static bool checked = false;
|
||||
static bool result = false;
|
||||
|
||||
if (checked)
|
||||
return result;
|
||||
checked = true;
|
||||
|
||||
if (gfxPrefs::Direct2DForceEnabled() ||
|
||||
gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
|
||||
{
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetModuleHandleW(L"igd10umd32.dll")) {
|
||||
const wchar_t* checkModules[] = {L"dlumd32.dll",
|
||||
L"dlumd11.dll",
|
||||
L"dlumd10.dll"};
|
||||
for (int i=0; i<PR_ARRAY_SIZE(checkModules); i+=1) {
|
||||
if (GetModuleHandleW(checkModules[i])) {
|
||||
nsString displayLinkModuleVersionString;
|
||||
gfxWindowsPlatform::GetDLLVersion(checkModules[i],
|
||||
displayLinkModuleVersionString);
|
||||
uint64_t displayLinkModuleVersion;
|
||||
if (!ParseDriverVersion(displayLinkModuleVersionString,
|
||||
&displayLinkModuleVersion)) {
|
||||
gfxCriticalError() << "DisplayLink: could not parse version "
|
||||
<< checkModules[i];
|
||||
return false;
|
||||
}
|
||||
if (displayLinkModuleVersion <= V(8,6,1,36484)) {
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DisplayLink: too old version " << displayLinkModuleVersionString.get();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TryCreateTexture2D(ID3D11Device *device,
|
||||
D3D11_TEXTURE2D_DESC* desc,
|
||||
D3D11_SUBRESOURCE_DATA* data,
|
||||
RefPtr<ID3D11Texture2D>& texture)
|
||||
{
|
||||
// Older Intel driver version (see bug 1221348 for version #s) crash when
|
||||
// creating a texture with shared keyed mutex and data.
|
||||
MOZ_SEH_TRY {
|
||||
return !FAILED(device->CreateTexture2D(desc, data, getter_AddRefs(texture)));
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
// For now we want to aggregrate all the crash signature to a known crash.
|
||||
gfxDevCrash(LogReason::TextureCreation) << "Crash creating texture. See bug 1221348.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
|
||||
// with E_OUTOFMEMORY.
|
||||
static bool
|
||||
DoesTextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT format, UINT bindflags)
|
||||
{
|
||||
// CreateTexture2D is known to crash on lower feature levels, see bugs
|
||||
// 1170211 and 1089413.
|
||||
if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gfxPrefs::Direct2DForceEnabled() ||
|
||||
gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetModuleHandleW(L"atidxx32.dll")) {
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
if (gfxInfo) {
|
||||
nsString vendorID, vendorID2;
|
||||
gfxInfo->GetAdapterVendorID(vendorID);
|
||||
gfxInfo->GetAdapterVendorID2(vendorID2);
|
||||
if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
|
||||
if (!gfxPrefs::LayersAMDSwitchableGfxEnabled()) {
|
||||
return false;
|
||||
}
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "PossiblyBrokenSurfaceSharing_UnexpectedAMDGPU";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
const int texture_size = 32;
|
||||
desc.Width = texture_size;
|
||||
desc.Height = texture_size;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
desc.BindFlags = bindflags;
|
||||
|
||||
uint32_t color[texture_size * texture_size];
|
||||
for (size_t i = 0; i < sizeof(color)/sizeof(color[0]); i++) {
|
||||
color[i] = 0xff00ffff;
|
||||
}
|
||||
// XXX If we pass the data directly at texture creation time we
|
||||
// get a crash on Intel 8.5.10.[18xx-1994] drivers.
|
||||
// We can work around this issue by doing UpdateSubresource.
|
||||
if (!TryCreateTexture2D(device, &desc, nullptr, texture)) {
|
||||
gfxCriticalNote << "DoesD3D11TextureSharingWork_TryCreateTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> sourceSharedMutex;
|
||||
texture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sourceSharedMutex));
|
||||
if (FAILED(sourceSharedMutex->AcquireSync(0, 30*1000))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceMutexTimeout";
|
||||
// only wait for 30 seconds
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> deviceContext;
|
||||
device->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||
|
||||
int stride = texture_size * 4;
|
||||
deviceContext->UpdateSubresource(texture, 0, nullptr, color, stride, stride * texture_size);
|
||||
|
||||
if (FAILED(sourceSharedMutex->ReleaseSync(0))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceReleaseSyncTimeout";
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE shareHandle;
|
||||
RefPtr<IDXGIResource> otherResource;
|
||||
if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource),
|
||||
getter_AddRefs(otherResource))))
|
||||
{
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetResourceFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(otherResource->GetSharedHandle(&shareHandle))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Resource> sharedResource;
|
||||
RefPtr<ID3D11Texture2D> sharedTexture;
|
||||
if (FAILED(device->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
|
||||
getter_AddRefs(sharedResource))))
|
||||
{
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "OpenSharedResource failed for format " << format;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(sharedResource->QueryInterface(__uuidof(ID3D11Texture2D),
|
||||
getter_AddRefs(sharedTexture))))
|
||||
{
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a staging texture for readback
|
||||
RefPtr<ID3D11Texture2D> cpuTexture;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
desc.BindFlags = 0;
|
||||
if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(cpuTexture)))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_CreateTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> sharedMutex;
|
||||
sharedResource->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sharedMutex));
|
||||
if (FAILED(sharedMutex->AcquireSync(0, 30*1000))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_AcquireSyncTimeout";
|
||||
// only wait for 30 seconds
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy to the cpu texture so that we can readback
|
||||
deviceContext->CopyResource(cpuTexture, sharedTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
int resultColor = 0;
|
||||
if (SUCCEEDED(deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped))) {
|
||||
// read the texture
|
||||
resultColor = *(int*)mapped.pData;
|
||||
deviceContext->Unmap(cpuTexture, 0);
|
||||
} else {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_MapFailed";
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedMutex->ReleaseSync(0);
|
||||
|
||||
// check that the color we put in is the color we get out
|
||||
if (resultColor != color[0]) {
|
||||
// Shared surfaces seem to be broken on dual AMD & Intel HW when using the
|
||||
// AMD GPU
|
||||
gfxCriticalNote << "DoesD3D11TextureSharingWork_ColorMismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11ShaderResourceView> sharedView;
|
||||
|
||||
// This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
|
||||
if (FAILED(device->CreateShaderResourceView(sharedTexture, NULL, getter_AddRefs(sharedView)))) {
|
||||
gfxCriticalNote << "CreateShaderResourceView failed for format" << format;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::DoesTextureSharingWork(ID3D11Device *device)
|
||||
{
|
||||
return DoesTextureSharingWorkInternal(device, DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::DoesAlphaTextureSharingWork(ID3D11Device *device)
|
||||
{
|
||||
return DoesTextureSharingWorkInternal(device, DXGI_FORMAT_R8_UNORM, D3D11_BIND_SHADER_RESOURCE);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out)
|
||||
{
|
||||
RefPtr<IDXGIDevice> dxgiDevice;
|
||||
HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), getter_AddRefs(dxgiDevice));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIAdapter> dxgiAdapter;
|
||||
if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SUCCEEDED(dxgiAdapter->GetDesc(out));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
D3D11Checks::WarnOnAdapterMismatch(ID3D11Device *device)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
PodZero(&desc);
|
||||
GetDxgiDesc(device, &desc);
|
||||
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
nsString vendorID;
|
||||
gfxInfo->GetAdapterVendorID(vendorID);
|
||||
nsresult ec;
|
||||
int32_t vendor = vendorID.ToInteger(&ec, 16);
|
||||
if (vendor != desc.VendorId) {
|
||||
gfxCriticalNote << "VendorIDMismatch V " << hexa(vendor) << " " << hexa(desc.VendorId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,28 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 mozilla_gfx_thebes_D3D11Checks_h
|
||||
#define mozilla_gfx_thebes_D3D11Checks_h
|
||||
|
||||
struct ID3D11Device;
|
||||
struct DXGI_ADAPTER_DESC;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
struct D3D11Checks
|
||||
{
|
||||
static bool DoesRenderTargetViewNeedRecreating(ID3D11Device* aDevice);
|
||||
static bool DoesD3D11DeviceWork();
|
||||
static bool DoesTextureSharingWork(ID3D11Device *device);
|
||||
static bool DoesAlphaTextureSharingWork(ID3D11Device *device);
|
||||
static void WarnOnAdapterMismatch(ID3D11Device* device);
|
||||
static bool GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out);
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_gfx_thebes_D3D11Checks_h
|
|
@ -1778,3 +1778,8 @@ gfxFontUtils::IsCffFont(const uint8_t* aFontData)
|
|||
|
||||
#endif
|
||||
|
||||
#undef acceptablePlatform
|
||||
#undef isSymbol
|
||||
#undef isUVSEncoding
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
|
|
|
@ -1603,3 +1603,6 @@ gfxPlatformFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
|||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
|
|
|
@ -1432,3 +1432,6 @@ gfxUserFontSet::UserFontCache::Dump()
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "imgLoader.h"
|
||||
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "GfxDriverInfo.h"
|
||||
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
|
||||
|
@ -75,6 +74,7 @@
|
|||
#include "DriverCrashGuard.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/gfx/DeviceManagerD3D11.h"
|
||||
#include "D3D11Checks.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -1539,374 +1539,6 @@ gfxWindowsPlatform::GetDXGIAdapter()
|
|||
return mAdapter;
|
||||
}
|
||||
|
||||
bool DoesD3D11DeviceWork()
|
||||
{
|
||||
static bool checked = false;
|
||||
static bool result = false;
|
||||
|
||||
if (checked)
|
||||
return result;
|
||||
checked = true;
|
||||
|
||||
if (gfxPrefs::Direct2DForceEnabled() ||
|
||||
gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
|
||||
{
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetModuleHandleW(L"igd10umd32.dll")) {
|
||||
const wchar_t* checkModules[] = {L"dlumd32.dll",
|
||||
L"dlumd11.dll",
|
||||
L"dlumd10.dll"};
|
||||
for (int i=0; i<PR_ARRAY_SIZE(checkModules); i+=1) {
|
||||
if (GetModuleHandleW(checkModules[i])) {
|
||||
nsString displayLinkModuleVersionString;
|
||||
gfxWindowsPlatform::GetDLLVersion(checkModules[i],
|
||||
displayLinkModuleVersionString);
|
||||
uint64_t displayLinkModuleVersion;
|
||||
if (!ParseDriverVersion(displayLinkModuleVersionString,
|
||||
&displayLinkModuleVersion)) {
|
||||
gfxCriticalError() << "DisplayLink: could not parse version "
|
||||
<< checkModules[i];
|
||||
return false;
|
||||
}
|
||||
if (displayLinkModuleVersion <= V(8,6,1,36484)) {
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DisplayLink: too old version " << displayLinkModuleVersionString.get();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out)
|
||||
{
|
||||
RefPtr<IDXGIDevice> dxgiDevice;
|
||||
HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), getter_AddRefs(dxgiDevice));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIAdapter> dxgiAdapter;
|
||||
if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SUCCEEDED(dxgiAdapter->GetDesc(out));
|
||||
}
|
||||
|
||||
static void
|
||||
CheckForAdapterMismatch(ID3D11Device *device)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
PodZero(&desc);
|
||||
GetDxgiDesc(device, &desc);
|
||||
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
nsString vendorID;
|
||||
gfxInfo->GetAdapterVendorID(vendorID);
|
||||
nsresult ec;
|
||||
int32_t vendor = vendorID.ToInteger(&ec, 16);
|
||||
if (vendor != desc.VendorId) {
|
||||
gfxCriticalNote << "VendorIDMismatch V " << hexa(vendor) << " " << hexa(desc.VendorId);
|
||||
}
|
||||
}
|
||||
|
||||
bool DoesRenderTargetViewNeedsRecreating(ID3D11Device *device)
|
||||
{
|
||||
bool result = false;
|
||||
// CreateTexture2D is known to crash on lower feature levels, see bugs
|
||||
// 1170211 and 1089413.
|
||||
if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> deviceContext;
|
||||
device->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||
int backbufferWidth = 32; int backbufferHeight = 32;
|
||||
RefPtr<ID3D11Texture2D> offscreenTexture;
|
||||
RefPtr<IDXGIKeyedMutex> keyedMutex;
|
||||
|
||||
D3D11_TEXTURE2D_DESC offscreenTextureDesc = { 0 };
|
||||
offscreenTextureDesc.Width = backbufferWidth;
|
||||
offscreenTextureDesc.Height = backbufferHeight;
|
||||
offscreenTextureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
offscreenTextureDesc.MipLevels = 0;
|
||||
offscreenTextureDesc.ArraySize = 1;
|
||||
offscreenTextureDesc.SampleDesc.Count = 1;
|
||||
offscreenTextureDesc.SampleDesc.Quality = 0;
|
||||
offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
offscreenTextureDesc.CPUAccessFlags = 0;
|
||||
offscreenTextureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
|
||||
HRESULT hr = device->CreateTexture2D(&offscreenTextureDesc, NULL, getter_AddRefs(offscreenTexture));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingCreateTexture2DFail";
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = offscreenTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(keyedMutex));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingKeyedMutexFailed";
|
||||
return false;
|
||||
}
|
||||
D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
|
||||
offscreenRTVDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
offscreenRTVDesc.Texture2D.MipSlice = 0;
|
||||
|
||||
RefPtr<ID3D11RenderTargetView> offscreenRTView;
|
||||
hr = device->CreateRenderTargetView(offscreenTexture, &offscreenRTVDesc, getter_AddRefs(offscreenRTView));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingCreateRenderTargetViewFailed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Acquire and clear
|
||||
keyedMutex->AcquireSync(0, INFINITE);
|
||||
FLOAT color1[4] = { 1, 1, 0.5, 1 };
|
||||
deviceContext->ClearRenderTargetView(offscreenRTView, color1);
|
||||
keyedMutex->ReleaseSync(0);
|
||||
|
||||
|
||||
keyedMutex->AcquireSync(0, INFINITE);
|
||||
FLOAT color2[4] = { 1, 1, 0, 1 };
|
||||
|
||||
deviceContext->ClearRenderTargetView(offscreenRTView, color2);
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
offscreenTexture->GetDesc(&desc);
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
desc.BindFlags = 0;
|
||||
ID3D11Texture2D* cpuTexture;
|
||||
hr = device->CreateTexture2D(&desc, NULL, &cpuTexture);
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingCreateCPUTextureFailed";
|
||||
return false;
|
||||
}
|
||||
|
||||
deviceContext->CopyResource(cpuTexture, offscreenTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
hr = deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped);
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DoesRecreatingMapFailed " << hexa(hr);
|
||||
return false;
|
||||
}
|
||||
int resultColor = *(int*)mapped.pData;
|
||||
deviceContext->Unmap(cpuTexture, 0);
|
||||
cpuTexture->Release();
|
||||
|
||||
// XXX on some drivers resultColor will not have changed to
|
||||
// match the clear
|
||||
if (resultColor != 0xffffff00) {
|
||||
gfxCriticalNote << "RenderTargetViewNeedsRecreating";
|
||||
result = true;
|
||||
}
|
||||
|
||||
keyedMutex->ReleaseSync(0);
|
||||
|
||||
// It seems like this may only happen when we're using the NVIDIA gpu
|
||||
CheckForAdapterMismatch(device);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool TryCreateTexture2D(ID3D11Device *device,
|
||||
D3D11_TEXTURE2D_DESC* desc,
|
||||
D3D11_SUBRESOURCE_DATA* data,
|
||||
RefPtr<ID3D11Texture2D>& texture)
|
||||
{
|
||||
// Older Intel driver version (see bug 1221348 for version #s) crash when
|
||||
// creating a texture with shared keyed mutex and data.
|
||||
MOZ_SEH_TRY {
|
||||
return !FAILED(device->CreateTexture2D(desc, data, getter_AddRefs(texture)));
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
// For now we want to aggregrate all the crash signature to a known crash.
|
||||
gfxDevCrash(LogReason::TextureCreation) << "Crash creating texture. See bug 1221348.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
|
||||
// with E_OUTOFMEMORY.
|
||||
bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT format, UINT bindflags)
|
||||
{
|
||||
// CreateTexture2D is known to crash on lower feature levels, see bugs
|
||||
// 1170211 and 1089413.
|
||||
if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gfxPrefs::Direct2DForceEnabled() ||
|
||||
gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetModuleHandleW(L"atidxx32.dll")) {
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
if (gfxInfo) {
|
||||
nsString vendorID, vendorID2;
|
||||
gfxInfo->GetAdapterVendorID(vendorID);
|
||||
gfxInfo->GetAdapterVendorID2(vendorID2);
|
||||
if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
|
||||
if (!gfxPrefs::LayersAMDSwitchableGfxEnabled()) {
|
||||
return false;
|
||||
}
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "PossiblyBrokenSurfaceSharing_UnexpectedAMDGPU";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
const int texture_size = 32;
|
||||
desc.Width = texture_size;
|
||||
desc.Height = texture_size;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
desc.BindFlags = bindflags;
|
||||
|
||||
uint32_t color[texture_size * texture_size];
|
||||
for (size_t i = 0; i < sizeof(color)/sizeof(color[0]); i++) {
|
||||
color[i] = 0xff00ffff;
|
||||
}
|
||||
// XXX If we pass the data directly at texture creation time we
|
||||
// get a crash on Intel 8.5.10.[18xx-1994] drivers.
|
||||
// We can work around this issue by doing UpdateSubresource.
|
||||
if (!TryCreateTexture2D(device, &desc, nullptr, texture)) {
|
||||
gfxCriticalNote << "DoesD3D11TextureSharingWork_TryCreateTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> sourceSharedMutex;
|
||||
texture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sourceSharedMutex));
|
||||
if (FAILED(sourceSharedMutex->AcquireSync(0, 30*1000))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceMutexTimeout";
|
||||
// only wait for 30 seconds
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> deviceContext;
|
||||
device->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||
|
||||
int stride = texture_size * 4;
|
||||
deviceContext->UpdateSubresource(texture, 0, nullptr, color, stride, stride * texture_size);
|
||||
|
||||
if (FAILED(sourceSharedMutex->ReleaseSync(0))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceReleaseSyncTimeout";
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE shareHandle;
|
||||
RefPtr<IDXGIResource> otherResource;
|
||||
if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource),
|
||||
getter_AddRefs(otherResource))))
|
||||
{
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetResourceFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(otherResource->GetSharedHandle(&shareHandle))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Resource> sharedResource;
|
||||
RefPtr<ID3D11Texture2D> sharedTexture;
|
||||
if (FAILED(device->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
|
||||
getter_AddRefs(sharedResource))))
|
||||
{
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "OpenSharedResource failed for format " << format;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(sharedResource->QueryInterface(__uuidof(ID3D11Texture2D),
|
||||
getter_AddRefs(sharedTexture))))
|
||||
{
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a staging texture for readback
|
||||
RefPtr<ID3D11Texture2D> cpuTexture;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
desc.BindFlags = 0;
|
||||
if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(cpuTexture)))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_CreateTextureFailure";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> sharedMutex;
|
||||
sharedResource->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sharedMutex));
|
||||
if (FAILED(sharedMutex->AcquireSync(0, 30*1000))) {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_AcquireSyncTimeout";
|
||||
// only wait for 30 seconds
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy to the cpu texture so that we can readback
|
||||
deviceContext->CopyResource(cpuTexture, sharedTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
int resultColor = 0;
|
||||
if (SUCCEEDED(deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped))) {
|
||||
// read the texture
|
||||
resultColor = *(int*)mapped.pData;
|
||||
deviceContext->Unmap(cpuTexture, 0);
|
||||
} else {
|
||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_MapFailed";
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedMutex->ReleaseSync(0);
|
||||
|
||||
// check that the color we put in is the color we get out
|
||||
if (resultColor != color[0]) {
|
||||
// Shared surfaces seem to be broken on dual AMD & Intel HW when using the
|
||||
// AMD GPU
|
||||
gfxCriticalNote << "DoesD3D11TextureSharingWork_ColorMismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11ShaderResourceView> sharedView;
|
||||
|
||||
// This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
|
||||
if (FAILED(device->CreateShaderResourceView(sharedTexture, NULL, getter_AddRefs(sharedView)))) {
|
||||
gfxCriticalNote << "CreateShaderResourceView failed for format" << format;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DoesD3D11TextureSharingWork(ID3D11Device *device)
|
||||
{
|
||||
return DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
|
||||
}
|
||||
|
||||
bool DoesD3D11AlphaTextureSharingWork(ID3D11Device *device)
|
||||
{
|
||||
return DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_R8_UNORM, D3D11_BIND_SHADER_RESOURCE);
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
IsWARPStable()
|
||||
{
|
||||
|
@ -2115,7 +1747,7 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
|
|||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
|
||||
return;
|
||||
}
|
||||
if (!DoesD3D11DeviceWork()) {
|
||||
if (!D3D11Checks::DoesD3D11DeviceWork()) {
|
||||
d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
|
||||
return;
|
||||
|
@ -2128,7 +1760,8 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
|
|||
|
||||
// Only test this when not using WARP since it can fail and cause
|
||||
// GetDeviceRemovedReason to return weird values.
|
||||
mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
|
||||
mCompositorD3D11TextureSharingWorks =
|
||||
D3D11Checks::DoesTextureSharingWork(mD3D11Device);
|
||||
|
||||
if (!mCompositorD3D11TextureSharingWorks) {
|
||||
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
|
||||
|
@ -2136,12 +1769,15 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
|
|||
"Texture sharing doesn't work");
|
||||
}
|
||||
|
||||
if (DoesRenderTargetViewNeedsRecreating(mD3D11Device)) {
|
||||
if (D3D11Checks::DoesRenderTargetViewNeedRecreating(mD3D11Device)) {
|
||||
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
|
||||
FeatureStatus::Broken,
|
||||
"RenderTargetViews need recreating");
|
||||
}
|
||||
|
||||
// It seems like this may only happen when we're using the NVIDIA gpu
|
||||
D3D11Checks::WarnOnAdapterMismatch(mD3D11Device);
|
||||
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = false;
|
||||
}
|
||||
|
@ -2200,7 +1836,8 @@ gfxWindowsPlatform::AttemptWARPDeviceCreation()
|
|||
// Only test for texture sharing on Windows 8 since it puts the device into
|
||||
// an unusable state if used on Windows 7
|
||||
if (IsWin8OrLater()) {
|
||||
mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
|
||||
mCompositorD3D11TextureSharingWorks =
|
||||
D3D11Checks::DoesTextureSharingWork(mD3D11Device);
|
||||
}
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = true;
|
||||
|
@ -2210,7 +1847,7 @@ bool
|
|||
gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (!GetDxgiDesc(device, &desc)) {
|
||||
if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
|
||||
gfxCriticalNote << "Could not query device DXGI adapter info";
|
||||
return false;
|
||||
}
|
||||
|
@ -2292,7 +1929,7 @@ gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
|
|||
// we re-check texture sharing against the newly created D3D11 content device.
|
||||
// If it fails, we won't use Direct2D.
|
||||
if (XRE_IsContentProcess()) {
|
||||
if (!DoesD3D11TextureSharingWork(mD3D11ContentDevice)) {
|
||||
if (!D3D11Checks::DoesTextureSharingWork(mD3D11ContentDevice)) {
|
||||
mD3D11ContentDevice = nullptr;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
@ -2345,7 +1982,7 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
|
|||
}
|
||||
|
||||
mD3D11ImageBridgeDevice->SetExceptionMode(0);
|
||||
if (!DoesD3D11AlphaTextureSharingWork(mD3D11ImageBridgeDevice)) {
|
||||
if (!D3D11Checks::DoesAlphaTextureSharingWork(mD3D11ImageBridgeDevice)) {
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
@ -2654,7 +2291,7 @@ gfxWindowsPlatform::CreateD3D11DecoderDevice()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !device || !DoesD3D11DeviceWork()) {
|
||||
if (FAILED(hr) || !device || !D3D11Checks::DoesD3D11DeviceWork()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -3007,7 +2644,7 @@ gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
|
|||
|
||||
if (mD3D11Device) {
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (!GetDxgiDesc(mD3D11Device, &desc)) {
|
||||
if (!D3D11Checks::GetDxgiDesc(mD3D11Device, &desc)) {
|
||||
return;
|
||||
}
|
||||
aOut->adapter() = DxgiAdapterDesc::From(desc);
|
||||
|
|
|
@ -235,6 +235,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
|||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'D3D11Checks.cpp',
|
||||
'DeviceManagerD3D11.cpp',
|
||||
]
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче