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/gpu/drm_overlay_validator.h" | 5 #include "ui/ozone/platform/drm/gpu/drm_overlay_validator.h" |
6 | 6 |
7 #include <drm_fourcc.h> | 7 #include <drm_fourcc.h> |
8 | 8 |
9 #include "ui/gfx/geometry/size_conversions.h" | 9 #include "ui/gfx/geometry/size_conversions.h" |
10 #include "ui/ozone/platform/drm/common/drm_util.h" | 10 #include "ui/ozone/platform/drm/common/drm_util.h" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 } | 99 } |
100 | 100 |
101 } // namespace | 101 } // namespace |
102 | 102 |
103 DrmOverlayValidator::OverlayHints::OverlayHints(uint32_t format, | 103 DrmOverlayValidator::OverlayHints::OverlayHints(uint32_t format, |
104 bool scale_buffer) | 104 bool scale_buffer) |
105 : optimal_format(format), handle_scaling(scale_buffer) {} | 105 : optimal_format(format), handle_scaling(scale_buffer) {} |
106 | 106 |
107 DrmOverlayValidator::OverlayHints::~OverlayHints() {} | 107 DrmOverlayValidator::OverlayHints::~OverlayHints() {} |
108 | 108 |
| 109 DrmOverlayValidator::OverlayBuffer::OverlayBuffer( |
| 110 const scoped_refptr<ScanoutBuffer>& buffer, |
| 111 bool is_in_use) |
| 112 : buffer(buffer), is_in_use(is_in_use) {} |
| 113 |
| 114 DrmOverlayValidator::OverlayBuffer::~OverlayBuffer() {} |
| 115 |
109 DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) | 116 DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) |
110 : window_(window), overlay_hints_cache_(kMaxCacheSize) {} | 117 : window_(window), overlay_hints_cache_(kMaxCacheSize) {} |
111 | 118 |
112 DrmOverlayValidator::~DrmOverlayValidator() {} | 119 DrmOverlayValidator::~DrmOverlayValidator() {} |
113 | 120 |
114 std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip( | 121 std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip( |
115 const std::vector<OverlayCheck_Params>& params, | 122 const std::vector<OverlayCheck_Params>& params, |
116 const OverlayPlaneList& last_used_planes, | 123 const OverlayPlaneList& last_used_planes, |
117 ScanoutBufferGenerator* buffer_generator) { | 124 ScanoutBufferGenerator* buffer_generator) { |
118 std::vector<OverlayCheck_Params> validated_params = params; | 125 std::vector<OverlayCheck_Params> validated_params = params; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 overlay.is_overlay_candidate = false; | 168 overlay.is_overlay_candidate = false; |
162 test_list.pop_back(); | 169 test_list.pop_back(); |
163 } | 170 } |
164 } | 171 } |
165 | 172 |
166 UpdateOverlayHintsCache(drm, test_list, buffer_generator, &reusable_buffers); | 173 UpdateOverlayHintsCache(drm, test_list, buffer_generator, &reusable_buffers); |
167 | 174 |
168 return validated_params; | 175 return validated_params; |
169 } | 176 } |
170 | 177 |
171 uint32_t DrmOverlayValidator::GetOptimalBufferFormat( | 178 OverlayPlaneList DrmOverlayValidator::ValidatePlanesForPageFlip( |
172 const OverlayPlane& plane, | 179 const OverlayPlaneList& planes, |
173 const OverlayPlaneList& plane_list) const { | 180 ScanoutBufferGenerator* buffer_generator) { |
174 const auto& iter = overlay_hints_cache_.Peek(plane_list); | 181 // Release any OverlayBuffer which is not in use and mark any in use as |
175 // We dont have any information in cache about this combination of layers, | 182 // available. |
176 // return standard BGRX format. | 183 if (!overlay_buffers_cache_.empty()) { |
177 if (iter == overlay_hints_cache_.end()) | 184 std::vector<OverlayBuffer> re_usable_buffers; |
178 return DRM_FORMAT_XRGB8888; | 185 for (const auto& processing_buffer : overlay_buffers_cache_) { |
| 186 if (processing_buffer.is_in_use) { |
| 187 re_usable_buffers.push_back(processing_buffer); |
| 188 re_usable_buffers.back().is_in_use = false; |
| 189 } |
| 190 } |
179 | 191 |
180 DCHECK(plane_list.size() == iter->second.size()); | 192 overlay_buffers_cache_.swap(re_usable_buffers); |
| 193 } |
181 | 194 |
182 size_t size = plane_list.size(); | 195 if (planes.size() <= 1) |
183 uint32_t index; | 196 return planes; |
184 for (index = 0; index < size; index++) { | 197 |
185 const OverlayPlane& test_plane = plane_list.at(index); | 198 HardwareDisplayController* controller = window_->GetController(); |
186 if (test_plane.z_order == plane.z_order && | 199 if (!controller) |
187 test_plane.plane_transform == plane.plane_transform && | 200 return planes; |
188 test_plane.display_bounds == plane.display_bounds && | 201 |
189 test_plane.crop_rect == plane.crop_rect) { | 202 OverlayPlaneList pending_planes = planes; |
190 break; | 203 std::sort(pending_planes.begin(), pending_planes.end(), |
| 204 [](const OverlayPlane& l, const OverlayPlane& r) { |
| 205 return l.z_order < r.z_order; |
| 206 }); |
| 207 |
| 208 const auto& iter = overlay_hints_cache_.Get(planes); |
| 209 scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); |
| 210 |
| 211 size_t size = planes.size(); |
| 212 bool use_hints = iter != overlay_hints_cache_.end(); |
| 213 |
| 214 for (size_t i = 0; i < size; i++) { |
| 215 auto& plane = pending_planes.at(i); |
| 216 if (plane.processing_callback.is_null()) |
| 217 continue; |
| 218 |
| 219 uint32_t original_format = plane.buffer->GetFramebufferPixelFormat(); |
| 220 uint32_t target_format = original_format; |
| 221 |
| 222 const gfx::Size& original_size = plane.buffer->GetSize(); |
| 223 gfx::Size target_size = |
| 224 GetScaledSize(original_size, plane.display_bounds, plane.crop_rect); |
| 225 |
| 226 if (use_hints) { |
| 227 DCHECK(size == iter->second.size()); |
| 228 const OverlayHints& hints = iter->second.at(i); |
| 229 target_format = hints.optimal_format; |
| 230 |
| 231 // We can handle plane scaling, avoid scaling buffer here. |
| 232 if (!hints.handle_scaling) |
| 233 target_size = original_size; |
| 234 } |
| 235 |
| 236 if (original_size != target_size || original_format != target_format) { |
| 237 scoped_refptr<ScanoutBuffer> buffer = GetBufferForPageFlip( |
| 238 drm, buffer_generator, target_size, target_format); |
| 239 DCHECK(buffer); |
| 240 |
| 241 if (plane.processing_callback.Run(plane.buffer, buffer)) |
| 242 plane.buffer = buffer; |
191 } | 243 } |
192 } | 244 } |
193 | 245 |
194 return iter->second.at(index).optimal_format; | 246 return pending_planes; |
195 } | 247 } |
196 | 248 |
197 void DrmOverlayValidator::ClearCache() { | 249 void DrmOverlayValidator::ClearCache() { |
198 overlay_hints_cache_.Clear(); | 250 overlay_hints_cache_.Clear(); |
| 251 overlay_buffers_cache_.clear(); |
199 } | 252 } |
200 | 253 |
201 void DrmOverlayValidator::UpdateOverlayHintsCache( | 254 void DrmOverlayValidator::UpdateOverlayHintsCache( |
202 const scoped_refptr<DrmDevice>& drm, | 255 const scoped_refptr<DrmDevice>& drm, |
203 const OverlayPlaneList& plane_list, | 256 const OverlayPlaneList& plane_list, |
204 ScanoutBufferGenerator* buffer_generator, | 257 ScanoutBufferGenerator* buffer_generator, |
205 std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers) { | 258 std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers) { |
206 const auto& iter = overlay_hints_cache_.Get(plane_list); | 259 const auto& iter = overlay_hints_cache_.Get(plane_list); |
207 if (iter != overlay_hints_cache_.end()) | 260 if (iter != overlay_hints_cache_.end()) |
208 return; | 261 return; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 } | 300 } |
248 | 301 |
249 // Make sure we dont hold reference to buffer when caching this plane list. | 302 // Make sure we dont hold reference to buffer when caching this plane list. |
250 for (auto& plane : preferred_format_test_list) | 303 for (auto& plane : preferred_format_test_list) |
251 plane.buffer = nullptr; | 304 plane.buffer = nullptr; |
252 | 305 |
253 DCHECK(preferred_format_test_list.size() == overlay_hints.size()); | 306 DCHECK(preferred_format_test_list.size() == overlay_hints.size()); |
254 overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints); | 307 overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints); |
255 } | 308 } |
256 | 309 |
| 310 scoped_refptr<ScanoutBuffer> DrmOverlayValidator::GetBufferForPageFlip( |
| 311 const scoped_refptr<DrmDevice>& drm_device, |
| 312 ScanoutBufferGenerator* buffer_generator, |
| 313 const gfx::Size& size, |
| 314 uint32_t format) { |
| 315 // Check if we can re-use existing buffers. |
| 316 for (auto& reusable_buffer : overlay_buffers_cache_) { |
| 317 if (reusable_buffer.buffer->GetFramebufferPixelFormat() == format && |
| 318 reusable_buffer.buffer->GetSize() == size && |
| 319 !reusable_buffer.is_in_use) { |
| 320 reusable_buffer.is_in_use = true; |
| 321 return reusable_buffer.buffer; |
| 322 } |
| 323 } |
| 324 |
| 325 gfx::BufferFormat buffer_format = GetBufferFormatFromFourCCFormat(format); |
| 326 scoped_refptr<ScanoutBuffer> scanout_buffer = |
| 327 buffer_generator->Create(drm_device, buffer_format, size); |
| 328 |
| 329 overlay_buffers_cache_.push_back( |
| 330 OverlayBuffer(scanout_buffer, true /* is_in_use */)); |
| 331 |
| 332 return scanout_buffer; |
| 333 } |
| 334 |
257 } // namespace ui | 335 } // namespace ui |
OLD | NEW |