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}
This commit is contained in:
zijiehe 2017-04-28 13:43:28 -07:00 committed by Commit bot
parent 281aecdca6
commit 049ec71e65
6 changed files with 41 additions and 8 deletions

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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_;

View File

@ -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

View File

@ -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<IDXGIOutput1> output_;
const DesktopRect desktop_rect_;
DesktopRect desktop_rect_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> duplication_;
DXGI_OUTDUPL_DESC desc_;
std::vector<uint8_t> metadata_;