blob: c511306466868b95151941d1f828d52e862e868b [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 Piquea38ea7e2019-04-16 18:10:26 -070028#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080029#include <compositionengine/impl/OutputLayer.h>
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070030#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Pique688abd42019-02-15 15:42:24 -080031#include <renderengine/DisplaySettings.h>
32#include <renderengine/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070033#include <ui/DebugUtils.h>
Lloyd Pique688abd42019-02-15 15:42:24 -080034#include <ui/HdrCapabilities.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080035#include <utils/Trace.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070036
Lloyd Pique688abd42019-02-15 15:42:24 -080037#include "TracedOrdinal.h"
38
Lloyd Piquefeb73d72018-12-04 17:23:44 -080039namespace android::compositionengine {
40
41Output::~Output() = default;
42
43namespace impl {
Lloyd Pique32cbe282018-10-19 13:09:22 -070044
Lloyd Piquec29e4c62019-03-07 21:48:19 -080045namespace {
46
47template <typename T>
48class Reversed {
49public:
50 explicit Reversed(const T& container) : mContainer(container) {}
51 auto begin() { return mContainer.rbegin(); }
52 auto end() { return mContainer.rend(); }
53
54private:
55 const T& mContainer;
56};
57
58// Helper for enumerating over a container in reverse order
59template <typename T>
60Reversed<T> reversed(const T& c) {
61 return Reversed<T>(c);
62}
63
64} // namespace
65
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070066std::shared_ptr<Output> createOutput(
67 const compositionengine::CompositionEngine& compositionEngine) {
68 return createOutputTemplated<Output>(compositionEngine);
69}
Lloyd Pique32cbe282018-10-19 13:09:22 -070070
71Output::~Output() = default;
72
Lloyd Pique32cbe282018-10-19 13:09:22 -070073bool 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) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070087 auto& outputState = editState();
88 if (outputState.isEnabled == enabled) {
Lloyd Pique32cbe282018-10-19 13:09:22 -070089 return;
90 }
91
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070092 outputState.isEnabled = enabled;
Lloyd Pique32cbe282018-10-19 13:09:22 -070093 dirtyEntireOutput();
94}
95
96void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame,
97 const Rect& viewport, const Rect& scissor, bool needsFiltering) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070098 auto& outputState = editState();
99 outputState.transform = transform;
100 outputState.orientation = orientation;
101 outputState.scissor = scissor;
102 outputState.frame = frame;
103 outputState.viewport = viewport;
104 outputState.needsFiltering = needsFiltering;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700105
106 dirtyEntireOutput();
107}
108
Lloyd Pique688abd42019-02-15 15:42:24 -0800109// TODO(b/121291683): Rename setSize() once more is moved.
Lloyd Pique31cb2942018-10-19 17:23:03 -0700110void Output::setBounds(const ui::Size& size) {
111 mRenderSurface->setDisplaySize(size);
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700112 // TODO(b/121291683): Rename outputState.size once more is moved.
113 editState().bounds = Rect(mRenderSurface->getSize());
Lloyd Pique32cbe282018-10-19 13:09:22 -0700114
115 dirtyEntireOutput();
116}
117
Lloyd Piqueef36b002019-01-23 17:52:04 -0800118void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700119 auto& outputState = editState();
120 outputState.layerStackId = layerStackId;
121 outputState.layerStackInternal = isInternal;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700122
123 dirtyEntireOutput();
124}
125
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800126void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700127 auto& colorTransformMatrix = editState().colorTransformMatrix;
128 if (!args.colorTransformMatrix || colorTransformMatrix == args.colorTransformMatrix) {
Lloyd Pique77f79a22019-04-29 15:55:40 -0700129 return;
130 }
131
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700132 colorTransformMatrix = *args.colorTransformMatrix;
Lloyd Piqueef958122019-02-05 18:00:12 -0800133
134 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700135}
136
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800137void Output::setColorProfile(const ColorProfile& colorProfile) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700138 ui::Dataspace targetDataspace =
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800139 getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
140 colorProfile.colorSpaceAgnosticDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800141
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700142 auto& outputState = editState();
143 if (outputState.colorMode == colorProfile.mode &&
144 outputState.dataspace == colorProfile.dataspace &&
145 outputState.renderIntent == colorProfile.renderIntent &&
146 outputState.targetDataspace == targetDataspace) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800147 return;
148 }
149
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700150 outputState.colorMode = colorProfile.mode;
151 outputState.dataspace = colorProfile.dataspace;
152 outputState.renderIntent = colorProfile.renderIntent;
153 outputState.targetDataspace = targetDataspace;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700154
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800155 mRenderSurface->setBufferDataspace(colorProfile.dataspace);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700156
Lloyd Pique32cbe282018-10-19 13:09:22 -0700157 ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800158 decodeColorMode(colorProfile.mode).c_str(), colorProfile.mode,
159 decodeRenderIntent(colorProfile.renderIntent).c_str(), colorProfile.renderIntent);
Lloyd Piqueef958122019-02-05 18:00:12 -0800160
161 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700162}
163
164void Output::dump(std::string& out) const {
165 using android::base::StringAppendF;
166
167 StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str());
168
169 out.append("\n ");
170
171 dumpBase(out);
172}
173
174void Output::dumpBase(std::string& out) const {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700175 dumpState(out);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700176
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700177 if (mDisplayColorProfile) {
178 mDisplayColorProfile->dump(out);
179 } else {
180 out.append(" No display color profile!\n");
181 }
182
Lloyd Pique31cb2942018-10-19 17:23:03 -0700183 if (mRenderSurface) {
184 mRenderSurface->dump(out);
185 } else {
186 out.append(" No render surface!\n");
187 }
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800188
Lloyd Pique207def92019-02-28 16:09:52 -0800189 android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800190 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
191 if (!outputLayer) {
192 continue;
193 }
194 outputLayer->dump(out);
195 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700196}
197
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700198compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
199 return mDisplayColorProfile.get();
200}
201
202void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
203 mDisplayColorProfile = std::move(mode);
204}
205
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800206const Output::ReleasedLayers& Output::getReleasedLayersForTest() const {
207 return mReleasedLayers;
208}
209
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700210void Output::setDisplayColorProfileForTest(
211 std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
212 mDisplayColorProfile = std::move(mode);
213}
214
Lloyd Pique31cb2942018-10-19 17:23:03 -0700215compositionengine::RenderSurface* Output::getRenderSurface() const {
216 return mRenderSurface.get();
217}
218
219void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
220 mRenderSurface = std::move(surface);
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700221 editState().bounds = Rect(mRenderSurface->getSize());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700222
223 dirtyEntireOutput();
224}
225
226void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
227 mRenderSurface = std::move(surface);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700228}
229
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000230Region Output::getDirtyRegion(bool repaintEverything) const {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700231 const auto& outputState = getState();
232 Region dirty(outputState.viewport);
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000233 if (!repaintEverything) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700234 dirty.andSelf(outputState.dirtyRegion);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700235 }
236 return dirty;
237}
238
Lloyd Piquec6687342019-03-07 21:34:57 -0800239bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
Lloyd Piqueef36b002019-01-23 17:52:04 -0800240 // The layerStackId's must match, and also the layer must not be internal
241 // only when not on an internal output.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700242 const auto& outputState = getState();
243 return layerStackId && (*layerStackId == outputState.layerStackId) &&
244 (!internalOnly || outputState.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 Piquedf336d92019-03-07 21:38:42 -0800277std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
278 const std::shared_ptr<compositionengine::Layer>& layer,
279 const sp<compositionengine::LayerFE>& layerFE) const {
280 return impl::createOutputLayer(*this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800281}
282
283void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
284 mOutputLayersOrderedByZ = std::move(layers);
285}
286
287const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
288 return mOutputLayersOrderedByZ;
289}
290
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800291void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
292 mReleasedLayers = std::move(layers);
293}
294
295Output::ReleasedLayers Output::takeReleasedLayers() {
296 return std::move(mReleasedLayers);
297}
298
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800299void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs,
300 LayerFESet& geomSnapshots) {
301 ATRACE_CALL();
302 ALOGV(__FUNCTION__);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800303
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800304 rebuildLayerStacks(refreshArgs, geomSnapshots);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800305}
306
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800307void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800308 ATRACE_CALL();
309 ALOGV(__FUNCTION__);
310
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800311 updateColorProfile(refreshArgs);
312 updateAndWriteCompositionState(refreshArgs);
313 setColorTransform(refreshArgs);
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800314 beginFrame();
315 prepareFrame();
316 devOptRepaintFlash(refreshArgs);
317 finishFrame(refreshArgs);
318 postFramebuffer();
319}
320
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800321void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
322 LayerFESet& layerFESet) {
323 ATRACE_CALL();
324 ALOGV(__FUNCTION__);
325
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700326 auto& outputState = editState();
327
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800328 // Do nothing if this output is not enabled or there is no need to perform this update
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700329 if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800330 return;
331 }
332
333 // Process the layers to determine visibility and coverage
334 compositionengine::Output::CoverageState coverage{layerFESet};
335 collectVisibleLayers(refreshArgs, coverage);
336
337 // Compute the resulting coverage for this output, and store it for later
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700338 const ui::Transform& tr = outputState.transform;
339 Region undefinedRegion{outputState.bounds};
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800340 undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
341
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700342 outputState.undefinedRegion = undefinedRegion;
343 outputState.dirtyRegion.orSelf(coverage.dirtyRegion);
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800344}
345
346void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
347 compositionengine::Output::CoverageState& coverage) {
348 // We build up a list of all layers that are going to be visible in the new
349 // frame.
350 compositionengine::Output::OutputLayers newLayersSortedByZ;
351
352 // Evaluate the layers from front to back to determine what is visible. This
353 // also incrementally calculates the coverage information for each layer as
354 // well as the entire output.
355 for (auto& layer : reversed(refreshArgs.layers)) {
356 // Incrementally process the coverage for each layer, obtaining an
357 // optional outputLayer if the layer is visible.
358 auto outputLayer = getOutputLayerIfVisible(layer, coverage);
359 if (outputLayer) {
360 newLayersSortedByZ.emplace_back(std::move(outputLayer));
361 }
362
363 // TODO(b/121291683): Stop early if the output is completely covered and
364 // no more layers could even be visible underneath the ones on top.
365 }
366
367 // Since we walked the layers in reverse order, we need to reverse
368 // newLayersSortedByZ to get the back-to-front ordered list of layers.
369 std::reverse(newLayersSortedByZ.begin(), newLayersSortedByZ.end());
370
371 // Generate a simple Z-order values to each visible output layer
372 uint32_t zOrder = 0;
373 for (auto& outputLayer : newLayersSortedByZ) {
374 outputLayer->editState().z = zOrder++;
375 }
376
377 setReleasedLayers(refreshArgs);
378
379 mOutputLayersOrderedByZ = std::move(newLayersSortedByZ);
380}
381
382std::unique_ptr<compositionengine::OutputLayer> Output::getOutputLayerIfVisible(
383 std::shared_ptr<compositionengine::Layer> layer,
384 compositionengine::Output::CoverageState& coverage) {
385 // Note: Converts a wp<LayerFE> to a sp<LayerFE>
386 auto layerFE = layer->getLayerFE();
387 if (layerFE == nullptr) {
388 return nullptr;
389 }
390
391 // Ensure we have a snapshot of the basic geometry layer state. Limit the
392 // snapshots to once per frame for each candidate layer, as layers may
393 // appear on multiple outputs.
394 if (!coverage.latchedLayers.count(layerFE)) {
395 coverage.latchedLayers.insert(layerFE);
Lloyd Pique9755fb72019-03-26 14:44:40 -0700396 layerFE->latchCompositionState(layer->editFEState(),
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800397 compositionengine::LayerFE::StateSubset::BasicGeometry);
398 }
399
400 // Obtain a read-only reference to the front-end layer state
Lloyd Pique9755fb72019-03-26 14:44:40 -0700401 const auto& layerFEState = layer->getFEState();
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800402
403 // Only consider the layers on the given layer stack
404 if (!belongsInOutput(layer.get())) {
405 return nullptr;
406 }
407
408 /*
409 * opaqueRegion: area of a surface that is fully opaque.
410 */
411 Region opaqueRegion;
412
413 /*
414 * visibleRegion: area of a surface that is visible on screen and not fully
415 * transparent. This is essentially the layer's footprint minus the opaque
416 * regions above it. Areas covered by a translucent surface are considered
417 * visible.
418 */
419 Region visibleRegion;
420
421 /*
422 * coveredRegion: area of a surface that is covered by all visible regions
423 * above it (which includes the translucent areas).
424 */
425 Region coveredRegion;
426
427 /*
428 * transparentRegion: area of a surface that is hinted to be completely
429 * transparent. This is only used to tell when the layer has no visible non-
430 * transparent regions and can be removed from the layer list. It does not
431 * affect the visibleRegion of this layer or any layers beneath it. The hint
432 * may not be correct if apps don't respect the SurfaceView restrictions
433 * (which, sadly, some don't).
434 */
435 Region transparentRegion;
436
437 // handle hidden surfaces by setting the visible region to empty
438 if (CC_UNLIKELY(!layerFEState.isVisible)) {
439 return nullptr;
440 }
441
442 const ui::Transform& tr = layerFEState.geomLayerTransform;
443
444 // Get the visible region
445 // TODO(b/121291683): Is it worth creating helper methods on LayerFEState
446 // for computations like this?
447 visibleRegion.set(Rect(tr.transform(layerFEState.geomLayerBounds)));
448
449 if (visibleRegion.isEmpty()) {
450 return nullptr;
451 }
452
453 // Remove the transparent area from the visible region
454 if (!layerFEState.isOpaque) {
455 if (tr.preserveRects()) {
456 // transform the transparent region
457 transparentRegion = tr.transform(layerFEState.transparentRegionHint);
458 } else {
459 // transformation too complex, can't do the
460 // transparent region optimization.
461 transparentRegion.clear();
462 }
463 }
464
465 // compute the opaque region
466 const int32_t layerOrientation = tr.getOrientation();
467 if (layerFEState.isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
468 // If we one of the simple category of transforms (0/90/180/270 rotation
469 // + any flip), then the opaque region is the layer's footprint.
470 // Otherwise we don't try and compute the opaque region since there may
471 // be errors at the edges, and we treat the entire layer as
472 // translucent.
473 opaqueRegion = visibleRegion;
474 }
475
476 // Clip the covered region to the visible region
477 coveredRegion = coverage.aboveCoveredLayers.intersect(visibleRegion);
478
479 // Update accumAboveCoveredLayers for next (lower) layer
480 coverage.aboveCoveredLayers.orSelf(visibleRegion);
481
482 // subtract the opaque region covered by the layers above us
483 visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
484
485 if (visibleRegion.isEmpty()) {
486 return nullptr;
487 }
488
489 // Get coverage information for the layer as previously displayed,
490 // also taking over ownership from mOutputLayersorderedByZ.
491 auto prevOutputLayer = takeOutputLayerForLayer(layer.get());
492
493 // Get coverage information for the layer as previously displayed
494 // TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
495 const Region kEmptyRegion;
496 const Region& oldVisibleRegion =
497 prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
498 const Region& oldCoveredRegion =
499 prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;
500
501 // compute this layer's dirty region
502 Region dirty;
503 if (layerFEState.contentDirty) {
504 // we need to invalidate the whole region
505 dirty = visibleRegion;
506 // as well, as the old visible region
507 dirty.orSelf(oldVisibleRegion);
508 } else {
509 /* compute the exposed region:
510 * the exposed region consists of two components:
511 * 1) what's VISIBLE now and was COVERED before
512 * 2) what's EXPOSED now less what was EXPOSED before
513 *
514 * note that (1) is conservative, we start with the whole visible region
515 * but only keep what used to be covered by something -- which mean it
516 * may have been exposed.
517 *
518 * (2) handles areas that were not covered by anything but got exposed
519 * because of a resize.
520 *
521 */
522 const Region newExposed = visibleRegion - coveredRegion;
523 const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
524 dirty = (visibleRegion & oldCoveredRegion) | (newExposed - oldExposed);
525 }
526 dirty.subtractSelf(coverage.aboveOpaqueLayers);
527
528 // accumulate to the screen dirty region
529 coverage.dirtyRegion.orSelf(dirty);
530
531 // Update accumAboveOpaqueLayers for next (lower) layer
532 coverage.aboveOpaqueLayers.orSelf(opaqueRegion);
533
534 // Compute the visible non-transparent region
535 Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);
536
537 // Peform the final check to see if this layer is visible on this output
538 // TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700539 const auto& outputState = getState();
540 Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
541 drawRegion.andSelf(outputState.bounds);
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800542 if (drawRegion.isEmpty()) {
543 return nullptr;
544 }
545
546 // The layer is visible. Either reuse the existing outputLayer if we have
547 // one, or create a new one if we do not.
548 std::unique_ptr<compositionengine::OutputLayer> result =
549 prevOutputLayer ? std::move(prevOutputLayer) : createOutputLayer(layer, layerFE);
550
551 // Store the layer coverage information into the layer state as some of it
552 // is useful later.
553 auto& outputLayerState = result->editState();
554 outputLayerState.visibleRegion = visibleRegion;
555 outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
556 outputLayerState.coveredRegion = coveredRegion;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700557 outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
558 outputLayerState.visibleRegion.intersect(outputState.viewport));
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800559
560 return result;
561}
562
563void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
564 // The base class does nothing with this call.
565}
566
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800567void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
568 for (auto& layer : mOutputLayersOrderedByZ) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700569 layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(),
Lloyd Piquec6687342019-03-07 21:34:57 -0800570 args.updatingGeometryThisFrame
571 ? LayerFE::StateSubset::GeometryAndContent
572 : LayerFE::StateSubset::Content);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800573 }
574}
575
576void Output::updateAndWriteCompositionState(
577 const compositionengine::CompositionRefreshArgs& refreshArgs) {
578 ATRACE_CALL();
579 ALOGV(__FUNCTION__);
580
581 for (auto& layer : mOutputLayersOrderedByZ) {
582 if (refreshArgs.devOptForceClientComposition) {
583 layer->editState().forceClientComposition = true;
584 }
585
586 layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame);
587
588 // Send the updated state to the HWC, if appropriate.
589 layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
590 }
591}
592
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800593void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
594 setColorProfile(pickColorProfile(refreshArgs));
595}
596
597// Returns a data space that fits all visible layers. The returned data space
598// can only be one of
599// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
600// - Dataspace::DISPLAY_P3
601// - Dataspace::DISPLAY_BT2020
602// The returned HDR data space is one of
603// - Dataspace::UNKNOWN
604// - Dataspace::BT2020_HLG
605// - Dataspace::BT2020_PQ
606ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
607 bool* outIsHdrClientComposition) const {
608 ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
609 *outHdrDataSpace = ui::Dataspace::UNKNOWN;
610
611 for (const auto& layer : mOutputLayersOrderedByZ) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700612 switch (layer->getLayer().getFEState().dataspace) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800613 case ui::Dataspace::V0_SCRGB:
614 case ui::Dataspace::V0_SCRGB_LINEAR:
615 case ui::Dataspace::BT2020:
616 case ui::Dataspace::BT2020_ITU:
617 case ui::Dataspace::BT2020_LINEAR:
618 case ui::Dataspace::DISPLAY_BT2020:
619 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
620 break;
621 case ui::Dataspace::DISPLAY_P3:
622 bestDataSpace = ui::Dataspace::DISPLAY_P3;
623 break;
624 case ui::Dataspace::BT2020_PQ:
625 case ui::Dataspace::BT2020_ITU_PQ:
626 bestDataSpace = ui::Dataspace::DISPLAY_P3;
627 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700628 *outIsHdrClientComposition = layer->getLayer().getFEState().forceClientComposition;
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800629 break;
630 case ui::Dataspace::BT2020_HLG:
631 case ui::Dataspace::BT2020_ITU_HLG:
632 bestDataSpace = ui::Dataspace::DISPLAY_P3;
633 // When there's mixed PQ content and HLG content, we set the HDR
634 // data space to be BT2020_PQ and convert HLG to PQ.
635 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
636 *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
637 }
638 break;
639 default:
640 break;
641 }
642 }
643
644 return bestDataSpace;
645}
646
647compositionengine::Output::ColorProfile Output::pickColorProfile(
648 const compositionengine::CompositionRefreshArgs& refreshArgs) const {
649 if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
650 return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
651 ui::RenderIntent::COLORIMETRIC,
652 refreshArgs.colorSpaceAgnosticDataspace};
653 }
654
655 ui::Dataspace hdrDataSpace;
656 bool isHdrClientComposition = false;
657 ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
658
659 switch (refreshArgs.forceOutputColorMode) {
660 case ui::ColorMode::SRGB:
661 bestDataSpace = ui::Dataspace::V0_SRGB;
662 break;
663 case ui::ColorMode::DISPLAY_P3:
664 bestDataSpace = ui::Dataspace::DISPLAY_P3;
665 break;
666 default:
667 break;
668 }
669
670 // respect hdrDataSpace only when there is no legacy HDR support
671 const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
672 !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
673 if (isHdr) {
674 bestDataSpace = hdrDataSpace;
675 }
676
677 ui::RenderIntent intent;
678 switch (refreshArgs.outputColorSetting) {
679 case OutputColorSetting::kManaged:
680 case OutputColorSetting::kUnmanaged:
681 intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
682 : ui::RenderIntent::COLORIMETRIC;
683 break;
684 case OutputColorSetting::kEnhanced:
685 intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
686 break;
687 default: // vendor display color setting
688 intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
689 break;
690 }
691
692 ui::ColorMode outMode;
693 ui::Dataspace outDataSpace;
694 ui::RenderIntent outRenderIntent;
695 mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
696 &outRenderIntent);
697
698 return ColorProfile{outMode, outDataSpace, outRenderIntent,
699 refreshArgs.colorSpaceAgnosticDataspace};
700}
701
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800702void Output::beginFrame() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700703 auto& outputState = editState();
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800704 const bool dirty = !getDirtyRegion(false).isEmpty();
705 const bool empty = mOutputLayersOrderedByZ.empty();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700706 const bool wasEmpty = !outputState.lastCompositionHadVisibleLayers;
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800707
708 // If nothing has changed (!dirty), don't recompose.
709 // If something changed, but we don't currently have any visible layers,
710 // and didn't when we last did a composition, then skip it this time.
711 // The second rule does two things:
712 // - When all layers are removed from a display, we'll emit one black
713 // frame, then nothing more until we get new layers.
714 // - When a display is created with a private layer stack, we won't
715 // emit any black frames until a layer is added to the layer stack.
716 const bool mustRecompose = dirty && !(empty && wasEmpty);
717
718 const char flagPrefix[] = {'-', '+'};
719 static_cast<void>(flagPrefix);
720 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
721 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
722 flagPrefix[empty], flagPrefix[wasEmpty]);
723
724 mRenderSurface->beginFrame(mustRecompose);
725
726 if (mustRecompose) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700727 outputState.lastCompositionHadVisibleLayers = !empty;
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800728 }
729}
730
Lloyd Pique66d68602019-02-13 14:23:31 -0800731void Output::prepareFrame() {
732 ATRACE_CALL();
733 ALOGV(__FUNCTION__);
734
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700735 const auto& outputState = getState();
736 if (!outputState.isEnabled) {
Lloyd Pique66d68602019-02-13 14:23:31 -0800737 return;
738 }
739
740 chooseCompositionStrategy();
741
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700742 mRenderSurface->prepareFrame(outputState.usesClientComposition,
743 outputState.usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800744}
745
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800746void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
747 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
748 return;
749 }
750
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700751 if (getState().isEnabled) {
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800752 // transform the dirty region into this screen's coordinate space
753 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
754 if (!dirtyRegion.isEmpty()) {
755 base::unique_fd readyFence;
756 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800757 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800758
759 mRenderSurface->queueBuffer(std::move(readyFence));
760 }
761 }
762
763 postFramebuffer();
764
765 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
766
767 prepareFrame();
768}
769
Lloyd Piqued3d69882019-02-28 16:03:46 -0800770void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
771 ATRACE_CALL();
772 ALOGV(__FUNCTION__);
773
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700774 if (!getState().isEnabled) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800775 return;
776 }
777
778 // Repaint the framebuffer (if needed), getting the optional fence for when
779 // the composition completes.
780 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
781 if (!optReadyFence) {
782 return;
783 }
784
785 // swap buffers (presentation)
786 mRenderSurface->queueBuffer(std::move(*optReadyFence));
787}
788
789std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800790 ATRACE_CALL();
791 ALOGV(__FUNCTION__);
792
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700793 const auto& outputState = getState();
Lloyd Pique688abd42019-02-15 15:42:24 -0800794 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700795 outputState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800796 base::unique_fd readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800797 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800798 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800799 }
800
801 ALOGV("hasClientComposition");
802
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700803 auto& renderEngine = getCompositionEngine().getRenderEngine();
Lloyd Pique688abd42019-02-15 15:42:24 -0800804 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
805
806 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700807 clientCompositionDisplay.physicalDisplay = outputState.scissor;
808 clientCompositionDisplay.clip = outputState.scissor;
809 clientCompositionDisplay.globalTransform = outputState.transform.asMatrix4();
810 clientCompositionDisplay.orientation = outputState.orientation;
811 clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
812 ? outputState.dataspace
813 : ui::Dataspace::UNKNOWN;
Lloyd Pique688abd42019-02-15 15:42:24 -0800814 clientCompositionDisplay.maxLuminance =
815 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
816
817 // Compute the global color transform matrix.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700818 if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
819 clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
Lloyd Pique688abd42019-02-15 15:42:24 -0800820 }
821
822 // Note: Updated by generateClientCompositionRequests
823 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
824
825 // Generate the client composition requests for the layers on this output.
826 std::vector<renderengine::LayerSettings> clientCompositionLayers =
827 generateClientCompositionRequests(supportsProtectedContent,
828 clientCompositionDisplay.clearRegion);
829 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
830
831 // If we the display is secure, protected content support is enabled, and at
832 // least one layer has protected content, we need to use a secure back
833 // buffer.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700834 if (outputState.isSecure && supportsProtectedContent) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800835 bool needsProtected =
836 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
837 [](auto& layer) {
Lloyd Pique9755fb72019-03-26 14:44:40 -0700838 return layer->getLayer().getFEState().hasProtectedContent;
Lloyd Pique688abd42019-02-15 15:42:24 -0800839 });
840 if (needsProtected != renderEngine.isProtected()) {
841 renderEngine.useProtectedContext(needsProtected);
842 }
843 if (needsProtected != mRenderSurface->isProtected() &&
844 needsProtected == renderEngine.isProtected()) {
845 mRenderSurface->setProtected(needsProtected);
846 }
847 }
848
849 base::unique_fd fd;
850 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
851 if (buf == nullptr) {
852 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
853 "client composition for this frame",
854 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800855 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800856 }
857
858 // We boost GPU frequency here because there will be color spaces conversion
859 // and it's expensive. We boost the GPU frequency so that GPU composition can
860 // finish in time. We must reset GPU frequency afterwards, because high frequency
861 // consumes extra battery.
862 const bool expensiveRenderingExpected =
863 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
864 if (expensiveRenderingExpected) {
865 setExpensiveRenderingExpected(true);
866 }
867
868 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
869 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800870 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800871
872 if (expensiveRenderingExpected) {
873 setExpensiveRenderingExpected(false);
874 }
875
Lloyd Piqued3d69882019-02-28 16:03:46 -0800876 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800877}
878
879std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
880 bool supportsProtectedContent, Region& clearRegion) {
881 std::vector<renderengine::LayerSettings> clientCompositionLayers;
882 ALOGV("Rendering client layers");
883
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700884 const auto& outputState = getState();
885 const Region viewportRegion(outputState.viewport);
Lloyd Pique688abd42019-02-15 15:42:24 -0800886 const bool useIdentityTransform = false;
887 bool firstLayer = true;
888 // Used when a layer clears part of the buffer.
889 Region dummyRegion;
890
891 for (auto& layer : mOutputLayersOrderedByZ) {
892 const auto& layerState = layer->getState();
Lloyd Pique9755fb72019-03-26 14:44:40 -0700893 const auto& layerFEState = layer->getLayer().getFEState();
Lloyd Pique688abd42019-02-15 15:42:24 -0800894 auto& layerFE = layer->getLayerFE();
895
Lloyd Piquea2468662019-03-07 21:31:06 -0800896 const Region clip(viewportRegion.intersect(layerState.visibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800897 ALOGV("Layer: %s", layerFE.getDebugName());
898 if (clip.isEmpty()) {
899 ALOGV(" Skipping for empty clip");
900 firstLayer = false;
901 continue;
902 }
903
904 bool clientComposition = layer->requiresClientComposition();
905
906 // We clear the client target for non-client composed layers if
907 // requested by the HWC. We skip this if the layer is not an opaque
908 // rectangle, as by definition the layer must blend with whatever is
909 // underneath. We also skip the first layer as the buffer target is
910 // guaranteed to start out cleared.
911 bool clearClientComposition =
912 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
913
914 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
915
916 if (clientComposition || clearClientComposition) {
917 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
918 clip,
919 useIdentityTransform,
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700920 layer->needsFiltering() || outputState.needsFiltering,
921 outputState.isSecure,
Lloyd Pique688abd42019-02-15 15:42:24 -0800922 supportsProtectedContent,
923 clientComposition ? clearRegion : dummyRegion,
924 };
925 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700926 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800927 auto& layerSettings = *result;
928 layerSettings.source.buffer.buffer = nullptr;
929 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
930 layerSettings.alpha = half(0.0);
931 layerSettings.disableBlending = true;
932 }
933
934 clientCompositionLayers.push_back(*result);
935 }
936 }
937
938 firstLayer = false;
939 }
940
941 return clientCompositionLayers;
942}
943
944void Output::appendRegionFlashRequests(
945 const Region& flashRegion,
946 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
947 if (flashRegion.isEmpty()) {
948 return;
949 }
950
951 renderengine::LayerSettings layerSettings;
952 layerSettings.source.buffer.buffer = nullptr;
953 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
954 layerSettings.alpha = half(1.0);
955
956 for (const auto& rect : flashRegion) {
957 layerSettings.geometry.boundaries = rect.toFloatRect();
958 clientCompositionLayers.push_back(layerSettings);
959 }
960}
961
962void Output::setExpensiveRenderingExpected(bool) {
963 // The base class does nothing with this call.
964}
965
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800966void Output::postFramebuffer() {
967 ATRACE_CALL();
968 ALOGV(__FUNCTION__);
969
970 if (!getState().isEnabled) {
971 return;
972 }
973
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700974 auto& outputState = editState();
975 outputState.dirtyRegion.clear();
Lloyd Piqued3d69882019-02-28 16:03:46 -0800976 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 Piquea38ea7e2019-04-16 18:10:26 -0700982 for (auto& layer : mOutputLayersOrderedByZ) {
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800983 // 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.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001000 if (outputState.usesClientComposition) {
Lloyd Pique35fca9d2019-02-13 14:24:11 -08001001 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
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001009 // mOutputLayersOrderedByZ. The best we can do is to
Lloyd Pique35fca9d2019-02-13 14:24:11 -08001010 // 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() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001022 auto& outputState = editState();
1023 outputState.dirtyRegion.set(outputState.bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -07001024}
1025
Lloyd Pique66d68602019-02-13 14:23:31 -08001026void Output::chooseCompositionStrategy() {
1027 // The base output implementation can only do client composition
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001028 auto& outputState = editState();
1029 outputState.usesClientComposition = true;
1030 outputState.usesDeviceComposition = false;
Lloyd Pique66d68602019-02-13 14:23:31 -08001031}
1032
Lloyd Pique688abd42019-02-15 15:42:24 -08001033bool Output::getSkipColorTransform() const {
1034 return true;
1035}
1036
Lloyd Pique35fca9d2019-02-13 14:24:11 -08001037compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
1038 compositionengine::Output::FrameFences result;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001039 if (getState().usesClientComposition) {
Lloyd Pique35fca9d2019-02-13 14:24:11 -08001040 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
1041 }
1042 return result;
1043}
1044
Lloyd Piquefeb73d72018-12-04 17:23:44 -08001045} // namespace impl
1046} // namespace android::compositionengine