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 |