summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc')
-rw-r--r--third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc185
1 files changed, 185 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc b/third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
new file mode 100644
index 0000000000..88ec4e25bf
--- /dev/null
+++ b/third_party/libwebrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
@@ -0,0 +1,185 @@
+/*
+ * 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 "modules/desktop_capture/win/dxgi_adapter_duplicator.h"
+
+#include <comdef.h>
+#include <dxgi.h>
+
+#include <algorithm>
+
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+using Microsoft::WRL::ComPtr;
+
+namespace {
+
+bool IsValidRect(const RECT& rect) {
+ return rect.right > rect.left && rect.bottom > rect.top;
+}
+
+} // namespace
+
+DxgiAdapterDuplicator::DxgiAdapterDuplicator(const D3dDevice& device)
+ : device_(device) {}
+DxgiAdapterDuplicator::DxgiAdapterDuplicator(DxgiAdapterDuplicator&&) = default;
+DxgiAdapterDuplicator::~DxgiAdapterDuplicator() = default;
+
+bool DxgiAdapterDuplicator::Initialize() {
+ if (DoInitialize()) {
+ return true;
+ }
+ duplicators_.clear();
+ return false;
+}
+
+bool DxgiAdapterDuplicator::DoInitialize() {
+ for (int i = 0;; i++) {
+ ComPtr<IDXGIOutput> output;
+ _com_error error =
+ device_.dxgi_adapter()->EnumOutputs(i, output.GetAddressOf());
+ if (error.Error() == DXGI_ERROR_NOT_FOUND) {
+ break;
+ }
+
+ if (error.Error() == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
+ RTC_LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returned "
+ << "NOT_CURRENTLY_AVAILABLE. This may happen when "
+ << "running in session 0.";
+ break;
+ }
+
+ if (error.Error() != S_OK || !output) {
+ RTC_LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returned an unexpected "
+ << "result: "
+ << desktop_capture::utils::ComErrorToString(error);
+ continue;
+ }
+
+ DXGI_OUTPUT_DESC desc;
+ error = output->GetDesc(&desc);
+ if (error.Error() == S_OK) {
+ if (desc.AttachedToDesktop && IsValidRect(desc.DesktopCoordinates)) {
+ ComPtr<IDXGIOutput1> output1;
+ error = output.As(&output1);
+ if (error.Error() != S_OK || !output1) {
+ RTC_LOG(LS_WARNING)
+ << "Failed to convert IDXGIOutput to IDXGIOutput1, this usually "
+ << "means the system does not support DirectX 11";
+ continue;
+ }
+ DxgiOutputDuplicator duplicator(device_, output1, desc);
+ if (!duplicator.Initialize()) {
+ RTC_LOG(LS_WARNING) << "Failed to initialize DxgiOutputDuplicator on "
+ << "output " << i;
+ continue;
+ }
+
+ duplicators_.push_back(std::move(duplicator));
+ desktop_rect_.UnionWith(duplicators_.back().desktop_rect());
+ } else {
+ RTC_LOG(LS_ERROR) << (desc.AttachedToDesktop ? "Attached" : "Detached")
+ << " output " << i << " ("
+ << desc.DesktopCoordinates.top << ", "
+ << desc.DesktopCoordinates.left << ") - ("
+ << desc.DesktopCoordinates.bottom << ", "
+ << desc.DesktopCoordinates.right << ") is ignored.";
+ }
+ } else {
+ RTC_LOG(LS_WARNING) << "Failed to get output description of device " << i
+ << ", ignore.";
+ }
+ }
+
+ if (duplicators_.empty()) {
+ RTC_LOG(LS_WARNING)
+ << "Cannot initialize any DxgiOutputDuplicator instance.";
+ }
+
+ return !duplicators_.empty();
+}
+
+void DxgiAdapterDuplicator::Setup(Context* context) {
+ RTC_DCHECK(context->contexts.empty());
+ context->contexts.resize(duplicators_.size());
+ for (size_t i = 0; i < duplicators_.size(); i++) {
+ duplicators_[i].Setup(&context->contexts[i]);
+ }
+}
+
+void DxgiAdapterDuplicator::Unregister(const Context* const context) {
+ RTC_DCHECK_EQ(context->contexts.size(), duplicators_.size());
+ for (size_t i = 0; i < duplicators_.size(); i++) {
+ duplicators_[i].Unregister(&context->contexts[i]);
+ }
+}
+
+bool DxgiAdapterDuplicator::Duplicate(Context* context,
+ SharedDesktopFrame* target) {
+ RTC_DCHECK_EQ(context->contexts.size(), duplicators_.size());
+ for (size_t i = 0; i < duplicators_.size(); i++) {
+ if (!duplicators_[i].Duplicate(&context->contexts[i],
+ duplicators_[i].desktop_rect().top_left(),
+ target)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DxgiAdapterDuplicator::DuplicateMonitor(Context* context,
+ int monitor_id,
+ SharedDesktopFrame* target) {
+ RTC_DCHECK_GE(monitor_id, 0);
+ RTC_DCHECK_LT(monitor_id, duplicators_.size());
+ RTC_DCHECK_EQ(context->contexts.size(), duplicators_.size());
+ return duplicators_[monitor_id].Duplicate(&context->contexts[monitor_id],
+ DesktopVector(), target);
+}
+
+DesktopRect DxgiAdapterDuplicator::ScreenRect(int id) const {
+ RTC_DCHECK_GE(id, 0);
+ RTC_DCHECK_LT(id, duplicators_.size());
+ return duplicators_[id].desktop_rect();
+}
+
+const std::string& DxgiAdapterDuplicator::GetDeviceName(int id) const {
+ RTC_DCHECK_GE(id, 0);
+ RTC_DCHECK_LT(id, duplicators_.size());
+ return duplicators_[id].device_name();
+}
+
+int DxgiAdapterDuplicator::screen_count() const {
+ return static_cast<int>(duplicators_.size());
+}
+
+int64_t DxgiAdapterDuplicator::GetNumFramesCaptured() const {
+ int64_t min = INT64_MAX;
+ for (const auto& duplicator : duplicators_) {
+ min = std::min(min, duplicator.num_frames_captured());
+ }
+
+ return min;
+}
+
+void DxgiAdapterDuplicator::TranslateRect(const DesktopVector& position) {
+ desktop_rect_.Translate(position);
+ RTC_DCHECK_GE(desktop_rect_.left(), 0);
+ RTC_DCHECK_GE(desktop_rect_.top(), 0);
+ for (auto& duplicator : duplicators_) {
+ duplicator.TranslateRect(position);
+ }
+}
+
+} // namespace webrtc