Index: ui/ozone/platform/drm/gpu/drm_overlay_validator.cc |
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc |
index 6604e83dd58f2ab3d0f6f75bc00c5f94ca07cec4..9a0e03b6ef1054505166e1b5c03900eab072c966 100644 |
--- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc |
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc |
@@ -106,6 +106,13 @@ DrmOverlayValidator::OverlayHints::OverlayHints(uint32_t format, |
DrmOverlayValidator::OverlayHints::~OverlayHints() {} |
+DrmOverlayValidator::OverlayBuffer::OverlayBuffer( |
+ const scoped_refptr<ScanoutBuffer>& buffer, |
+ bool is_in_use) |
+ : buffer(buffer), is_in_use(is_in_use) {} |
+ |
+DrmOverlayValidator::OverlayBuffer::~OverlayBuffer() {} |
+ |
DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) |
: window_(window), overlay_hints_cache_(kMaxCacheSize) {} |
@@ -168,34 +175,80 @@ std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip( |
return validated_params; |
} |
-uint32_t DrmOverlayValidator::GetOptimalBufferFormat( |
- const OverlayPlane& plane, |
- const OverlayPlaneList& plane_list) const { |
- const auto& iter = overlay_hints_cache_.Peek(plane_list); |
- // We dont have any information in cache about this combination of layers, |
- // return standard BGRX format. |
- if (iter == overlay_hints_cache_.end()) |
- return DRM_FORMAT_XRGB8888; |
- |
- DCHECK(plane_list.size() == iter->second.size()); |
- |
- size_t size = plane_list.size(); |
- uint32_t index; |
- for (index = 0; index < size; index++) { |
- const OverlayPlane& test_plane = plane_list.at(index); |
- if (test_plane.z_order == plane.z_order && |
- test_plane.plane_transform == plane.plane_transform && |
- test_plane.display_bounds == plane.display_bounds && |
- test_plane.crop_rect == plane.crop_rect) { |
- break; |
+OverlayPlaneList DrmOverlayValidator::ValidatePlanesForPageFlip( |
+ const OverlayPlaneList& planes, |
+ ScanoutBufferGenerator* buffer_generator) { |
+ // Release any OverlayBuffer which is not in use and mark any in use as |
+ // available. |
+ if (!overlay_buffers_cache_.empty()) { |
+ std::vector<OverlayBuffer> re_usable_buffers; |
+ for (const auto& processing_buffer : overlay_buffers_cache_) { |
+ if (processing_buffer.is_in_use) { |
+ re_usable_buffers.push_back(processing_buffer); |
+ re_usable_buffers.back().is_in_use = false; |
+ } |
} |
+ |
+ overlay_buffers_cache_.swap(re_usable_buffers); |
} |
- return iter->second.at(index).optimal_format; |
+ if (planes.size() <= 1) |
+ return planes; |
+ |
+ HardwareDisplayController* controller = window_->GetController(); |
+ if (!controller) |
+ return planes; |
+ |
+ OverlayPlaneList pending_planes = planes; |
+ std::sort(pending_planes.begin(), pending_planes.end(), |
+ [](const OverlayPlane& l, const OverlayPlane& r) { |
+ return l.z_order < r.z_order; |
+ }); |
+ |
+ const auto& iter = overlay_hints_cache_.Get(planes); |
+ scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); |
+ |
+ size_t size = planes.size(); |
+ bool use_hints = iter != overlay_hints_cache_.end(); |
+ |
+ for (size_t i = 0; i < size; i++) { |
+ auto& plane = pending_planes.at(i); |
+ if (plane.processing_callback.is_null()) |
+ continue; |
+ |
+ uint32_t original_format = plane.buffer->GetFramebufferPixelFormat(); |
+ uint32_t target_format = original_format; |
+ |
+ const gfx::Size& original_size = plane.buffer->GetSize(); |
+ gfx::Size target_size = |
+ GetScaledSize(original_size, plane.display_bounds, plane.crop_rect); |
+ |
+ if (use_hints) { |
+ DCHECK(size == iter->second.size()); |
+ const OverlayHints& hints = iter->second.at(i); |
+ target_format = hints.optimal_format; |
+ |
+ // We can handle plane scaling, avoid scaling buffer here. |
+ if (!hints.handle_scaling) |
+ target_size = original_size; |
+ } |
+ |
+ if (original_size != target_size || original_format != target_format) { |
+ scoped_refptr<ScanoutBuffer> buffer = GetBufferForPageFlip( |
+ drm, buffer_generator, target_size, target_format); |
+ DCHECK(buffer); |
+ |
+ if (plane.processing_callback.Run(plane.buffer, buffer)) |
+ plane.buffer = buffer; |
+ } |
+ } |
+ |
+ return pending_planes; |
} |
void DrmOverlayValidator::ClearCache() { |
overlay_hints_cache_.Clear(); |
+ overlay_buffers_cache_.clear(); |
} |
void DrmOverlayValidator::UpdateOverlayHintsCache( |
@@ -254,4 +307,29 @@ void DrmOverlayValidator::UpdateOverlayHintsCache( |
overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints); |
} |
+scoped_refptr<ScanoutBuffer> DrmOverlayValidator::GetBufferForPageFlip( |
+ const scoped_refptr<DrmDevice>& drm_device, |
+ ScanoutBufferGenerator* buffer_generator, |
+ const gfx::Size& size, |
+ uint32_t format) { |
+ // Check if we can re-use existing buffers. |
+ for (auto& reusable_buffer : overlay_buffers_cache_) { |
+ if (reusable_buffer.buffer->GetFramebufferPixelFormat() == format && |
+ reusable_buffer.buffer->GetSize() == size && |
+ !reusable_buffer.is_in_use) { |
+ reusable_buffer.is_in_use = true; |
+ return reusable_buffer.buffer; |
+ } |
+ } |
+ |
+ gfx::BufferFormat buffer_format = GetBufferFormatFromFourCCFormat(format); |
+ scoped_refptr<ScanoutBuffer> scanout_buffer = |
+ buffer_generator->Create(drm_device, buffer_format, size); |
+ |
+ overlay_buffers_cache_.push_back( |
+ OverlayBuffer(scanout_buffer, true /* is_in_use */)); |
+ |
+ return scanout_buffer; |
+} |
+ |
} // namespace ui |