text: // 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/logging.h"
  #include "base/strings/string_split.h"
  #include "base/strings/string_util.h"
  #include "remoting/host/base/host_exit_codes.h"
  #include "remoting/host/base/switches.h"
  #include "remoting/host/evaluate_capability.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(), &current_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
  