blob: e721cf5375302bd8d5e00431ab034d583ba8aaee [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
318 // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
319 // value recomputed / set every frame.
320 mState.visibleRegion = outputState.transform.transform(
321 layerFEState.geomVisibleRegion.intersect(outputState.viewport));
322
323 // These are evaluated every frame as they can potentially change at any
324 // time.
325 if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
326 mState.forceClientComposition = true;
327 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800328}
329
Lloyd Piquef5275482019-01-29 18:42:42 -0800330void OutputLayer::writeStateToHWC(bool includeGeometry) {
Lloyd Piquea83776c2019-01-29 18:42:32 -0800331 // Skip doing this if there is no HWC interface
332 if (!mState.hwc) {
333 return;
334 }
335
336 auto& hwcLayer = (*mState.hwc).hwcLayer;
337 if (!hwcLayer) {
338 ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
339 mLayerFE->getDebugName(), mOutput.getName().c_str());
340 return;
341 }
342
Lloyd Piquef5275482019-01-29 18:42:42 -0800343 const auto& outputIndependentState = mLayer->getState().frontEnd;
344 auto requestedCompositionType = outputIndependentState.compositionType;
345
Lloyd Piquea83776c2019-01-29 18:42:32 -0800346 if (includeGeometry) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800347 writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
348 writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState);
349 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800350
Lloyd Piquef5275482019-01-29 18:42:42 -0800351 writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
352 writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState);
Lloyd Piquea83776c2019-01-29 18:42:32 -0800353
Lloyd Piquef5275482019-01-29 18:42:42 -0800354 writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType);
355}
Lloyd Piquea83776c2019-01-29 18:42:32 -0800356
Lloyd Piquef5275482019-01-29 18:42:42 -0800357void OutputLayer::writeOutputDependentGeometryStateToHWC(
358 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
359 const auto& outputDependentState = getState();
360
361 if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
362 error != HWC2::Error::None) {
363 ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
364 mLayerFE->getDebugName(), outputDependentState.displayFrame.left,
365 outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
366 outputDependentState.displayFrame.bottom, to_string(error).c_str(),
367 static_cast<int32_t>(error));
368 }
369
370 if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop);
371 error != HWC2::Error::None) {
372 ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
373 "%s (%d)",
374 mLayerFE->getDebugName(), outputDependentState.sourceCrop.left,
375 outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right,
376 outputDependentState.sourceCrop.bottom, to_string(error).c_str(),
377 static_cast<int32_t>(error));
378 }
379
380 if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
381 ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z,
382 to_string(error).c_str(), static_cast<int32_t>(error));
383 }
384
385 // Solid-color layers should always use an identity transform.
386 const auto bufferTransform =
387 requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR
388 ? outputDependentState.bufferTransform
389 : static_cast<Hwc2::Transform>(0);
390 if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
391 error != HWC2::Error::None) {
392 ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
393 toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
394 static_cast<int32_t>(error));
395 }
396}
397
398void OutputLayer::writeOutputIndependentGeometryStateToHWC(
399 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
400 if (auto error = hwcLayer->setBlendMode(
401 static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
402 error != HWC2::Error::None) {
403 ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
404 toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
405 static_cast<int32_t>(error));
406 }
407
408 if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
409 error != HWC2::Error::None) {
410 ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
411 outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
412 }
413
414 if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
415 error != HWC2::Error::None) {
416 ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(),
417 static_cast<int32_t>(error));
418 }
419}
420
421void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
422 const auto& outputDependentState = getState();
423
424 // TODO(lpique): b/121291683 visibleRegion is output-dependent geometry
425 // state and should not change every frame.
426 if (auto error = hwcLayer->setVisibleRegion(outputDependentState.visibleRegion);
427 error != HWC2::Error::None) {
428 ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
429 to_string(error).c_str(), static_cast<int32_t>(error));
430 outputDependentState.visibleRegion.dump(LOG_TAG);
431 }
432
433 if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
434 error != HWC2::Error::None) {
435 ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(),
436 outputDependentState.dataspace, to_string(error).c_str(),
437 static_cast<int32_t>(error));
438 }
439}
440
441void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
442 HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
443 switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
444 case HWC2::Error::None:
445 break;
446 case HWC2::Error::Unsupported:
447 editState().forceClientComposition = true;
448 break;
449 default:
450 ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800451 to_string(error).c_str(), static_cast<int32_t>(error));
Lloyd Piquef5275482019-01-29 18:42:42 -0800452 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800453
Lloyd Piquef5275482019-01-29 18:42:42 -0800454 if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
455 error != HWC2::Error::None) {
456 ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(),
457 to_string(error).c_str(), static_cast<int32_t>(error));
458 outputIndependentState.surfaceDamage.dump(LOG_TAG);
459 }
460
461 // Content-specific per-frame state
462 switch (outputIndependentState.compositionType) {
463 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
464 writeSolidColorStateToHWC(hwcLayer, outputIndependentState);
465 break;
466 case Hwc2::IComposerClient::Composition::SIDEBAND:
467 writeSidebandStateToHWC(hwcLayer, outputIndependentState);
468 break;
469 case Hwc2::IComposerClient::Composition::CURSOR:
470 case Hwc2::IComposerClient::Composition::DEVICE:
471 writeBufferStateToHWC(hwcLayer, outputIndependentState);
472 break;
473 case Hwc2::IComposerClient::Composition::INVALID:
474 case Hwc2::IComposerClient::Composition::CLIENT:
475 // Ignored
476 break;
477 }
478}
479
480void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
481 const LayerFECompositionState& outputIndependentState) {
482 hwc_color_t color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
483 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
484 static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
485 255};
486
487 if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
488 ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(),
489 to_string(error).c_str(), static_cast<int32_t>(error));
490 }
491}
492
493void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
494 const LayerFECompositionState& outputIndependentState) {
495 if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
496 error != HWC2::Error::None) {
497 ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(),
498 outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
499 static_cast<int32_t>(error));
500 }
501}
502
503void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
504 const LayerFECompositionState& outputIndependentState) {
505 auto supportedPerFrameMetadata =
506 mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata();
507 if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
508 outputIndependentState.hdrMetadata);
509 error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
510 ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(),
511 to_string(error).c_str(), static_cast<int32_t>(error));
512 }
513
514 uint32_t hwcSlot = 0;
515 sp<GraphicBuffer> hwcBuffer;
516 // We need access to the output-dependent state for the buffer cache there,
517 // though otherwise the buffer is not output-dependent.
518 editState().hwc->hwcBufferCache.getHwcBuffer(outputIndependentState.bufferSlot,
519 outputIndependentState.buffer, &hwcSlot,
520 &hwcBuffer);
521
522 if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
523 error != HWC2::Error::None) {
524 ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(),
525 outputIndependentState.buffer->handle, to_string(error).c_str(),
526 static_cast<int32_t>(error));
527 }
528}
529
530void OutputLayer::writeCompositionTypeToHWC(
531 HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
532 auto& outputDependentState = editState();
533
534 // If we are forcing client composition, we need to tell the HWC
535 if (outputDependentState.forceClientComposition) {
536 requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
537 }
538
539 // Set the requested composition type with the HWC whenever it changes
540 if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
541 outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
542
543 if (auto error = hwcLayer->setCompositionType(
544 static_cast<HWC2::Composition>(requestedCompositionType));
Lloyd Piquea83776c2019-01-29 18:42:32 -0800545 error != HWC2::Error::None) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800546 ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(),
547 toString(requestedCompositionType).c_str(), to_string(error).c_str(),
Lloyd Piquea83776c2019-01-29 18:42:32 -0800548 static_cast<int32_t>(error));
549 }
Lloyd Piquea83776c2019-01-29 18:42:32 -0800550 }
551}
552
Lloyd Pique66d68602019-02-13 14:23:31 -0800553HWC2::Layer* OutputLayer::getHwcLayer() const {
554 return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
555}
556
557bool OutputLayer::requiresClientComposition() const {
558 return !mState.hwc ||
559 mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
560}
561
562void OutputLayer::detectDisallowedCompositionTypeChange(
563 Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
564 bool result = false;
565 switch (from) {
566 case Hwc2::IComposerClient::Composition::INVALID:
567 case Hwc2::IComposerClient::Composition::CLIENT:
568 result = false;
569 break;
570
571 case Hwc2::IComposerClient::Composition::DEVICE:
572 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
573 result = (to == Hwc2::IComposerClient::Composition::CLIENT);
574 break;
575
576 case Hwc2::IComposerClient::Composition::CURSOR:
577 case Hwc2::IComposerClient::Composition::SIDEBAND:
578 result = (to == Hwc2::IComposerClient::Composition::CLIENT ||
579 to == Hwc2::IComposerClient::Composition::DEVICE);
580 break;
581 }
582
583 if (!result) {
584 ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
585 mLayerFE->getDebugName(), toString(from).c_str(), static_cast<int>(from),
586 toString(to).c_str(), static_cast<int>(to));
587 }
588}
589
590void OutputLayer::applyDeviceCompositionTypeChange(
591 Hwc2::IComposerClient::Composition compositionType) {
592 LOG_FATAL_IF(!mState.hwc);
593 auto& hwcState = *mState.hwc;
594
595 detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
596
597 hwcState.hwcCompositionType = compositionType;
598}
599
600void OutputLayer::prepareForDeviceLayerRequests() {
601 mState.clearClientTarget = false;
602}
603
604void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
605 switch (request) {
606 case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
607 mState.clearClientTarget = true;
608 break;
609
610 default:
611 ALOGE("[%s] Unknown device layer request %s (%d)", mLayerFE->getDebugName(),
612 toString(request).c_str(), static_cast<int>(request));
613 break;
614 }
615}
616
Lloyd Pique688abd42019-02-15 15:42:24 -0800617bool OutputLayer::needsFiltering() const {
618 const auto& displayFrame = mState.displayFrame;
619 const auto& sourceCrop = mState.sourceCrop;
620 return sourceCrop.getHeight() != displayFrame.getHeight() ||
621 sourceCrop.getWidth() != displayFrame.getWidth();
622}
623
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800624void OutputLayer::dump(std::string& out) const {
625 using android::base::StringAppendF;
626
Lloyd Pique207def92019-02-28 16:09:52 -0800627 StringAppendF(&out, " - Output Layer %p (Composition layer %p) (%s)\n", this, mLayer.get(),
628 mLayerFE->getDebugName());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800629 mState.dump(out);
630}
631
Lloyd Piquecc01a452018-12-04 17:24:00 -0800632} // namespace impl
633} // namespace android::compositionengine