blob: 43ab87a74aa552917279f5745996809260d7c6e3 [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 Piquef5275482019-01-29 18:42:42 -080018#include <compositionengine/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080019#include <compositionengine/Layer.h>
20#include <compositionengine/LayerFE.h>
Lloyd Pique9755fb72019-03-26 14:44:40 -070021#include <compositionengine/LayerFECompositionState.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080022#include <compositionengine/Output.h>
Lloyd Piquea83776c2019-01-29 18:42:32 -080023#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080024#include <compositionengine/impl/OutputLayer.h>
Lloyd Piquea83776c2019-01-29 18:42:32 -080025#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080026
Lloyd Pique07e33212018-12-18 16:33:37 -080027#include "DisplayHardware/HWComposer.h"
28
Lloyd Piquecc01a452018-12-04 17:24:00 -080029namespace android::compositionengine {
30
31OutputLayer::~OutputLayer() = default;
32
33namespace impl {
34
Lloyd Piquea83776c2019-01-29 18:42:32 -080035namespace {
36
37FloatRect reduce(const FloatRect& win, const Region& exclude) {
38 if (CC_LIKELY(exclude.isEmpty())) {
39 return win;
40 }
41 // Convert through Rect (by rounding) for lack of FloatRegion
42 return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
43}
44
45} // namespace
46
Lloyd Piquecc01a452018-12-04 17:24:00 -080047std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
Lloyd Piquedf336d92019-03-07 21:38:42 -080048 const compositionengine::Output& output,
49 const std::shared_ptr<compositionengine::Layer>& layer,
50 const sp<compositionengine::LayerFE>& layerFE) {
51 return std::make_unique<OutputLayer>(output, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -080052}
53
Lloyd Piquedf336d92019-03-07 21:38:42 -080054OutputLayer::OutputLayer(const Output& output, const std::shared_ptr<Layer>& layer,
55 const sp<LayerFE>& layerFE)
Lloyd Piquecc01a452018-12-04 17:24:00 -080056 : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
57
58OutputLayer::~OutputLayer() = default;
59
Lloyd Piquedf336d92019-03-07 21:38:42 -080060void OutputLayer::setHwcLayer(std::shared_ptr<HWC2::Layer> hwcLayer) {
61 if (hwcLayer) {
62 mState.hwc.emplace(hwcLayer);
63 } else {
64 mState.hwc.reset();
Lloyd Pique07e33212018-12-18 16:33:37 -080065 }
Lloyd Pique07e33212018-12-18 16:33:37 -080066}
67
Lloyd Piquecc01a452018-12-04 17:24:00 -080068const compositionengine::Output& OutputLayer::getOutput() const {
69 return mOutput;
70}
71
72compositionengine::Layer& OutputLayer::getLayer() const {
73 return *mLayer;
74}
75
76compositionengine::LayerFE& OutputLayer::getLayerFE() const {
77 return *mLayerFE;
78}
79
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080080const OutputLayerCompositionState& OutputLayer::getState() const {
81 return mState;
82}
83
84OutputLayerCompositionState& OutputLayer::editState() {
85 return mState;
86}
87
Lloyd Piquea83776c2019-01-29 18:42:32 -080088Rect OutputLayer::calculateInitialCrop() const {
Lloyd Pique9755fb72019-03-26 14:44:40 -070089 const auto& layerState = mLayer->getFEState();
Lloyd Piquea83776c2019-01-29 18:42:32 -080090
91 // apply the projection's clipping to the window crop in
92 // layerstack space, and convert-back to layer space.
93 // if there are no window scaling involved, this operation will map to full
94 // pixels in the buffer.
95
96 FloatRect activeCropFloat =
Lloyd Piquec6687342019-03-07 21:34:57 -080097 reduce(layerState.geomLayerBounds, layerState.transparentRegionHint);
Lloyd Piquea83776c2019-01-29 18:42:32 -080098
99 const Rect& viewport = mOutput.getState().viewport;
100 const ui::Transform& layerTransform = layerState.geomLayerTransform;
101 const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
102 // Transform to screen space.
103 activeCropFloat = layerTransform.transform(activeCropFloat);
104 activeCropFloat = activeCropFloat.intersect(viewport.toFloatRect());
105 // Back to layer space to work with the content crop.
106 activeCropFloat = inverseLayerTransform.transform(activeCropFloat);
107
108 // This needs to be here as transform.transform(Rect) computes the
109 // transformed rect and then takes the bounding box of the result before
110 // returning. This means
111 // transform.inverse().transform(transform.transform(Rect)) != Rect
112 // in which case we need to make sure the final rect is clipped to the
113 // display bounds.
114 Rect activeCrop{activeCropFloat};
115 if (!activeCrop.intersect(layerState.geomBufferSize, &activeCrop)) {
116 activeCrop.clear();
117 }
118 return activeCrop;
119}
120
121FloatRect OutputLayer::calculateOutputSourceCrop() const {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700122 const auto& layerState = mLayer->getFEState();
Lloyd Piquea83776c2019-01-29 18:42:32 -0800123 const auto& outputState = mOutput.getState();
124
125 if (!layerState.geomUsesSourceCrop) {
126 return {};
127 }
128
129 // the content crop is the area of the content that gets scaled to the
130 // layer's size. This is in buffer space.
131 FloatRect crop = layerState.geomContentCrop.toFloatRect();
132
133 // In addition there is a WM-specified crop we pull from our drawing state.
134 Rect activeCrop = calculateInitialCrop();
135 const Rect& bufferSize = layerState.geomBufferSize;
136
137 int winWidth = bufferSize.getWidth();
138 int winHeight = bufferSize.getHeight();
139
140 // The bufferSize for buffer state layers can be unbounded ([0, 0, -1, -1])
141 // if display frame hasn't been set and the parent is an unbounded layer.
142 if (winWidth < 0 && winHeight < 0) {
143 return crop;
144 }
145
146 // Transform the window crop to match the buffer coordinate system,
147 // which means using the inverse of the current transform set on the
148 // SurfaceFlingerConsumer.
149 uint32_t invTransform = layerState.geomBufferTransform;
150 if (layerState.geomBufferUsesDisplayInverseTransform) {
151 /*
152 * the code below applies the primary display's inverse transform to the
153 * buffer
154 */
155 uint32_t invTransformOrient = outputState.orientation;
156 // calculate the inverse transform
157 if (invTransformOrient & HAL_TRANSFORM_ROT_90) {
158 invTransformOrient ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
159 }
160 // and apply to the current transform
161 invTransform =
162 (ui::Transform(invTransformOrient) * ui::Transform(invTransform)).getOrientation();
163 }
164
165 if (invTransform & HAL_TRANSFORM_ROT_90) {
166 // If the activeCrop has been rotate the ends are rotated but not
167 // the space itself so when transforming ends back we can't rely on
168 // a modification of the axes of rotation. To account for this we
169 // need to reorient the inverse rotation in terms of the current
170 // axes of rotation.
171 bool is_h_flipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
172 bool is_v_flipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
173 if (is_h_flipped == is_v_flipped) {
174 invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
175 }
176 std::swap(winWidth, winHeight);
177 }
178 const Rect winCrop =
179 activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
180
181 // below, crop is intersected with winCrop expressed in crop's coordinate space
182 float xScale = crop.getWidth() / float(winWidth);
183 float yScale = crop.getHeight() / float(winHeight);
184
185 float insetL = winCrop.left * xScale;
186 float insetT = winCrop.top * yScale;
187 float insetR = (winWidth - winCrop.right) * xScale;
188 float insetB = (winHeight - winCrop.bottom) * yScale;
189
190 crop.left += insetL;
191 crop.top += insetT;
192 crop.right -= insetR;
193 crop.bottom -= insetB;
194
195 return crop;
196}
197
198Rect OutputLayer::calculateOutputDisplayFrame() const {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700199 const auto& layerState = mLayer->getFEState();
Lloyd Piquea83776c2019-01-29 18:42:32 -0800200 const auto& outputState = mOutput.getState();
201
202 // apply the layer's transform, followed by the display's global transform
203 // here we're guaranteed that the layer's transform preserves rects
Lloyd Piquec6687342019-03-07 21:34:57 -0800204 Region activeTransparentRegion = layerState.transparentRegionHint;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800205 const ui::Transform& layerTransform = layerState.geomLayerTransform;
206 const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
207 const Rect& bufferSize = layerState.geomBufferSize;
208 Rect activeCrop = layerState.geomCrop;
209 if (!activeCrop.isEmpty() && bufferSize.isValid()) {
210 activeCrop = layerTransform.transform(activeCrop);
211 if (!activeCrop.intersect(outputState.viewport, &activeCrop)) {
212 activeCrop.clear();
213 }
214 activeCrop = inverseLayerTransform.transform(activeCrop, true);
215 // This needs to be here as transform.transform(Rect) computes the
216 // transformed rect and then takes the bounding box of the result before
217 // returning. This means
218 // transform.inverse().transform(transform.transform(Rect)) != Rect
219 // in which case we need to make sure the final rect is clipped to the
220 // display bounds.
221 if (!activeCrop.intersect(bufferSize, &activeCrop)) {
222 activeCrop.clear();
223 }
224 // mark regions outside the crop as transparent
225 activeTransparentRegion.orSelf(Rect(0, 0, bufferSize.getWidth(), activeCrop.top));
226 activeTransparentRegion.orSelf(
227 Rect(0, activeCrop.bottom, bufferSize.getWidth(), bufferSize.getHeight()));
228 activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
229 activeTransparentRegion.orSelf(
230 Rect(activeCrop.right, activeCrop.top, bufferSize.getWidth(), activeCrop.bottom));
231 }
232
233 // reduce uses a FloatRect to provide more accuracy during the
234 // transformation. We then round upon constructing 'frame'.
235 Rect frame{
236 layerTransform.transform(reduce(layerState.geomLayerBounds, activeTransparentRegion))};
237 if (!frame.intersect(outputState.viewport, &frame)) {
238 frame.clear();
239 }
240 const ui::Transform displayTransform{outputState.transform};
241
242 return displayTransform.transform(frame);
243}
244
245uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700246 const auto& layerState = mLayer->getFEState();
Lloyd Piquea83776c2019-01-29 18:42:32 -0800247 const auto& outputState = mOutput.getState();
248
249 /*
250 * Transformations are applied in this order:
251 * 1) buffer orientation/flip/mirror
252 * 2) state transformation (window manager)
253 * 3) layer orientation (screen orientation)
254 * (NOTE: the matrices are multiplied in reverse order)
255 */
256 const ui::Transform& layerTransform = layerState.geomLayerTransform;
257 const ui::Transform displayTransform{outputState.orientation};
258 const ui::Transform bufferTransform{layerState.geomBufferTransform};
259 ui::Transform transform(displayTransform * layerTransform * bufferTransform);
260
261 if (layerState.geomBufferUsesDisplayInverseTransform) {
262 /*
263 * the code below applies the primary display's inverse transform to the
264 * buffer
265 */
266 uint32_t invTransform = outputState.orientation;
267 // calculate the inverse transform
268 if (invTransform & HAL_TRANSFORM_ROT_90) {
269 invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
270 }
271
272 /*
273 * Here we cancel out the orientation component of the WM transform.
274 * The scaling and translate components are already included in our bounds
275 * computation so it's enough to just omit it in the composition.
276 * See comment in BufferLayer::prepareClientLayer with ref to b/36727915 for why.
277 */
Lloyd Pique546a2452019-03-18 20:53:27 +0000278 transform = ui::Transform(invTransform) * displayTransform * bufferTransform;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800279 }
280
281 // this gives us only the "orientation" component of the transform
282 return transform.getOrientation();
283} // namespace impl
284
285void OutputLayer::updateCompositionState(bool includeGeometry) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700286 const auto& layerFEState = mLayer->getFEState();
Lloyd Piquef5275482019-01-29 18:42:42 -0800287 const auto& outputState = mOutput.getState();
288 const auto& profile = *mOutput.getDisplayColorProfile();
289
Lloyd Piquea83776c2019-01-29 18:42:32 -0800290 if (includeGeometry) {
Lloyd Piquefe671022019-09-24 10:43:03 -0700291 // Clear the forceClientComposition flag before it is set for any
292 // reason. Note that since it can be set by some checks below when
293 // updating the geometry state, we only clear it when updating the
294 // geometry since those conditions for forcing client composition won't
295 // go away otherwise.
296 mState.forceClientComposition = false;
297
Lloyd Piquea83776c2019-01-29 18:42:32 -0800298 mState.displayFrame = calculateOutputDisplayFrame();
299 mState.sourceCrop = calculateOutputSourceCrop();
300 mState.bufferTransform =
301 static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
302
Lloyd Piquef5275482019-01-29 18:42:42 -0800303 if ((layerFEState.isSecure && !outputState.isSecure) ||
Lloyd Piquea83776c2019-01-29 18:42:32 -0800304 (mState.bufferTransform & ui::Transform::ROT_INVALID)) {
305 mState.forceClientComposition = true;
306 }
307 }
Lloyd Piquef5275482019-01-29 18:42:42 -0800308
309 // Determine the output dependent dataspace for this layer. If it is
310 // colorspace agnostic, it just uses the dataspace chosen for the output to
311 // avoid the need for color conversion.
312 mState.dataspace = layerFEState.isColorspaceAgnostic &&
313 outputState.targetDataspace != ui::Dataspace::UNKNOWN
314 ? outputState.targetDataspace
315 : layerFEState.dataspace;
316
Lloyd Piquef5275482019-01-29 18:42:42 -0800317 // These are evaluated every frame as they can potentially change at any
318 // time.
319 if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
320 mState.forceClientComposition = true;
321 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800322}
323
Lloyd Piquef5275482019-01-29 18:42:42 -0800324void OutputLayer::writeStateToHWC(bool includeGeometry) {
Lloyd Piquea83776c2019-01-29 18:42:32 -0800325 // Skip doing this if there is no HWC interface
326 if (!mState.hwc) {
327 return;
328 }
329
330 auto& hwcLayer = (*mState.hwc).hwcLayer;
331 if (!hwcLayer) {
332 ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
333 mLayerFE->getDebugName(), mOutput.getName().c_str());
334 return;
335 }
336
Lloyd Pique9755fb72019-03-26 14:44:40 -0700337 const auto& outputIndependentState = mLayer->getFEState();
Lloyd Piquef5275482019-01-29 18:42:42 -0800338 auto requestedCompositionType = outputIndependentState.compositionType;
339
Lloyd Piquea83776c2019-01-29 18:42:32 -0800340 if (includeGeometry) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800341 writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
342 writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState);
343 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800344
Lloyd Piquef5275482019-01-29 18:42:42 -0800345 writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
346 writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState);
Lloyd Piquea83776c2019-01-29 18:42:32 -0800347
Lloyd Piquef5275482019-01-29 18:42:42 -0800348 writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType);
349}
Lloyd Piquea83776c2019-01-29 18:42:32 -0800350
Lloyd Piquef5275482019-01-29 18:42:42 -0800351void OutputLayer::writeOutputDependentGeometryStateToHWC(
352 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
353 const auto& outputDependentState = getState();
354
355 if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
356 error != HWC2::Error::None) {
357 ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
358 mLayerFE->getDebugName(), outputDependentState.displayFrame.left,
359 outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
360 outputDependentState.displayFrame.bottom, to_string(error).c_str(),
361 static_cast<int32_t>(error));
362 }
363
364 if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop);
365 error != HWC2::Error::None) {
366 ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
367 "%s (%d)",
368 mLayerFE->getDebugName(), outputDependentState.sourceCrop.left,
369 outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right,
370 outputDependentState.sourceCrop.bottom, to_string(error).c_str(),
371 static_cast<int32_t>(error));
372 }
373
374 if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
375 ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z,
376 to_string(error).c_str(), static_cast<int32_t>(error));
377 }
378
379 // Solid-color layers should always use an identity transform.
380 const auto bufferTransform =
381 requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR
382 ? outputDependentState.bufferTransform
383 : static_cast<Hwc2::Transform>(0);
384 if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
385 error != HWC2::Error::None) {
386 ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
387 toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
388 static_cast<int32_t>(error));
389 }
390}
391
392void OutputLayer::writeOutputIndependentGeometryStateToHWC(
393 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
394 if (auto error = hwcLayer->setBlendMode(
395 static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
396 error != HWC2::Error::None) {
397 ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
398 toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
399 static_cast<int32_t>(error));
400 }
401
402 if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
403 error != HWC2::Error::None) {
404 ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
405 outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
406 }
407
408 if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
409 error != HWC2::Error::None) {
410 ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(),
411 static_cast<int32_t>(error));
412 }
413}
414
415void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
416 const auto& outputDependentState = getState();
417
Lloyd Piquea2468662019-03-07 21:31:06 -0800418 // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
Lloyd Piquef5275482019-01-29 18:42:42 -0800419 // state and should not change every frame.
Lloyd Piquea2468662019-03-07 21:31:06 -0800420 if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion);
Lloyd Piquef5275482019-01-29 18:42:42 -0800421 error != HWC2::Error::None) {
422 ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
423 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquea2468662019-03-07 21:31:06 -0800424 outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG);
Lloyd Piquef5275482019-01-29 18:42:42 -0800425 }
426
427 if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
428 error != HWC2::Error::None) {
429 ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(),
430 outputDependentState.dataspace, to_string(error).c_str(),
431 static_cast<int32_t>(error));
432 }
433}
434
435void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
436 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
437 switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
438 case HWC2::Error::None:
439 break;
440 case HWC2::Error::Unsupported:
441 editState().forceClientComposition = true;
442 break;
443 default:
444 ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800445 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquef5275482019-01-29 18:42:42 -0800446 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800447
Lloyd Piquef5275482019-01-29 18:42:42 -0800448 if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
449 error != HWC2::Error::None) {
450 ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(),
451 to_string(error).c_str(), static_cast<int32_t>(error));
452 outputIndependentState.surfaceDamage.dump(LOG_TAG);
453 }
454
455 // Content-specific per-frame state
456 switch (outputIndependentState.compositionType) {
457 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
458 writeSolidColorStateToHWC(hwcLayer, outputIndependentState);
459 break;
460 case Hwc2::IComposerClient::Composition::SIDEBAND:
461 writeSidebandStateToHWC(hwcLayer, outputIndependentState);
462 break;
463 case Hwc2::IComposerClient::Composition::CURSOR:
464 case Hwc2::IComposerClient::Composition::DEVICE:
465 writeBufferStateToHWC(hwcLayer, outputIndependentState);
466 break;
467 case Hwc2::IComposerClient::Composition::INVALID:
468 case Hwc2::IComposerClient::Composition::CLIENT:
469 // Ignored
470 break;
471 }
472}
473
474void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
475 const LayerFECompositionState& outputIndependentState) {
476 hwc_color_t color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
477 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
478 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
479 255};
480
481 if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
482 ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(),
483 to_string(error).c_str(), static_cast<int32_t>(error));
484 }
485}
486
487void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
488 const LayerFECompositionState& outputIndependentState) {
489 if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
490 error != HWC2::Error::None) {
491 ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(),
492 outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
493 static_cast<int32_t>(error));
494 }
495}
496
497void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
498 const LayerFECompositionState& outputIndependentState) {
499 auto supportedPerFrameMetadata =
500 mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata();
501 if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
502 outputIndependentState.hdrMetadata);
503 error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
504 ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(),
505 to_string(error).c_str(), static_cast<int32_t>(error));
506 }
507
508 uint32_t hwcSlot = 0;
509 sp<GraphicBuffer> hwcBuffer;
510 // We need access to the output-dependent state for the buffer cache there,
511 // though otherwise the buffer is not output-dependent.
512 editState().hwc->hwcBufferCache.getHwcBuffer(outputIndependentState.bufferSlot,
513 outputIndependentState.buffer, &hwcSlot,
514 &hwcBuffer);
515
516 if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
517 error != HWC2::Error::None) {
518 ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(),
519 outputIndependentState.buffer->handle, to_string(error).c_str(),
520 static_cast<int32_t>(error));
521 }
522}
523
524void OutputLayer::writeCompositionTypeToHWC(
525 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
526 auto& outputDependentState = editState();
527
528 // If we are forcing client composition, we need to tell the HWC
529 if (outputDependentState.forceClientComposition) {
530 requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
531 }
532
533 // Set the requested composition type with the HWC whenever it changes
534 if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
535 outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
536
537 if (auto error = hwcLayer->setCompositionType(
538 static_cast<HWC2::Composition>(requestedCompositionType));
Lloyd Piquea83776c2019-01-29 18:42:32 -0800539 error != HWC2::Error::None) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800540 ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(),
541 toString(requestedCompositionType).c_str(), to_string(error).c_str(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800542 static_cast<int32_t>(error));
543 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800544 }
545}
546
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800547void OutputLayer::writeCursorPositionToHWC() const {
548 // Skip doing this if there is no HWC interface
549 auto hwcLayer = getHwcLayer();
550 if (!hwcLayer) {
551 return;
552 }
553
Lloyd Pique9755fb72019-03-26 14:44:40 -0700554 const auto& layerFEState = mLayer->getFEState();
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800555 const auto& outputState = mOutput.getState();
556
557 Rect frame = layerFEState.cursorFrame;
558 frame.intersect(outputState.viewport, &frame);
559 Rect position = outputState.transform.transform(frame);
560
561 if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
562 error != HWC2::Error::None) {
563 ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)", mLayerFE->getDebugName(),
564 position.left, position.top, to_string(error).c_str(), static_cast<int32_t>(error));
565 }
566}
567
Lloyd Pique66d68602019-02-13 14:23:31 -0800568HWC2::Layer* OutputLayer::getHwcLayer() const {
569 return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
570}
571
572bool OutputLayer::requiresClientComposition() const {
573 return !mState.hwc ||
574 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
575}
576
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800577bool OutputLayer::isHardwareCursor() const {
578 return mState.hwc &&
579 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
580}
581
Lloyd Pique66d68602019-02-13 14:23:31 -0800582void OutputLayer::detectDisallowedCompositionTypeChange(
583 Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
584 bool result = false;
585 switch (from) {
586 case Hwc2::IComposerClient::Composition::INVALID:
587 case Hwc2::IComposerClient::Composition::CLIENT:
588 result = false;
589 break;
590
591 case Hwc2::IComposerClient::Composition::DEVICE:
592 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
593 result = (to == Hwc2::IComposerClient::Composition::CLIENT);
594 break;
595
596 case Hwc2::IComposerClient::Composition::CURSOR:
597 case Hwc2::IComposerClient::Composition::SIDEBAND:
598 result = (to == Hwc2::IComposerClient::Composition::CLIENT ||
599 to == Hwc2::IComposerClient::Composition::DEVICE);
600 break;
601 }
602
603 if (!result) {
604 ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
605 mLayerFE->getDebugName(), toString(from).c_str(), static_cast<int>(from),
606 toString(to).c_str(), static_cast<int>(to));
607 }
608}
609
610void OutputLayer::applyDeviceCompositionTypeChange(
611 Hwc2::IComposerClient::Composition compositionType) {
612 LOG_FATAL_IF(!mState.hwc);
613 auto& hwcState = *mState.hwc;
614
615 detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
616
617 hwcState.hwcCompositionType = compositionType;
618}
619
620void OutputLayer::prepareForDeviceLayerRequests() {
621 mState.clearClientTarget = false;
622}
623
624void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
625 switch (request) {
626 case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
627 mState.clearClientTarget = true;
628 break;
629
630 default:
631 ALOGE("[%s] Unknown device layer request %s (%d)", mLayerFE->getDebugName(),
632 toString(request).c_str(), static_cast<int>(request));
633 break;
634 }
635}
636
Lloyd Pique688abd42019-02-15 15:42:24 -0800637bool OutputLayer::needsFiltering() const {
638 const auto& displayFrame = mState.displayFrame;
639 const auto& sourceCrop = mState.sourceCrop;
640 return sourceCrop.getHeight() != displayFrame.getHeight() ||
641 sourceCrop.getWidth() != displayFrame.getWidth();
642}
643
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800644void OutputLayer::dump(std::string& out) const {
645 using android::base::StringAppendF;
646
Lloyd Pique207def92019-02-28 16:09:52 -0800647 StringAppendF(&out, " - Output Layer %p (Composition layer %p) (%s)\n", this, mLayer.get(),
648 mLayerFE->getDebugName());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800649 mState.dump(out);
650}
651
Lloyd Piquecc01a452018-12-04 17:24:00 -0800652} // namespace impl
653} // namespace android::compositionengine