Commit 12d3490b authored by Zijie He's avatar Zijie He Committed by Commit Bot

Use EvaluateCapability() to execute D3D check

This change adds EvaluateD3D() function to evaluate the D3D capability of the
host, which is used by HostAttributes. If the binary crashes, or DXGI components
cannot be initialized, No-DirectX-Capturer will be added to the host attributes.
So client can decide to let the host opt-out the experiment.

Bug: 741926
Change-Id: I48f842790b6e016efa541ab767b12d4d0e67edb6
Reviewed-on: https://chromium-review.googlesource.com/592996
Commit-Queue: Zijie He <zijiehe@chromium.org>
Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491215}
parent c330ec66
......@@ -8,6 +8,11 @@
#include <utility>
#include "base/optional.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "remoting/host/win/evaluate_d3d.h"
#endif
namespace remoting {
......@@ -40,7 +45,14 @@ DesktopEnvironmentOptions::operator=(
void DesktopEnvironmentOptions::Initialize() {
desktop_capture_options_.set_detect_updated_region(true);
#if defined (OS_WIN)
desktop_capture_options_.set_allow_directx_capturer(true);
// Whether DirectX capturer can be enabled depends on various facts, include
// also how many applications are using related APIs. WebRTC/DesktopCapturer
// will take care of all the details. So the check here only ensures it won't
// crash the binary: GetD3DCapability() returns false only when the binary
// crashes.
if (GetD3DCapability()) {
desktop_capture_options_.set_allow_directx_capturer(true);
}
#endif
}
......
......@@ -18,6 +18,10 @@
#include "remoting/host/ipc_constants.h"
#include "remoting/host/switches.h"
#if defined(OS_WIN)
#include "remoting/host/win/evaluate_d3d.h"
#endif
namespace remoting {
namespace {
......@@ -117,6 +121,11 @@ int EvaluateCapabilityLocally(const std::string& type) {
if (type == kEvaluateForward) {
return EvaluateForward();
}
#if defined(OS_WIN)
if (type == kEvaluateD3D) {
return EvaluateD3D();
}
#endif
return kInvalidCommandLineExitCode;
}
......
......@@ -4,7 +4,9 @@
#include "remoting/host/host_attributes.h"
#include <string>
#include <type_traits>
#include <vector>
#include "base/atomicops.h"
#include "base/logging.h"
......@@ -14,11 +16,8 @@
#include "build/build_config.h"
#if defined(OS_WIN)
#include <D3DCommon.h>
#include "base/win/windows_version.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"
#include "remoting/host/win/evaluate_d3d.h"
#endif
namespace remoting {
......@@ -89,7 +88,7 @@ static constexpr Attribute kAttributes[] = {
static_assert(std::is_pod<Attribute>::value, "Attribute should be POD.");
std::string GetHostAttributes() {
std::vector<base::StringPiece> result;
std::vector<std::string> result;
// By using ranged for-loop, MSVC throws error C3316:
// 'const remoting::StaticAttribute [0]':
// an array of unknown size cannot be used in a range-based for statement.
......@@ -102,17 +101,7 @@ std::string GetHostAttributes() {
}
#if defined(OS_WIN)
{
webrtc::DxgiDuplicatorController::D3dInfo info;
webrtc::ScreenCapturerWinDirectx::RetrieveD3dInfo(&info);
if (info.min_feature_level >= D3D_FEATURE_LEVEL_10_0) {
result.push_back("MinD3DGT10");
}
if (info.min_feature_level >= D3D_FEATURE_LEVEL_11_0) {
result.push_back("MinD3DGT11");
}
if (info.min_feature_level >= D3D_FEATURE_LEVEL_12_0) {
result.push_back("MinD3DGT12");
}
GetD3DCapability(&result);
auto version = base::win::GetVersion();
if (version >= base::win::VERSION_WIN8) {
......
......@@ -13,6 +13,8 @@ namespace remoting {
// vary if any system configurations change. So consumers should not cache the
// result.
// This function is thread-safe.
// Note, this is not a cheap call on Windows: it spawns a new process to
// retrieve some of the attributes.
std::string GetHostAttributes();
} // namespace remoting
......
......@@ -8,6 +8,7 @@
#include <vector>
#include "base/strings/string_split.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace remoting {
......@@ -32,4 +33,13 @@ TEST(HostAttributesTest, NoDuplicateKeys) {
}
}
#if defined(OS_WIN)
TEST(HostAttributesTest, D3DInfoAreIncluded) {
std::string result = GetHostAttributes();
if (result.find("MinD3D") == std::string::npos) {
ASSERT_NE(result.find("No-DirectX-Capturer"), std::string::npos);
}
}
#endif
} // namespace remoting
......@@ -4,6 +4,8 @@
#include "remoting/host/switches.h"
#include "build/build_config.h"
namespace remoting {
const char kElevateSwitchName[] = "elevate";
......@@ -25,6 +27,10 @@ const char kEvaluateTest[] = "test";
const char kEvaluateCrash[] = "crash";
const char kEvaluateForward[] = "forward";
#if defined(OS_WIN)
const char kEvaluateD3D[] = "d3d-support";
#endif
const char kParentWindowSwitchName[] = "parent-window";
const char kInputSwitchName[] = "input";
......
......@@ -5,6 +5,8 @@
#ifndef REMOTING_HOST_SWITCHES_H_
#define REMOTING_HOST_SWITCHES_H_
#include "build/build_config.h"
namespace remoting {
// "--elevate=<binary>" requests |binary| to be launched elevated (possibly
......@@ -42,6 +44,11 @@ extern const char kEvaluateCrash[];
// Executes EvaluateForward() function, this is for test purpose only.
extern const char kEvaluateForward[];
#if defined(OS_WIN)
// Executes EvaluateD3D() function.
extern const char kEvaluateD3D[];
#endif
// Used to pass the HWND for the parent process to a child process.
extern const char kParentWindowSwitchName[];
......
......@@ -81,6 +81,8 @@ source_set("win") {
"com_security.h",
"default_audio_device_change_detector.cc",
"default_audio_device_change_detector.h",
"evaluate_d3d.cc",
"evaluate_d3d.h",
"launch_process_with_token.cc",
"launch_process_with_token.h",
"omaha.cc",
......
// 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 "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 GetD3DCapability(std::vector<std::string>* result /* = nullptr */) {
std::string d3d_info;
if (EvaluateCapability(kEvaluateD3D, &d3d_info) != kSuccessExitCode) {
if (result) {
result->push_back(kNoDirectXCapturer);
}
return false;
}
if (result) {
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;
}
} // namespace remoting
// 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.
#ifndef REMOTING_HOST_WIN_EVALUATE_D3D_H_
#define REMOTING_HOST_WIN_EVALUATE_D3D_H_
#include <string>
#include <vector>
namespace remoting {
// Evaluates the D3D capability of the system and outputs the results into
// stdout.
// DO NOT call this method within the host process. Only call in an isolated
// child process. I.e. from EvaluateCapabilityLocally().
int EvaluateD3D();
// Evaluates the D3D capability of the system in a separate process. Returns
// true if the process succeeded. The capabilities will be stored in |result| if
// it's not nullptr.
// Note, this is not a cheap call, it uses EvaluateCapability() internally to
// spawn a new process, which may take a noticeable amount of time.
bool GetD3DCapability(std::vector<std::string>* result = nullptr);
} // namespace remoting
#endif // REMOTING_HOST_WIN_EVALUATE_D3D_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment