blob: 21f0ce8b153721280e40e6e59c4f8e78b69a53c6 [file] [log] [blame]
Lloyd Piquecc01a452018-12-04 17:24:00 -08001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080017#include <android-base/stringprintf.h>
Lloyd Pique07e33212018-12-18 16:33:37 -080018#include <compositionengine/CompositionEngine.h>
Lloyd Piquef5275482019-01-29 18:42:42 -080019#include <compositionengine/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080020#include <compositionengine/Layer.h>
21#include <compositionengine/LayerFE.h>
22#include <compositionengine/Output.h>
Lloyd Piquea83776c2019-01-29 18:42:32 -080023#include <compositionengine/impl/LayerCompositionState.h>
24#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080025#include <compositionengine/impl/OutputLayer.h>
Lloyd Piquea83776c2019-01-29 18:42:32 -080026#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080027
Lloyd Pique07e33212018-12-18 16:33:37 -080028#include "DisplayHardware/HWComposer.h"
29
Lloyd Piquecc01a452018-12-04 17:24:00 -080030namespace android::compositionengine {
31
32OutputLayer::~OutputLayer() = default;
33
34namespace impl {
35
Lloyd Piquea83776c2019-01-29 18:42:32 -080036namespace {
37
38FloatRect reduce(const FloatRect& win, const Region& exclude) {
39 if (CC_LIKELY(exclude.isEmpty())) {
40 return win;
41 }
42 // Convert through Rect (by rounding) for lack of FloatRegion
43 return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
44}
45
46} // namespace
47
Lloyd Piquecc01a452018-12-04 17:24:00 -080048std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
Lloyd Pique07e33212018-12-18 16:33:37 -080049 const CompositionEngine& compositionEngine, std::optional<DisplayId> displayId,
50 const compositionengine::Output& output, std::shared_ptr<compositionengine::Layer> layer,
Lloyd Piquecc01a452018-12-04 17:24:00 -080051 sp<compositionengine::LayerFE> layerFE) {
Lloyd Pique07e33212018-12-18 16:33:37 -080052 auto result = std::make_unique<OutputLayer>(output, layer, layerFE);
53 result->initialize(compositionEngine, displayId);
54 return result;
Lloyd Piquecc01a452018-12-04 17:24:00 -080055}
56
57OutputLayer::OutputLayer(const Output& output, std::shared_ptr<Layer> layer, sp<LayerFE> layerFE)
58 : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
59
60OutputLayer::~OutputLayer() = default;
61
Lloyd Pique07e33212018-12-18 16:33:37 -080062void OutputLayer::initialize(const CompositionEngine& compositionEngine,
63 std::optional<DisplayId> displayId) {
64 if (!displayId) {
65 return;
66 }
67
68 auto& hwc = compositionEngine.getHwComposer();
69
70 mState.hwc.emplace(std::shared_ptr<HWC2::Layer>(hwc.createLayer(*displayId),
71 [&hwc, displayId](HWC2::Layer* layer) {
72 hwc.destroyLayer(*displayId, layer);
73 }));
74}
75
Lloyd Piquecc01a452018-12-04 17:24:00 -080076const compositionengine::Output& OutputLayer::getOutput() const {
77 return mOutput;
78}
79
80compositionengine::Layer& OutputLayer::getLayer() const {
81 return *mLayer;
82}
83
84compositionengine::LayerFE& OutputLayer::getLayerFE() const {
85 return *mLayerFE;
86}
87
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080088const OutputLayerCompositionState& OutputLayer::getState() const {
89 return mState;
90}
91
92OutputLayerCompositionState& OutputLayer::editState() {
93 return mState;
94}
95
Lloyd Piquea83776c2019-01-29 18:42:32 -080096Rect OutputLayer::calculateInitialCrop() const {
97 const auto& layerState = mLayer->getState().frontEnd;
98
99 // apply the projection's clipping to the window crop in
100 // layerstack space, and convert-back to layer space.
101 // if there are no window scaling involved, this operation will map to full
102 // pixels in the buffer.
103
104 FloatRect activeCropFloat =
105 reduce(layerState.geomLayerBounds, layerState.geomActiveTransparentRegion);
106
107 const Rect& viewport = mOutput.getState().viewport;
108 const ui::Transform& layerTransform = layerState.geomLayerTransform;
109 const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
110 // Transform to screen space.
111 activeCropFloat = layerTransform.transform(activeCropFloat);
112 activeCropFloat = activeCropFloat.intersect(viewport.toFloatRect());
113 // Back to layer space to work with the content crop.
114 activeCropFloat = inverseLayerTransform.transform(activeCropFloat);
115
116 // This needs to be here as transform.transform(Rect) computes the
117 // transformed rect and then takes the bounding box of the result before
118 // returning. This means
119 // transform.inverse().transform(transform.transform(Rect)) != Rect
120 // in which case we need to make sure the final rect is clipped to the
121 // display bounds.
122 Rect activeCrop{activeCropFloat};
123 if (!activeCrop.intersect(layerState.geomBufferSize, &activeCrop)) {
124 activeCrop.clear();
125 }
126 return activeCrop;
127}
128
129FloatRect OutputLayer::calculateOutputSourceCrop() const {
130 const auto& layerState = mLayer->getState().frontEnd;
131 const auto& outputState = mOutput.getState();
132
133 if (!layerState.geomUsesSourceCrop) {
134 return {};
135 }
136
137 // the content crop is the area of the content that gets scaled to the
138 // layer's size. This is in buffer space.
139 FloatRect crop = layerState.geomContentCrop.toFloatRect();
140
141 // In addition there is a WM-specified crop we pull from our drawing state.
142 Rect activeCrop = calculateInitialCrop();
143 const Rect& bufferSize = layerState.geomBufferSize;
144
145 int winWidth = bufferSize.getWidth();
146 int winHeight = bufferSize.getHeight();
147
148 // The bufferSize for buffer state layers can be unbounded ([0, 0, -1, -1])
149 // if display frame hasn't been set and the parent is an unbounded layer.
150 if (winWidth < 0 && winHeight < 0) {
151 return crop;
152 }
153
154 // Transform the window crop to match the buffer coordinate system,
155 // which means using the inverse of the current transform set on the
156 // SurfaceFlingerConsumer.
157 uint32_t invTransform = layerState.geomBufferTransform;
158 if (layerState.geomBufferUsesDisplayInverseTransform) {
159 /*
160 * the code below applies the primary display's inverse transform to the
161 * buffer
162 */
163 uint32_t invTransformOrient = outputState.orientation;
164 // calculate the inverse transform
165 if (invTransformOrient & HAL_TRANSFORM_ROT_90) {
166 invTransformOrient ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
167 }
168 // and apply to the current transform
169 invTransform =
170 (ui::Transform(invTransformOrient) * ui::Transform(invTransform)).getOrientation();
171 }
172
173 if (invTransform & HAL_TRANSFORM_ROT_90) {
174 // If the activeCrop has been rotate the ends are rotated but not
175 // the space itself so when transforming ends back we can't rely on
176 // a modification of the axes of rotation. To account for this we
177 // need to reorient the inverse rotation in terms of the current
178 // axes of rotation.
179 bool is_h_flipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
180 bool is_v_flipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
181 if (is_h_flipped == is_v_flipped) {
182 invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
183 }
184 std::swap(winWidth, winHeight);
185 }
186 const Rect winCrop =
187 activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
188
189 // below, crop is intersected with winCrop expressed in crop's coordinate space
190 float xScale = crop.getWidth() / float(winWidth);
191 float yScale = crop.getHeight() / float(winHeight);
192
193 float insetL = winCrop.left * xScale;
194 float insetT = winCrop.top * yScale;
195 float insetR = (winWidth - winCrop.right) * xScale;
196 float insetB = (winHeight - winCrop.bottom) * yScale;
197
198 crop.left += insetL;
199 crop.top += insetT;
200 crop.right -= insetR;
201 crop.bottom -= insetB;
202
203 return crop;
204}
205
206Rect OutputLayer::calculateOutputDisplayFrame() const {
207 const auto& layerState = mLayer->getState().frontEnd;
208 const auto& outputState = mOutput.getState();
209
210 // apply the layer's transform, followed by the display's global transform
211 // here we're guaranteed that the layer's transform preserves rects
212 Region activeTransparentRegion = layerState.geomActiveTransparentRegion;
213 const ui::Transform& layerTransform = layerState.geomLayerTransform;
214 const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
215 const Rect& bufferSize = layerState.geomBufferSize;
216 Rect activeCrop = layerState.geomCrop;
217 if (!activeCrop.isEmpty() && bufferSize.isValid()) {
218 activeCrop = layerTransform.transform(activeCrop);
219 if (!activeCrop.intersect(outputState.viewport, &activeCrop)) {
220 activeCrop.clear();
221 }
222 activeCrop = inverseLayerTransform.transform(activeCrop, true);
223 // This needs to be here as transform.transform(Rect) computes the
224 // transformed rect and then takes the bounding box of the result before
225 // returning. This means
226 // transform.inverse().transform(transform.transform(Rect)) != Rect
227 // in which case we need to make sure the final rect is clipped to the
228 // display bounds.
229 if (!activeCrop.intersect(bufferSize, &activeCrop)) {
230 activeCrop.clear();
231 }
232 // mark regions outside the crop as transparent
233 activeTransparentRegion.orSelf(Rect(0, 0, bufferSize.getWidth(), activeCrop.top));
234 activeTransparentRegion.orSelf(
235 Rect(0, activeCrop.bottom, bufferSize.getWidth(), bufferSize.getHeight()));
236 activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
237 activeTransparentRegion.orSelf(
238 Rect(activeCrop.right, activeCrop.top, bufferSize.getWidth(), activeCrop.bottom));
239 }
240
241 // reduce uses a FloatRect to provide more accuracy during the
242 // transformation. We then round upon constructing 'frame'.
243 Rect frame{
244 layerTransform.transform(reduce(layerState.geomLayerBounds, activeTransparentRegion))};
245 if (!frame.intersect(outputState.viewport, &frame)) {
246 frame.clear();
247 }
248 const ui::Transform displayTransform{outputState.transform};
249
250 return displayTransform.transform(frame);
251}
252
253uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
254 const auto& layerState = mLayer->getState().frontEnd;
255 const auto& outputState = mOutput.getState();
256
257 /*
258 * Transformations are applied in this order:
259 * 1) buffer orientation/flip/mirror
260 * 2) state transformation (window manager)
261 * 3) layer orientation (screen orientation)
262 * (NOTE: the matrices are multiplied in reverse order)
263 */
264 const ui::Transform& layerTransform = layerState.geomLayerTransform;
265 const ui::Transform displayTransform{outputState.orientation};
266 const ui::Transform bufferTransform{layerState.geomBufferTransform};
267 ui::Transform transform(displayTransform * layerTransform * bufferTransform);
268
269 if (layerState.geomBufferUsesDisplayInverseTransform) {
270 /*
271 * the code below applies the primary display's inverse transform to the
272 * buffer
273 */
274 uint32_t invTransform = outputState.orientation;
275 // calculate the inverse transform
276 if (invTransform & HAL_TRANSFORM_ROT_90) {
277 invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
278 }
279
280 /*
281 * Here we cancel out the orientation component of the WM transform.
282 * The scaling and translate components are already included in our bounds
283 * computation so it's enough to just omit it in the composition.
284 * See comment in BufferLayer::prepareClientLayer with ref to b/36727915 for why.
285 */
Lloyd Pique546a2452019-03-18 20:53:27 +0000286 transform = ui::Transform(invTransform) * displayTransform * bufferTransform;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800287 }
288
289 // this gives us only the "orientation" component of the transform
290 return transform.getOrientation();
291} // namespace impl
292
293void OutputLayer::updateCompositionState(bool includeGeometry) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800294 const auto& layerFEState = mLayer->getState().frontEnd;
295 const auto& outputState = mOutput.getState();
296 const auto& profile = *mOutput.getDisplayColorProfile();
297
Lloyd Piquea83776c2019-01-29 18:42:32 -0800298 if (includeGeometry) {
299 mState.displayFrame = calculateOutputDisplayFrame();
300 mState.sourceCrop = calculateOutputSourceCrop();
301 mState.bufferTransform =
302 static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
303
Lloyd Piquef5275482019-01-29 18:42:42 -0800304 if ((layerFEState.isSecure && !outputState.isSecure) ||
Lloyd Piquea83776c2019-01-29 18:42:32 -0800305 (mState.bufferTransform & ui::Transform::ROT_INVALID)) {
306 mState.forceClientComposition = true;
307 }
308 }
Lloyd Piquef5275482019-01-29 18:42:42 -0800309
310 // Determine the output dependent dataspace for this layer. If it is
311 // colorspace agnostic, it just uses the dataspace chosen for the output to
312 // avoid the need for color conversion.
313 mState.dataspace = layerFEState.isColorspaceAgnostic &&
314 outputState.targetDataspace != ui::Dataspace::UNKNOWN
315 ? outputState.targetDataspace
316 : layerFEState.dataspace;
317
Lloyd Piquef5275482019-01-29 18:42:42 -0800318 // These are evaluated every frame as they can potentially change at any
319 // time.
320 if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
321 mState.forceClientComposition = true;
322 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800323}
324
Lloyd Piquef5275482019-01-29 18:42:42 -0800325void OutputLayer::writeStateToHWC(bool includeGeometry) {
Lloyd Piquea83776c2019-01-29 18:42:32 -0800326 // Skip doing this if there is no HWC interface
327 if (!mState.hwc) {
328 return;
329 }
330
331 auto& hwcLayer = (*mState.hwc).hwcLayer;
332 if (!hwcLayer) {
333 ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
334 mLayerFE->getDebugName(), mOutput.getName().c_str());
335 return;
336 }
337
Lloyd Piquef5275482019-01-29 18:42:42 -0800338 const auto& outputIndependentState = mLayer->getState().frontEnd;
339 auto requestedCompositionType = outputIndependentState.compositionType;
340
Lloyd Piquea83776c2019-01-29 18:42:32 -0800341 if (includeGeometry) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800342 writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
343 writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState);
344 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800345
Lloyd Piquef5275482019-01-29 18:42:42 -0800346 writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
347 writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState);
Lloyd Piquea83776c2019-01-29 18:42:32 -0800348
Lloyd Piquef5275482019-01-29 18:42:42 -0800349 writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType);
350}
Lloyd Piquea83776c2019-01-29 18:42:32 -0800351
Lloyd Piquef5275482019-01-29 18:42:42 -0800352void OutputLayer::writeOutputDependentGeometryStateToHWC(
353 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
354 const auto& outputDependentState = getState();
355
356 if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
357 error != HWC2::Error::None) {
358 ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
359 mLayerFE->getDebugName(), outputDependentState.displayFrame.left,
360 outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
361 outputDependentState.displayFrame.bottom, to_string(error).c_str(),
362 static_cast<int32_t>(error));
363 }
364
365 if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop);
366 error != HWC2::Error::None) {
367 ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
368 "%s (%d)",
369 mLayerFE->getDebugName(), outputDependentState.sourceCrop.left,
370 outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right,
371 outputDependentState.sourceCrop.bottom, to_string(error).c_str(),
372 static_cast<int32_t>(error));
373 }
374
375 if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
376 ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z,
377 to_string(error).c_str(), static_cast<int32_t>(error));
378 }
379
380 // Solid-color layers should always use an identity transform.
381 const auto bufferTransform =
382 requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR
383 ? outputDependentState.bufferTransform
384 : static_cast<Hwc2::Transform>(0);
385 if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
386 error != HWC2::Error::None) {
387 ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
388 toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
389 static_cast<int32_t>(error));
390 }
391}
392
393void OutputLayer::writeOutputIndependentGeometryStateToHWC(
394 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
395 if (auto error = hwcLayer->setBlendMode(
396 static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
397 error != HWC2::Error::None) {
398 ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
399 toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
400 static_cast<int32_t>(error));
401 }
402
403 if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
404 error != HWC2::Error::None) {
405 ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
406 outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
407 }
408
409 if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
410 error != HWC2::Error::None) {
411 ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(),
412 static_cast<int32_t>(error));
413 }
414}
415
416void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
417 const auto& outputDependentState = getState();
418
Lloyd Piquea2468662019-03-07 21:31:06 -0800419 // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
Lloyd Piquef5275482019-01-29 18:42:42 -0800420 // state and should not change every frame.
Lloyd Piquea2468662019-03-07 21:31:06 -0800421 if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion);
Lloyd Piquef5275482019-01-29 18:42:42 -0800422 error != HWC2::Error::None) {
423 ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
424 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquea2468662019-03-07 21:31:06 -0800425 outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG);
Lloyd Piquef5275482019-01-29 18:42:42 -0800426 }
427
428 if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
429 error != HWC2::Error::None) {
430 ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(),
431 outputDependentState.dataspace, to_string(error).c_str(),
432 static_cast<int32_t>(error));
433 }
434}
435
436void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
437 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
438 switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
439 case HWC2::Error::None:
440 break;
441 case HWC2::Error::Unsupported:
442 editState().forceClientComposition = true;
443 break;
444 default:
445 ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800446 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquef5275482019-01-29 18:42:42 -0800447 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800448
Lloyd Piquef5275482019-01-29 18:42:42 -0800449 if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
450 error != HWC2::Error::None) {
451 ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(),
452 to_string(error).c_str(), static_cast<int32_t>(error));
453 outputIndependentState.surfaceDamage.dump(LOG_TAG);
454 }
455
456 // Content-specific per-frame state
457 switch (outputIndependentState.compositionType) {
458 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
459 writeSolidColorStateToHWC(hwcLayer, outputIndependentState);
460 break;
461 case Hwc2::IComposerClient::Composition::SIDEBAND:
462 writeSidebandStateToHWC(hwcLayer, outputIndependentState);
463 break;
464 case Hwc2::IComposerClient::Composition::CURSOR:
465 case Hwc2::IComposerClient::Composition::DEVICE:
466 writeBufferStateToHWC(hwcLayer, outputIndependentState);
467 break;
468 case Hwc2::IComposerClient::Composition::INVALID:
469 case Hwc2::IComposerClient::Composition::CLIENT:
470 // Ignored
471 break;
472 }
473}
474
475void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
476 const LayerFECompositionState& outputIndependentState) {
477 hwc_color_t color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
478 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
479 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
480 255};
481
482 if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
483 ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(),
484 to_string(error).c_str(), static_cast<int32_t>(error));
485 }
486}
487
488void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
489 const LayerFECompositionState& outputIndependentState) {
490 if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
491 error != HWC2::Error::None) {
492 ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(),
493 outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
494 static_cast<int32_t>(error));
495 }
496}
497
498void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
499 const LayerFECompositionState& outputIndependentState) {
500 auto supportedPerFrameMetadata =
501 mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata();
502 if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
503 outputIndependentState.hdrMetadata);
504 error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
505 ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(),
506 to_string(error).c_str(), static_cast<int32_t>(error));
507 }
508
509 uint32_t hwcSlot = 0;
510 sp<GraphicBuffer> hwcBuffer;
511 // We need access to the output-dependent state for the buffer cache there,
512 // though otherwise the buffer is not output-dependent.
513 editState().hwc->hwcBufferCache.getHwcBuffer(outputIndependentState.bufferSlot,
514 outputIndependentState.buffer, &hwcSlot,
515 &hwcBuffer);
516
517 if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
518 error != HWC2::Error::None) {
519 ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(),
520 outputIndependentState.buffer->handle, to_string(error).c_str(),
521 static_cast<int32_t>(error));
522 }
523}
524
525void OutputLayer::writeCompositionTypeToHWC(
526 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
527 auto& outputDependentState = editState();
528
529 // If we are forcing client composition, we need to tell the HWC
530 if (outputDependentState.forceClientComposition) {
531 requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
532 }
533
534 // Set the requested composition type with the HWC whenever it changes
535 if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
536 outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
537
538 if (auto error = hwcLayer->setCompositionType(
539 static_cast<HWC2::Composition>(requestedCompositionType));
Lloyd Piquea83776c2019-01-29 18:42:32 -0800540 error != HWC2::Error::None) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800541 ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(),
542 toString(requestedCompositionType).c_str(), to_string(error).c_str(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800543 static_cast<int32_t>(error));
544 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800545 }
546}
547
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800548void OutputLayer::writeCursorPositionToHWC() const {
549 // Skip doing this if there is no HWC interface
550 auto hwcLayer = getHwcLayer();
551 if (!hwcLayer) {
552 return;
553 }
554
555 const auto& layerFEState = mLayer->getState().frontEnd;
556 const auto& outputState = mOutput.getState();
557
558 Rect frame = layerFEState.cursorFrame;
559 frame.intersect(outputState.viewport, &frame);
560 Rect position = outputState.transform.transform(frame);
561
562 if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
563 error != HWC2::Error::None) {
564 ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)", mLayerFE->getDebugName(),
565 position.left, position.top, to_string(error).c_str(), static_cast<int32_t>(error));
566 }
567}
568
Lloyd Pique66d68602019-02-13 14:23:31 -0800569HWC2::Layer* OutputLayer::getHwcLayer() const {
570 return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
571}
572
573bool OutputLayer::requiresClientComposition() const {
574 return !mState.hwc ||
575 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
576}
577
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800578bool OutputLayer::isHardwareCursor() const {
579 return mState.hwc &&
580 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
581}
582
Lloyd Pique66d68602019-02-13 14:23:31 -0800583void OutputLayer::detectDisallowedCompositionTypeChange(
584 Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
585 bool result = false;
586 switch (from) {
587 case Hwc2::IComposerClient::Composition::INVALID:
588 case Hwc2::IComposerClient::Composition::CLIENT:
589 result = false;
590 break;
591
592 case Hwc2::IComposerClient::Composition::DEVICE:
593 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
594 result = (to == Hwc2::IComposerClient::Composition::CLIENT);
595 break;
596
597 case Hwc2::IComposerClient::Composition::CURSOR:
598 case Hwc2::IComposerClient::Composition::SIDEBAND:
599 result = (to == Hwc2::IComposerClient::Composition::CLIENT ||
600 to == Hwc2::IComposerClient::Composition::DEVICE);
601 break;
602 }
603
604 if (!result) {
605 ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
606 mLayerFE->getDebugName(), toString(from).c_str(), static_cast<int>(from),
607 toString(to).c_str(), static_cast<int>(to));
608 }
609}
610
611void OutputLayer::applyDeviceCompositionTypeChange(
612 Hwc2::IComposerClient::Composition compositionType) {
613 LOG_FATAL_IF(!mState.hwc);
614 auto& hwcState = *mState.hwc;
615
616 detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
617
618 hwcState.hwcCompositionType = compositionType;
619}
620
621void OutputLayer::prepareForDeviceLayerRequests() {
622 mState.clearClientTarget = false;
623}
624
625void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
626 switch (request) {
627 case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
628 mState.clearClientTarget = true;
629 break;
630
631 default:
632 ALOGE("[%s] Unknown device layer request %s (%d)", mLayerFE->getDebugName(),
633 toString(request).c_str(), static_cast<int>(request));
634 break;
635 }
636}
637
Lloyd Pique688abd42019-02-15 15:42:24 -0800638bool OutputLayer::needsFiltering() const {
639 const auto& displayFrame = mState.displayFrame;
640 const auto& sourceCrop = mState.sourceCrop;
641 return sourceCrop.getHeight() != displayFrame.getHeight() ||
642 sourceCrop.getWidth() != displayFrame.getWidth();
643}
644
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800645void OutputLayer::dump(std::string& out) const {
646 using android::base::StringAppendF;
647
Lloyd Pique207def92019-02-28 16:09:52 -0800648 StringAppendF(&out, " - Output Layer %p (Composition layer %p) (%s)\n", this, mLayer.get(),
649 mLayerFE->getDebugName());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800650 mState.dump(out);
651}
652
Lloyd Piquecc01a452018-12-04 17:24:00 -0800653} // namespace impl
654} // namespace android::compositionengine