blob: 02ebc1fc4faa4ea36a84b2bc0163e95306f8035d [file] [log] [blame]
Lloyd Pique32cbe282018-10-19 13:09:22 -07001/*
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 Piquef8cf14d2019-02-28 16:03:12 -080017#include <thread>
18
Lloyd Pique32cbe282018-10-19 13:09:22 -070019#include <android-base/stringprintf.h>
20#include <compositionengine/CompositionEngine.h>
Lloyd Piquef8cf14d2019-02-28 16:03:12 -080021#include <compositionengine/CompositionRefreshArgs.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070022#include <compositionengine/DisplayColorProfile.h>
Lloyd Pique688abd42019-02-15 15:42:24 -080023#include <compositionengine/Layer.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080024#include <compositionengine/LayerFE.h>
Lloyd Pique9755fb72019-03-26 14:44:40 -070025#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070026#include <compositionengine/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070027#include <compositionengine/impl/Output.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080028#include <compositionengine/impl/OutputLayer.h>
Lloyd Pique688abd42019-02-15 15:42:24 -080029#include <renderengine/DisplaySettings.h>
30#include <renderengine/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070031#include <ui/DebugUtils.h>
Lloyd Pique688abd42019-02-15 15:42:24 -080032#include <ui/HdrCapabilities.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080033#include <utils/Trace.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070034
Lloyd Pique688abd42019-02-15 15:42:24 -080035#include "TracedOrdinal.h"
36
Lloyd Piquefeb73d72018-12-04 17:23:44 -080037namespace android::compositionengine {
38
39Output::~Output() = default;
40
41namespace impl {
Lloyd Pique32cbe282018-10-19 13:09:22 -070042
Lloyd Piquec29e4c62019-03-07 21:48:19 -080043namespace {
44
45template <typename T>
46class Reversed {
47public:
48 explicit Reversed(const T& container) : mContainer(container) {}
49 auto begin() { return mContainer.rbegin(); }
50 auto end() { return mContainer.rend(); }
51
52private:
53 const T& mContainer;
54};
55
56// Helper for enumerating over a container in reverse order
57template <typename T>
58Reversed<T> reversed(const T& c) {
59 return Reversed<T>(c);
60}
61
62} // namespace
63
Lloyd Pique32cbe282018-10-19 13:09:22 -070064Output::Output(const CompositionEngine& compositionEngine)
65 : mCompositionEngine(compositionEngine) {}
66
67Output::~Output() = default;
68
69const CompositionEngine& Output::getCompositionEngine() const {
70 return mCompositionEngine;
71}
72
73bool Output::isValid() const {
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070074 return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
75 mRenderSurface->isValid();
Lloyd Pique32cbe282018-10-19 13:09:22 -070076}
77
78const std::string& Output::getName() const {
79 return mName;
80}
81
82void Output::setName(const std::string& name) {
83 mName = name;
84}
85
86void Output::setCompositionEnabled(bool enabled) {
87 if (mState.isEnabled == enabled) {
88 return;
89 }
90
91 mState.isEnabled = enabled;
92 dirtyEntireOutput();
93}
94
95void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame,
96 const Rect& viewport, const Rect& scissor, bool needsFiltering) {
97 mState.transform = transform;
98 mState.orientation = orientation;
99 mState.scissor = scissor;
100 mState.frame = frame;
101 mState.viewport = viewport;
102 mState.needsFiltering = needsFiltering;
103
104 dirtyEntireOutput();
105}
106
Lloyd Pique688abd42019-02-15 15:42:24 -0800107// TODO(b/121291683): Rename setSize() once more is moved.
Lloyd Pique31cb2942018-10-19 17:23:03 -0700108void Output::setBounds(const ui::Size& size) {
109 mRenderSurface->setDisplaySize(size);
Lloyd Pique688abd42019-02-15 15:42:24 -0800110 // TODO(b/121291683): Rename mState.size once more is moved.
Lloyd Pique31cb2942018-10-19 17:23:03 -0700111 mState.bounds = Rect(mRenderSurface->getSize());
Lloyd Pique32cbe282018-10-19 13:09:22 -0700112
113 dirtyEntireOutput();
114}
115
Lloyd Piqueef36b002019-01-23 17:52:04 -0800116void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
117 mState.layerStackId = layerStackId;
118 mState.layerStackInternal = isInternal;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700119
120 dirtyEntireOutput();
121}
122
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800123void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
124 if (!args.colorTransformMatrix || mState.colorTransformMatrix == *args.colorTransformMatrix) {
Lloyd Pique77f79a22019-04-29 15:55:40 -0700125 return;
126 }
127
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800128 mState.colorTransformMatrix = *args.colorTransformMatrix;
Lloyd Piqueef958122019-02-05 18:00:12 -0800129
130 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700131}
132
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800133void Output::setColorProfile(const ColorProfile& colorProfile) {
134 const ui::Dataspace targetDataspace =
135 getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
136 colorProfile.colorSpaceAgnosticDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800137
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800138 if (mState.colorMode == colorProfile.mode && mState.dataspace == colorProfile.dataspace &&
139 mState.renderIntent == colorProfile.renderIntent &&
140 mState.targetDataspace == targetDataspace) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800141 return;
142 }
143
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800144 mState.colorMode = colorProfile.mode;
145 mState.dataspace = colorProfile.dataspace;
146 mState.renderIntent = colorProfile.renderIntent;
Lloyd Piquef5275482019-01-29 18:42:42 -0800147 mState.targetDataspace = targetDataspace;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700148
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800149 mRenderSurface->setBufferDataspace(colorProfile.dataspace);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700150
Lloyd Pique32cbe282018-10-19 13:09:22 -0700151 ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800152 decodeColorMode(colorProfile.mode).c_str(), colorProfile.mode,
153 decodeRenderIntent(colorProfile.renderIntent).c_str(), colorProfile.renderIntent);
Lloyd Piqueef958122019-02-05 18:00:12 -0800154
155 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700156}
157
158void Output::dump(std::string& out) const {
159 using android::base::StringAppendF;
160
161 StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str());
162
163 out.append("\n ");
164
165 dumpBase(out);
166}
167
168void Output::dumpBase(std::string& out) const {
169 mState.dump(out);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700170
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700171 if (mDisplayColorProfile) {
172 mDisplayColorProfile->dump(out);
173 } else {
174 out.append(" No display color profile!\n");
175 }
176
Lloyd Pique31cb2942018-10-19 17:23:03 -0700177 if (mRenderSurface) {
178 mRenderSurface->dump(out);
179 } else {
180 out.append(" No render surface!\n");
181 }
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800182
Lloyd Pique207def92019-02-28 16:09:52 -0800183 android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800184 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
185 if (!outputLayer) {
186 continue;
187 }
188 outputLayer->dump(out);
189 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700190}
191
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700192compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
193 return mDisplayColorProfile.get();
194}
195
196void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
197 mDisplayColorProfile = std::move(mode);
198}
199
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800200const Output::ReleasedLayers& Output::getReleasedLayersForTest() const {
201 return mReleasedLayers;
202}
203
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700204void Output::setDisplayColorProfileForTest(
205 std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
206 mDisplayColorProfile = std::move(mode);
207}
208
Lloyd Pique31cb2942018-10-19 17:23:03 -0700209compositionengine::RenderSurface* Output::getRenderSurface() const {
210 return mRenderSurface.get();
211}
212
213void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
214 mRenderSurface = std::move(surface);
215 mState.bounds = Rect(mRenderSurface->getSize());
216
217 dirtyEntireOutput();
218}
219
220void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
221 mRenderSurface = std::move(surface);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700222}
223
224const OutputCompositionState& Output::getState() const {
225 return mState;
226}
227
228OutputCompositionState& Output::editState() {
229 return mState;
230}
231
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000232Region Output::getDirtyRegion(bool repaintEverything) const {
233 Region dirty(mState.viewport);
234 if (!repaintEverything) {
235 dirty.andSelf(mState.dirtyRegion);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700236 }
237 return dirty;
238}
239
Lloyd Piquec6687342019-03-07 21:34:57 -0800240bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
Lloyd Piqueef36b002019-01-23 17:52:04 -0800241 // The layerStackId's must match, and also the layer must not be internal
242 // only when not on an internal output.
Lloyd Piquec6687342019-03-07 21:34:57 -0800243 return layerStackId && (*layerStackId == mState.layerStackId) &&
244 (!internalOnly || mState.layerStackInternal);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700245}
246
Lloyd Pique66c20c42019-03-07 21:44:02 -0800247bool Output::belongsInOutput(const compositionengine::Layer* layer) const {
248 if (!layer) {
249 return false;
250 }
251
Lloyd Pique9755fb72019-03-26 14:44:40 -0700252 const auto& layerFEState = layer->getFEState();
Lloyd Pique66c20c42019-03-07 21:44:02 -0800253 return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly);
254}
255
Lloyd Piquecc01a452018-12-04 17:24:00 -0800256compositionengine::OutputLayer* Output::getOutputLayerForLayer(
257 compositionengine::Layer* layer) const {
258 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
259 if (outputLayer && &outputLayer->getLayer() == layer) {
260 return outputLayer.get();
261 }
262 }
263 return nullptr;
264}
265
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800266std::unique_ptr<compositionengine::OutputLayer> Output::takeOutputLayerForLayer(
267 compositionengine::Layer* layer) {
268 // Removes the outputLayer from mOutputLayersorderedByZ and transfers ownership to the caller.
Lloyd Piquecc01a452018-12-04 17:24:00 -0800269 for (auto& outputLayer : mOutputLayersOrderedByZ) {
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800270 if (outputLayer && &outputLayer->getLayer() == layer) {
Lloyd Piquecc01a452018-12-04 17:24:00 -0800271 return std::move(outputLayer);
272 }
273 }
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800274 return nullptr;
275}
Lloyd Piquedf336d92019-03-07 21:38:42 -0800276
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800277std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
278 std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
279 auto result = takeOutputLayerForLayer(layer.get());
280 if (!result) {
281 result = createOutputLayer(layer, layerFE);
282 }
283 return result;
Lloyd Piquedf336d92019-03-07 21:38:42 -0800284}
285
286std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
287 const std::shared_ptr<compositionengine::Layer>& layer,
288 const sp<compositionengine::LayerFE>& layerFE) const {
289 return impl::createOutputLayer(*this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800290}
291
292void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
293 mOutputLayersOrderedByZ = std::move(layers);
294}
295
296const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
297 return mOutputLayersOrderedByZ;
298}
299
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800300void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
301 mReleasedLayers = std::move(layers);
302}
303
304Output::ReleasedLayers Output::takeReleasedLayers() {
305 return std::move(mReleasedLayers);
306}
307
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800308void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs,
309 LayerFESet& geomSnapshots) {
310 ATRACE_CALL();
311 ALOGV(__FUNCTION__);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800312
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800313 rebuildLayerStacks(refreshArgs, geomSnapshots);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800314}
315
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800316void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800317 ATRACE_CALL();
318 ALOGV(__FUNCTION__);
319
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800320 updateColorProfile(refreshArgs);
321 updateAndWriteCompositionState(refreshArgs);
322 setColorTransform(refreshArgs);
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800323 beginFrame();
324 prepareFrame();
325 devOptRepaintFlash(refreshArgs);
326 finishFrame(refreshArgs);
327 postFramebuffer();
328}
329
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800330void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
331 LayerFESet& layerFESet) {
332 ATRACE_CALL();
333 ALOGV(__FUNCTION__);
334
335 // Do nothing if this output is not enabled or there is no need to perform this update
336 if (!mState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
337 return;
338 }
339
340 // Process the layers to determine visibility and coverage
341 compositionengine::Output::CoverageState coverage{layerFESet};
342 collectVisibleLayers(refreshArgs, coverage);
343
344 // Compute the resulting coverage for this output, and store it for later
345 const ui::Transform& tr = mState.transform;
346 Region undefinedRegion{mState.bounds};
347 undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
348
349 mState.undefinedRegion = undefinedRegion;
350 mState.dirtyRegion.orSelf(coverage.dirtyRegion);
351}
352
353void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
354 compositionengine::Output::CoverageState& coverage) {
355 // We build up a list of all layers that are going to be visible in the new
356 // frame.
357 compositionengine::Output::OutputLayers newLayersSortedByZ;
358
359 // Evaluate the layers from front to back to determine what is visible. This
360 // also incrementally calculates the coverage information for each layer as
361 // well as the entire output.
362 for (auto& layer : reversed(refreshArgs.layers)) {
363 // Incrementally process the coverage for each layer, obtaining an
364 // optional outputLayer if the layer is visible.
365 auto outputLayer = getOutputLayerIfVisible(layer, coverage);
366 if (outputLayer) {
367 newLayersSortedByZ.emplace_back(std::move(outputLayer));
368 }
369
370 // TODO(b/121291683): Stop early if the output is completely covered and
371 // no more layers could even be visible underneath the ones on top.
372 }
373
374 // Since we walked the layers in reverse order, we need to reverse
375 // newLayersSortedByZ to get the back-to-front ordered list of layers.
376 std::reverse(newLayersSortedByZ.begin(), newLayersSortedByZ.end());
377
378 // Generate a simple Z-order values to each visible output layer
379 uint32_t zOrder = 0;
380 for (auto& outputLayer : newLayersSortedByZ) {
381 outputLayer->editState().z = zOrder++;
382 }
383
384 setReleasedLayers(refreshArgs);
385
386 mOutputLayersOrderedByZ = std::move(newLayersSortedByZ);
387}
388
389std::unique_ptr<compositionengine::OutputLayer> Output::getOutputLayerIfVisible(
390 std::shared_ptr<compositionengine::Layer> layer,
391 compositionengine::Output::CoverageState& coverage) {
392 // Note: Converts a wp<LayerFE> to a sp<LayerFE>
393 auto layerFE = layer->getLayerFE();
394 if (layerFE == nullptr) {
395 return nullptr;
396 }
397
398 // Ensure we have a snapshot of the basic geometry layer state. Limit the
399 // snapshots to once per frame for each candidate layer, as layers may
400 // appear on multiple outputs.
401 if (!coverage.latchedLayers.count(layerFE)) {
402 coverage.latchedLayers.insert(layerFE);
Lloyd Pique9755fb72019-03-26 14:44:40 -0700403 layerFE->latchCompositionState(layer->editFEState(),
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800404 compositionengine::LayerFE::StateSubset::BasicGeometry);
405 }
406
407 // Obtain a read-only reference to the front-end layer state
Lloyd Pique9755fb72019-03-26 14:44:40 -0700408 const auto& layerFEState = layer->getFEState();
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800409
410 // Only consider the layers on the given layer stack
411 if (!belongsInOutput(layer.get())) {
412 return nullptr;
413 }
414
415 /*
416 * opaqueRegion: area of a surface that is fully opaque.
417 */
418 Region opaqueRegion;
419
420 /*
421 * visibleRegion: area of a surface that is visible on screen and not fully
422 * transparent. This is essentially the layer's footprint minus the opaque
423 * regions above it. Areas covered by a translucent surface are considered
424 * visible.
425 */
426 Region visibleRegion;
427
428 /*
429 * coveredRegion: area of a surface that is covered by all visible regions
430 * above it (which includes the translucent areas).
431 */
432 Region coveredRegion;
433
434 /*
435 * transparentRegion: area of a surface that is hinted to be completely
436 * transparent. This is only used to tell when the layer has no visible non-
437 * transparent regions and can be removed from the layer list. It does not
438 * affect the visibleRegion of this layer or any layers beneath it. The hint
439 * may not be correct if apps don't respect the SurfaceView restrictions
440 * (which, sadly, some don't).
441 */
442 Region transparentRegion;
443
444 // handle hidden surfaces by setting the visible region to empty
445 if (CC_UNLIKELY(!layerFEState.isVisible)) {
446 return nullptr;
447 }
448
449 const ui::Transform& tr = layerFEState.geomLayerTransform;
450
451 // Get the visible region
452 // TODO(b/121291683): Is it worth creating helper methods on LayerFEState
453 // for computations like this?
454 visibleRegion.set(Rect(tr.transform(layerFEState.geomLayerBounds)));
455
456 if (visibleRegion.isEmpty()) {
457 return nullptr;
458 }
459
460 // Remove the transparent area from the visible region
461 if (!layerFEState.isOpaque) {
462 if (tr.preserveRects()) {
463 // transform the transparent region
464 transparentRegion = tr.transform(layerFEState.transparentRegionHint);
465 } else {
466 // transformation too complex, can't do the
467 // transparent region optimization.
468 transparentRegion.clear();
469 }
470 }
471
472 // compute the opaque region
473 const int32_t layerOrientation = tr.getOrientation();
474 if (layerFEState.isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
475 // If we one of the simple category of transforms (0/90/180/270 rotation
476 // + any flip), then the opaque region is the layer's footprint.
477 // Otherwise we don't try and compute the opaque region since there may
478 // be errors at the edges, and we treat the entire layer as
479 // translucent.
480 opaqueRegion = visibleRegion;
481 }
482
483 // Clip the covered region to the visible region
484 coveredRegion = coverage.aboveCoveredLayers.intersect(visibleRegion);
485
486 // Update accumAboveCoveredLayers for next (lower) layer
487 coverage.aboveCoveredLayers.orSelf(visibleRegion);
488
489 // subtract the opaque region covered by the layers above us
490 visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
491
492 if (visibleRegion.isEmpty()) {
493 return nullptr;
494 }
495
496 // Get coverage information for the layer as previously displayed,
497 // also taking over ownership from mOutputLayersorderedByZ.
498 auto prevOutputLayer = takeOutputLayerForLayer(layer.get());
499
500 // Get coverage information for the layer as previously displayed
501 // TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
502 const Region kEmptyRegion;
503 const Region& oldVisibleRegion =
504 prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
505 const Region& oldCoveredRegion =
506 prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;
507
508 // compute this layer's dirty region
509 Region dirty;
510 if (layerFEState.contentDirty) {
511 // we need to invalidate the whole region
512 dirty = visibleRegion;
513 // as well, as the old visible region
514 dirty.orSelf(oldVisibleRegion);
515 } else {
516 /* compute the exposed region:
517 * the exposed region consists of two components:
518 * 1) what's VISIBLE now and was COVERED before
519 * 2) what's EXPOSED now less what was EXPOSED before
520 *
521 * note that (1) is conservative, we start with the whole visible region
522 * but only keep what used to be covered by something -- which mean it
523 * may have been exposed.
524 *
525 * (2) handles areas that were not covered by anything but got exposed
526 * because of a resize.
527 *
528 */
529 const Region newExposed = visibleRegion - coveredRegion;
530 const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
531 dirty = (visibleRegion & oldCoveredRegion) | (newExposed - oldExposed);
532 }
533 dirty.subtractSelf(coverage.aboveOpaqueLayers);
534
535 // accumulate to the screen dirty region
536 coverage.dirtyRegion.orSelf(dirty);
537
538 // Update accumAboveOpaqueLayers for next (lower) layer
539 coverage.aboveOpaqueLayers.orSelf(opaqueRegion);
540
541 // Compute the visible non-transparent region
542 Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);
543
544 // Peform the final check to see if this layer is visible on this output
545 // TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
546 Region drawRegion(mState.transform.transform(visibleNonTransparentRegion));
547 drawRegion.andSelf(mState.bounds);
548 if (drawRegion.isEmpty()) {
549 return nullptr;
550 }
551
552 // The layer is visible. Either reuse the existing outputLayer if we have
553 // one, or create a new one if we do not.
554 std::unique_ptr<compositionengine::OutputLayer> result =
555 prevOutputLayer ? std::move(prevOutputLayer) : createOutputLayer(layer, layerFE);
556
557 // Store the layer coverage information into the layer state as some of it
558 // is useful later.
559 auto& outputLayerState = result->editState();
560 outputLayerState.visibleRegion = visibleRegion;
561 outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
562 outputLayerState.coveredRegion = coveredRegion;
563 outputLayerState.outputSpaceVisibleRegion =
564 mState.transform.transform(outputLayerState.visibleRegion.intersect(mState.viewport));
565
566 return result;
567}
568
569void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
570 // The base class does nothing with this call.
571}
572
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800573void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
574 for (auto& layer : mOutputLayersOrderedByZ) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700575 layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(),
Lloyd Piquec6687342019-03-07 21:34:57 -0800576 args.updatingGeometryThisFrame
577 ? LayerFE::StateSubset::GeometryAndContent
578 : LayerFE::StateSubset::Content);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800579 }
580}
581
582void Output::updateAndWriteCompositionState(
583 const compositionengine::CompositionRefreshArgs& refreshArgs) {
584 ATRACE_CALL();
585 ALOGV(__FUNCTION__);
586
587 for (auto& layer : mOutputLayersOrderedByZ) {
588 if (refreshArgs.devOptForceClientComposition) {
589 layer->editState().forceClientComposition = true;
590 }
591
592 layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame);
593
594 // Send the updated state to the HWC, if appropriate.
595 layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
596 }
597}
598
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800599void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
600 setColorProfile(pickColorProfile(refreshArgs));
601}
602
603// Returns a data space that fits all visible layers. The returned data space
604// can only be one of
605// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
606// - Dataspace::DISPLAY_P3
607// - Dataspace::DISPLAY_BT2020
608// The returned HDR data space is one of
609// - Dataspace::UNKNOWN
610// - Dataspace::BT2020_HLG
611// - Dataspace::BT2020_PQ
612ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
613 bool* outIsHdrClientComposition) const {
614 ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
615 *outHdrDataSpace = ui::Dataspace::UNKNOWN;
616
617 for (const auto& layer : mOutputLayersOrderedByZ) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700618 switch (layer->getLayer().getFEState().dataspace) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800619 case ui::Dataspace::V0_SCRGB:
620 case ui::Dataspace::V0_SCRGB_LINEAR:
621 case ui::Dataspace::BT2020:
622 case ui::Dataspace::BT2020_ITU:
623 case ui::Dataspace::BT2020_LINEAR:
624 case ui::Dataspace::DISPLAY_BT2020:
625 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
626 break;
627 case ui::Dataspace::DISPLAY_P3:
628 bestDataSpace = ui::Dataspace::DISPLAY_P3;
629 break;
630 case ui::Dataspace::BT2020_PQ:
631 case ui::Dataspace::BT2020_ITU_PQ:
632 bestDataSpace = ui::Dataspace::DISPLAY_P3;
633 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700634 *outIsHdrClientComposition = layer->getLayer().getFEState().forceClientComposition;
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800635 break;
636 case ui::Dataspace::BT2020_HLG:
637 case ui::Dataspace::BT2020_ITU_HLG:
638 bestDataSpace = ui::Dataspace::DISPLAY_P3;
639 // When there's mixed PQ content and HLG content, we set the HDR
640 // data space to be BT2020_PQ and convert HLG to PQ.
641 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
642 *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
643 }
644 break;
645 default:
646 break;
647 }
648 }
649
650 return bestDataSpace;
651}
652
653compositionengine::Output::ColorProfile Output::pickColorProfile(
654 const compositionengine::CompositionRefreshArgs& refreshArgs) const {
655 if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
656 return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
657 ui::RenderIntent::COLORIMETRIC,
658 refreshArgs.colorSpaceAgnosticDataspace};
659 }
660
661 ui::Dataspace hdrDataSpace;
662 bool isHdrClientComposition = false;
663 ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
664
665 switch (refreshArgs.forceOutputColorMode) {
666 case ui::ColorMode::SRGB:
667 bestDataSpace = ui::Dataspace::V0_SRGB;
668 break;
669 case ui::ColorMode::DISPLAY_P3:
670 bestDataSpace = ui::Dataspace::DISPLAY_P3;
671 break;
672 default:
673 break;
674 }
675
676 // respect hdrDataSpace only when there is no legacy HDR support
677 const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
678 !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
679 if (isHdr) {
680 bestDataSpace = hdrDataSpace;
681 }
682
683 ui::RenderIntent intent;
684 switch (refreshArgs.outputColorSetting) {
685 case OutputColorSetting::kManaged:
686 case OutputColorSetting::kUnmanaged:
687 intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
688 : ui::RenderIntent::COLORIMETRIC;
689 break;
690 case OutputColorSetting::kEnhanced:
691 intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
692 break;
693 default: // vendor display color setting
694 intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
695 break;
696 }
697
698 ui::ColorMode outMode;
699 ui::Dataspace outDataSpace;
700 ui::RenderIntent outRenderIntent;
701 mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
702 &outRenderIntent);
703
704 return ColorProfile{outMode, outDataSpace, outRenderIntent,
705 refreshArgs.colorSpaceAgnosticDataspace};
706}
707
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800708void Output::beginFrame() {
709 const bool dirty = !getDirtyRegion(false).isEmpty();
710 const bool empty = mOutputLayersOrderedByZ.empty();
711 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
712
713 // If nothing has changed (!dirty), don't recompose.
714 // If something changed, but we don't currently have any visible layers,
715 // and didn't when we last did a composition, then skip it this time.
716 // The second rule does two things:
717 // - When all layers are removed from a display, we'll emit one black
718 // frame, then nothing more until we get new layers.
719 // - When a display is created with a private layer stack, we won't
720 // emit any black frames until a layer is added to the layer stack.
721 const bool mustRecompose = dirty && !(empty && wasEmpty);
722
723 const char flagPrefix[] = {'-', '+'};
724 static_cast<void>(flagPrefix);
725 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
726 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
727 flagPrefix[empty], flagPrefix[wasEmpty]);
728
729 mRenderSurface->beginFrame(mustRecompose);
730
731 if (mustRecompose) {
732 mState.lastCompositionHadVisibleLayers = !empty;
733 }
734}
735
Lloyd Pique66d68602019-02-13 14:23:31 -0800736void Output::prepareFrame() {
737 ATRACE_CALL();
738 ALOGV(__FUNCTION__);
739
740 if (!mState.isEnabled) {
741 return;
742 }
743
744 chooseCompositionStrategy();
745
746 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
747}
748
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800749void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
750 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
751 return;
752 }
753
754 if (mState.isEnabled) {
755 // transform the dirty region into this screen's coordinate space
756 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
757 if (!dirtyRegion.isEmpty()) {
758 base::unique_fd readyFence;
759 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800760 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800761
762 mRenderSurface->queueBuffer(std::move(readyFence));
763 }
764 }
765
766 postFramebuffer();
767
768 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
769
770 prepareFrame();
771}
772
Lloyd Piqued3d69882019-02-28 16:03:46 -0800773void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
774 ATRACE_CALL();
775 ALOGV(__FUNCTION__);
776
777 if (!mState.isEnabled) {
778 return;
779 }
780
781 // Repaint the framebuffer (if needed), getting the optional fence for when
782 // the composition completes.
783 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
784 if (!optReadyFence) {
785 return;
786 }
787
788 // swap buffers (presentation)
789 mRenderSurface->queueBuffer(std::move(*optReadyFence));
790}
791
792std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800793 ATRACE_CALL();
794 ALOGV(__FUNCTION__);
795
796 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
797 mState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800798 base::unique_fd readyFence;
799
Lloyd Pique688abd42019-02-15 15:42:24 -0800800 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800801 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800802 }
803
804 ALOGV("hasClientComposition");
805
806 auto& renderEngine = mCompositionEngine.getRenderEngine();
807 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
808
809 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700810 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800811 clientCompositionDisplay.clip = mState.scissor;
812 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
813 clientCompositionDisplay.orientation = mState.orientation;
814 clientCompositionDisplay.outputDataspace =
815 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
816 clientCompositionDisplay.maxLuminance =
817 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
818
819 // Compute the global color transform matrix.
820 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800821 clientCompositionDisplay.colorTransform = mState.colorTransformMatrix;
Lloyd Pique688abd42019-02-15 15:42:24 -0800822 }
823
824 // Note: Updated by generateClientCompositionRequests
825 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
826
827 // Generate the client composition requests for the layers on this output.
828 std::vector<renderengine::LayerSettings> clientCompositionLayers =
829 generateClientCompositionRequests(supportsProtectedContent,
830 clientCompositionDisplay.clearRegion);
831 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
832
833 // If we the display is secure, protected content support is enabled, and at
834 // least one layer has protected content, we need to use a secure back
835 // buffer.
836 if (mState.isSecure && supportsProtectedContent) {
837 bool needsProtected =
838 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
839 [](auto& layer) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700840 return layer->getLayer().getFEState().hasProtectedContent;
Lloyd Pique688abd42019-02-15 15:42:24 -0800841 });
842 if (needsProtected != renderEngine.isProtected()) {
843 renderEngine.useProtectedContext(needsProtected);
844 }
845 if (needsProtected != mRenderSurface->isProtected() &&
846 needsProtected == renderEngine.isProtected()) {
847 mRenderSurface->setProtected(needsProtected);
848 }
849 }
850
851 base::unique_fd fd;
852 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
853 if (buf == nullptr) {
854 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
855 "client composition for this frame",
856 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800857 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800858 }
859
860 // We boost GPU frequency here because there will be color spaces conversion
861 // and it's expensive. We boost the GPU frequency so that GPU composition can
862 // finish in time. We must reset GPU frequency afterwards, because high frequency
863 // consumes extra battery.
864 const bool expensiveRenderingExpected =
865 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
866 if (expensiveRenderingExpected) {
867 setExpensiveRenderingExpected(true);
868 }
869
870 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
871 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800872 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800873
874 if (expensiveRenderingExpected) {
875 setExpensiveRenderingExpected(false);
876 }
877
Lloyd Piqued3d69882019-02-28 16:03:46 -0800878 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800879}
880
881std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
882 bool supportsProtectedContent, Region& clearRegion) {
883 std::vector<renderengine::LayerSettings> clientCompositionLayers;
884 ALOGV("Rendering client layers");
885
886 const Region viewportRegion(mState.viewport);
887 const bool useIdentityTransform = false;
888 bool firstLayer = true;
889 // Used when a layer clears part of the buffer.
890 Region dummyRegion;
891
892 for (auto& layer : mOutputLayersOrderedByZ) {
893 const auto& layerState = layer->getState();
Lloyd Pique9755fb72019-03-26 14:44:40 -0700894 const auto& layerFEState = layer->getLayer().getFEState();
Lloyd Pique688abd42019-02-15 15:42:24 -0800895 auto& layerFE = layer->getLayerFE();
896
Lloyd Piquea2468662019-03-07 21:31:06 -0800897 const Region clip(viewportRegion.intersect(layerState.visibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800898 ALOGV("Layer: %s", layerFE.getDebugName());
899 if (clip.isEmpty()) {
900 ALOGV(" Skipping for empty clip");
901 firstLayer = false;
902 continue;
903 }
904
905 bool clientComposition = layer->requiresClientComposition();
906
907 // We clear the client target for non-client composed layers if
908 // requested by the HWC. We skip this if the layer is not an opaque
909 // rectangle, as by definition the layer must blend with whatever is
910 // underneath. We also skip the first layer as the buffer target is
911 // guaranteed to start out cleared.
912 bool clearClientComposition =
913 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
914
915 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
916
917 if (clientComposition || clearClientComposition) {
918 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
919 clip,
920 useIdentityTransform,
921 layer->needsFiltering() || mState.needsFiltering,
922 mState.isSecure,
923 supportsProtectedContent,
924 clientComposition ? clearRegion : dummyRegion,
925 };
926 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700927 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800928 auto& layerSettings = *result;
929 layerSettings.source.buffer.buffer = nullptr;
930 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
931 layerSettings.alpha = half(0.0);
932 layerSettings.disableBlending = true;
933 }
934
935 clientCompositionLayers.push_back(*result);
936 }
937 }
938
939 firstLayer = false;
940 }
941
942 return clientCompositionLayers;
943}
944
945void Output::appendRegionFlashRequests(
946 const Region& flashRegion,
947 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
948 if (flashRegion.isEmpty()) {
949 return;
950 }
951
952 renderengine::LayerSettings layerSettings;
953 layerSettings.source.buffer.buffer = nullptr;
954 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
955 layerSettings.alpha = half(1.0);
956
957 for (const auto& rect : flashRegion) {
958 layerSettings.geometry.boundaries = rect.toFloatRect();
959 clientCompositionLayers.push_back(layerSettings);
960 }
961}
962
963void Output::setExpensiveRenderingExpected(bool) {
964 // The base class does nothing with this call.
965}
966
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800967void Output::postFramebuffer() {
968 ATRACE_CALL();
969 ALOGV(__FUNCTION__);
970
971 if (!getState().isEnabled) {
972 return;
973 }
974
Lloyd Piqued3d69882019-02-28 16:03:46 -0800975 mState.dirtyRegion.clear();
976 mRenderSurface->flip();
977
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800978 auto frame = presentAndGetFrameFences();
979
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700980 mRenderSurface->onPresentDisplayCompleted();
981
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800982 for (auto& layer : getOutputLayersOrderedByZ()) {
983 // The layer buffer from the previous frame (if any) is released
984 // by HWC only when the release fence from this frame (if any) is
985 // signaled. Always get the release fence from HWC first.
986 sp<Fence> releaseFence = Fence::NO_FENCE;
987
988 if (auto hwcLayer = layer->getHwcLayer()) {
989 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
990 releaseFence = f->second;
991 }
992 }
993
994 // If the layer was client composited in the previous frame, we
995 // need to merge with the previous client target acquire fence.
996 // Since we do not track that, always merge with the current
997 // client target acquire fence when it is available, even though
998 // this is suboptimal.
999 // TODO(b/121291683): Track previous frame client target acquire fence.
1000 if (mState.usesClientComposition) {
1001 releaseFence =
1002 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
1003 }
1004
1005 layer->getLayerFE().onLayerDisplayed(releaseFence);
1006 }
1007
1008 // We've got a list of layers needing fences, that are disjoint with
1009 // getOutputLayersOrderedByZ. The best we can do is to
1010 // supply them with the present fence.
1011 for (auto& weakLayer : mReleasedLayers) {
1012 if (auto layer = weakLayer.promote(); layer != nullptr) {
1013 layer->onLayerDisplayed(frame.presentFence);
1014 }
1015 }
1016
1017 // Clear out the released layers now that we're done with them.
1018 mReleasedLayers.clear();
1019}
1020
Lloyd Pique32cbe282018-10-19 13:09:22 -07001021void Output::dirtyEntireOutput() {
1022 mState.dirtyRegion.set(mState.bounds);
1023}
1024
Lloyd Pique66d68602019-02-13 14:23:31 -08001025void Output::chooseCompositionStrategy() {
1026 // The base output implementation can only do client composition
1027 mState.usesClientComposition = true;
1028 mState.usesDeviceComposition = false;
1029}
1030
Lloyd Pique688abd42019-02-15 15:42:24 -08001031bool Output::getSkipColorTransform() const {
1032 return true;
1033}
1034
Lloyd Pique35fca9d2019-02-13 14:24:11 -08001035compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
1036 compositionengine::Output::FrameFences result;
1037 if (mState.usesClientComposition) {
1038 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
1039 }
1040 return result;
1041}
1042
Lloyd Piquefeb73d72018-12-04 17:23:44 -08001043} // namespace impl
1044} // namespace android::compositionengine