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

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

Powered by Google App Engine
This is Rietveld 408576698