summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h
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_duplicator_controller.h
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_duplicator_controller.h')
-rw-r--r--third_party/libwebrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h257
1 files changed, 257 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/third_party/libwebrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h
new file mode 100644
index 0000000000..2b1e0ab041
--- /dev/null
+++ b/third_party/libwebrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h
@@ -0,0 +1,257 @@
+/*
+ * 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.
+ */
+
+#ifndef MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
+#define MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
+
+#include <d3dcommon.h>
+
+#include <atomic>
+#include <string>
+#include <vector>
+
+#include "api/scoped_refptr.h"
+#include "modules/desktop_capture/desktop_geometry.h"
+#include "modules/desktop_capture/shared_desktop_frame.h"
+#include "modules/desktop_capture/win/d3d_device.h"
+#include "modules/desktop_capture/win/display_configuration_monitor.h"
+#include "modules/desktop_capture/win/dxgi_adapter_duplicator.h"
+#include "modules/desktop_capture/win/dxgi_context.h"
+#include "modules/desktop_capture/win/dxgi_frame.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "rtc_base/system/rtc_export.h"
+
+namespace webrtc {
+
+// A controller for all the objects we need to call Windows DirectX capture APIs
+// It's a singleton because only one IDXGIOutputDuplication instance per monitor
+// is allowed per application.
+//
+// Consumers should create a DxgiDuplicatorController::Context and keep it
+// throughout their lifetime, and pass it when calling Duplicate(). Consumers
+// can also call IsSupported() to determine whether the system supports DXGI
+// duplicator or not. If a previous IsSupported() function call returns true,
+// but a later Duplicate() returns false, this usually means the display mode is
+// changing. Consumers should retry after a while. (Typically 50 milliseconds,
+// but according to hardware performance, this time may vary.)
+// The underlying DxgiOutputDuplicators may take an additional reference on the
+// frame passed in to the Duplicate methods so that they can guarantee delivery
+// of new frames when requested; since if there have been no updates to the
+// surface, they may be unable to capture a frame.
+class RTC_EXPORT DxgiDuplicatorController {
+ public:
+ using Context = DxgiFrameContext;
+
+ // A collection of D3d information we are interested in, which may impact
+ // capturer performance or reliability.
+ struct D3dInfo {
+ // Each video adapter has its own D3D_FEATURE_LEVEL, so this structure
+ // contains the minimum and maximium D3D_FEATURE_LEVELs current system
+ // supports.
+ // Both fields can be 0, which is the default value to indicate no valid
+ // D3D_FEATURE_LEVEL has been retrieved from underlying OS APIs.
+ D3D_FEATURE_LEVEL min_feature_level;
+ D3D_FEATURE_LEVEL max_feature_level;
+
+ // TODO(zijiehe): Add more fields, such as manufacturer name, mode, driver
+ // version.
+ };
+
+ // These values are persisted to logs. Entries should not be renumbered or
+ // reordered and numeric values should never be reused. This enum corresponds
+ // to WebRtcDirectXCapturerResult in tools/metrics/histograms/enums.xml.
+ enum class Result {
+ SUCCEEDED = 0,
+ UNSUPPORTED_SESSION = 1,
+ FRAME_PREPARE_FAILED = 2,
+ INITIALIZATION_FAILED = 3,
+ DUPLICATION_FAILED = 4,
+ INVALID_MONITOR_ID = 5,
+ MAX_VALUE = INVALID_MONITOR_ID
+ };
+
+ // Converts `result` into user-friendly string representation. The return
+ // value should not be used to identify error types.
+ static std::string ResultName(Result result);
+
+ // Returns the singleton instance of DxgiDuplicatorController.
+ static rtc::scoped_refptr<DxgiDuplicatorController> Instance();
+
+ // See ScreenCapturerWinDirectx::IsCurrentSessionSupported().
+ static bool IsCurrentSessionSupported();
+
+ // All the following public functions implicitly call Initialize() function.
+
+ // Detects whether the system supports DXGI based capturer.
+ bool IsSupported();
+
+ // Returns a copy of D3dInfo composed by last Initialize() function call. This
+ // function always copies the latest information into `info`. But once the
+ // function returns false, the information in `info` may not accurate.
+ bool RetrieveD3dInfo(D3dInfo* info);
+
+ // Captures current screen and writes into `frame`. May retain a reference to
+ // `frame`'s underlying |SharedDesktopFrame|.
+ // TODO(zijiehe): Windows cannot guarantee the frames returned by each
+ // IDXGIOutputDuplication are synchronized. But we are using a totally
+ // different threading model than the way Windows suggested, it's hard to
+ // synchronize them manually. We should find a way to do it.
+ Result Duplicate(DxgiFrame* frame);
+
+ // Captures one monitor and writes into target. `monitor_id` must be >= 0. If
+ // `monitor_id` is greater than the total screen count of all the Duplicators,
+ // this function returns false. May retain a reference to `frame`'s underlying
+ // |SharedDesktopFrame|.
+ Result DuplicateMonitor(DxgiFrame* frame, int monitor_id);
+
+ // Returns dpi of current system. Returns an empty DesktopVector if system
+ // does not support DXGI based capturer.
+ DesktopVector system_dpi();
+
+ // Returns the count of screens on the system. These screens can be retrieved
+ // by an integer in the range of [0, ScreenCount()). If system does not
+ // support DXGI based capturer, this function returns 0.
+ int ScreenCount();
+
+ // Returns the device names of all screens on the system in utf8 encoding.
+ // These screens can be retrieved by an integer in the range of
+ // [0, output->size()). If system does not support DXGI based capturer, this
+ // function returns false.
+ bool GetDeviceNames(std::vector<std::string>* output);
+
+ private:
+ // DxgiFrameContext calls private Unregister(Context*) function in Reset().
+ friend void DxgiFrameContext::Reset();
+
+ // scoped_refptr<DxgiDuplicatorController> accesses private AddRef() and
+ // Release() functions.
+ friend class rtc::scoped_refptr<DxgiDuplicatorController>;
+
+ // A private constructor to ensure consumers to use
+ // DxgiDuplicatorController::Instance().
+ DxgiDuplicatorController();
+
+ // Not implemented: The singleton DxgiDuplicatorController instance should not
+ // be deleted.
+ ~DxgiDuplicatorController();
+
+ // RefCountedInterface implementations.
+ void AddRef();
+ void Release();
+
+ // Does the real duplication work. Setting `monitor_id` < 0 to capture entire
+ // screen. This function calls Initialize(). And if the duplication failed,
+ // this function calls Deinitialize() to ensure the Dxgi components can be
+ // reinitialized next time.
+ Result DoDuplicate(DxgiFrame* frame, int monitor_id);
+
+ // Unload all the DXGI components and releases the resources. This function
+ // wraps Deinitialize() with `mutex_`.
+ void Unload();
+
+ // Unregisters Context from this instance and all DxgiAdapterDuplicator(s)
+ // it owns.
+ void Unregister(const Context* const context);
+
+ // All functions below should be called in `mutex_` locked scope and should be
+ // after a successful Initialize().
+
+ // If current instance has not been initialized, executes DoInitialize()
+ // function, and returns initialize result. Otherwise directly returns true.
+ // This function may calls Deinitialize() if initialization failed.
+ bool Initialize() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Does the real initialization work, this function should only be called in
+ // Initialize().
+ bool DoInitialize() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Clears all COM components referred to by this instance. So next Duplicate()
+ // call will eventually initialize this instance again.
+ void Deinitialize() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // A helper function to check whether a Context has been expired.
+ bool ContextExpired(const Context* const context) const
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Updates Context if needed.
+ void Setup(Context* context) RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ bool DoDuplicateUnlocked(Context* context,
+ int monitor_id,
+ SharedDesktopFrame* target)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Captures all monitors.
+ bool DoDuplicateAll(Context* context, SharedDesktopFrame* target)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Captures one monitor.
+ bool DoDuplicateOne(Context* context,
+ int monitor_id,
+ SharedDesktopFrame* target)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // The minimum GetNumFramesCaptured() returned by `duplicators_`.
+ int64_t GetNumFramesCaptured() const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Returns a DesktopSize to cover entire `desktop_rect_`.
+ DesktopSize desktop_size() const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Returns the size of one screen. `id` should be >= 0. If system does not
+ // support DXGI based capturer, or `id` is greater than the total screen count
+ // of all the Duplicators, this function returns an empty DesktopRect.
+ DesktopRect ScreenRect(int id) const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ int ScreenCountUnlocked() const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ void GetDeviceNamesUnlocked(std::vector<std::string>* output) const
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Returns the desktop size of the selected screen `monitor_id`. Setting
+ // `monitor_id` < 0 to return the entire screen size.
+ DesktopSize SelectedDesktopSize(int monitor_id) const
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Retries DoDuplicateAll() for several times until GetNumFramesCaptured() is
+ // large enough. Returns false if DoDuplicateAll() returns false, or
+ // GetNumFramesCaptured() has never reached the requirement.
+ // According to http://crbug.com/682112, dxgi capturer returns a black frame
+ // during first several capture attempts.
+ bool EnsureFrameCaptured(Context* context, SharedDesktopFrame* target)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Moves `desktop_rect_` and all underlying `duplicators_`, putting top left
+ // corner of the desktop at (0, 0). This is necessary because DXGI_OUTPUT_DESC
+ // may return negative coordinates. Called from DoInitialize() after all
+ // DxgiAdapterDuplicator and DxgiOutputDuplicator instances are initialized.
+ void TranslateRect() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // The count of references which are now "living".
+ std::atomic_int refcount_;
+
+ // This lock must be locked whenever accessing any of the following objects.
+ Mutex mutex_;
+
+ // A self-incremented integer to compare with the one in Context. It ensures
+ // a Context instance is always initialized after DxgiDuplicatorController.
+ int identity_ RTC_GUARDED_BY(mutex_) = 0;
+ DesktopRect desktop_rect_ RTC_GUARDED_BY(mutex_);
+ DesktopVector system_dpi_ RTC_GUARDED_BY(mutex_);
+ std::vector<DxgiAdapterDuplicator> duplicators_ RTC_GUARDED_BY(mutex_);
+ D3dInfo d3d_info_ RTC_GUARDED_BY(mutex_);
+ DisplayConfigurationMonitor display_configuration_monitor_
+ RTC_GUARDED_BY(mutex_);
+ // A number to indicate how many successful duplications have been performed.
+ uint32_t succeeded_duplications_ RTC_GUARDED_BY(mutex_) = 0;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_