OLD | NEW |
---|---|
(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_adapter_duplicator.h" | |
12 | |
13 #include <comdef.h> | |
14 #include <DXGI.h> | |
15 | |
16 #include <algorithm> | |
17 | |
18 #include "webrtc/base/checks.h" | |
19 #include "webrtc/base/logging.h" | |
20 | |
21 namespace webrtc { | |
22 | |
23 using Microsoft::WRL::ComPtr; | |
24 | |
25 namespace { | |
26 | |
27 bool IsValidRect(const RECT& rect) { | |
28 return rect.left >= 0 && rect.top >= 0 && rect.right > rect.left && | |
29 rect.bottom > rect.top; | |
30 } | |
31 | |
32 } // namespace | |
33 | |
34 DxgiAdapterDuplicator::DxgiAdapterDuplicator(const D3dDevice& device) | |
35 : device_(device) {} | |
36 | |
37 DxgiAdapterDuplicator::DxgiAdapterDuplicator(DxgiAdapterDuplicator&&) = default; | |
38 | |
39 bool DxgiAdapterDuplicator::Initialize() { | |
40 if (DoInitialize()) { | |
41 return true; | |
42 } | |
43 duplicators_.clear(); | |
44 return false; | |
45 } | |
46 | |
47 bool DxgiAdapterDuplicator::DoInitialize() { | |
48 for (int i = 0;; i++) { | |
49 ComPtr<IDXGIOutput> output; | |
50 _com_error error = | |
51 device_.dxgi_adapter()->EnumOutputs(i, output.GetAddressOf()); | |
52 if (error.Error() == DXGI_ERROR_NOT_FOUND) { | |
53 break; | |
54 } | |
55 | |
56 if (error.Error() != S_OK || !output) { | |
57 LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returns an unexpected " | |
58 "result " | |
59 << error.ErrorMessage() << " with error code" | |
60 << error.Error(); | |
61 return false; | |
62 } | |
63 | |
64 DXGI_OUTPUT_DESC desc; | |
65 error = _com_error(output->GetDesc(&desc)); | |
66 if (error.Error() == S_OK) { | |
67 if (desc.AttachedToDesktop && IsValidRect(desc.DesktopCoordinates)) { | |
68 ComPtr<IDXGIOutput1> output1; | |
69 error = _com_error(output.As(&output1)); | |
70 if (error.Error() != S_OK || !output1) { | |
71 LOG(LS_WARNING) << "Failed to convert IDXGIOutput to IDXGIOutput1, " | |
72 "this usually means the system does not support " | |
73 "DirectX 11"; | |
74 return false; | |
75 } | |
76 duplicators_.emplace_back(device_, output1, desc); | |
77 if (!duplicators_.back().Initialize()) { | |
78 return false; | |
79 } | |
80 if (desktop_rect_.is_empty()) { | |
81 desktop_rect_ = duplicators_.back().desktop_rect(); | |
82 } else { | |
83 const DesktopRect& left = desktop_rect_; | |
84 const DesktopRect& right = duplicators_.back().desktop_rect(); | |
85 desktop_rect_ = | |
86 DesktopRect::MakeLTRB(std::min(left.left(), right.left()), | |
87 std::min(left.top(), right.top()), | |
88 std::max(left.right(), right.right()), | |
89 std::max(left.bottom(), right.bottom())); | |
90 } | |
91 } | |
92 } else { | |
93 LOG(LS_WARNING) << "Failed to get output description of device " << i | |
94 << ", ignore."; | |
95 } | |
96 } | |
97 return true; | |
98 } | |
99 | |
100 void DxgiAdapterDuplicator::Setup(DxgiAdapterContext* context) { | |
101 RTC_DCHECK(context->contexts.empty()); | |
102 context->contexts.resize(duplicators_.size()); | |
103 for (size_t i = 0; i < duplicators_.size(); i++) { | |
104 duplicators_[i].Setup(&context->contexts[i]); | |
105 } | |
106 } | |
107 | |
108 void DxgiAdapterDuplicator::Unregister( | |
109 const DxgiAdapterContext* const context) { | |
110 RTC_DCHECK(context->contexts.size() == duplicators_.size()); | |
Sergey Ulanov
2016/08/06 01:27:57
RTC_DCHECK_EQ
Hzj_jie
2016/08/08 00:16:08
Done.
| |
111 for (size_t i = 0; i < duplicators_.size(); i++) { | |
112 duplicators_[i].Unregister(&context->contexts[i]); | |
113 } | |
114 } | |
115 | |
116 bool DxgiAdapterDuplicator::Duplicate(DxgiAdapterContext* context, | |
117 const DesktopFrame* last_frame, | |
118 DesktopFrame* target) { | |
119 RTC_DCHECK(context->contexts.size() == duplicators_.size()); | |
Sergey Ulanov
2016/08/06 01:27:57
RTC_DCHECK_EQ
Hzj_jie
2016/08/08 00:16:08
Done.
| |
120 for (size_t i = 0; i < duplicators_.size(); i++) { | |
121 if (!duplicators_[i].Duplicate(&context->contexts[i], last_frame, | |
122 duplicators_[i].desktop_rect().top_left(), | |
123 target)) { | |
124 return false; | |
125 } | |
126 } | |
127 return true; | |
128 } | |
129 | |
130 bool DxgiAdapterDuplicator::DuplicateMonitor(DxgiAdapterContext* context, | |
131 int monitor_id, | |
132 const DesktopFrame* last_frame, | |
133 DesktopFrame* target) { | |
134 RTC_DCHECK(monitor_id >= 0 && | |
135 monitor_id < static_cast<int>(duplicators_.size()) && | |
136 context->contexts.size() == duplicators_.size()); | |
137 return duplicators_[monitor_id].Duplicate( | |
138 &context->contexts[monitor_id], last_frame, DesktopVector(), target); | |
139 } | |
140 | |
141 DesktopRect DxgiAdapterDuplicator::ScreenRect(int id) const { | |
142 RTC_DCHECK(id >= 0 && id < static_cast<int>(duplicators_.size())); | |
143 return duplicators_[id].desktop_rect(); | |
144 } | |
145 | |
146 } // namespace webrtc | |
OLD | NEW |