| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/host/win/evaluate_d3d.h" |
| |
| #include <D3DCommon.h> |
| |
| #include <iostream> |
| |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| #include "remoting/host/evaluate_capability.h" |
| #include "remoting/host/host_exit_codes.h" |
| #include "remoting/host/switches.h" |
| #include "remoting/host/win/evaluate_3d_display_mode.h" |
| #include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h" |
| #include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" |
| |
| namespace remoting { |
| |
| namespace { |
| |
| constexpr char kNoDirectXCapturer[] = "No-DirectX-Capturer"; |
| |
| } // namespace |
| |
| int EvaluateD3D() { |
| // Creates a capturer instance to avoid the DxgiDuplicatorController to be |
| // initialized and deinitialized for each static call to |
| // webrtc::ScreenCapturerWinDirectx below. |
| webrtc::ScreenCapturerWinDirectx capturer; |
| |
| if (webrtc::ScreenCapturerWinDirectx::IsSupported()) { |
| // Guaranteed to work. |
| // This string is also hard-coded in host_attributes_unittests.cc. |
| std::cout << "DirectX-Capturer" << std::endl; |
| } else if (webrtc::ScreenCapturerWinDirectx::IsCurrentSessionSupported()) { |
| // If we are in a supported session, but DirectX capturer is not able to be |
| // initialized. Something must be wrong, we should actively disable it. |
| std::cout << kNoDirectXCapturer << std::endl; |
| } |
| |
| webrtc::DxgiDuplicatorController::D3dInfo info; |
| webrtc::ScreenCapturerWinDirectx::RetrieveD3dInfo(&info); |
| if (info.min_feature_level < D3D_FEATURE_LEVEL_10_0) { |
| std::cout << "MinD3DLT10" << std::endl; |
| } else { |
| std::cout << "MinD3DGE10" << std::endl; |
| } |
| if (info.min_feature_level >= D3D_FEATURE_LEVEL_11_0) { |
| std::cout << "MinD3DGE11" << std::endl; |
| } |
| if (info.min_feature_level >= D3D_FEATURE_LEVEL_12_0) { |
| std::cout << "MinD3DGE12" << std::endl; |
| } |
| |
| return kSuccessExitCode; |
| } |
| |
| bool BlockD3DCheck() { |
| DWORD console_session = WTSGetActiveConsoleSessionId(); |
| DWORD current_session = 0; |
| if (!ProcessIdToSessionId(GetCurrentProcessId(), ¤t_session)) { |
| PLOG(WARNING) << "ProcessIdToSessionId failed: "; |
| } |
| |
| // Session 0 is not curtained as it does not have an interactive desktop. |
| bool is_curtained_session = |
| current_session != 0 && current_session != console_session; |
| |
| // Skip D3D checks if we are in a curtained session and 3D Display mode is |
| // enabled. Attempting to create a D3D device in this scenario takes a long |
| // time which often results in the user being disconnected due to timeouts. |
| // After digging in, it looks like the call to D3D11CreateDevice() is spinning |
| // while enumerating the display drivers. There isn't a simple fix for this |
| // so instead we should skip the D3D caps check and any other D3D related |
| // calls. This will mean falling back to the GDI capturer. |
| return is_curtained_session && Get3dDisplayModeEnabled(); |
| } |
| |
| bool GetD3DCapabilities(std::vector<std::string>* result) { |
| if (BlockD3DCheck()) { |
| result->push_back(kNoDirectXCapturer); |
| return false; |
| } |
| |
| std::string d3d_info; |
| if (EvaluateCapability(kEvaluateD3D, &d3d_info) != kSuccessExitCode) { |
| result->push_back(kNoDirectXCapturer); |
| return false; |
| } |
| |
| auto capabilities = |
| base::SplitString(d3d_info, base::kWhitespaceASCII, base::TRIM_WHITESPACE, |
| base::SPLIT_WANT_NONEMPTY); |
| for (const auto& capability : capabilities) { |
| result->push_back(capability); |
| } |
| |
| return true; |
| } |
| |
| bool IsD3DAvailable() { |
| if (BlockD3DCheck()) |
| return false; |
| |
| std::string unused; |
| return (EvaluateCapability(kEvaluateD3D, &unused) == kSuccessExitCode); |
| } |
| |
| } // namespace remoting |