mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	This reverts commit e25a5f344af32bdd689500bae7b4f24f205ba9f0. We believe bug 1664063 was causing to hit some broken device reset handling code. Differential Revision: https://phabricator.services.mozilla.com/D201658
		
			
				
	
	
		
			505 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			505 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 20; 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 "D3D11Checks.h"
 | 
						|
#include "DXVA2Manager.h"
 | 
						|
#include "gfxConfig.h"
 | 
						|
#include "GfxDriverInfo.h"
 | 
						|
#include "gfxWindowsPlatform.h"
 | 
						|
#include "mozilla/Components.h"
 | 
						|
#include "mozilla/RefPtr.h"
 | 
						|
#include "mozilla/StaticPrefs_gfx.h"
 | 
						|
#include "mozilla/StaticPrefs_layers.h"
 | 
						|
#include "mozilla/StaticPrefs_media.h"
 | 
						|
#include "mozilla/gfx/gfxVars.h"
 | 
						|
#include "mozilla/gfx/Logging.h"
 | 
						|
#include "mozilla/layers/TextureD3D11.h"
 | 
						|
#include "nsIGfxInfo.h"
 | 
						|
#include <dxgi.h>
 | 
						|
#include <dxgi1_2.h>
 | 
						|
#include <d3d10_1.h>
 | 
						|
#include <d3d11.h>
 | 
						|
#include <d3d11_1.h>
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace gfx {
 | 
						|
 | 
						|
using namespace mozilla::widget;
 | 
						|
using mozilla::layers::AutoTextureLock;
 | 
						|
 | 
						|
/* 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_NTHANDLE |
 | 
						|
                                   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
 | 
						|
    HRESULT hr;
 | 
						|
    AutoTextureLock lock(keyedMutex, hr, INFINITE);
 | 
						|
    FLOAT color1[4] = {1, 1, 0.5, 1};
 | 
						|
    deviceContext->ClearRenderTargetView(offscreenRTView, color1);
 | 
						|
  }
 | 
						|
 | 
						|
  {
 | 
						|
    HRESULT hr;
 | 
						|
    AutoTextureLock lock(keyedMutex, hr, 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;
 | 
						|
    RefPtr<ID3D11Texture2D> cpuTexture;
 | 
						|
    hr = aDevice->CreateTexture2D(&desc, NULL, getter_AddRefs(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;
 | 
						|
    }
 | 
						|
    uint32_t resultColor = *(uint32_t*)mapped.pData;
 | 
						|
    deviceContext->Unmap(cpuTexture, 0);
 | 
						|
    cpuTexture = nullptr;
 | 
						|
 | 
						|
    // XXX on some drivers resultColor will not have changed to
 | 
						|
    // match the clear
 | 
						|
    if (resultColor != 0xffffff00) {
 | 
						|
      gfxCriticalNote << "RenderTargetViewNeedsRecreating";
 | 
						|
      result = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
/* static */
 | 
						|
bool D3D11Checks::DoesDeviceWork() {
 | 
						|
  static bool checked = false;
 | 
						|
  static bool result = false;
 | 
						|
 | 
						|
  if (checked) return result;
 | 
						|
  checked = true;
 | 
						|
 | 
						|
  if (StaticPrefs::gfx_direct2d_force_enabled_AtStartup() ||
 | 
						|
      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 (size_t 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)) {
 | 
						|
          NS_ConvertUTF16toUTF8 version(displayLinkModuleVersionString);
 | 
						|
          gfxCriticalError(CriticalLog::DefaultOptions(false))
 | 
						|
              << "DisplayLink: too old version " << version.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 (StaticPrefs::gfx_direct2d_force_enabled_AtStartup() ||
 | 
						|
      gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING)) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (GetModuleHandleW(L"atidxx32.dll")) {
 | 
						|
    nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
 | 
						|
    if (gfxInfo) {
 | 
						|
      nsString vendorID, vendorID2;
 | 
						|
      gfxInfo->GetAdapterVendorID(vendorID);
 | 
						|
      gfxInfo->GetAdapterVendorID2(vendorID2);
 | 
						|
      if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
 | 
						|
        if (!StaticPrefs::layers_amd_switchable_gfx_enabled_AtStartup()) {
 | 
						|
          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_NTHANDLE |
 | 
						|
                   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;
 | 
						|
  }
 | 
						|
 | 
						|
  RefPtr<IDXGIResource1> otherResource;
 | 
						|
  if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource1),
 | 
						|
                                     getter_AddRefs(otherResource)))) {
 | 
						|
    gfxCriticalError() << "DoesD3D11TextureSharingWork_GetResourceFailure";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  HANDLE sharedHandle;
 | 
						|
  if (FAILED(otherResource->CreateSharedHandle(
 | 
						|
          nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
 | 
						|
          nullptr, &sharedHandle))) {
 | 
						|
    gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  auto handle = ipc::FileDescriptor(UniqueFileHandle(sharedHandle));
 | 
						|
 | 
						|
  RefPtr<ID3D11Device1> device1;
 | 
						|
  device->QueryInterface((ID3D11Device1**)getter_AddRefs(device1));
 | 
						|
  if (!device1) {
 | 
						|
    gfxCriticalNoteOnce << "Failed to get ID3D11Device1";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  RefPtr<ID3D11Resource> sharedResource;
 | 
						|
  RefPtr<ID3D11Texture2D> sharedTexture;
 | 
						|
  auto raw = handle.TakePlatformHandle();
 | 
						|
  if (FAILED(device1->OpenSharedResource1(raw.get(), __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));
 | 
						|
  {
 | 
						|
    HRESULT hr;
 | 
						|
    AutoTextureLock lock(sharedMutex, hr, 30 * 1000);
 | 
						|
    if (FAILED(hr)) {
 | 
						|
      gfxCriticalError() << "DoesD3D11TextureSharingWork_AcquireSyncTimeout";
 | 
						|
      // only wait for 30 seconds
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // Copy to the cpu texture so that we can readback
 | 
						|
    deviceContext->CopyResource(cpuTexture, sharedTexture);
 | 
						|
 | 
						|
    // We only need to hold on to the mutex during the copy.
 | 
						|
    sharedMutex->ReleaseSync(0);
 | 
						|
  }
 | 
						|
 | 
						|
  D3D11_MAPPED_SUBRESOURCE mapped;
 | 
						|
  uint32_t resultColor = 0;
 | 
						|
  if (SUCCEEDED(
 | 
						|
          deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped))) {
 | 
						|
    // read the texture
 | 
						|
    resultColor = *(uint32_t*)mapped.pData;
 | 
						|
    deviceContext->Unmap(cpuTexture, 0);
 | 
						|
  } else {
 | 
						|
    gfxCriticalError() << "DoesD3D11TextureSharingWork_MapFailed";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // 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 = components::GfxInfo::Service();
 | 
						|
  nsString vendorID;
 | 
						|
  gfxInfo->GetAdapterVendorID(vendorID);
 | 
						|
  nsresult ec;
 | 
						|
  int32_t vendor = vendorID.ToInteger(&ec, 16);
 | 
						|
  if (vendor != static_cast<int32_t>(desc.VendorId)) {
 | 
						|
    gfxCriticalNote << "VendorIDMismatch V " << hexa(vendor) << " "
 | 
						|
                    << hexa(desc.VendorId);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* static */
 | 
						|
bool D3D11Checks::DoesRemotePresentWork(IDXGIAdapter* adapter) {
 | 
						|
  // Remote presentation was added in DXGI 1.2, for Windows 8 and the Platform
 | 
						|
  // Update to Windows 7.
 | 
						|
  RefPtr<IDXGIAdapter2> check;
 | 
						|
  HRESULT hr =
 | 
						|
      adapter->QueryInterface(__uuidof(IDXGIAdapter2), getter_AddRefs(check));
 | 
						|
  return SUCCEEDED(hr) && check;
 | 
						|
}
 | 
						|
 | 
						|
/* static */ D3D11Checks::VideoFormatOptionSet D3D11Checks::FormatOptions(
 | 
						|
    ID3D11Device* device) {
 | 
						|
  auto doesNV12Work = [&]() {
 | 
						|
    if (gfxVars::DXNV12Blocked()) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    DXGI_ADAPTER_DESC desc;
 | 
						|
    PodZero(&desc);
 | 
						|
    if (!GetDxgiDesc(device, &desc)) {
 | 
						|
      // Failed to retrieve device information, assume it doesn't work
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    UINT formatSupport;
 | 
						|
    HRESULT hr = device->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
 | 
						|
    if (FAILED(hr) || !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    nsString version;
 | 
						|
    nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
 | 
						|
    if (gfxInfo) {
 | 
						|
      gfxInfo->GetAdapterDriverVersion(version);
 | 
						|
    }
 | 
						|
    return DXVA2Manager::IsNV12Supported(desc.VendorId, desc.DeviceId, version);
 | 
						|
  };
 | 
						|
 | 
						|
  auto doesP010Work = [&]() {
 | 
						|
    if (gfxVars::DXP010Blocked() &&
 | 
						|
        !StaticPrefs::media_wmf_force_allow_p010_format()) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    UINT formatSupport;
 | 
						|
    HRESULT hr = device->CheckFormatSupport(DXGI_FORMAT_P010, &formatSupport);
 | 
						|
    return (SUCCEEDED(hr) && (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D));
 | 
						|
  };
 | 
						|
 | 
						|
  auto doesP016Work = [&]() {
 | 
						|
    if (gfxVars::DXP016Blocked() &&
 | 
						|
        !StaticPrefs::media_wmf_force_allow_p010_format()) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    UINT formatSupport;
 | 
						|
    HRESULT hr = device->CheckFormatSupport(DXGI_FORMAT_P016, &formatSupport);
 | 
						|
    return (SUCCEEDED(hr) && (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D));
 | 
						|
  };
 | 
						|
 | 
						|
  VideoFormatOptionSet options;
 | 
						|
  if (!doesNV12Work()) {
 | 
						|
    // If the device doesn't support NV12, there's really no point testing for
 | 
						|
    // P010 and P016.
 | 
						|
    return options;
 | 
						|
  }
 | 
						|
  options += VideoFormatOption::NV12;
 | 
						|
  if (doesP010Work()) {
 | 
						|
    options += VideoFormatOption::P010;
 | 
						|
  }
 | 
						|
  if (doesP016Work()) {
 | 
						|
    options += VideoFormatOption::P016;
 | 
						|
  }
 | 
						|
  return options;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace gfx
 | 
						|
}  // namespace mozilla
 |