| 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::DrmOverlayValidator(DrmWindow* window) | 109 DrmOverlayValidator::DrmOverlayValidator( |
| 110 : window_(window), overlay_hints_cache_(kMaxCacheSize) {} | 110 DrmWindow* window, |
| 111 ScanoutBufferGenerator* buffer_generator) |
| 112 : window_(window), |
| 113 buffer_generator_(buffer_generator), |
| 114 overlay_hints_cache_(kMaxCacheSize) {} |
| 111 | 115 |
| 112 DrmOverlayValidator::~DrmOverlayValidator() {} | 116 DrmOverlayValidator::~DrmOverlayValidator() {} |
| 113 | 117 |
| 114 std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip( | 118 std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip( |
| 115 const std::vector<OverlayCheck_Params>& params, | 119 const std::vector<OverlayCheck_Params>& params, |
| 116 const OverlayPlaneList& last_used_planes, | 120 const OverlayPlaneList& last_used_planes) { |
| 117 ScanoutBufferGenerator* buffer_generator) { | |
| 118 std::vector<OverlayCheck_Params> validated_params = params; | 121 std::vector<OverlayCheck_Params> validated_params = params; |
| 119 HardwareDisplayController* controller = window_->GetController(); | 122 HardwareDisplayController* controller = window_->GetController(); |
| 120 if (!controller) { | 123 if (!controller) { |
| 121 // Nothing much we can do here. | 124 // Nothing much we can do here. |
| 122 for (auto& overlay : validated_params) | 125 for (auto& overlay : validated_params) |
| 123 overlay.is_overlay_candidate = false; | 126 overlay.is_overlay_candidate = false; |
| 124 | 127 |
| 125 return validated_params; | 128 return validated_params; |
| 126 } | 129 } |
| 127 | 130 |
| 128 OverlayPlaneList test_list; | 131 OverlayPlaneList test_list; |
| 129 std::vector<scoped_refptr<ScanoutBuffer>> reusable_buffers; | 132 std::vector<scoped_refptr<ScanoutBuffer>> reusable_buffers; |
| 130 scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); | 133 scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); |
| 131 | 134 |
| 132 for (const auto& plane : last_used_planes) | 135 for (const auto& plane : last_used_planes) |
| 133 reusable_buffers.push_back(plane.buffer); | 136 reusable_buffers.push_back(plane.buffer); |
| 134 | 137 |
| 135 for (auto& overlay : validated_params) { | 138 for (auto& overlay : validated_params) { |
| 136 if (!overlay.is_overlay_candidate) | 139 if (!overlay.is_overlay_candidate) |
| 137 continue; | 140 continue; |
| 138 | 141 |
| 139 gfx::Size scaled_buffer_size = GetScaledSize( | 142 gfx::Size scaled_buffer_size = GetScaledSize( |
| 140 overlay.buffer_size, overlay.display_rect, overlay.crop_rect); | 143 overlay.buffer_size, overlay.display_rect, overlay.crop_rect); |
| 141 | 144 |
| 142 scoped_refptr<ScanoutBuffer> buffer = GetBufferForPageFlipTest( | 145 scoped_refptr<ScanoutBuffer> buffer = GetBufferForPageFlipTest( |
| 143 drm, scaled_buffer_size, GetFourCCFormatForFramebuffer(overlay.format), | 146 drm, scaled_buffer_size, GetFourCCFormatForFramebuffer(overlay.format), |
| 144 buffer_generator, &reusable_buffers); | 147 buffer_generator_, &reusable_buffers); |
| 145 DCHECK(buffer); | 148 DCHECK(buffer); |
| 146 | 149 |
| 147 OverlayPlane plane(buffer, overlay.plane_z_order, overlay.transform, | 150 OverlayPlane plane(buffer, overlay.plane_z_order, overlay.transform, |
| 148 overlay.display_rect, overlay.crop_rect); | 151 overlay.display_rect, overlay.crop_rect); |
| 149 test_list.push_back(plane); | 152 test_list.push_back(plane); |
| 150 | 153 |
| 151 if (controller->TestPageFlip(test_list)) { | 154 if (controller->TestPageFlip(test_list)) { |
| 152 overlay.is_overlay_candidate = true; | 155 overlay.is_overlay_candidate = true; |
| 153 } else { | 156 } else { |
| 154 // If test failed here, platform cannot support this configuration | 157 // If test failed here, platform cannot support this configuration |
| 155 // with current combination of layers. This is usually the case when this | 158 // with current combination of layers. This is usually the case when this |
| 156 // plane has requested post processing capability which needs additional | 159 // plane has requested post processing capability which needs additional |
| 157 // hardware resources and they might be already in use by other planes. | 160 // hardware resources and they might be already in use by other planes. |
| 158 // For example this plane has requested scaling capabilities and all | 161 // For example this plane has requested scaling capabilities and all |
| 159 // available scalars are already in use by other planes. | 162 // available scalars are already in use by other planes. |
| 160 DCHECK(test_list.size() > 1); | 163 DCHECK(test_list.size() > 1); |
| 161 overlay.is_overlay_candidate = false; | 164 overlay.is_overlay_candidate = false; |
| 162 test_list.pop_back(); | 165 test_list.pop_back(); |
| 163 } | 166 } |
| 164 } | 167 } |
| 165 | 168 |
| 166 UpdateOverlayHintsCache(drm, test_list, buffer_generator, &reusable_buffers); | 169 UpdateOverlayHintsCache(drm, test_list, &reusable_buffers); |
| 167 | 170 |
| 168 return validated_params; | 171 return validated_params; |
| 169 } | 172 } |
| 170 | 173 |
| 171 uint32_t DrmOverlayValidator::GetOptimalBufferFormat( | 174 OverlayPlaneList DrmOverlayValidator::PrepareBuffersForPageFlip( |
| 172 const OverlayPlane& plane, | 175 const OverlayPlaneList& planes) { |
| 173 const OverlayPlaneList& plane_list) const { | 176 if (planes.size() <= 1) |
| 174 const auto& iter = overlay_hints_cache_.Peek(plane_list); | 177 return planes; |
| 175 // We dont have any information in cache about this combination of layers, | |
| 176 // return standard BGRX format. | |
| 177 if (iter == overlay_hints_cache_.end()) | |
| 178 return DRM_FORMAT_XRGB8888; | |
| 179 | 178 |
| 180 DCHECK(plane_list.size() == iter->second.size()); | 179 HardwareDisplayController* controller = window_->GetController(); |
| 180 if (!controller) |
| 181 return planes; |
| 181 | 182 |
| 182 size_t size = plane_list.size(); | 183 OverlayPlaneList pending_planes = planes; |
| 183 uint32_t index; | 184 const auto& overlay_hints = overlay_hints_cache_.Get(planes); |
| 184 for (index = 0; index < size; index++) { | 185 |
| 185 const OverlayPlane& test_plane = plane_list.at(index); | 186 size_t size = planes.size(); |
| 186 if (test_plane.z_order == plane.z_order && | 187 bool use_hints = overlay_hints != overlay_hints_cache_.end(); |
| 187 test_plane.plane_transform == plane.plane_transform && | 188 |
| 188 test_plane.display_bounds == plane.display_bounds && | 189 for (size_t i = 0; i < size; i++) { |
| 189 test_plane.crop_rect == plane.crop_rect) { | 190 auto& plane = pending_planes.at(i); |
| 190 break; | 191 if (plane.processing_callback.is_null()) |
| 192 continue; |
| 193 |
| 194 uint32_t original_format = plane.buffer->GetFramebufferPixelFormat(); |
| 195 uint32_t target_format = original_format; |
| 196 |
| 197 const gfx::Size& original_size = plane.buffer->GetSize(); |
| 198 gfx::Size target_size = |
| 199 GetScaledSize(original_size, plane.display_bounds, plane.crop_rect); |
| 200 |
| 201 if (use_hints) { |
| 202 DCHECK(size == overlay_hints->second.size()); |
| 203 const OverlayHints& hints = overlay_hints->second.at(i); |
| 204 target_format = hints.optimal_format; |
| 205 |
| 206 // We can handle plane scaling, avoid scaling buffer here. |
| 207 if (!hints.handle_scaling) |
| 208 target_size = original_size; |
| 209 } |
| 210 |
| 211 if (original_size != target_size || original_format != target_format) { |
| 212 scoped_refptr<ScanoutBuffer> processed_buffer = |
| 213 plane.processing_callback.Run(target_size, target_format); |
| 214 |
| 215 if (processed_buffer) |
| 216 plane.buffer = processed_buffer; |
| 191 } | 217 } |
| 192 } | 218 } |
| 193 | 219 |
| 194 return iter->second.at(index).optimal_format; | 220 return pending_planes; |
| 195 } | 221 } |
| 196 | 222 |
| 197 void DrmOverlayValidator::ClearCache() { | 223 void DrmOverlayValidator::ClearCache() { |
| 198 overlay_hints_cache_.Clear(); | 224 overlay_hints_cache_.Clear(); |
| 199 } | 225 } |
| 200 | 226 |
| 201 void DrmOverlayValidator::UpdateOverlayHintsCache( | 227 void DrmOverlayValidator::UpdateOverlayHintsCache( |
| 202 const scoped_refptr<DrmDevice>& drm, | 228 const scoped_refptr<DrmDevice>& drm, |
| 203 const OverlayPlaneList& plane_list, | 229 const OverlayPlaneList& plane_list, |
| 204 ScanoutBufferGenerator* buffer_generator, | |
| 205 std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers) { | 230 std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers) { |
| 206 const auto& iter = overlay_hints_cache_.Get(plane_list); | 231 const auto& iter = overlay_hints_cache_.Get(plane_list); |
| 207 if (iter != overlay_hints_cache_.end()) | 232 if (iter != overlay_hints_cache_.end()) |
| 208 return; | 233 return; |
| 209 | 234 |
| 210 OverlayPlaneList preferred_format_test_list = plane_list; | 235 OverlayPlaneList preferred_format_test_list = plane_list; |
| 211 HardwareDisplayController* controller = window_->GetController(); | 236 HardwareDisplayController* controller = window_->GetController(); |
| 212 OverlayHintsList overlay_hints; | 237 OverlayHintsList overlay_hints; |
| 213 for (auto& plane : preferred_format_test_list) { | 238 for (auto& plane : preferred_format_test_list) { |
| 214 uint32_t original_format = plane.buffer->GetFramebufferPixelFormat(); | 239 uint32_t original_format = plane.buffer->GetFramebufferPixelFormat(); |
| 215 | 240 |
| 216 if (plane.z_order == 0) { | 241 if (plane.z_order == 0) { |
| 217 overlay_hints.push_back( | 242 overlay_hints.push_back( |
| 218 OverlayHints(original_format, true /* scaling */)); | 243 OverlayHints(original_format, true /* scaling */)); |
| 219 continue; | 244 continue; |
| 220 } | 245 } |
| 221 | 246 |
| 222 uint32_t optimal_format = FindOptimalBufferFormat( | 247 uint32_t optimal_format = FindOptimalBufferFormat( |
| 223 original_format, plane.z_order, plane.display_bounds, window_->bounds(), | 248 original_format, plane.z_order, plane.display_bounds, window_->bounds(), |
| 224 controller); | 249 controller); |
| 225 | 250 |
| 226 if (optimal_format != original_format) { | 251 if (optimal_format != original_format) { |
| 227 scoped_refptr<ScanoutBuffer> original_buffer = plane.buffer; | 252 scoped_refptr<ScanoutBuffer> original_buffer = plane.buffer; |
| 228 plane.buffer = | 253 plane.buffer = |
| 229 GetBufferForPageFlipTest(drm, plane.buffer->GetSize(), optimal_format, | 254 GetBufferForPageFlipTest(drm, plane.buffer->GetSize(), optimal_format, |
| 230 buffer_generator, reusable_buffers); | 255 buffer_generator_, reusable_buffers); |
| 231 | 256 |
| 232 if (!controller->TestPageFlip(preferred_format_test_list)) { | 257 if (!controller->TestPageFlip(preferred_format_test_list)) { |
| 233 // If test failed here, it means even though optimal_format is | 258 // If test failed here, it means even though optimal_format is |
| 234 // supported, platform cannot support it with current combination of | 259 // supported, platform cannot support it with current combination of |
| 235 // layers. This is usually the case when optimal_format needs certain | 260 // layers. This is usually the case when optimal_format needs certain |
| 236 // capabilites (i.e. conversion, scaling etc) and needed hardware | 261 // capabilites (i.e. conversion, scaling etc) and needed hardware |
| 237 // resources might be already in use. Fall back to original format. | 262 // resources might be already in use. Fall back to original format. |
| 238 optimal_format = original_format; | 263 optimal_format = original_format; |
| 239 plane.buffer = original_buffer; | 264 plane.buffer = original_buffer; |
| 240 } | 265 } |
| 241 } | 266 } |
| 242 | 267 |
| 243 // TODO(kalyank): We always request scaling to be done by 3D engine, VPP | 268 // TODO(kalyank): We always request scaling to be done by 3D engine, VPP |
| 244 // etc. We should use them only if downscaling is needed and let display | 269 // etc. We should use them only if downscaling is needed and let display |
| 245 // controller handle up-scaling on platforms which support it. | 270 // controller handle up-scaling on platforms which support it. |
| 246 overlay_hints.push_back(OverlayHints(optimal_format, true /* scaling */)); | 271 overlay_hints.push_back(OverlayHints(optimal_format, true /* scaling */)); |
| 247 } | 272 } |
| 248 | 273 |
| 249 // Make sure we dont hold reference to buffer when caching this plane list. | 274 // Make sure we dont hold reference to buffer when caching this plane list. |
| 250 for (auto& plane : preferred_format_test_list) | 275 for (auto& plane : preferred_format_test_list) |
| 251 plane.buffer = nullptr; | 276 plane.buffer = nullptr; |
| 252 | 277 |
| 253 DCHECK(preferred_format_test_list.size() == overlay_hints.size()); | 278 DCHECK(preferred_format_test_list.size() == overlay_hints.size()); |
| 254 overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints); | 279 overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints); |
| 255 } | 280 } |
| 256 | 281 |
| 257 } // namespace ui | 282 } // namespace ui |
| OLD | NEW |