From 049ec71e657eef3d15e0f15d60acb1a71e81b521 Mon Sep 17 00:00:00 2001 From: zijiehe Date: Fri, 28 Apr 2017 13:43:28 -0700 Subject: [PATCH] Allow Windows to return a monitor out of the first quadrant Windows may return a DesktopCoordinate out of the first quadrant (x >= 0 && y >= 0), this typically happens when the primary and secondary monitors are swapped. i.e. The secondary monitor is on the left but the primary one is on the right. This change "moves" the entire screen from any quadrant to the (0, 0), so we can capture the monitors in other quadrants. BUG=chromium:715689 Review-Url: https://codereview.webrtc.org/2848443004 Cr-Commit-Position: refs/heads/master@{#17935} --- .../desktop_capture/win/dxgi_adapter_duplicator.cc | 11 +++++++++-- .../desktop_capture/win/dxgi_adapter_duplicator.h | 4 ++++ .../win/dxgi_duplicator_controller.cc | 12 +++++++++++- .../desktop_capture/win/dxgi_duplicator_controller.h | 10 +++++++--- .../desktop_capture/win/dxgi_output_duplicator.cc | 7 ++++++- .../desktop_capture/win/dxgi_output_duplicator.h | 5 ++++- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc index caef1c2ca7..5947daf5dc 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc @@ -25,8 +25,7 @@ using Microsoft::WRL::ComPtr; namespace { bool IsValidRect(const RECT& rect) { - return rect.left >= 0 && rect.top >= 0 && rect.right > rect.left && - rect.bottom > rect.top; + return rect.right > rect.left && rect.bottom > rect.top; } } // namespace @@ -153,4 +152,12 @@ int64_t DxgiAdapterDuplicator::GetNumFramesCaptured() const { return min; } +void DxgiAdapterDuplicator::TranslateRect(const DesktopVector& position) { + desktop_rect_.Translate(position); + RTC_DCHECK(desktop_rect_.left() >= 0 && desktop_rect_.top() >= 0); + for (auto& duplicator : duplicators_) { + duplicator.TranslateRect(position); + } +} + } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h index 4aee8b85b0..cf33353f22 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h +++ b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h @@ -71,6 +71,10 @@ class DxgiAdapterDuplicator { // The minimum num_frames_captured() returned by |duplicators_|. int64_t GetNumFramesCaptured() const; + // Moves |desktop_rect_| and all underlying |duplicators_|. See + // DxgiDuplicatorController::TranslateRect(). + void TranslateRect(const DesktopVector& position); + private: bool DoInitialize(); diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc index 12876c2c89..ad7fd7036e 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc @@ -193,6 +193,7 @@ bool DxgiDuplicatorController::DoInitialize() { std::max(left.right(), right.right()), std::max(left.bottom(), right.bottom())); } + TranslateRect(); } HDC hdc = GetDC(nullptr); @@ -295,7 +296,7 @@ int64_t DxgiDuplicatorController::GetNumFramesCaptured() const { } DesktopSize DxgiDuplicatorController::desktop_size() const { - return DesktopSize(desktop_rect_.right(), desktop_rect_.bottom()); + return desktop_rect_.size(); } DesktopRect DxgiDuplicatorController::ScreenRect(int id) const { @@ -378,4 +379,13 @@ bool DxgiDuplicatorController::EnsureFrameCaptured(Context* context, return true; } +void DxgiDuplicatorController::TranslateRect() { + const DesktopVector position = + DesktopVector().subtract(desktop_rect_.top_left()); + desktop_rect_.Translate(position); + for (auto& duplicator : duplicators_) { + duplicator.TranslateRect(position); + } +} + } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h index 364690bcb9..c9838ad7a1 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h @@ -158,9 +158,7 @@ class DxgiDuplicatorController { // The minimum GetNumFramesCaptured() returned by |duplicators_|. int64_t GetNumFramesCaptured() const; - // Returns a DesktopSize to cover entire desktop_rect. This may be different - // than desktop_rect().size(), since top-left of the screen does not need to - // be started from (0, 0). + // Returns a DesktopSize to cover entire |desktop_rect_|. DesktopSize desktop_size() const; // Returns the size of one screen. |id| should be >= 0. If system does not @@ -181,6 +179,12 @@ class DxgiDuplicatorController { // during first several capture attempts. bool EnsureFrameCaptured(Context* context, SharedDesktopFrame* target); + // 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(); + // This lock must be locked whenever accessing any of the following objects. rtc::CriticalSection lock_; diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc index fb8dacb720..c02fc91fa2 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc @@ -67,7 +67,7 @@ DxgiOutputDuplicator::DxgiOutputDuplicator(const D3dDevice& device, desktop_rect_(RECTToDesktopRect(desc.DesktopCoordinates)) { RTC_DCHECK(output_); RTC_DCHECK(!desktop_rect_.is_empty()); - RTC_DCHECK(desktop_rect_.left() >= 0 && desktop_rect_.top() >= 0); + RTC_DCHECK(desktop_rect_.width() > 0 && desktop_rect_.height() > 0); } DxgiOutputDuplicator::DxgiOutputDuplicator(DxgiOutputDuplicator&& other) = @@ -381,4 +381,9 @@ int64_t DxgiOutputDuplicator::num_frames_captured() const { return num_frames_captured_; } +void DxgiOutputDuplicator::TranslateRect(const DesktopVector& position) { + desktop_rect_.Translate(position); + RTC_DCHECK(desktop_rect_.left() >= 0 && desktop_rect_.top() >= 0); +} + } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h index 7d2c2edef6..dfc19af61c 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h +++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h @@ -75,6 +75,9 @@ class DxgiOutputDuplicator { // How many frames have been captured by this DxigOutputDuplicator. int64_t num_frames_captured() const; + // Moves |desktop_rect_|. See DxgiDuplicatorController::TranslateRect(). + void TranslateRect(const DesktopVector& position); + private: // Calls DoDetectUpdatedRegion(). If it fails, this function sets the // |updated_region| as entire UntranslatedDesktopRect(). @@ -109,7 +112,7 @@ class DxgiOutputDuplicator { const D3dDevice device_; const Microsoft::WRL::ComPtr output_; - const DesktopRect desktop_rect_; + DesktopRect desktop_rect_; Microsoft::WRL::ComPtr duplication_; DXGI_OUTDUPL_DESC desc_; std::vector metadata_;