blob: 2e45953e5fd89fc5af67ef13113ecd93642f8f0a [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) {
291 mState.displayFrame = calculateOutputDisplayFrame();
292 mState.sourceCrop = calculateOutputSourceCrop();
293 mState.bufferTransform =
294 static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
295
Lloyd Piquef5275482019-01-29 18:42:42 -0800296 if ((layerFEState.isSecure && !outputState.isSecure) ||
Lloyd Piquea83776c2019-01-29 18:42:32 -0800297 (mState.bufferTransform & ui::Transform::ROT_INVALID)) {
298 mState.forceClientComposition = true;
299 }
300 }
Lloyd Piquef5275482019-01-29 18:42:42 -0800301
302 // Determine the output dependent dataspace for this layer. If it is
303 // colorspace agnostic, it just uses the dataspace chosen for the output to
304 // avoid the need for color conversion.
305 mState.dataspace = layerFEState.isColorspaceAgnostic &&
306 outputState.targetDataspace != ui::Dataspace::UNKNOWN
307 ? outputState.targetDataspace
308 : layerFEState.dataspace;
309
Lloyd Piquef5275482019-01-29 18:42:42 -0800310 // These are evaluated every frame as they can potentially change at any
311 // time.
312 if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
313 mState.forceClientComposition = true;
314 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800315}
316
Lloyd Piquef5275482019-01-29 18:42:42 -0800317void OutputLayer::writeStateToHWC(bool includeGeometry) {
Lloyd Piquea83776c2019-01-29 18:42:32 -0800318 // Skip doing this if there is no HWC interface
319 if (!mState.hwc) {
320 return;
321 }
322
323 auto& hwcLayer = (*mState.hwc).hwcLayer;
324 if (!hwcLayer) {
325 ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
326 mLayerFE->getDebugName(), mOutput.getName().c_str());
327 return;
328 }
329
Lloyd Pique9755fb72019-03-26 14:44:40 -0700330 const auto& outputIndependentState = mLayer->getFEState();
Lloyd Piquef5275482019-01-29 18:42:42 -0800331 auto requestedCompositionType = outputIndependentState.compositionType;
332
Lloyd Piquea83776c2019-01-29 18:42:32 -0800333 if (includeGeometry) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800334 writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
335 writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState);
336 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800337
Lloyd Piquef5275482019-01-29 18:42:42 -0800338 writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
339 writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState);
Lloyd Piquea83776c2019-01-29 18:42:32 -0800340
Lloyd Piquef5275482019-01-29 18:42:42 -0800341 writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType);
342}
Lloyd Piquea83776c2019-01-29 18:42:32 -0800343
Lloyd Piquef5275482019-01-29 18:42:42 -0800344void OutputLayer::writeOutputDependentGeometryStateToHWC(
345 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
346 const auto& outputDependentState = getState();
347
348 if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
349 error != HWC2::Error::None) {
350 ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
351 mLayerFE->getDebugName(), outputDependentState.displayFrame.left,
352 outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
353 outputDependentState.displayFrame.bottom, to_string(error).c_str(),
354 static_cast<int32_t>(error));
355 }
356
357 if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop);
358 error != HWC2::Error::None) {
359 ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
360 "%s (%d)",
361 mLayerFE->getDebugName(), outputDependentState.sourceCrop.left,
362 outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right,
363 outputDependentState.sourceCrop.bottom, to_string(error).c_str(),
364 static_cast<int32_t>(error));
365 }
366
367 if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
368 ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z,
369 to_string(error).c_str(), static_cast<int32_t>(error));
370 }
371
372 // Solid-color layers should always use an identity transform.
373 const auto bufferTransform =
374 requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR
375 ? outputDependentState.bufferTransform
376 : static_cast<Hwc2::Transform>(0);
377 if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
378 error != HWC2::Error::None) {
379 ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
380 toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
381 static_cast<int32_t>(error));
382 }
383}
384
385void OutputLayer::writeOutputIndependentGeometryStateToHWC(
386 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
387 if (auto error = hwcLayer->setBlendMode(
388 static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
389 error != HWC2::Error::None) {
390 ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
391 toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
392 static_cast<int32_t>(error));
393 }
394
395 if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
396 error != HWC2::Error::None) {
397 ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
398 outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
399 }
400
401 if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
402 error != HWC2::Error::None) {
403 ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(),
404 static_cast<int32_t>(error));
405 }
406}
407
408void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
409 const auto& outputDependentState = getState();
410
Lloyd Piquea2468662019-03-07 21:31:06 -0800411 // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
Lloyd Piquef5275482019-01-29 18:42:42 -0800412 // state and should not change every frame.
Lloyd Piquea2468662019-03-07 21:31:06 -0800413 if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion);
Lloyd Piquef5275482019-01-29 18:42:42 -0800414 error != HWC2::Error::None) {
415 ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
416 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquea2468662019-03-07 21:31:06 -0800417 outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG);
Lloyd Piquef5275482019-01-29 18:42:42 -0800418 }
419
420 if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
421 error != HWC2::Error::None) {
422 ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(),
423 outputDependentState.dataspace, to_string(error).c_str(),
424 static_cast<int32_t>(error));
425 }
426}
427
428void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
429 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
430 switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
431 case HWC2::Error::None:
432 break;
433 case HWC2::Error::Unsupported:
434 editState().forceClientComposition = true;
435 break;
436 default:
437 ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800438 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquef5275482019-01-29 18:42:42 -0800439 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800440
Lloyd Piquef5275482019-01-29 18:42:42 -0800441 if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
442 error != HWC2::Error::None) {
443 ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(),
444 to_string(error).c_str(), static_cast<int32_t>(error));
445 outputIndependentState.surfaceDamage.dump(LOG_TAG);
446 }
447
448 // Content-specific per-frame state
449 switch (outputIndependentState.compositionType) {
450 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
451 writeSolidColorStateToHWC(hwcLayer, outputIndependentState);
452 break;
453 case Hwc2::IComposerClient::Composition::SIDEBAND:
454 writeSidebandStateToHWC(hwcLayer, outputIndependentState);
455 break;
456 case Hwc2::IComposerClient::Composition::CURSOR:
457 case Hwc2::IComposerClient::Composition::DEVICE:
458 writeBufferStateToHWC(hwcLayer, outputIndependentState);
459 break;
460 case Hwc2::IComposerClient::Composition::INVALID:
461 case Hwc2::IComposerClient::Composition::CLIENT:
462 // Ignored
463 break;
464 }
465}
466
467void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
468 const LayerFECompositionState& outputIndependentState) {
469 hwc_color_t color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
470 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
471 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
472 255};
473
474 if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
475 ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(),
476 to_string(error).c_str(), static_cast<int32_t>(error));
477 }
478}
479
480void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
481 const LayerFECompositionState& outputIndependentState) {
482 if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
483 error != HWC2::Error::None) {
484 ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(),
485 outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
486 static_cast<int32_t>(error));
487 }
488}
489
490void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
491 const LayerFECompositionState& outputIndependentState) {
492 auto supportedPerFrameMetadata =
493 mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata();
494 if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
495 outputIndependentState.hdrMetadata);
496 error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
497 ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(),
498 to_string(error).c_str(), static_cast<int32_t>(error));
499 }
500
501 uint32_t hwcSlot = 0;
502 sp<GraphicBuffer> hwcBuffer;
503 // We need access to the output-dependent state for the buffer cache there,
504 // though otherwise the buffer is not output-dependent.
505 editState().hwc->hwcBufferCache.getHwcBuffer(outputIndependentState.bufferSlot,
506 outputIndependentState.buffer, &hwcSlot,
507 &hwcBuffer);
508
509 if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
510 error != HWC2::Error::None) {
511 ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(),
512 outputIndependentState.buffer->handle, to_string(error).c_str(),
513 static_cast<int32_t>(error));
514 }
515}
516
517void OutputLayer::writeCompositionTypeToHWC(
518 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
519 auto& outputDependentState = editState();
520
521 // If we are forcing client composition, we need to tell the HWC
522 if (outputDependentState.forceClientComposition) {
523 requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
524 }
525
526 // Set the requested composition type with the HWC whenever it changes
527 if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
528 outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
529
530 if (auto error = hwcLayer->setCompositionType(
531 static_cast<HWC2::Composition>(requestedCompositionType));
Lloyd Piquea83776c2019-01-29 18:42:32 -0800532 error != HWC2::Error::None) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800533 ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(),
534 toString(requestedCompositionType).c_str(), to_string(error).c_str(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800535 static_cast<int32_t>(error));
536 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800537 }
538}
539
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800540void OutputLayer::writeCursorPositionToHWC() const {
541 // Skip doing this if there is no HWC interface
542 auto hwcLayer = getHwcLayer();
543 if (!hwcLayer) {
544 return;
545 }
546
Lloyd Pique9755fb72019-03-26 14:44:40 -0700547 const auto& layerFEState = mLayer->getFEState();
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800548 const auto& outputState = mOutput.getState();
549
550 Rect frame = layerFEState.cursorFrame;
551 frame.intersect(outputState.viewport, &frame);
552 Rect position = outputState.transform.transform(frame);
553
554 if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
555 error != HWC2::Error::None) {
556 ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)", mLayerFE->getDebugName(),
557 position.left, position.top, to_string(error).c_str(), static_cast<int32_t>(error));
558 }
559}
560
Lloyd Pique66d68602019-02-13 14:23:31 -0800561HWC2::Layer* OutputLayer::getHwcLayer() const {
562 return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
563}
564
565bool OutputLayer::requiresClientComposition() const {
566 return !mState.hwc ||
567 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
568}
569
Lloyd Piquec7b0c752019-03-07 20:59:59 -0800570bool OutputLayer::isHardwareCursor() const {
571 return mState.hwc &&
572 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
573}
574
Lloyd Pique66d68602019-02-13 14:23:31 -0800575void OutputLayer::detectDisallowedCompositionTypeChange(
576 Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
577 bool result = false;
578 switch (from) {
579 case Hwc2::IComposerClient::Composition::INVALID:
580 case Hwc2::IComposerClient::Composition::CLIENT:
581 result = false;
582 break;
583
584 case Hwc2::IComposerClient::Composition::DEVICE:
585 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
586 result = (to == Hwc2::IComposerClient::Composition::CLIENT);
587 break;
588
589 case Hwc2::IComposerClient::Composition::CURSOR:
590 case Hwc2::IComposerClient::Composition::SIDEBAND:
591 result = (to == Hwc2::IComposerClient::Composition::CLIENT ||
592 to == Hwc2::IComposerClient::Composition::DEVICE);
593 break;
594 }
595
596 if (!result) {
597 ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
598 mLayerFE->getDebugName(), toString(from).c_str(), static_cast<int>(from),
599 toString(to).c_str(), static_cast<int>(to));
600 }
601}
602
603void OutputLayer::applyDeviceCompositionTypeChange(
604 Hwc2::IComposerClient::Composition compositionType) {
605 LOG_FATAL_IF(!mState.hwc);
606 auto& hwcState = *mState.hwc;
607
608 detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
609
610 hwcState.hwcCompositionType = compositionType;
611}
612
613void OutputLayer::prepareForDeviceLayerRequests() {
614 mState.clearClientTarget = false;
615}
616
617void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
618 switch (request) {
619 case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
620 mState.clearClientTarget = true;
621 break;
622
623 default:
624 ALOGE("[%s] Unknown device layer request %s (%d)", mLayerFE->getDebugName(),
625 toString(request).c_str(), static_cast<int>(request));
626 break;
627 }
628}
629
Lloyd Pique688abd42019-02-15 15:42:24 -0800630bool OutputLayer::needsFiltering() const {
631 const auto& displayFrame = mState.displayFrame;
632 const auto& sourceCrop = mState.sourceCrop;
633 return sourceCrop.getHeight() != displayFrame.getHeight() ||
634 sourceCrop.getWidth() != displayFrame.getWidth();
635}
636
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800637void OutputLayer::dump(std::string& out) const {
638 using android::base::StringAppendF;
639
Lloyd Pique207def92019-02-28 16:09:52 -0800640 StringAppendF(&out, " - Output Layer %p (Composition layer %p) (%s)\n", this, mLayer.get(),
641 mLayerFE->getDebugName());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800642 mState.dump(out);
643}
644
Lloyd Piquecc01a452018-12-04 17:24:00 -0800645} // namespace impl
646} // namespace android::compositionengine