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 |