blob: 83df628f253beeab73b2ff1cc286456c98eb3b59 [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 Pique31cb2942018-10-19 17:23:03 -070025#include <compositionengine/RenderSurface.h>
Lloyd Pique688abd42019-02-15 15:42:24 -080026#include <compositionengine/impl/LayerCompositionState.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
252 const auto& layerFEState = layer->getState().frontEnd;
253 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);
403 layerFE->latchCompositionState(layer->editState().frontEnd,
404 compositionengine::LayerFE::StateSubset::BasicGeometry);
405 }
406
407 // Obtain a read-only reference to the front-end layer state
408 const auto& layerFEState = layer->getState().frontEnd;
409
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) {
575 layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd,
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) {
618 switch (layer->getLayer().getState().frontEnd.dataspace) {
619 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;
634 *outIsHdrClientComposition =
635 layer->getLayer().getState().frontEnd.forceClientComposition;
636 break;
637 case ui::Dataspace::BT2020_HLG:
638 case ui::Dataspace::BT2020_ITU_HLG:
639 bestDataSpace = ui::Dataspace::DISPLAY_P3;
640 // When there's mixed PQ content and HLG content, we set the HDR
641 // data space to be BT2020_PQ and convert HLG to PQ.
642 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
643 *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
644 }
645 break;
646 default:
647 break;
648 }
649 }
650
651 return bestDataSpace;
652}
653
654compositionengine::Output::ColorProfile Output::pickColorProfile(
655 const compositionengine::CompositionRefreshArgs& refreshArgs) const {
656 if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
657 return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
658 ui::RenderIntent::COLORIMETRIC,
659 refreshArgs.colorSpaceAgnosticDataspace};
660 }
661
662 ui::Dataspace hdrDataSpace;
663 bool isHdrClientComposition = false;
664 ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
665
666 switch (refreshArgs.forceOutputColorMode) {
667 case ui::ColorMode::SRGB:
668 bestDataSpace = ui::Dataspace::V0_SRGB;
669 break;
670 case ui::ColorMode::DISPLAY_P3:
671 bestDataSpace = ui::Dataspace::DISPLAY_P3;
672 break;
673 default:
674 break;
675 }
676
677 // respect hdrDataSpace only when there is no legacy HDR support
678 const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
679 !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
680 if (isHdr) {
681 bestDataSpace = hdrDataSpace;
682 }
683
684 ui::RenderIntent intent;
685 switch (refreshArgs.outputColorSetting) {
686 case OutputColorSetting::kManaged:
687 case OutputColorSetting::kUnmanaged:
688 intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
689 : ui::RenderIntent::COLORIMETRIC;
690 break;
691 case OutputColorSetting::kEnhanced:
692 intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
693 break;
694 default: // vendor display color setting
695 intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
696 break;
697 }
698
699 ui::ColorMode outMode;
700 ui::Dataspace outDataSpace;
701 ui::RenderIntent outRenderIntent;
702 mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
703 &outRenderIntent);
704
705 return ColorProfile{outMode, outDataSpace, outRenderIntent,
706 refreshArgs.colorSpaceAgnosticDataspace};
707}
708
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800709void Output::beginFrame() {
710 const bool dirty = !getDirtyRegion(false).isEmpty();
711 const bool empty = mOutputLayersOrderedByZ.empty();
712 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
713
714 // If nothing has changed (!dirty), don't recompose.
715 // If something changed, but we don't currently have any visible layers,
716 // and didn't when we last did a composition, then skip it this time.
717 // The second rule does two things:
718 // - When all layers are removed from a display, we'll emit one black
719 // frame, then nothing more until we get new layers.
720 // - When a display is created with a private layer stack, we won't
721 // emit any black frames until a layer is added to the layer stack.
722 const bool mustRecompose = dirty && !(empty && wasEmpty);
723
724 const char flagPrefix[] = {'-', '+'};
725 static_cast<void>(flagPrefix);
726 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
727 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
728 flagPrefix[empty], flagPrefix[wasEmpty]);
729
730 mRenderSurface->beginFrame(mustRecompose);
731
732 if (mustRecompose) {
733 mState.lastCompositionHadVisibleLayers = !empty;
734 }
735}
736
Lloyd Pique66d68602019-02-13 14:23:31 -0800737void Output::prepareFrame() {
738 ATRACE_CALL();
739 ALOGV(__FUNCTION__);
740
741 if (!mState.isEnabled) {
742 return;
743 }
744
745 chooseCompositionStrategy();
746
747 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
748}
749
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800750void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
751 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
752 return;
753 }
754
755 if (mState.isEnabled) {
756 // transform the dirty region into this screen's coordinate space
757 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
758 if (!dirtyRegion.isEmpty()) {
759 base::unique_fd readyFence;
760 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800761 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800762
763 mRenderSurface->queueBuffer(std::move(readyFence));
764 }
765 }
766
767 postFramebuffer();
768
769 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
770
771 prepareFrame();
772}
773
Lloyd Piqued3d69882019-02-28 16:03:46 -0800774void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
775 ATRACE_CALL();
776 ALOGV(__FUNCTION__);
777
778 if (!mState.isEnabled) {
779 return;
780 }
781
782 // Repaint the framebuffer (if needed), getting the optional fence for when
783 // the composition completes.
784 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
785 if (!optReadyFence) {
786 return;
787 }
788
789 // swap buffers (presentation)
790 mRenderSurface->queueBuffer(std::move(*optReadyFence));
791}
792
793std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800794 ATRACE_CALL();
795 ALOGV(__FUNCTION__);
796
797 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
798 mState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800799 base::unique_fd readyFence;
800
Lloyd Pique688abd42019-02-15 15:42:24 -0800801 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800802 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800803 }
804
805 ALOGV("hasClientComposition");
806
807 auto& renderEngine = mCompositionEngine.getRenderEngine();
808 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
809
810 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700811 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800812 clientCompositionDisplay.clip = mState.scissor;
813 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
814 clientCompositionDisplay.orientation = mState.orientation;
815 clientCompositionDisplay.outputDataspace =
816 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
817 clientCompositionDisplay.maxLuminance =
818 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
819
820 // Compute the global color transform matrix.
821 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800822 clientCompositionDisplay.colorTransform = mState.colorTransformMatrix;
Lloyd Pique688abd42019-02-15 15:42:24 -0800823 }
824
825 // Note: Updated by generateClientCompositionRequests
826 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
827
828 // Generate the client composition requests for the layers on this output.
829 std::vector<renderengine::LayerSettings> clientCompositionLayers =
830 generateClientCompositionRequests(supportsProtectedContent,
831 clientCompositionDisplay.clearRegion);
832 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
833
834 // If we the display is secure, protected content support is enabled, and at
835 // least one layer has protected content, we need to use a secure back
836 // buffer.
837 if (mState.isSecure && supportsProtectedContent) {
838 bool needsProtected =
839 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
840 [](auto& layer) {
841 return layer->getLayer().getState().frontEnd.hasProtectedContent;
842 });
843 if (needsProtected != renderEngine.isProtected()) {
844 renderEngine.useProtectedContext(needsProtected);
845 }
846 if (needsProtected != mRenderSurface->isProtected() &&
847 needsProtected == renderEngine.isProtected()) {
848 mRenderSurface->setProtected(needsProtected);
849 }
850 }
851
852 base::unique_fd fd;
853 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
854 if (buf == nullptr) {
855 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
856 "client composition for this frame",
857 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800858 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800859 }
860
861 // We boost GPU frequency here because there will be color spaces conversion
862 // and it's expensive. We boost the GPU frequency so that GPU composition can
863 // finish in time. We must reset GPU frequency afterwards, because high frequency
864 // consumes extra battery.
865 const bool expensiveRenderingExpected =
866 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
867 if (expensiveRenderingExpected) {
868 setExpensiveRenderingExpected(true);
869 }
870
871 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
872 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800873 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800874
875 if (expensiveRenderingExpected) {
876 setExpensiveRenderingExpected(false);
877 }
878
Lloyd Piqued3d69882019-02-28 16:03:46 -0800879 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800880}
881
882std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
883 bool supportsProtectedContent, Region& clearRegion) {
884 std::vector<renderengine::LayerSettings> clientCompositionLayers;
885 ALOGV("Rendering client layers");
886
887 const Region viewportRegion(mState.viewport);
888 const bool useIdentityTransform = false;
889 bool firstLayer = true;
890 // Used when a layer clears part of the buffer.
891 Region dummyRegion;
892
893 for (auto& layer : mOutputLayersOrderedByZ) {
894 const auto& layerState = layer->getState();
895 const auto& layerFEState = layer->getLayer().getState().frontEnd;
896 auto& layerFE = layer->getLayerFE();
897
Lloyd Piquea2468662019-03-07 21:31:06 -0800898 const Region clip(viewportRegion.intersect(layerState.visibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800899 ALOGV("Layer: %s", layerFE.getDebugName());
900 if (clip.isEmpty()) {
901 ALOGV(" Skipping for empty clip");
902 firstLayer = false;
903 continue;
904 }
905
906 bool clientComposition = layer->requiresClientComposition();
907
908 // We clear the client target for non-client composed layers if
909 // requested by the HWC. We skip this if the layer is not an opaque
910 // rectangle, as by definition the layer must blend with whatever is
911 // underneath. We also skip the first layer as the buffer target is
912 // guaranteed to start out cleared.
913 bool clearClientComposition =
914 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
915
916 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
917
918 if (clientComposition || clearClientComposition) {
919 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
920 clip,
921 useIdentityTransform,
922 layer->needsFiltering() || mState.needsFiltering,
923 mState.isSecure,
924 supportsProtectedContent,
925 clientComposition ? clearRegion : dummyRegion,
926 };
927 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700928 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800929 auto& layerSettings = *result;
930 layerSettings.source.buffer.buffer = nullptr;
931 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
932 layerSettings.alpha = half(0.0);
933 layerSettings.disableBlending = true;
934 }
935
936 clientCompositionLayers.push_back(*result);
937 }
938 }
939
940 firstLayer = false;
941 }
942
943 return clientCompositionLayers;
944}
945
946void Output::appendRegionFlashRequests(
947 const Region& flashRegion,
948 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
949 if (flashRegion.isEmpty()) {
950 return;
951 }
952
953 renderengine::LayerSettings layerSettings;
954 layerSettings.source.buffer.buffer = nullptr;
955 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
956 layerSettings.alpha = half(1.0);
957
958 for (const auto& rect : flashRegion) {
959 layerSettings.geometry.boundaries = rect.toFloatRect();
960 clientCompositionLayers.push_back(layerSettings);
961 }
962}
963
964void Output::setExpensiveRenderingExpected(bool) {
965 // The base class does nothing with this call.
966}
967
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800968void Output::postFramebuffer() {
969 ATRACE_CALL();
970 ALOGV(__FUNCTION__);
971
972 if (!getState().isEnabled) {
973 return;
974 }
975
Lloyd Piqued3d69882019-02-28 16:03:46 -0800976 mState.dirtyRegion.clear();
977 mRenderSurface->flip();
978
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800979 auto frame = presentAndGetFrameFences();
980
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700981 mRenderSurface->onPresentDisplayCompleted();
982
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800983 for (auto& layer : getOutputLayersOrderedByZ()) {
984 // The layer buffer from the previous frame (if any) is released
985 // by HWC only when the release fence from this frame (if any) is
986 // signaled. Always get the release fence from HWC first.
987 sp<Fence> releaseFence = Fence::NO_FENCE;
988
989 if (auto hwcLayer = layer->getHwcLayer()) {
990 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
991 releaseFence = f->second;
992 }
993 }
994
995 // If the layer was client composited in the previous frame, we
996 // need to merge with the previous client target acquire fence.
997 // Since we do not track that, always merge with the current
998 // client target acquire fence when it is available, even though
999 // this is suboptimal.
1000 // TODO(b/121291683): Track previous frame client target acquire fence.
1001 if (mState.usesClientComposition) {
1002 releaseFence =
1003 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
1004 }
1005
1006 layer->getLayerFE().onLayerDisplayed(releaseFence);
1007 }
1008
1009 // We've got a list of layers needing fences, that are disjoint with
1010 // getOutputLayersOrderedByZ. The best we can do is to
1011 // supply them with the present fence.
1012 for (auto& weakLayer : mReleasedLayers) {
1013 if (auto layer = weakLayer.promote(); layer != nullptr) {
1014 layer->onLayerDisplayed(frame.presentFence);
1015 }
1016 }
1017
1018 // Clear out the released layers now that we're done with them.
1019 mReleasedLayers.clear();
1020}
1021
Lloyd Pique32cbe282018-10-19 13:09:22 -07001022void Output::dirtyEntireOutput() {
1023 mState.dirtyRegion.set(mState.bounds);
1024}
1025
Lloyd Pique66d68602019-02-13 14:23:31 -08001026void Output::chooseCompositionStrategy() {
1027 // The base output implementation can only do client composition
1028 mState.usesClientComposition = true;
1029 mState.usesDeviceComposition = false;
1030}
1031
Lloyd Pique688abd42019-02-15 15:42:24 -08001032bool Output::getSkipColorTransform() const {
1033 return true;
1034}
1035
Lloyd Pique35fca9d2019-02-13 14:24:11 -08001036compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
1037 compositionengine::Output::FrameFences result;
1038 if (mState.usesClientComposition) {
1039 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
1040 }
1041 return result;
1042}
1043
Lloyd Piquefeb73d72018-12-04 17:23:44 -08001044} // namespace impl
1045} // namespace android::compositionengine