1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/host/win/evaluate_d3d.h" 6 7 #include <D3DCommon.h> 8 9 #include <iostream> 10 11 #include "base/logging.h" 12 #include "base/strings/string_split.h" 13 #include "base/strings/string_util.h" 14 #include "remoting/host/evaluate_capability.h" 15 #include "remoting/host/host_exit_codes.h" 16 #include "remoting/host/switches.h" 17 #include "remoting/host/win/evaluate_3d_display_mode.h" 18 #include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h" 19 #include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" 20 21 namespace remoting { 22 23 namespace { 24 25 constexpr char kNoDirectXCapturer[] = "No-DirectX-Capturer"; 26 27 } // namespace 28 EvaluateD3D()29int EvaluateD3D() { 30 // Creates a capturer instance to avoid the DxgiDuplicatorController to be 31 // initialized and deinitialized for each static call to 32 // webrtc::ScreenCapturerWinDirectx below. 33 webrtc::ScreenCapturerWinDirectx capturer; 34 35 if (webrtc::ScreenCapturerWinDirectx::IsSupported()) { 36 // Guaranteed to work. 37 // This string is also hard-coded in host_attributes_unittests.cc. 38 std::cout << "DirectX-Capturer" << std::endl; 39 } else if (webrtc::ScreenCapturerWinDirectx::IsCurrentSessionSupported()) { 40 // If we are in a supported session, but DirectX capturer is not able to be 41 // initialized. Something must be wrong, we should actively disable it. 42 std::cout << kNoDirectXCapturer << std::endl; 43 } 44 45 webrtc::DxgiDuplicatorController::D3dInfo info; 46 webrtc::ScreenCapturerWinDirectx::RetrieveD3dInfo(&info); 47 if (info.min_feature_level < D3D_FEATURE_LEVEL_10_0) { 48 std::cout << "MinD3DLT10" << std::endl; 49 } else { 50 std::cout << "MinD3DGE10" << std::endl; 51 } 52 if (info.min_feature_level >= D3D_FEATURE_LEVEL_11_0) { 53 std::cout << "MinD3DGE11" << std::endl; 54 } 55 if (info.min_feature_level >= D3D_FEATURE_LEVEL_12_0) { 56 std::cout << "MinD3DGE12" << std::endl; 57 } 58 59 return kSuccessExitCode; 60 } 61 BlockD3DCheck()62bool BlockD3DCheck() { 63 DWORD console_session = WTSGetActiveConsoleSessionId(); 64 DWORD current_session = 0; 65 if (!ProcessIdToSessionId(GetCurrentProcessId(), ¤t_session)) { 66 PLOG(WARNING) << "ProcessIdToSessionId failed: "; 67 } 68 69 // Session 0 is not curtained as it does not have an interactive desktop. 70 bool is_curtained_session = 71 current_session != 0 && current_session != console_session; 72 73 // Skip D3D checks if we are in a curtained session and 3D Display mode is 74 // enabled. Attempting to create a D3D device in this scenario takes a long 75 // time which often results in the user being disconnected due to timeouts. 76 // After digging in, it looks like the call to D3D11CreateDevice() is spinning 77 // while enumerating the display drivers. There isn't a simple fix for this 78 // so instead we should skip the D3D caps check and any other D3D related 79 // calls. This will mean falling back to the GDI capturer. 80 return is_curtained_session && Get3dDisplayModeEnabled(); 81 } 82 GetD3DCapabilities(std::vector<std::string> * result)83bool GetD3DCapabilities(std::vector<std::string>* result) { 84 if (BlockD3DCheck()) { 85 result->push_back(kNoDirectXCapturer); 86 return false; 87 } 88 89 std::string d3d_info; 90 if (EvaluateCapability(kEvaluateD3D, &d3d_info) != kSuccessExitCode) { 91 result->push_back(kNoDirectXCapturer); 92 return false; 93 } 94 95 auto capabilities = 96 base::SplitString(d3d_info, base::kWhitespaceASCII, base::TRIM_WHITESPACE, 97 base::SPLIT_WANT_NONEMPTY); 98 for (const auto& capability : capabilities) { 99 result->push_back(capability); 100 } 101 102 return true; 103 } 104 IsD3DAvailable()105bool IsD3DAvailable() { 106 if (BlockD3DCheck()) 107 return false; 108 109 std::string unused; 110 return (EvaluateCapability(kEvaluateD3D, &unused) == kSuccessExitCode); 111 } 112 113 } // namespace remoting 114