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

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

Issue 2099123002: [Chromoting] Improve DirectX capturer to support multiple outputs (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fix several lint errors Created 4 years, 4 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_controller.h"
12
13 #include <windows.h>
14
15 #include <algorithm>
16
17 #include "webrtc/base/checks.h"
18
19 namespace webrtc {
20
21 DxgiDuplicatorController::Context::~Context() {
22 DxgiDuplicatorController::Instance()->Unregister(this);
23 }
24
25 // static
26 DxgiDuplicatorController* DxgiDuplicatorController::Instance() {
27 // The static instance won't be deleted to ensure it can be used by other
28 // threads even during program exiting.
29 static DxgiDuplicatorController* instance = new DxgiDuplicatorController();
30 return instance;
31 }
32
33 DxgiDuplicatorController::DxgiDuplicatorController() = default;
34
35 DxgiDuplicatorController::~DxgiDuplicatorController() {
36 rtc::CritScope lock(&lock_);
37 Deinitialize();
38 }
39
40 bool DxgiDuplicatorController::IsSupported() {
41 rtc::CritScope lock(&lock_);
42 return Initialize();
43 }
44
45 DesktopVector DxgiDuplicatorController::dpi() {
46 rtc::CritScope lock(&lock_);
47 if (Initialize()) {
48 return dpi_;
49 }
50 return DesktopVector();
51 }
52
53 DesktopRect DxgiDuplicatorController::desktop_rect() {
54 rtc::CritScope lock(&lock_);
55 if (Initialize()) {
56 return desktop_rect_;
57 }
58 return DesktopRect();
59 }
60
61 DesktopSize DxgiDuplicatorController::desktop_size() {
62 DesktopRect rect = desktop_rect();
63 return DesktopSize(rect.right(), rect.bottom());
64 }
65
66 DesktopRect DxgiDuplicatorController::ScreenRect(int id) {
67 RTC_DCHECK(id >= 0);
68 rtc::CritScope lock(&lock_);
69 if (!Initialize()) {
70 return DesktopRect();
71 }
72 for (size_t i = 0; i < duplicators_.size(); i++) {
73 if (id >= duplicators_[i].screen_count()) {
74 id -= duplicators_[i].screen_count();
75 } else {
76 return duplicators_[i].ScreenRect(id);
77 }
78 }
79 return DesktopRect();
80 }
81
82 int DxgiDuplicatorController::ScreenCount() {
83 rtc::CritScope lock(&lock_);
84 if (!Initialize()) {
85 return 0;
86 }
87 int result = 0;
88 for (auto& duplicator : duplicators_) {
89 result += duplicator.screen_count();
90 }
91 return result;
92 }
93
94 void DxgiDuplicatorController::Unregister(const Context* const context) {
95 rtc::CritScope lock(&lock_);
96 if (ContextExpired(context)) {
97 // The Context has not been setup after a recent initialization, so it
98 // should not been registered in duplicators.
99 return;
100 }
101 for (size_t i = 0; i < duplicators_.size(); i++) {
102 duplicators_[i].Unregister(&context->contexts_[i]);
103 }
104 }
105
106 bool DxgiDuplicatorController::Initialize() {
107 if (!duplicators_.empty()) {
108 return true;
109 }
110
111 if (DoInitialize()) {
112 return true;
113 }
114 Deinitialize();
115 return false;
116 }
117
118 bool DxgiDuplicatorController::DoInitialize() {
119 RTC_DCHECK(desktop_rect_.is_empty());
120 RTC_DCHECK(duplicators_.empty());
121
122 std::vector<D3dDevice> devices = D3dDevice::EnumDevices();
123 if (devices.empty()) {
124 return false;
125 }
126
127 for (size_t i = 0; i < devices.size(); i++) {
128 duplicators_.emplace_back(devices[i]);
129 if (!duplicators_.back().Initialize()) {
130 return false;
131 }
132 if (desktop_rect_.is_empty()) {
133 desktop_rect_ = duplicators_.back().desktop_rect();
134 } else {
135 const DesktopRect& left = desktop_rect_;
136 const DesktopRect& right = duplicators_.back().desktop_rect();
137 desktop_rect_ =
138 DesktopRect::MakeLTRB(std::min(left.left(), right.left()),
139 std::min(left.top(), right.top()),
140 std::max(left.right(), right.right()),
141 std::max(left.bottom(), right.bottom()));
142 }
143 }
144
145 HDC hdc = GetDC(nullptr);
146 // Use old DPI value if failed.
147 if (hdc) {
148 dpi_.set(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
149 ReleaseDC(nullptr, hdc);
150 }
151
152 identity_++;
153 return true;
154 }
155
156 void DxgiDuplicatorController::Deinitialize() {
157 desktop_rect_ = DesktopRect();
158 duplicators_.clear();
159 }
160
161 bool DxgiDuplicatorController::ContextExpired(
162 const Context* const context) const {
163 return context->identity_ != identity_ ||
164 context->contexts_.size() != duplicators_.size();
165 }
166
167 void DxgiDuplicatorController::Setup(Context* context) {
168 if (ContextExpired(context)) {
169 context->contexts_.clear();
170 context->contexts_.resize(duplicators_.size());
171 for (size_t i = 0; i < duplicators_.size(); i++) {
172 duplicators_[i].Setup(&context->contexts_[i]);
173 }
174 context->identity_ = identity_;
175 }
176 }
177
178 bool DxgiDuplicatorController::Duplicate(Context* context,
179 const DesktopFrame* last_frame,
180 DesktopFrame* target) {
181 return DoDuplicate(context, -1, last_frame, target);
182 }
183
184 bool DxgiDuplicatorController::DuplicateMonitor(Context* context,
185 int monitor_id,
186 const DesktopFrame* last_frame,
187 DesktopFrame* target) {
188 RTC_DCHECK_GE(monitor_id, 0);
189 return DoDuplicate(context, monitor_id, last_frame, target);
190 }
191
192 bool DxgiDuplicatorController::DoDuplicate(Context* context,
193 int monitor_id,
194 const DesktopFrame* last_frame,
195 DesktopFrame* target) {
196 RTC_DCHECK(target);
197 if (last_frame && !target->size().equals(last_frame->size())) {
198 return false;
199 }
200 target->mutable_updated_region()->Clear();
201 rtc::CritScope lock(&lock_);
202 if (!Initialize()) {
203 // Cannot initialize COM components now, display mode may be changing.
204 return false;
205 }
206 Setup(context);
207 if (monitor_id < 0) {
208 // Capture entire screen.
209 for (size_t i = 0; i < duplicators_.size(); i++) {
210 if (!duplicators_[i].Duplicate(&context->contexts_[i], last_frame,
211 target)) {
212 Deinitialize();
213 return false;
214 }
215 }
216 target->set_dpi(dpi());
217 return true;
218 }
219
220 // Capture one monitor.
221 for (size_t i = 0; i < duplicators_.size() && i < context->contexts_.size();
222 i++) {
223 if (monitor_id >= duplicators_[i].screen_count()) {
224 monitor_id -= duplicators_[i].screen_count();
225 } else {
226 if (duplicators_[i].DuplicateMonitor(&context->contexts_[i], monitor_id,
227 last_frame, target)) {
228 target->set_dpi(dpi());
229 return true;
230 }
231 Deinitialize();
232 return false;
233 }
234 }
235 // id >= ScreenCount(). This is a user error, so we do not need to
236 // deinitialize.
237 return false;
238 }
239
240 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698