Current DirectX capturer cannot capture multiple video cards or monitors. But according to DXGI desktop duplication sample (https://goo.gl/An0L9l), we can capture multiple video cards and monitors by duplicating them one by one. So instead of one IDXGIOutputDuplication instance, this change creates an IDXGIOutputDuplication instance for each monitor, and merge the output into one DesktopFrame. Several other changes are also included, 1. Add supports to DXGI_OUTDUPL_DESC.DesktopImageInSystemMemory. When this flag is true, we won't copy its content to staging buffer. 2. Capture one monitor instead of entire screen. Above changes make the logic complex. But with some refactor work, the logic is not disordered. Please refer to the doc @ https://goo.gl/hU1ifG. BUG=314516 Review-Url: https://codereview.webrtc.org/2099123002 Cr-Commit-Position: refs/heads/master@{#13684}
94 lines
3.0 KiB
C++
94 lines
3.0 KiB
C++
/*
|
|
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/modules/desktop_capture/win/d3d_device.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "webrtc/system_wrappers/include/logging.h"
|
|
|
|
namespace webrtc {
|
|
|
|
using Microsoft::WRL::ComPtr;
|
|
|
|
D3dDevice::D3dDevice() = default;
|
|
D3dDevice::~D3dDevice() = default;
|
|
|
|
bool D3dDevice::Initialize(const ComPtr<IDXGIAdapter>& adapter) {
|
|
dxgi_adapter_ = adapter;
|
|
if (!dxgi_adapter_) {
|
|
LOG(LS_WARNING) << "An empty IDXGIAdapter instance has been received.";
|
|
return false;
|
|
}
|
|
|
|
D3D_FEATURE_LEVEL feature_level;
|
|
_com_error error = D3D11CreateDevice(
|
|
adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
|
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_SINGLETHREADED,
|
|
nullptr, 0, D3D11_SDK_VERSION, d3d_device_.GetAddressOf(), &feature_level,
|
|
context_.GetAddressOf());
|
|
if (error.Error() != S_OK || !d3d_device_ || !context_) {
|
|
LOG(LS_WARNING) << "D3D11CreateDeivce returns error "
|
|
<< error.ErrorMessage() << " with code " << error.Error();
|
|
return false;
|
|
}
|
|
|
|
if (feature_level < D3D_FEATURE_LEVEL_11_0) {
|
|
LOG(LS_WARNING) << "D3D11CreateDevice returns an instance without DirectX "
|
|
"11 support, level "
|
|
<< feature_level;
|
|
return false;
|
|
}
|
|
|
|
error = _com_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";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// static
|
|
std::vector<D3dDevice> D3dDevice::EnumDevices() {
|
|
ComPtr<IDXGIFactory1> factory;
|
|
_com_error error = _com_error(
|
|
CreateDXGIFactory1(__uuidof(IDXGIFactory1),
|
|
reinterpret_cast<void**>(factory.GetAddressOf())));
|
|
if (error.Error() != S_OK || !factory) {
|
|
return std::vector<D3dDevice>();
|
|
}
|
|
|
|
std::vector<D3dDevice> result;
|
|
for (int i = 0;; i++) {
|
|
ComPtr<IDXGIAdapter> adapter;
|
|
error = _com_error(factory->EnumAdapters(i, adapter.GetAddressOf()));
|
|
if (error.Error() == S_OK) {
|
|
D3dDevice device;
|
|
if (!device.Initialize(adapter)) {
|
|
return std::vector<D3dDevice>();
|
|
}
|
|
result.push_back(std::move(device));
|
|
} else if (error.Error() == DXGI_ERROR_NOT_FOUND) {
|
|
break;
|
|
} else {
|
|
LOG(LS_WARNING) << "IDXGIFactory1::EnumAdapters returns an unexpected "
|
|
"error "
|
|
<< error.ErrorMessage() << " with code " << error.Error();
|
|
return std::vector<D3dDevice>();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace webrtc
|