OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h" | 5 #include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ui/gfx/geometry/rect_conversions.h" | 9 #include "ui/gfx/geometry/rect_conversions.h" |
10 #include "ui/ozone/common/gpu/ozone_gpu_messages.h" | 10 #include "ui/ozone/common/gpu/ozone_gpu_messages.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 return true; | 36 return true; |
37 if (l.transform > r.transform) | 37 if (l.transform > r.transform) |
38 return false; | 38 return false; |
39 if (l.buffer_size.width() < r.buffer_size.width()) | 39 if (l.buffer_size.width() < r.buffer_size.width()) |
40 return true; | 40 return true; |
41 if (l.buffer_size.width() > r.buffer_size.width()) | 41 if (l.buffer_size.width() > r.buffer_size.width()) |
42 return false; | 42 return false; |
43 return l.buffer_size.height() < r.buffer_size.height(); | 43 return l.buffer_size.height() < r.buffer_size.height(); |
44 } | 44 } |
45 | 45 |
46 DrmOverlayCandidatesHost::HardwareDisplayPlaneProxy::HardwareDisplayPlaneProxy( | |
47 uint32_t id) | |
48 : plane_id(id) {} | |
49 | |
50 DrmOverlayCandidatesHost::HardwareDisplayPlaneProxy:: | |
51 ~HardwareDisplayPlaneProxy() {} | |
52 | |
53 DrmOverlayCandidatesHost::DrmOverlayCandidatesHost( | 46 DrmOverlayCandidatesHost::DrmOverlayCandidatesHost( |
54 DrmGpuPlatformSupportHost* platform_support, | 47 DrmGpuPlatformSupportHost* platform_support, |
55 DrmWindowHost* window) | 48 DrmWindowHost* window) |
56 : platform_support_(platform_support), | 49 : platform_support_(platform_support), |
57 window_(window), | 50 window_(window), |
58 cache_(kMaxCacheSize) { | 51 cache_(kMaxCacheSize) { |
59 platform_support_->RegisterHandler(this); | 52 platform_support_->RegisterHandler(this); |
60 window_->SetOverlayCandidatesHost(this); | 53 window_->SetOverlayCandidatesHost(this); |
61 } | 54 } |
62 | 55 |
63 DrmOverlayCandidatesHost::~DrmOverlayCandidatesHost() { | 56 DrmOverlayCandidatesHost::~DrmOverlayCandidatesHost() { |
64 platform_support_->UnregisterHandler(this); | 57 platform_support_->UnregisterHandler(this); |
65 window_->SetOverlayCandidatesHost(nullptr); | 58 window_->SetOverlayCandidatesHost(nullptr); |
66 } | 59 } |
67 | 60 |
68 void DrmOverlayCandidatesHost::CheckOverlaySupport( | 61 void DrmOverlayCandidatesHost::CheckOverlaySupport( |
69 OverlaySurfaceCandidateList* candidates) { | 62 OverlaySurfaceCandidateList* candidates) { |
70 uint32_t compatible_candidates = 0; | 63 bool validate_params = false; |
71 uint32_t planes_in_use = 0; | |
72 bool force_validation = false; | |
73 std::vector<OverlayCheck_Params> new_candidates; | |
74 for (auto& candidate : *candidates) { | 64 for (auto& candidate : *candidates) { |
75 if (!CanHandleCandidate(candidate)) | 65 if (!CanHandleCandidate(candidate)) |
76 continue; | 66 continue; |
77 | 67 |
| 68 if (candidate.plane_z_order == 0) |
| 69 candidate.buffer_size = window_->GetBounds().size(); |
| 70 |
| 71 // TODO(kalyank): We should get correct storage format used for Video from |
| 72 // GPU process. |
| 73 if (candidate.format == gfx::BufferFormat::BGRA_8888) |
| 74 candidate.format = gfx::BufferFormat::BGRX_8888; |
| 75 |
78 OverlayCheck_Params lookup(candidate); | 76 OverlayCheck_Params lookup(candidate); |
79 if (!force_validation) { | |
80 CompatibleParams::const_iterator last_iter = | |
81 in_use_compatible_params_.find(lookup); | |
82 if (last_iter != in_use_compatible_params_.end()) { | |
83 candidate.overlay_handled = last_iter->second; | |
84 compatible_candidates++; | |
85 if (candidate.overlay_handled) | |
86 planes_in_use++; | |
87 | 77 |
88 continue; | 78 std::vector<OverlayCheck_Params>::iterator it; |
89 } | 79 it = std::find(in_use_params_.begin(), in_use_params_.end(), lookup); |
| 80 if (it != in_use_params_.end()) { |
| 81 candidate.overlay_handled = it->state == OverlayCheck_Params::kOverlay; |
| 82 continue; |
90 } | 83 } |
91 | 84 |
92 auto iter = cache_.Get(lookup); | 85 auto iter = cache_.Peek(lookup); |
93 if (iter == cache_.end()) { | 86 if (iter == cache_.end()) { |
94 lookup.weight = CalculateCandidateWeight(candidate); | 87 lookup.weight = CalculateCandidateWeight(candidate); |
95 cache_.Put(lookup, false); | |
96 // It is possible that the cc rect we get actually falls off the edge of | 88 // It is possible that the cc rect we get actually falls off the edge of |
97 // the screen. Usually this is prevented via things like status bars | 89 // the screen. Usually this is prevented via things like status bars |
98 // blocking overlaying or cc clipping it, but in case it wasn't properly | 90 // blocking overlaying or cc clipping it, but in case it wasn't properly |
99 // clipped (since GL will render this situation fine) just ignore it here. | 91 // clipped (since GL will render this situation fine) just ignore it here. |
100 // This should be an extremely rare occurrance. | 92 // This should be an extremely rare occurrance. |
101 if (lookup.plane_z_order != 0 && | 93 if (lookup.plane_z_order != 0 && |
102 !window_->GetBounds().Contains(lookup.display_rect)) { | 94 !window_->GetBounds().Contains(lookup.display_rect)) { |
103 continue; | 95 lookup.state = OverlayCheck_Params::kInvalid; |
| 96 } else { |
| 97 lookup.state = OverlayCheck_Params::kTest; |
| 98 validate_params = true; |
104 } | 99 } |
105 | 100 |
106 new_candidates.push_back(lookup); | 101 cache_.Put(lookup, lookup.state); |
107 } else if (iter->second) { | 102 } else if (iter->second == OverlayCheck_Params::kCompatible) { |
108 force_validation = true; | 103 validate_params = true; |
109 } | 104 } |
110 } | 105 } |
111 | 106 |
112 // We have new candidates whose configuration needs to be validated in GPU | 107 if (validate_params) |
113 // side. | 108 ValidateCandidates(*candidates); |
114 if (!new_candidates.empty()) | |
115 SendRequest(new_candidates); | |
116 | |
117 if (compatible_candidates > planes_in_use && | |
118 planes_in_use < hardware_plane_proxy_.size()) { | |
119 force_validation = true; | |
120 } | |
121 | |
122 if (!force_validation) { | |
123 DCHECK(planes_in_use <= hardware_plane_proxy_.size()) | |
124 << "Total layers promoted to use Overlay:" << planes_in_use | |
125 << "While the maximum layers which can be actually supported are:" | |
126 << hardware_plane_proxy_.size(); | |
127 return; | |
128 } | |
129 | |
130 // A new layer has been added or removed from the last validation. We expect | |
131 // this to be very rare situation, hence not fully optimized. We always | |
132 // validate the new combination of layers. | |
133 ValidateCandidates(candidates); | |
134 } | 109 } |
135 | 110 |
136 void DrmOverlayCandidatesHost::OnChannelEstablished( | 111 void DrmOverlayCandidatesHost::OnChannelEstablished( |
137 int host_id, | 112 int host_id, |
138 scoped_refptr<base::SingleThreadTaskRunner> send_runner, | 113 scoped_refptr<base::SingleThreadTaskRunner> send_runner, |
139 const base::Callback<void(IPC::Message*)>& sender) { | 114 const base::Callback<void(IPC::Message*)>& sender) { |
140 // Reset any old cache. | 115 // Reset any old cache. |
141 ResetCache(); | 116 ResetCache(); |
142 } | 117 } |
143 | 118 |
144 void DrmOverlayCandidatesHost::OnChannelDestroyed(int host_id) { | 119 void DrmOverlayCandidatesHost::OnChannelDestroyed(int host_id) { |
145 } | 120 } |
146 | 121 |
147 bool DrmOverlayCandidatesHost::OnMessageReceived(const IPC::Message& message) { | 122 bool DrmOverlayCandidatesHost::OnMessageReceived(const IPC::Message& message) { |
148 bool handled = false; | 123 bool handled = false; |
149 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(DrmOverlayCandidatesHost, message, &handled) | 124 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(DrmOverlayCandidatesHost, message, &handled) |
150 IPC_MESSAGE_FORWARD(OzoneHostMsg_OverlayCapabilitiesReceived, this, | 125 IPC_MESSAGE_FORWARD(OzoneHostMsg_OverlayCapabilitiesReceived, this, |
151 DrmOverlayCandidatesHost::OnOverlayResult) | 126 DrmOverlayCandidatesHost::OnOverlayResult) |
152 IPC_END_MESSAGE_MAP() | 127 IPC_END_MESSAGE_MAP() |
153 return handled; | 128 return handled; |
154 } | 129 } |
155 | 130 |
156 void DrmOverlayCandidatesHost::ResetCache() { | 131 void DrmOverlayCandidatesHost::ResetCache() { |
157 cache_.Clear(); | 132 cache_.Clear(); |
158 in_use_compatible_params_.clear(); | 133 in_use_params_.clear(); |
159 hardware_plane_proxy_.clear(); | |
160 } | 134 } |
161 | 135 |
162 void DrmOverlayCandidatesHost::SendRequest( | 136 void DrmOverlayCandidatesHost::SendRequest( |
163 const std::vector<OverlayCheck_Params>& list) { | 137 const std::vector<OverlayCheck_Params>& current_list, |
| 138 const std::vector<OverlayCheck_Params>& new_list) { |
164 if (!platform_support_->IsConnected()) | 139 if (!platform_support_->IsConnected()) |
165 return; | 140 return; |
166 | 141 |
167 platform_support_->Send(new OzoneGpuMsg_CheckOverlayCapabilities( | 142 platform_support_->Send(new OzoneGpuMsg_CheckOverlayCapabilities( |
168 window_->GetAcceleratedWidget(), list)); | 143 window_->GetAcceleratedWidget(), current_list, new_list)); |
169 } | 144 } |
170 | 145 |
171 void DrmOverlayCandidatesHost::OnOverlayResult( | 146 void DrmOverlayCandidatesHost::OnOverlayResult( |
172 bool* handled, | 147 bool* handled, |
173 gfx::AcceleratedWidget widget, | 148 gfx::AcceleratedWidget widget, |
174 const std::vector<OverlayCheck_Params>& params) { | 149 const std::vector<OverlayCheck_Params>& params) { |
175 if (widget != window_->GetAcceleratedWidget()) | 150 if (widget != window_->GetAcceleratedWidget()) |
176 return; | 151 return; |
177 | 152 |
178 *handled = true; | 153 *handled = true; |
| 154 for (const auto& compatible_param : in_use_params_) { |
| 155 OverlayCheck_Params param = compatible_param; |
| 156 if (param.state == OverlayCheck_Params::kOverlay) |
| 157 param.state = OverlayCheck_Params::kCompatible; |
| 158 |
| 159 cache_.Put(param, OverlayCheck_Params::kCompatible); |
| 160 } |
| 161 |
| 162 in_use_params_.clear(); |
179 for (const auto& check : params) { | 163 for (const auto& check : params) { |
180 // We expect params to contain only supported configurations. | 164 in_use_params_.push_back(check); |
181 cache_.Put(check, true); | 165 cache_.Put(check, OverlayCheck_Params::kCompatible); |
182 for (const auto& plane_id : check.plane_ids) { | |
183 bool plane_found = false; | |
184 for (const auto* plane : hardware_plane_proxy_) { | |
185 if (plane->plane_id == plane_id) { | |
186 plane_found = true; | |
187 break; | |
188 } | |
189 } | |
190 | |
191 if (!plane_found) { | |
192 hardware_plane_proxy_.push_back( | |
193 make_scoped_ptr(new HardwareDisplayPlaneProxy(plane_id))); | |
194 } | |
195 } | |
196 } | 166 } |
197 } | 167 } |
198 | 168 |
199 bool DrmOverlayCandidatesHost::CanHandleCandidate( | 169 bool DrmOverlayCandidatesHost::CanHandleCandidate( |
200 const OverlaySurfaceCandidate& candidate) const { | 170 const OverlaySurfaceCandidate& candidate) const { |
201 // 0.01 constant chosen to match DCHECKs in gfx::ToNearestRect and avoid | 171 // 0.01 constant chosen to match DCHECKs in gfx::ToNearestRect and avoid |
202 // that code asserting on quads that we accept. | 172 // that code asserting on quads that we accept. |
203 if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f)) | 173 if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f)) |
204 return false; | 174 return false; |
205 | 175 |
(...skipping 27 matching lines...) Expand all Loading... |
233 weight++; | 203 weight++; |
234 } | 204 } |
235 | 205 |
236 // TODO(kalyank): We want to consider size based on power benefits. | 206 // TODO(kalyank): We want to consider size based on power benefits. |
237 } | 207 } |
238 | 208 |
239 return weight; | 209 return weight; |
240 } | 210 } |
241 | 211 |
242 void DrmOverlayCandidatesHost::ValidateCandidates( | 212 void DrmOverlayCandidatesHost::ValidateCandidates( |
243 OverlaySurfaceCandidateList* candidates) { | 213 const OverlaySurfaceCandidateList& candidates) { |
244 // Make sure params being currently used are in cache. They might have been | 214 std::vector<OverlayCheck_Params> current_overlay_params; |
245 // removed in case we haven't tried to get them from cache for a while. | 215 std::vector<OverlayCheck_Params> new_params; |
246 for (const auto& param : in_use_compatible_params_) | 216 for (const auto& param : in_use_params_) { |
247 cache_.Put(param.first, true); | 217 if (param.state == OverlayCheck_Params::kOverlay) |
| 218 current_overlay_params.push_back(param); |
248 | 219 |
249 in_use_compatible_params_.clear(); | 220 // Make sure params being currently used are in cache. They might have |
250 typedef std::pair<OverlaySurfaceCandidate*, OverlayCheck_Params> | 221 // been removed in case we haven't tried to get them from cache for a |
251 CandidatePair; | 222 // while. |
252 std::vector<CandidatePair> compatible_candidates; | 223 cache_.Put(param, OverlayCheck_Params::kCompatible); |
253 for (auto& candidate : *candidates) { | 224 } |
254 candidate.overlay_handled = false; | |
255 | 225 |
| 226 for (const auto& candidate : candidates) { |
256 if (!CanHandleCandidate(candidate)) | 227 if (!CanHandleCandidate(candidate)) |
257 continue; | 228 continue; |
258 | 229 |
259 OverlayCheck_Params lookup(candidate); | 230 OverlayCheck_Params lookup(candidate); |
260 auto iter = cache_.Peek(lookup); | 231 auto iter = cache_.Get(lookup); |
261 DCHECK(iter != cache_.end()); | 232 DCHECK(iter != cache_.end()); |
262 if (!iter->second) | 233 if (iter->second != OverlayCheck_Params::kInvalid) |
263 continue; | 234 new_params.push_back(lookup); |
264 | |
265 in_use_compatible_params_[iter->first] = false; | |
266 compatible_candidates.push_back(std::make_pair(&candidate, iter->first)); | |
267 } | 235 } |
268 | 236 |
269 uint32_t available_overlays = hardware_plane_proxy_.size(); | |
270 for (auto* plane : hardware_plane_proxy_) | |
271 plane->in_use = false; | |
272 | |
273 // Sort in decending order w.r.t weight. | 237 // Sort in decending order w.r.t weight. |
274 std::sort(compatible_candidates.begin(), compatible_candidates.end(), | 238 std::sort(new_params.begin(), new_params.end(), |
275 [](const CandidatePair& l, const CandidatePair& r) { | 239 [](const OverlayCheck_Params& l, const OverlayCheck_Params& r) { |
276 return l.second.weight > r.second.weight; | 240 return l.weight > r.weight; |
277 }); | 241 }); |
278 | 242 |
279 // Make sure we don't handle more candidates than what we can support in | 243 SendRequest(current_overlay_params, new_params); |
280 // GPU side. | |
281 for (const auto& candidate : compatible_candidates) { | |
282 for (auto* plane : hardware_plane_proxy_) { | |
283 // Plane is already in use. | |
284 if (plane->in_use) | |
285 continue; | |
286 | |
287 for (const auto& plane_id : candidate.second.plane_ids) { | |
288 if (plane->plane_id == plane_id) { | |
289 available_overlays--; | |
290 auto iter = in_use_compatible_params_.find(candidate.second); | |
291 DCHECK(iter != in_use_compatible_params_.end()); | |
292 iter->second = true; | |
293 candidate.first->overlay_handled = true; | |
294 plane->in_use = true; | |
295 break; | |
296 } | |
297 } | |
298 | |
299 // We have succefully found a plane. | |
300 if (plane->in_use) | |
301 break; | |
302 } | |
303 | |
304 // We dont have any free hardware resources. | |
305 if (!available_overlays) | |
306 break; | |
307 } | |
308 } | 244 } |
309 | 245 |
310 } // namespace ui | 246 } // namespace ui |
OLD | NEW |