blob: cc7e4533f421a4a5e177b08a42321c7076286649 [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
43Output::Output(const CompositionEngine& compositionEngine)
44 : mCompositionEngine(compositionEngine) {}
45
46Output::~Output() = default;
47
48const CompositionEngine& Output::getCompositionEngine() const {
49 return mCompositionEngine;
50}
51
52bool Output::isValid() const {
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070053 return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
54 mRenderSurface->isValid();
Lloyd Pique32cbe282018-10-19 13:09:22 -070055}
56
57const std::string& Output::getName() const {
58 return mName;
59}
60
61void Output::setName(const std::string& name) {
62 mName = name;
63}
64
65void Output::setCompositionEnabled(bool enabled) {
66 if (mState.isEnabled == enabled) {
67 return;
68 }
69
70 mState.isEnabled = enabled;
71 dirtyEntireOutput();
72}
73
74void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame,
75 const Rect& viewport, const Rect& scissor, bool needsFiltering) {
76 mState.transform = transform;
77 mState.orientation = orientation;
78 mState.scissor = scissor;
79 mState.frame = frame;
80 mState.viewport = viewport;
81 mState.needsFiltering = needsFiltering;
82
83 dirtyEntireOutput();
84}
85
Lloyd Pique688abd42019-02-15 15:42:24 -080086// TODO(b/121291683): Rename setSize() once more is moved.
Lloyd Pique31cb2942018-10-19 17:23:03 -070087void Output::setBounds(const ui::Size& size) {
88 mRenderSurface->setDisplaySize(size);
Lloyd Pique688abd42019-02-15 15:42:24 -080089 // TODO(b/121291683): Rename mState.size once more is moved.
Lloyd Pique31cb2942018-10-19 17:23:03 -070090 mState.bounds = Rect(mRenderSurface->getSize());
Lloyd Pique32cbe282018-10-19 13:09:22 -070091
92 dirtyEntireOutput();
93}
94
Lloyd Piqueef36b002019-01-23 17:52:04 -080095void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
96 mState.layerStackId = layerStackId;
97 mState.layerStackInternal = isInternal;
Lloyd Pique32cbe282018-10-19 13:09:22 -070098
99 dirtyEntireOutput();
100}
101
102void Output::setColorTransform(const mat4& transform) {
Lloyd Pique77f79a22019-04-29 15:55:40 -0700103 if (mState.colorTransformMat == transform) {
104 return;
105 }
106
Lloyd Pique32cbe282018-10-19 13:09:22 -0700107 const bool isIdentity = (transform == mat4());
Lloyd Piqueef958122019-02-05 18:00:12 -0800108 const auto newColorTransform =
Lloyd Pique32cbe282018-10-19 13:09:22 -0700109 isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
Lloyd Piqueef958122019-02-05 18:00:12 -0800110
Lloyd Piqueef958122019-02-05 18:00:12 -0800111 mState.colorTransform = newColorTransform;
Alec Mouric7e8ce82019-04-02 12:28:05 -0700112 mState.colorTransformMat = transform;
Lloyd Piqueef958122019-02-05 18:00:12 -0800113
114 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700115}
116
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800117void Output::setColorProfile(const ColorProfile& colorProfile) {
118 const ui::Dataspace targetDataspace =
119 getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
120 colorProfile.colorSpaceAgnosticDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800121
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800122 if (mState.colorMode == colorProfile.mode && mState.dataspace == colorProfile.dataspace &&
123 mState.renderIntent == colorProfile.renderIntent &&
124 mState.targetDataspace == targetDataspace) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800125 return;
126 }
127
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800128 mState.colorMode = colorProfile.mode;
129 mState.dataspace = colorProfile.dataspace;
130 mState.renderIntent = colorProfile.renderIntent;
Lloyd Piquef5275482019-01-29 18:42:42 -0800131 mState.targetDataspace = targetDataspace;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700132
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800133 mRenderSurface->setBufferDataspace(colorProfile.dataspace);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700134
Lloyd Pique32cbe282018-10-19 13:09:22 -0700135 ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800136 decodeColorMode(colorProfile.mode).c_str(), colorProfile.mode,
137 decodeRenderIntent(colorProfile.renderIntent).c_str(), colorProfile.renderIntent);
Lloyd Piqueef958122019-02-05 18:00:12 -0800138
139 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700140}
141
142void Output::dump(std::string& out) const {
143 using android::base::StringAppendF;
144
145 StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str());
146
147 out.append("\n ");
148
149 dumpBase(out);
150}
151
152void Output::dumpBase(std::string& out) const {
153 mState.dump(out);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700154
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700155 if (mDisplayColorProfile) {
156 mDisplayColorProfile->dump(out);
157 } else {
158 out.append(" No display color profile!\n");
159 }
160
Lloyd Pique31cb2942018-10-19 17:23:03 -0700161 if (mRenderSurface) {
162 mRenderSurface->dump(out);
163 } else {
164 out.append(" No render surface!\n");
165 }
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800166
Lloyd Pique207def92019-02-28 16:09:52 -0800167 android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800168 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
169 if (!outputLayer) {
170 continue;
171 }
172 outputLayer->dump(out);
173 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700174}
175
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700176compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
177 return mDisplayColorProfile.get();
178}
179
180void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
181 mDisplayColorProfile = std::move(mode);
182}
183
184void Output::setDisplayColorProfileForTest(
185 std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
186 mDisplayColorProfile = std::move(mode);
187}
188
Lloyd Pique31cb2942018-10-19 17:23:03 -0700189compositionengine::RenderSurface* Output::getRenderSurface() const {
190 return mRenderSurface.get();
191}
192
193void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
194 mRenderSurface = std::move(surface);
195 mState.bounds = Rect(mRenderSurface->getSize());
196
197 dirtyEntireOutput();
198}
199
200void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
201 mRenderSurface = std::move(surface);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700202}
203
204const OutputCompositionState& Output::getState() const {
205 return mState;
206}
207
208OutputCompositionState& Output::editState() {
209 return mState;
210}
211
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000212Region Output::getDirtyRegion(bool repaintEverything) const {
213 Region dirty(mState.viewport);
214 if (!repaintEverything) {
215 dirty.andSelf(mState.dirtyRegion);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700216 }
217 return dirty;
218}
219
Lloyd Piqueef36b002019-01-23 17:52:04 -0800220bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
221 // The layerStackId's must match, and also the layer must not be internal
222 // only when not on an internal output.
223 return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700224}
225
Lloyd Piquecc01a452018-12-04 17:24:00 -0800226compositionengine::OutputLayer* Output::getOutputLayerForLayer(
227 compositionengine::Layer* layer) const {
228 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
229 if (outputLayer && &outputLayer->getLayer() == layer) {
230 return outputLayer.get();
231 }
232 }
233 return nullptr;
234}
235
236std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
Lloyd Pique07e33212018-12-18 16:33:37 -0800237 std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
238 sp<compositionengine::LayerFE> layerFE) {
Lloyd Piquecc01a452018-12-04 17:24:00 -0800239 for (auto& outputLayer : mOutputLayersOrderedByZ) {
240 if (outputLayer && &outputLayer->getLayer() == layer.get()) {
241 return std::move(outputLayer);
242 }
243 }
Lloyd Pique07e33212018-12-18 16:33:37 -0800244 return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800245}
246
247void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
248 mOutputLayersOrderedByZ = std::move(layers);
249}
250
251const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
252 return mOutputLayersOrderedByZ;
253}
254
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800255void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
256 mReleasedLayers = std::move(layers);
257}
258
259Output::ReleasedLayers Output::takeReleasedLayers() {
260 return std::move(mReleasedLayers);
261}
262
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800263void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
264 setColorProfile(pickColorProfile(refreshArgs));
265}
266
267// Returns a data space that fits all visible layers. The returned data space
268// can only be one of
269// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
270// - Dataspace::DISPLAY_P3
271// - Dataspace::DISPLAY_BT2020
272// The returned HDR data space is one of
273// - Dataspace::UNKNOWN
274// - Dataspace::BT2020_HLG
275// - Dataspace::BT2020_PQ
276ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
277 bool* outIsHdrClientComposition) const {
278 ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
279 *outHdrDataSpace = ui::Dataspace::UNKNOWN;
280
281 for (const auto& layer : mOutputLayersOrderedByZ) {
282 switch (layer->getLayer().getState().frontEnd.dataspace) {
283 case ui::Dataspace::V0_SCRGB:
284 case ui::Dataspace::V0_SCRGB_LINEAR:
285 case ui::Dataspace::BT2020:
286 case ui::Dataspace::BT2020_ITU:
287 case ui::Dataspace::BT2020_LINEAR:
288 case ui::Dataspace::DISPLAY_BT2020:
289 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
290 break;
291 case ui::Dataspace::DISPLAY_P3:
292 bestDataSpace = ui::Dataspace::DISPLAY_P3;
293 break;
294 case ui::Dataspace::BT2020_PQ:
295 case ui::Dataspace::BT2020_ITU_PQ:
296 bestDataSpace = ui::Dataspace::DISPLAY_P3;
297 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
298 *outIsHdrClientComposition =
299 layer->getLayer().getState().frontEnd.forceClientComposition;
300 break;
301 case ui::Dataspace::BT2020_HLG:
302 case ui::Dataspace::BT2020_ITU_HLG:
303 bestDataSpace = ui::Dataspace::DISPLAY_P3;
304 // When there's mixed PQ content and HLG content, we set the HDR
305 // data space to be BT2020_PQ and convert HLG to PQ.
306 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
307 *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
308 }
309 break;
310 default:
311 break;
312 }
313 }
314
315 return bestDataSpace;
316}
317
318compositionengine::Output::ColorProfile Output::pickColorProfile(
319 const compositionengine::CompositionRefreshArgs& refreshArgs) const {
320 if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
321 return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
322 ui::RenderIntent::COLORIMETRIC,
323 refreshArgs.colorSpaceAgnosticDataspace};
324 }
325
326 ui::Dataspace hdrDataSpace;
327 bool isHdrClientComposition = false;
328 ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
329
330 switch (refreshArgs.forceOutputColorMode) {
331 case ui::ColorMode::SRGB:
332 bestDataSpace = ui::Dataspace::V0_SRGB;
333 break;
334 case ui::ColorMode::DISPLAY_P3:
335 bestDataSpace = ui::Dataspace::DISPLAY_P3;
336 break;
337 default:
338 break;
339 }
340
341 // respect hdrDataSpace only when there is no legacy HDR support
342 const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
343 !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
344 if (isHdr) {
345 bestDataSpace = hdrDataSpace;
346 }
347
348 ui::RenderIntent intent;
349 switch (refreshArgs.outputColorSetting) {
350 case OutputColorSetting::kManaged:
351 case OutputColorSetting::kUnmanaged:
352 intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
353 : ui::RenderIntent::COLORIMETRIC;
354 break;
355 case OutputColorSetting::kEnhanced:
356 intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
357 break;
358 default: // vendor display color setting
359 intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
360 break;
361 }
362
363 ui::ColorMode outMode;
364 ui::Dataspace outDataSpace;
365 ui::RenderIntent outRenderIntent;
366 mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
367 &outRenderIntent);
368
369 return ColorProfile{outMode, outDataSpace, outRenderIntent,
370 refreshArgs.colorSpaceAgnosticDataspace};
371}
372
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800373void Output::beginFrame() {
374 const bool dirty = !getDirtyRegion(false).isEmpty();
375 const bool empty = mOutputLayersOrderedByZ.empty();
376 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
377
378 // If nothing has changed (!dirty), don't recompose.
379 // If something changed, but we don't currently have any visible layers,
380 // and didn't when we last did a composition, then skip it this time.
381 // The second rule does two things:
382 // - When all layers are removed from a display, we'll emit one black
383 // frame, then nothing more until we get new layers.
384 // - When a display is created with a private layer stack, we won't
385 // emit any black frames until a layer is added to the layer stack.
386 const bool mustRecompose = dirty && !(empty && wasEmpty);
387
388 const char flagPrefix[] = {'-', '+'};
389 static_cast<void>(flagPrefix);
390 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
391 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
392 flagPrefix[empty], flagPrefix[wasEmpty]);
393
394 mRenderSurface->beginFrame(mustRecompose);
395
396 if (mustRecompose) {
397 mState.lastCompositionHadVisibleLayers = !empty;
398 }
399}
400
Lloyd Pique66d68602019-02-13 14:23:31 -0800401void Output::prepareFrame() {
402 ATRACE_CALL();
403 ALOGV(__FUNCTION__);
404
405 if (!mState.isEnabled) {
406 return;
407 }
408
409 chooseCompositionStrategy();
410
411 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
412}
413
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800414void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
415 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
416 return;
417 }
418
419 if (mState.isEnabled) {
420 // transform the dirty region into this screen's coordinate space
421 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
422 if (!dirtyRegion.isEmpty()) {
423 base::unique_fd readyFence;
424 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800425 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800426
427 mRenderSurface->queueBuffer(std::move(readyFence));
428 }
429 }
430
431 postFramebuffer();
432
433 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
434
435 prepareFrame();
436}
437
Lloyd Piqued3d69882019-02-28 16:03:46 -0800438void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
439 ATRACE_CALL();
440 ALOGV(__FUNCTION__);
441
442 if (!mState.isEnabled) {
443 return;
444 }
445
446 // Repaint the framebuffer (if needed), getting the optional fence for when
447 // the composition completes.
448 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
449 if (!optReadyFence) {
450 return;
451 }
452
453 // swap buffers (presentation)
454 mRenderSurface->queueBuffer(std::move(*optReadyFence));
455}
456
457std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800458 ATRACE_CALL();
459 ALOGV(__FUNCTION__);
460
461 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
462 mState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800463 base::unique_fd readyFence;
464
Lloyd Pique688abd42019-02-15 15:42:24 -0800465 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800466 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800467 }
468
469 ALOGV("hasClientComposition");
470
471 auto& renderEngine = mCompositionEngine.getRenderEngine();
472 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
473
474 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700475 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800476 clientCompositionDisplay.clip = mState.scissor;
477 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
478 clientCompositionDisplay.orientation = mState.orientation;
479 clientCompositionDisplay.outputDataspace =
480 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
481 clientCompositionDisplay.maxLuminance =
482 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
483
484 // Compute the global color transform matrix.
485 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
486 clientCompositionDisplay.colorTransform = mState.colorTransformMat;
487 }
488
489 // Note: Updated by generateClientCompositionRequests
490 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
491
492 // Generate the client composition requests for the layers on this output.
493 std::vector<renderengine::LayerSettings> clientCompositionLayers =
494 generateClientCompositionRequests(supportsProtectedContent,
495 clientCompositionDisplay.clearRegion);
496 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
497
498 // If we the display is secure, protected content support is enabled, and at
499 // least one layer has protected content, we need to use a secure back
500 // buffer.
501 if (mState.isSecure && supportsProtectedContent) {
502 bool needsProtected =
503 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
504 [](auto& layer) {
505 return layer->getLayer().getState().frontEnd.hasProtectedContent;
506 });
507 if (needsProtected != renderEngine.isProtected()) {
508 renderEngine.useProtectedContext(needsProtected);
509 }
510 if (needsProtected != mRenderSurface->isProtected() &&
511 needsProtected == renderEngine.isProtected()) {
512 mRenderSurface->setProtected(needsProtected);
513 }
514 }
515
516 base::unique_fd fd;
517 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
518 if (buf == nullptr) {
519 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
520 "client composition for this frame",
521 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800522 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800523 }
524
525 // We boost GPU frequency here because there will be color spaces conversion
526 // and it's expensive. We boost the GPU frequency so that GPU composition can
527 // finish in time. We must reset GPU frequency afterwards, because high frequency
528 // consumes extra battery.
529 const bool expensiveRenderingExpected =
530 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
531 if (expensiveRenderingExpected) {
532 setExpensiveRenderingExpected(true);
533 }
534
535 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
536 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800537 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800538
539 if (expensiveRenderingExpected) {
540 setExpensiveRenderingExpected(false);
541 }
542
Lloyd Piqued3d69882019-02-28 16:03:46 -0800543 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800544}
545
546std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
547 bool supportsProtectedContent, Region& clearRegion) {
548 std::vector<renderengine::LayerSettings> clientCompositionLayers;
549 ALOGV("Rendering client layers");
550
551 const Region viewportRegion(mState.viewport);
552 const bool useIdentityTransform = false;
553 bool firstLayer = true;
554 // Used when a layer clears part of the buffer.
555 Region dummyRegion;
556
557 for (auto& layer : mOutputLayersOrderedByZ) {
558 const auto& layerState = layer->getState();
559 const auto& layerFEState = layer->getLayer().getState().frontEnd;
560 auto& layerFE = layer->getLayerFE();
561
Lloyd Pique56eba802019-08-28 15:45:25 -0700562 const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800563 ALOGV("Layer: %s", layerFE.getDebugName());
564 if (clip.isEmpty()) {
565 ALOGV(" Skipping for empty clip");
566 firstLayer = false;
567 continue;
568 }
569
570 bool clientComposition = layer->requiresClientComposition();
571
572 // We clear the client target for non-client composed layers if
573 // requested by the HWC. We skip this if the layer is not an opaque
574 // rectangle, as by definition the layer must blend with whatever is
575 // underneath. We also skip the first layer as the buffer target is
576 // guaranteed to start out cleared.
577 bool clearClientComposition =
578 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
579
580 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
581
582 if (clientComposition || clearClientComposition) {
583 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
584 clip,
585 useIdentityTransform,
586 layer->needsFiltering() || mState.needsFiltering,
587 mState.isSecure,
588 supportsProtectedContent,
589 clientComposition ? clearRegion : dummyRegion,
590 };
591 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700592 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800593 auto& layerSettings = *result;
594 layerSettings.source.buffer.buffer = nullptr;
595 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
596 layerSettings.alpha = half(0.0);
597 layerSettings.disableBlending = true;
598 }
599
600 clientCompositionLayers.push_back(*result);
601 }
602 }
603
604 firstLayer = false;
605 }
606
607 return clientCompositionLayers;
608}
609
610void Output::appendRegionFlashRequests(
611 const Region& flashRegion,
612 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
613 if (flashRegion.isEmpty()) {
614 return;
615 }
616
617 renderengine::LayerSettings layerSettings;
618 layerSettings.source.buffer.buffer = nullptr;
619 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
620 layerSettings.alpha = half(1.0);
621
622 for (const auto& rect : flashRegion) {
623 layerSettings.geometry.boundaries = rect.toFloatRect();
624 clientCompositionLayers.push_back(layerSettings);
625 }
626}
627
628void Output::setExpensiveRenderingExpected(bool) {
629 // The base class does nothing with this call.
630}
631
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800632void Output::postFramebuffer() {
633 ATRACE_CALL();
634 ALOGV(__FUNCTION__);
635
636 if (!getState().isEnabled) {
637 return;
638 }
639
Lloyd Piqued3d69882019-02-28 16:03:46 -0800640 mState.dirtyRegion.clear();
641 mRenderSurface->flip();
642
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800643 auto frame = presentAndGetFrameFences();
644
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700645 mRenderSurface->onPresentDisplayCompleted();
646
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800647 for (auto& layer : getOutputLayersOrderedByZ()) {
648 // The layer buffer from the previous frame (if any) is released
649 // by HWC only when the release fence from this frame (if any) is
650 // signaled. Always get the release fence from HWC first.
651 sp<Fence> releaseFence = Fence::NO_FENCE;
652
653 if (auto hwcLayer = layer->getHwcLayer()) {
654 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
655 releaseFence = f->second;
656 }
657 }
658
659 // If the layer was client composited in the previous frame, we
660 // need to merge with the previous client target acquire fence.
661 // Since we do not track that, always merge with the current
662 // client target acquire fence when it is available, even though
663 // this is suboptimal.
664 // TODO(b/121291683): Track previous frame client target acquire fence.
665 if (mState.usesClientComposition) {
666 releaseFence =
667 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
668 }
669
670 layer->getLayerFE().onLayerDisplayed(releaseFence);
671 }
672
673 // We've got a list of layers needing fences, that are disjoint with
674 // getOutputLayersOrderedByZ. The best we can do is to
675 // supply them with the present fence.
676 for (auto& weakLayer : mReleasedLayers) {
677 if (auto layer = weakLayer.promote(); layer != nullptr) {
678 layer->onLayerDisplayed(frame.presentFence);
679 }
680 }
681
682 // Clear out the released layers now that we're done with them.
683 mReleasedLayers.clear();
684}
685
Lloyd Pique32cbe282018-10-19 13:09:22 -0700686void Output::dirtyEntireOutput() {
687 mState.dirtyRegion.set(mState.bounds);
688}
689
Lloyd Pique66d68602019-02-13 14:23:31 -0800690void Output::chooseCompositionStrategy() {
691 // The base output implementation can only do client composition
692 mState.usesClientComposition = true;
693 mState.usesDeviceComposition = false;
694}
695
Lloyd Pique688abd42019-02-15 15:42:24 -0800696bool Output::getSkipColorTransform() const {
697 return true;
698}
699
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800700compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
701 compositionengine::Output::FrameFences result;
702 if (mState.usesClientComposition) {
703 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
704 }
705 return result;
706}
707
Lloyd Piquefeb73d72018-12-04 17:23:44 -0800708} // namespace impl
709} // namespace android::compositionengine