diff --git a/webrtc/modules/desktop_capture/win/d3d_device.cc b/webrtc/modules/desktop_capture/win/d3d_device.cc index 67d1298078..078c0c4295 100644 --- a/webrtc/modules/desktop_capture/win/d3d_device.cc +++ b/webrtc/modules/desktop_capture/win/d3d_device.cc @@ -31,6 +31,7 @@ bool D3dDevice::Initialize(const ComPtr& 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& 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; } diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc index 03dc15aa07..975d7e4770 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc @@ -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(0); + d3d_info_.max_feature_level = static_cast(0); + std::vector 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 { diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h index 1abfe81d92..9d37010551 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h @@ -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 + #include #include @@ -57,6 +59,21 @@ class DxgiDuplicatorController { std::vector 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 duplicators_; + D3dInfo d3d_info_; }; } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc index bbd5c6976f..c30356e575 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc @@ -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) {} diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h index 078bf17892..4677b200ed 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h @@ -13,6 +13,8 @@ #include "webrtc/modules/desktop_capture/screen_capturer.h" +#include + #include #include @@ -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;