Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/ozone/platform/drm/gpu/drm_overlay_candidate.h" | |
| 6 | |
| 7 #include <drm_fourcc.h> | |
| 8 | |
| 9 #include "ui/gfx/geometry/size_conversions.h" | |
| 10 #include "ui/ozone/platform/drm/gpu/drm_device.h" | |
| 11 #include "ui/ozone/platform/drm/gpu/drm_window.h" | |
| 12 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" | |
| 13 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h" | |
| 14 | |
| 15 namespace ui { | |
| 16 | |
| 17 DrmOverlayCandidate::DrmOverlayCandidate(DrmWindow* window) : window_(window) {} | |
| 18 | |
| 19 DrmOverlayCandidate::~DrmOverlayCandidate() {} | |
| 20 | |
| 21 std::vector<OverlayCheck_Params> DrmOverlayCandidate::TestPageFlip( | |
| 22 const std::vector<OverlayCheck_Params>& current_combination, | |
| 23 const std::vector<OverlayCheck_Params>& new_combination, | |
| 24 const OverlayPlaneList& last_used_planes, | |
| 25 ScanoutBufferGenerator* buffer_generator) { | |
| 26 std::vector<OverlayCheck_Params> validated_params; | |
| 27 HardwareDisplayController* controller = window_->GetController(); | |
| 28 if (!controller) { | |
| 29 // Nothing much we can do here. | |
| 30 return validated_params; | |
| 31 } | |
| 32 | |
| 33 overlay_params_.clear(); | |
| 34 OverlayPlaneList test_list; | |
| 35 std::vector<scoped_refptr<ScanoutBuffer>> reusable_buffers; | |
| 36 scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); | |
| 37 const OverlayPlane& primary_plane = | |
| 38 *OverlayPlane::GetPrimaryPlane(last_used_planes); | |
| 39 | |
| 40 for (const auto& plane : last_used_planes) | |
| 41 reusable_buffers.push_back(plane.buffer); | |
| 42 | |
| 43 // We save the current in use configurations as we might have frames using | |
| 44 // these configurations queued in SurfaceOzone. | |
| 45 for (const auto& param : current_combination) | |
| 46 overlay_params_.push_back(param); | |
| 47 | |
| 48 for (const auto& overlay : new_combination) { | |
| 49 bool needs_flip_test = true; | |
| 50 OverlayCheck_Params param(overlay); | |
| 51 DCHECK(param.state != OverlayCheck_Params::kInvalid); | |
| 52 OverlayPlane plane(nullptr, overlay.plane_z_order, overlay.transform, | |
| 53 overlay.display_rect, overlay.crop_rect); | |
| 54 | |
| 55 if (param.state == OverlayCheck_Params::kTest) | |
| 56 EvaluateBufferConfiguration(¶m, controller); | |
| 57 | |
| 58 // We expect this combination to always work. | |
| 59 if (param.plane_z_order == 0 && | |
| 60 param.required_buffer_size == primary_plane.buffer->GetSize() && | |
| 61 param.optimal_format == gfx::BufferFormat::BGRX_8888) { | |
| 62 param.state = OverlayCheck_Params::kOverlay; | |
| 63 plane.buffer = primary_plane.buffer; | |
| 64 overlay_params_.push_back(param); | |
| 65 validated_params.push_back(param); | |
| 66 test_list.push_back(plane); | |
| 67 continue; | |
| 68 } | |
| 69 | |
| 70 if (param.state != OverlayCheck_Params::kTest) { | |
| 71 plane.buffer = GetBufferForPageFlipTest( | |
| 72 buffer_generator, &reusable_buffers, param.required_buffer_size, | |
| 73 param.optimal_format, drm); | |
| 74 } else { | |
| 75 ValidateConfiguration(buffer_generator, &plane, ¶m, &reusable_buffers, | |
| 76 primary_plane, drm); | |
| 77 // We can skip page flip test in case test_list size is less than 2 as the | |
| 78 // result will be same as in ValidateConfiguration. | |
| 79 needs_flip_test = test_list.size() > 1; | |
| 80 } | |
| 81 | |
| 82 if (!plane.buffer) { | |
| 83 param.state = OverlayCheck_Params::kInvalid; | |
| 84 validated_params.push_back(param); | |
| 85 continue; | |
| 86 } | |
| 87 | |
| 88 test_list.push_back(plane); | |
| 89 bool status = true; | |
| 90 if (needs_flip_test) | |
| 91 status = controller->TestPageFlip(test_list); | |
| 92 | |
| 93 if (status) { | |
| 94 param.state = OverlayCheck_Params::kOverlay; | |
| 95 overlay_params_.push_back(param); | |
| 96 } else { | |
| 97 // If test failed here, it means even though this configuration is | |
| 98 // compatible, platform cannot support the current combination of layers. | |
| 99 // This is usually the case when this plane has requested post processing | |
| 100 // capability which needs additional hardware resources and they might | |
| 101 // be already in use by other planes. For example this plane has requested | |
| 102 // scaling capabilities and all available scalars are already in use by | |
| 103 // other planes. | |
| 104 DCHECK(test_list.size() > 1); | |
| 105 param.state = OverlayCheck_Params::kCompatible; | |
| 106 test_list.pop_back(); | |
| 107 } | |
| 108 | |
| 109 validated_params.push_back(param); | |
| 110 } | |
| 111 | |
| 112 return validated_params; | |
| 113 } | |
| 114 | |
| 115 std::vector<OverlayCheck_Params> DrmOverlayCandidate::GetOverlayConfigurations() | |
| 116 const { | |
| 117 return overlay_params_; | |
| 118 } | |
| 119 | |
| 120 scoped_refptr<ScanoutBuffer> DrmOverlayCandidate::GetBufferForPageFlipTest( | |
| 121 ScanoutBufferGenerator* buffer_generator, | |
| 122 std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers, | |
| 123 const gfx::Size& size, | |
| 124 gfx::BufferFormat buffer_format, | |
| 125 const scoped_refptr<DrmDevice>& drm_device) { | |
| 126 scoped_refptr<ScanoutBuffer> scanout_buffer; | |
| 127 uint32_t format = GetFourCCFormatFromBufferFormat(buffer_format); | |
| 128 // Check if we can re-use existing buffers. | |
| 129 for (const auto& buffer : *reusable_buffers) { | |
| 130 if (buffer->GetFramebufferPixelFormat() == format && | |
| 131 buffer->GetSize() == size) { | |
| 132 scanout_buffer = buffer; | |
| 133 break; | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 if (!scanout_buffer) { | |
| 138 scanout_buffer = buffer_generator->Create(drm_device, buffer_format, size); | |
| 139 reusable_buffers->push_back(scanout_buffer); | |
| 140 } | |
| 141 | |
| 142 return scanout_buffer; | |
| 143 } | |
| 144 | |
| 145 void DrmOverlayCandidate::ValidateConfiguration( | |
|
dnicoara
2015/11/23 19:22:54
Could you document what this does? My understandin
| |
| 146 ScanoutBufferGenerator* buffer_generator, | |
| 147 OverlayPlane* plane, | |
| 148 OverlayCheck_Params* param, | |
| 149 std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers, | |
| 150 const OverlayPlane& primary_plane, | |
| 151 const scoped_refptr<DrmDevice>& drm) { | |
| 152 OverlayPlaneList compatible_test_list; | |
| 153 HardwareDisplayController* controller = window_->GetController(); | |
| 154 | |
| 155 plane->buffer = GetBufferForPageFlipTest(buffer_generator, reusable_buffers, | |
| 156 param->required_buffer_size, | |
| 157 param->optimal_format, drm); | |
| 158 | |
| 159 if (!plane->buffer) | |
| 160 return; | |
| 161 | |
| 162 if (plane->z_order != 0) | |
| 163 compatible_test_list.push_back(primary_plane); | |
| 164 | |
| 165 compatible_test_list.push_back(*plane); | |
| 166 | |
| 167 bool compatible = controller->TestPageFlip(compatible_test_list); | |
| 168 | |
| 169 if (!compatible) { | |
| 170 plane->buffer = nullptr; | |
| 171 if (param->optimal_format == param->format) | |
| 172 return; | |
| 173 | |
| 174 // We tried to optimize the format and failed, check if original format | |
| 175 // request can be supported. | |
| 176 param->optimal_format = param->format; | |
| 177 plane->buffer = GetBufferForPageFlipTest(buffer_generator, reusable_buffers, | |
| 178 param->required_buffer_size, | |
| 179 param->optimal_format, drm); | |
| 180 | |
| 181 if (!plane->buffer) | |
| 182 return; | |
| 183 | |
| 184 compatible_test_list.back().buffer = plane->buffer; | |
| 185 | |
| 186 if (!controller->TestPageFlip(compatible_test_list)) | |
| 187 plane->buffer = nullptr; | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 void DrmOverlayCandidate::EvaluateBufferConfiguration( | |
| 192 OverlayCheck_Params* param, | |
| 193 HardwareDisplayController* controller) { | |
| 194 uint32_t plane_z_order = param->plane_z_order; | |
| 195 // TODO(kalyank): We always request scaling to be done by 3D engine, VPP etc. | |
| 196 // We should only use them only if downscaling is needed and let display | |
| 197 // controller handle up-scaling on platforms which support it. | |
| 198 if (!param->crop_rect.IsEmpty()) { | |
| 199 param->required_buffer_size = gfx::ToCeiledSize( | |
| 200 gfx::SizeF(param->display_rect.width() / param->crop_rect.width(), | |
| 201 param->display_rect.height() / param->crop_rect.height())); | |
| 202 } | |
| 203 | |
| 204 gfx::BufferFormat format = param->format; | |
| 205 // TODO(kalyank): We assume that it's always a Video buffer in case | |
| 206 // plane_z_order > 0. This needs to be revisited when we add Overlay support | |
| 207 // for other layers. | |
| 208 if (param->plane_z_order > 0) { | |
| 209 format = gfx::BufferFormat::BGRX_8888; | |
|
dnicoara
2015/11/23 19:22:54
Shouldn't this be in the following if-statement? W
| |
| 210 // Full screen is a special case, Plane manager will collapse Overlay plane | |
| 211 // to primary. | |
| 212 if (param->display_rect == window_->bounds()) | |
| 213 plane_z_order = 0; | |
| 214 | |
| 215 // TODO(kalyank): In fullscreen case, we always fall back to BGRX format. | |
| 216 // Currently, PlaneManager collapses planes to one only if format is BGRX. | |
| 217 // This is due to the fact that page flip can fail on non-atomic kernels, | |
| 218 // when trying to flip a buffer of format other than what was used during | |
| 219 // Modeset with primary. However, with Atomic we can use test commit to | |
| 220 // check if the actual commit will pass or not and make a decision. Remove | |
| 221 // this restriction here and in plane manager once we are able to test it. | |
| 222 if (plane_z_order && | |
| 223 controller->IsFormatSupported(DRM_FORMAT_UYVY, plane_z_order)) { | |
| 224 format = gfx::BufferFormat::UYVY_422; | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 param->optimal_format = format; | |
| 229 } | |
| 230 | |
| 231 } // namespace ui | |
| OLD | NEW |