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

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: 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 "webrtc/base/checks.h"
16
17 namespace webrtc {
18
19 bool DxgiDuplicatorContainer::SingleEntry::Enter() {
Sergey Ulanov 2016/07/08 22:36:54 I don't think you really need SingleEntry.
Hzj_jie 2016/07/11 00:55:00 Same as below.
20 rtc::CritScope lock(&lock_);
21 if (entered_) {
22 return false;
23 }
24 entered_ = true;
25 return true;
26 }
27
28 void DxgiDuplicatorContainer::SingleEntry::Exit() {
29 rtc::CritScope lock(&lock_);
30 RTC_DCHECK(entered_);
31 entered_ = false;
32 }
33
34 bool DxgiDuplicatorContainer::SingleEntry::Hold() const {
35 rtc::CritScope lock(&lock_);
36 return entered_;
37 }
38
39 class DxgiDuplicatorContainer::AutoExit {
40 public:
41 explicit AutoExit(DxgiDuplicatorContainer::SingleEntry* gate) : gate_(gate) {
42 RTC_DCHECK(gate_);
43 }
44
45 ~AutoExit() { gate_->Exit(); }
46
47 private:
48 DxgiDuplicatorContainer::SingleEntry* gate_;
49 };
50
51 /* static */ DxgiDuplicatorContainer* DxgiDuplicatorContainer::Instance() {
Sergey Ulanov 2016/07/08 22:36:54 Move the comment to a separate line: // static Dx
Hzj_jie 2016/07/11 00:55:00 Done.
52 // The static instance won't be deleted to ensure it can be used by other
53 // threads even during program exiting.
54 static DxgiDuplicatorContainer* instance = new DxgiDuplicatorContainer();
55 return instance;
56 }
57
58 DxgiDuplicatorContainer::~DxgiDuplicatorContainer() {
59 rtc::CritScope lock(&lock_);
60 Deinitialize();
61 }
62
63 bool DxgiDuplicatorContainer::Prepare() {
64 // If the instance has been initialized already, does nothing and returns
65 // true.
66 {
67 rtc::CritScope lock(&lock_);
68 if (!devices_.empty()) {
69 return true;
70 }
71 }
72
73 if (initializing_.Enter()) {
Sergey Ulanov 2016/07/08 22:36:54 I think you can implement the same thing without S
Hzj_jie 2016/07/11 00:55:00 Hold on, this logic won't correct. If the Event is
74 AutoExit exit(&initializing_);
75 rtc::CritScope lock(&lock_);
76 if (!devices_.empty()) {
77 // Another thread has initialized this instance before this thread reaches
78 // line initializing_.Enter(), so does nothing and returns true.
Sergey Ulanov 2016/07/08 22:36:55 How is that possible?
Hzj_jie 2016/07/11 00:55:00 Another thread has called initializing_.Exit befor
79 return true;
80 }
81
82 if (DoInitialize()) {
83 return true;
84 }
85
86 Deinitialize();
87 return false;
88 } else {
89 // Some other thread is initializing, wait for its finish and check the
90 // result.
91 while (initializing_.Hold()) {
92 rtc::CritScope lock(&lock_);
93 }
94 return !devices_.empty();
Sergey Ulanov 2016/07/08 22:36:54 Here the case when initialization has failed and w
Sergey Ulanov 2016/07/08 22:36:54 don't you need to hold the lock_ when verifying th
Hzj_jie 2016/07/11 00:55:00 If there is no device for any reason, DxgiDuplicat
Hzj_jie 2016/07/11 00:55:00 Yes, I missed.
95 }
96 }
97
98 void DxgiDuplicatorContainer::Deinitialize() {
99 desktop_rect_ = DesktopRect();
100 duplicators_.clear();
101 devices_.clear();
102 }
103
104 bool DxgiDuplicatorContainer::DoInitialize() {
105 RTC_DCHECK(desktop_rect_.is_empty());
106 RTC_DCHECK(duplicators_.empty());
107 RTC_DCHECK(devices_.empty());
108
109 devices_ = D3dDevice::EnumDevices();
Sergey Ulanov 2016/07/08 22:36:54 We enumerate devices only once here, but they can
Hzj_jie 2016/07/11 00:55:00 Yes, that's the reason we call Prepare each time b
110 if (devices_.empty()) {
111 return false;
112 }
113
114 for (size_t i = 0; i < devices_.size(); i++) {
115 duplicators_.emplace_back();
116 if (!duplicators_.back().Initialize(devices_[i])) {
117 return false;
118 }
119 if (desktop_rect_.is_empty()) {
120 desktop_rect_ = duplicators_.back().desktop_rect();
121 } else {
122 desktop_rect_.JoinWith(duplicators_.back().desktop_rect());
123 }
124 }
125
126 HDC hdc = GetDC(nullptr);
127 // Use old DPI value if failed.
128 if (hdc != nullptr) {
129 dpi_.set(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
Sergey Ulanov 2016/07/08 22:36:55 dpi can change dynamically, but this class won't d
Hzj_jie 2016/07/11 00:55:00 Same as above, we will reset the dpi_ once display
130 ReleaseDC(nullptr, hdc);
131 }
132
133 return true;
134 }
135
136 DesktopRect DxgiDuplicatorContainer::ScreenRect(int id) const {
137 if (id < 0) {
Sergey Ulanov 2016/07/08 22:36:54 DCHECK(id >= 0)
Hzj_jie 2016/07/11 00:55:00 Done.
138 return DesktopRect();
139 }
140 rtc::CritScope lock(&lock_);
141 for (size_t i = 0; i < duplicators_.size(); i++) {
142 if (id >= duplicators_[i].screen_count()) {
143 id -= duplicators_[i].screen_count();
144 } else {
145 return duplicators_[i].ScreenRect(id);
146 }
147 }
148 return DesktopRect();
149 }
150
151 int DxgiDuplicatorContainer::ScreenCount() const {
152 rtc::CritScope lock(&lock_);
153 int result = 0;
154 for (size_t i = 0; i < duplicators_.size(); i++) {
155 result += duplicators_[i].screen_count();
156 }
157 return result;
158 }
159
160 bool DxgiDuplicatorContainer::Duplicate(DesktopFrame* target,
161 const DesktopFrame* last_frame) {
162 RTC_DCHECK(target);
163 if (last_frame != nullptr && !target->size().equals(last_frame->size())) {
164 return false;
165 }
166 target->mutable_updated_region()->Clear();
167 rtc::CritScope lock(&lock_);
168 for (size_t i = 0; i < duplicators_.size(); i++) {
169 if (!duplicators_[i].Duplicate(target, last_frame)) {
170 Deinitialize();
171 return false;
172 }
173 }
174 target->set_dpi(dpi());
175 return true;
176 }
177
178 bool DxgiDuplicatorContainer::Duplicate(int id,
179 DesktopFrame* target,
180 const DesktopFrame* last_frame) {
181 RTC_DCHECK(target);
182 if (id < 0) {
183 return false;
184 }
185 if (last_frame != nullptr && !target->size().equals(last_frame->size())) {
186 return false;
187 }
188 target->mutable_updated_region()->Clear();
189 rtc::CritScope lock(&lock_);
190 for (size_t i = 0; i < duplicators_.size(); i++) {
191 if (id >= duplicators_[i].screen_count()) {
192 id -= duplicators_[i].screen_count();
193 } else {
194 if (duplicators_[i].Duplicate(id, target, last_frame)) {
195 target->set_dpi(dpi());
196 return true;
197 }
198 Deinitialize();
199 return false;
200 }
201 }
202 // id >= ScreenCount()
203 return false;
204 }
205
206 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698