Remove the requirement of D3D_FEATURE_LEVEL_11_0, but export the D3D_FEATURE_LEVEL through APIs

D3D_FEATURE_LEVEL_11_0 is not offically documented on MSDN to be a requirement
of DXGI duplicator APIs. So instead of using D3D_FEATURE_LEVEL_11_0 as a
requirement in D3dDevice::Initialize(), this change adds a
ScreenCapturerWinDirectx::SupportedFeatureLevel() function to retrieves minimum
and maximium for further reference (in HostTraits to control the experiment).

BUG=314516

Review-Url: https://codereview.webrtc.org/2468083002
Cr-Commit-Position: refs/heads/master@{#14962}
This commit is contained in:
zijiehe 2016-11-07 18:35:15 -08:00 committed by Commit bot
parent 6f601afcf4
commit 556f49d6b6
5 changed files with 78 additions and 7 deletions

View File

@ -31,6 +31,7 @@ bool D3dDevice::Initialize(const ComPtr<IDXGIAdapter>& adapter) {
}
D3D_FEATURE_LEVEL feature_level;
// Default feature levels contain D3D 9.1 through D3D 11.0.
_com_error error = D3D11CreateDevice(
adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_SINGLETHREADED,
@ -44,16 +45,18 @@ bool D3dDevice::Initialize(const ComPtr<IDXGIAdapter>& adapter) {
if (feature_level < D3D_FEATURE_LEVEL_11_0) {
LOG(LS_WARNING) << "D3D11CreateDevice returns an instance without DirectX "
"11 support, level "
<< feature_level;
return false;
"11 support, level " << feature_level
<< ". Following initialization may fail.";
// D3D_FEATURE_LEVEL_11_0 is not officially documented on MSDN to be a
// requirement of Dxgi duplicator APIs.
}
error = d3d_device_.As(&dxgi_device_);
if (error.Error() != S_OK || !dxgi_device_) {
LOG(LS_WARNING) << "ID3D11Device is not an implementation of IDXGIDevice, "
"this usually means the system does not support DirectX "
"11";
"11. Error "
<< error.ErrorMessage() << " with code " << error.Error();
return false;
}

View File

@ -44,6 +44,15 @@ bool DxgiDuplicatorController::IsSupported() {
return Initialize();
}
bool DxgiDuplicatorController::RetrieveD3dInfo(D3dInfo* info) {
rtc::CritScope lock(&lock_);
if (!Initialize()) {
return false;
}
*info = d3d_info_;
return true;
}
DesktopVector DxgiDuplicatorController::dpi() {
rtc::CritScope lock(&lock_);
if (Initialize()) {
@ -121,6 +130,9 @@ bool DxgiDuplicatorController::DoInitialize() {
RTC_DCHECK(desktop_rect_.is_empty());
RTC_DCHECK(duplicators_.empty());
d3d_info_.min_feature_level = static_cast<D3D_FEATURE_LEVEL>(0);
d3d_info_.max_feature_level = static_cast<D3D_FEATURE_LEVEL>(0);
std::vector<D3dDevice> devices = D3dDevice::EnumDevices();
if (devices.empty()) {
return false;
@ -131,6 +143,18 @@ bool DxgiDuplicatorController::DoInitialize() {
if (!duplicators_.back().Initialize()) {
return false;
}
D3D_FEATURE_LEVEL feature_level =
devices[i].d3d_device()->GetFeatureLevel();
if (d3d_info_.max_feature_level == 0 ||
feature_level > d3d_info_.max_feature_level) {
d3d_info_.max_feature_level = feature_level;
}
if (d3d_info_.min_feature_level == 0 ||
feature_level < d3d_info_.min_feature_level) {
d3d_info_.min_feature_level = feature_level;
}
if (desktop_rect_.is_empty()) {
desktop_rect_ = duplicators_.back().desktop_rect();
} else {

View File

@ -11,6 +11,8 @@
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
#include <D3DCommon.h>
#include <memory>
#include <vector>
@ -57,6 +59,21 @@ class DxgiDuplicatorController {
std::vector<DxgiAdapterDuplicator::Context> contexts_;
};
// A collection of D3d information we are interested on, which may impact
// capturer performance or reliability.
struct D3dInfo {
// Each video adapter has its own D3D_FEATURE_LEVEL, so this structure
// contains the minimum and maximium D3D_FEATURE_LEVELs current system
// supports.
// Both fields can be 0, which is the default value to indicate no valid
// D3D_FEATURE_LEVEL has been retrieved from underlying OS APIs.
D3D_FEATURE_LEVEL min_feature_level;
D3D_FEATURE_LEVEL max_feature_level;
// TODO(zijiehe): Add more fields, such as manufacturer name, mode, driver
// version.
};
// Returns the singleton instance of DxgiDuplicatorController.
static DxgiDuplicatorController* Instance();
@ -64,9 +81,15 @@ class DxgiDuplicatorController {
// containers are destructed in correct order.
~DxgiDuplicatorController();
// All the following functions implicitly call Initialize() function is
// current instance has not been initialized.
// Detects whether the system supports DXGI based capturer.
bool IsSupported();
// Returns a copy of D3dInfo composed by last Initialize() function call.
bool RetrieveD3dInfo(D3dInfo* info);
// Captures current screen and writes into target. Since we are using double
// buffering, |last_frame|.updated_region() is used to represent the not
// updated regions in current |target| frame, which should also be copied this
@ -153,6 +176,7 @@ class DxgiDuplicatorController {
DesktopRect desktop_rect_;
DesktopVector dpi_;
std::vector<DxgiAdapterDuplicator> duplicators_;
D3dInfo d3d_info_;
};
} // namespace webrtc

View File

@ -23,10 +23,17 @@ using Microsoft::WRL::ComPtr;
// static
bool ScreenCapturerWinDirectx::IsSupported() {
// Forward IsSupported function call to DxgiDuplicatorController.
// Forwards IsSupported() function call to DxgiDuplicatorController.
return DxgiDuplicatorController::Instance()->IsSupported();
}
// static
bool ScreenCapturerWinDirectx::RetrieveD3dInfo(D3dInfo* info) {
// Forwards SupportedFeatureLevels() function call to
// DxgiDuplicatorController.
return DxgiDuplicatorController::Instance()->RetrieveD3dInfo(info);
}
ScreenCapturerWinDirectx::ScreenCapturerWinDirectx(
const DesktopCaptureOptions& options)
: callback_(nullptr) {}

View File

@ -13,6 +13,8 @@
#include "webrtc/modules/desktop_capture/screen_capturer.h"
#include <D3DCommon.h>
#include <memory>
#include <vector>
@ -24,13 +26,24 @@
namespace webrtc {
// ScreenCapturerWinDirectx captures 32bit RGBA using DirectX. This
// implementation won't work when ScreenCaptureFrameQueue.kQueueLength is not 2.
// ScreenCapturerWinDirectx captures 32bit RGBA using DirectX.
class ScreenCapturerWinDirectx : public ScreenCapturer {
public:
using D3dInfo = DxgiDuplicatorController::D3dInfo;
// Whether the system supports DirectX based capturing.
static bool IsSupported();
// Returns a most recent D3dInfo composed by
// DxgiDuplicatorController::Initialize() function. This function implicitly
// calls DxgiDuplicatorController::Initialize() if it has not been
// initialized. This function returns false and output parameter is kept
// unchanged if DxgiDuplicatorController::Initialize() failed.
// The D3dInfo may change based on hardware configuration even without
// restarting the hardware and software. Refer to https://goo.gl/OOCppq. So
// consumers should not cache the result returned by this function.
static bool RetrieveD3dInfo(D3dInfo* info);
explicit ScreenCapturerWinDirectx(const DesktopCaptureOptions& options);
~ScreenCapturerWinDirectx() override;