Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: webrtc/modules/desktop_capture/win/dxgi_duplicator_container.cc

Issue 2099123002: [Chromoting] Improve DirectX capturer to support multiple outputs (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Resolve review comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/desktop_capture/win/dxgi_duplicator_container.h"
12
13 #include <windows.h>
14
15 #include <algorithm>
16
17 #include "webrtc/base/checks.h"
18
19 namespace webrtc {
20
21 bool DxgiDuplicatorContainer::SingleEntry::Enter() {
22 rtc::CritScope lock(&lock_);
23 if (entered_) {
24 return false;
25 }
26 entered_ = true;
27 return true;
28 }
29
30 void DxgiDuplicatorContainer::SingleEntry::Exit() {
31 rtc::CritScope lock(&lock_);
32 RTC_DCHECK(entered_);
33 entered_ = false;
34 }
35
36 bool DxgiDuplicatorContainer::SingleEntry::Hold() const {
37 rtc::CritScope lock(&lock_);
38 return entered_;
39 }
40
41 class DxgiDuplicatorContainer::AutoExit {
42 public:
43 explicit AutoExit(DxgiDuplicatorContainer::SingleEntry* gate) : gate_(gate) {
44 RTC_DCHECK(gate_);
45 }
46
47 ~AutoExit() { gate_->Exit(); }
48
49 private:
50 DxgiDuplicatorContainer::SingleEntry* gate_;
51 };
52
53 // static
54 DxgiDuplicatorContainer* DxgiDuplicatorContainer::Instance() {
55 // The static instance won't be deleted to ensure it can be used by other
56 // threads even during program exiting.
57 static DxgiDuplicatorContainer* instance = new DxgiDuplicatorContainer();
58 return instance;
59 }
60
61 DxgiDuplicatorContainer::~DxgiDuplicatorContainer() {
62 rtc::CritScope lock(&lock_);
63 Deinitialize();
64 }
65
66 bool DxgiDuplicatorContainer::Prepare() {
67 // If the instance has been initialized already, does nothing and returns
68 // true.
69 {
70 rtc::CritScope lock(&lock_);
71 if (!devices_.empty()) {
72 return true;
73 }
74 }
75
76 if (initializing_.Enter()) {
77 AutoExit exit(&initializing_);
78 rtc::CritScope lock(&lock_);
79 if (!devices_.empty()) {
80 // Another thread has initialized this instance before this thread reaches
81 // line initializing_.Enter(), so does nothing and returns true.
82 return true;
83 }
84
85 if (DoInitialize()) {
86 return true;
87 }
88
89 Deinitialize();
90 return false;
91 } else {
92 // Some other thread is initializing, wait for its finish and check the
93 // result.
94 while (initializing_.Hold()) {
95 rtc::CritScope lock(&lock_);
96 }
97 rtc::CritScope lock(&lock_);
98 return !devices_.empty();
99 }
100 }
101
102 void DxgiDuplicatorContainer::Deinitialize() {
103 desktop_rect_ = DesktopRect();
104 duplicators_.clear();
105 devices_.clear();
106 }
107
108 bool DxgiDuplicatorContainer::DoInitialize() {
109 RTC_DCHECK(desktop_rect_.is_empty());
110 RTC_DCHECK(duplicators_.empty());
111 RTC_DCHECK(devices_.empty());
112
113 devices_ = D3dDevice::EnumDevices();
114 if (devices_.empty()) {
115 return false;
116 }
117
118 for (size_t i = 0; i < devices_.size(); i++) {
119 duplicators_.emplace_back();
120 if (!duplicators_.back().Initialize(devices_[i])) {
121 return false;
122 }
123 if (desktop_rect_.is_empty()) {
124 desktop_rect_ = duplicators_.back().desktop_rect();
125 } else {
126 const DesktopRect& left = desktop_rect_;
127 const DesktopRect& right = duplicators_.back().desktop_rect();
128 desktop_rect_ = DesktopRect::MakeLTRB(
129 std::min(left.left(), right.left()),
130 std::min(left.top(), right.top()),
131 std::max(left.right(), right.right()),
132 std::max(left.bottom(), right.bottom()));
133 }
134 }
135
136 HDC hdc = GetDC(nullptr);
137 // Use old DPI value if failed.
138 if (hdc != nullptr) {
139 dpi_.set(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
140 ReleaseDC(nullptr, hdc);
141 }
142
143 return true;
144 }
145
146 DesktopRect DxgiDuplicatorContainer::ScreenRect(int id) const {
147 RTC_DCHECK(id >= 0);
148 rtc::CritScope lock(&lock_);
149 for (size_t i = 0; i < duplicators_.size(); i++) {
150 if (id >= duplicators_[i].screen_count()) {
151 id -= duplicators_[i].screen_count();
152 } else {
153 return duplicators_[i].ScreenRect(id);
154 }
155 }
156 return DesktopRect();
157 }
158
159 int DxgiDuplicatorContainer::ScreenCount() const {
160 rtc::CritScope lock(&lock_);
161 int result = 0;
162 for (auto& duplicator : duplicators_) {
163 result += duplicator.screen_count();
164 }
165 return result;
166 }
167
168 bool DxgiDuplicatorContainer::Duplicate(DesktopFrame* target,
169 const DesktopFrame* last_frame) {
170 RTC_DCHECK(target);
171 if (last_frame != nullptr && !target->size().equals(last_frame->size())) {
172 return false;
173 }
174 target->mutable_updated_region()->Clear();
175 rtc::CritScope lock(&lock_);
176 if (duplicators_.empty()) {
177 return false;
178 }
179 for (auto& duplicator : duplicators_) {
180 if (!duplicator.Duplicate(target, last_frame)) {
181 Deinitialize();
182 return false;
183 }
184 }
185 target->set_dpi(dpi());
186 return true;
187 }
188
189 bool DxgiDuplicatorContainer::Duplicate(int id,
190 DesktopFrame* target,
191 const DesktopFrame* last_frame) {
192 RTC_DCHECK(target);
193 RTC_DCHECK(id >= 0);
194 if (last_frame != nullptr && !target->size().equals(last_frame->size())) {
195 return false;
196 }
197 target->mutable_updated_region()->Clear();
198 rtc::CritScope lock(&lock_);
199 for (auto& duplicator : duplicators_) {
200 if (id >= duplicator.screen_count()) {
201 id -= duplicator.screen_count();
202 } else {
203 if (duplicator.Duplicate(id, target, last_frame)) {
204 target->set_dpi(dpi());
205 return true;
206 }
207 Deinitialize();
208 return false;
209 }
210 }
211 // id >= ScreenCount()
212 return false;
213 }
214
215 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698