blob: a9b1d5540bf7293f15103997a98ea3536f10f5d7 [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
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800102void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
103 if (!args.colorTransformMatrix || mState.colorTransformMatrix == *args.colorTransformMatrix) {
Lloyd Pique77f79a22019-04-29 15:55:40 -0700104 return;
105 }
106
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800107 mState.colorTransformMatrix = *args.colorTransformMatrix;
Lloyd Piqueef958122019-02-05 18:00:12 -0800108
109 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700110}
111
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800112void Output::setColorProfile(const ColorProfile& colorProfile) {
113 const ui::Dataspace targetDataspace =
114 getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
115 colorProfile.colorSpaceAgnosticDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800116
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800117 if (mState.colorMode == colorProfile.mode && mState.dataspace == colorProfile.dataspace &&
118 mState.renderIntent == colorProfile.renderIntent &&
119 mState.targetDataspace == targetDataspace) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800120 return;
121 }
122
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800123 mState.colorMode = colorProfile.mode;
124 mState.dataspace = colorProfile.dataspace;
125 mState.renderIntent = colorProfile.renderIntent;
Lloyd Piquef5275482019-01-29 18:42:42 -0800126 mState.targetDataspace = targetDataspace;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700127
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800128 mRenderSurface->setBufferDataspace(colorProfile.dataspace);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700129
Lloyd Pique32cbe282018-10-19 13:09:22 -0700130 ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800131 decodeColorMode(colorProfile.mode).c_str(), colorProfile.mode,
132 decodeRenderIntent(colorProfile.renderIntent).c_str(), colorProfile.renderIntent);
Lloyd Piqueef958122019-02-05 18:00:12 -0800133
134 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700135}
136
137void Output::dump(std::string& out) const {
138 using android::base::StringAppendF;
139
140 StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str());
141
142 out.append("\n ");
143
144 dumpBase(out);
145}
146
147void Output::dumpBase(std::string& out) const {
148 mState.dump(out);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700149
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700150 if (mDisplayColorProfile) {
151 mDisplayColorProfile->dump(out);
152 } else {
153 out.append(" No display color profile!\n");
154 }
155
Lloyd Pique31cb2942018-10-19 17:23:03 -0700156 if (mRenderSurface) {
157 mRenderSurface->dump(out);
158 } else {
159 out.append(" No render surface!\n");
160 }
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800161
Lloyd Pique207def92019-02-28 16:09:52 -0800162 android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800163 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
164 if (!outputLayer) {
165 continue;
166 }
167 outputLayer->dump(out);
168 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700169}
170
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700171compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
172 return mDisplayColorProfile.get();
173}
174
175void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
176 mDisplayColorProfile = std::move(mode);
177}
178
179void Output::setDisplayColorProfileForTest(
180 std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
181 mDisplayColorProfile = std::move(mode);
182}
183
Lloyd Pique31cb2942018-10-19 17:23:03 -0700184compositionengine::RenderSurface* Output::getRenderSurface() const {
185 return mRenderSurface.get();
186}
187
188void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
189 mRenderSurface = std::move(surface);
190 mState.bounds = Rect(mRenderSurface->getSize());
191
192 dirtyEntireOutput();
193}
194
195void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
196 mRenderSurface = std::move(surface);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700197}
198
199const OutputCompositionState& Output::getState() const {
200 return mState;
201}
202
203OutputCompositionState& Output::editState() {
204 return mState;
205}
206
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000207Region Output::getDirtyRegion(bool repaintEverything) const {
208 Region dirty(mState.viewport);
209 if (!repaintEverything) {
210 dirty.andSelf(mState.dirtyRegion);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700211 }
212 return dirty;
213}
214
Lloyd Piquec6687342019-03-07 21:34:57 -0800215bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
Lloyd Piqueef36b002019-01-23 17:52:04 -0800216 // The layerStackId's must match, and also the layer must not be internal
217 // only when not on an internal output.
Lloyd Piquec6687342019-03-07 21:34:57 -0800218 return layerStackId && (*layerStackId == mState.layerStackId) &&
219 (!internalOnly || mState.layerStackInternal);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700220}
221
Lloyd Pique66c20c42019-03-07 21:44:02 -0800222bool Output::belongsInOutput(const compositionengine::Layer* layer) const {
223 if (!layer) {
224 return false;
225 }
226
227 const auto& layerFEState = layer->getState().frontEnd;
228 return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly);
229}
230
Lloyd Piquecc01a452018-12-04 17:24:00 -0800231compositionengine::OutputLayer* Output::getOutputLayerForLayer(
232 compositionengine::Layer* layer) const {
233 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
234 if (outputLayer && &outputLayer->getLayer() == layer) {
235 return outputLayer.get();
236 }
237 }
238 return nullptr;
239}
240
241std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
Lloyd Piquedf336d92019-03-07 21:38:42 -0800242 std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
Lloyd Piquecc01a452018-12-04 17:24:00 -0800243 for (auto& outputLayer : mOutputLayersOrderedByZ) {
244 if (outputLayer && &outputLayer->getLayer() == layer.get()) {
245 return std::move(outputLayer);
246 }
247 }
Lloyd Piquedf336d92019-03-07 21:38:42 -0800248
249 return createOutputLayer(layer, layerFE);
250}
251
252std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
253 const std::shared_ptr<compositionengine::Layer>& layer,
254 const sp<compositionengine::LayerFE>& layerFE) const {
255 return impl::createOutputLayer(*this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800256}
257
258void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
259 mOutputLayersOrderedByZ = std::move(layers);
260}
261
262const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
263 return mOutputLayersOrderedByZ;
264}
265
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800266void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
267 mReleasedLayers = std::move(layers);
268}
269
270Output::ReleasedLayers Output::takeReleasedLayers() {
271 return std::move(mReleasedLayers);
272}
273
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800274void Output::prepare(compositionengine::CompositionRefreshArgs& refreshArgs) {
275 if (CC_LIKELY(!refreshArgs.updatingGeometryThisFrame)) {
276 return;
277 }
278
279 uint32_t zOrder = 0;
280 for (auto& layer : mOutputLayersOrderedByZ) {
281 // Assign a simple Z order sequence to each visible layer.
282 layer->editState().z = zOrder++;
283 }
284}
285
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800286void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800287 updateColorProfile(refreshArgs);
288 updateAndWriteCompositionState(refreshArgs);
289 setColorTransform(refreshArgs);
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800290 beginFrame();
291 prepareFrame();
292 devOptRepaintFlash(refreshArgs);
293 finishFrame(refreshArgs);
294 postFramebuffer();
295}
296
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800297void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
298 for (auto& layer : mOutputLayersOrderedByZ) {
299 layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd,
Lloyd Piquec6687342019-03-07 21:34:57 -0800300 args.updatingGeometryThisFrame
301 ? LayerFE::StateSubset::GeometryAndContent
302 : LayerFE::StateSubset::Content);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800303 }
304}
305
306void Output::updateAndWriteCompositionState(
307 const compositionengine::CompositionRefreshArgs& refreshArgs) {
308 ATRACE_CALL();
309 ALOGV(__FUNCTION__);
310
311 for (auto& layer : mOutputLayersOrderedByZ) {
312 if (refreshArgs.devOptForceClientComposition) {
313 layer->editState().forceClientComposition = true;
314 }
315
316 layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame);
317
318 // Send the updated state to the HWC, if appropriate.
319 layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
320 }
321}
322
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800323void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
324 setColorProfile(pickColorProfile(refreshArgs));
325}
326
327// Returns a data space that fits all visible layers. The returned data space
328// can only be one of
329// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
330// - Dataspace::DISPLAY_P3
331// - Dataspace::DISPLAY_BT2020
332// The returned HDR data space is one of
333// - Dataspace::UNKNOWN
334// - Dataspace::BT2020_HLG
335// - Dataspace::BT2020_PQ
336ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
337 bool* outIsHdrClientComposition) const {
338 ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
339 *outHdrDataSpace = ui::Dataspace::UNKNOWN;
340
341 for (const auto& layer : mOutputLayersOrderedByZ) {
342 switch (layer->getLayer().getState().frontEnd.dataspace) {
343 case ui::Dataspace::V0_SCRGB:
344 case ui::Dataspace::V0_SCRGB_LINEAR:
345 case ui::Dataspace::BT2020:
346 case ui::Dataspace::BT2020_ITU:
347 case ui::Dataspace::BT2020_LINEAR:
348 case ui::Dataspace::DISPLAY_BT2020:
349 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
350 break;
351 case ui::Dataspace::DISPLAY_P3:
352 bestDataSpace = ui::Dataspace::DISPLAY_P3;
353 break;
354 case ui::Dataspace::BT2020_PQ:
355 case ui::Dataspace::BT2020_ITU_PQ:
356 bestDataSpace = ui::Dataspace::DISPLAY_P3;
357 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
358 *outIsHdrClientComposition =
359 layer->getLayer().getState().frontEnd.forceClientComposition;
360 break;
361 case ui::Dataspace::BT2020_HLG:
362 case ui::Dataspace::BT2020_ITU_HLG:
363 bestDataSpace = ui::Dataspace::DISPLAY_P3;
364 // When there's mixed PQ content and HLG content, we set the HDR
365 // data space to be BT2020_PQ and convert HLG to PQ.
366 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
367 *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
368 }
369 break;
370 default:
371 break;
372 }
373 }
374
375 return bestDataSpace;
376}
377
378compositionengine::Output::ColorProfile Output::pickColorProfile(
379 const compositionengine::CompositionRefreshArgs& refreshArgs) const {
380 if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
381 return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
382 ui::RenderIntent::COLORIMETRIC,
383 refreshArgs.colorSpaceAgnosticDataspace};
384 }
385
386 ui::Dataspace hdrDataSpace;
387 bool isHdrClientComposition = false;
388 ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
389
390 switch (refreshArgs.forceOutputColorMode) {
391 case ui::ColorMode::SRGB:
392 bestDataSpace = ui::Dataspace::V0_SRGB;
393 break;
394 case ui::ColorMode::DISPLAY_P3:
395 bestDataSpace = ui::Dataspace::DISPLAY_P3;
396 break;
397 default:
398 break;
399 }
400
401 // respect hdrDataSpace only when there is no legacy HDR support
402 const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
403 !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
404 if (isHdr) {
405 bestDataSpace = hdrDataSpace;
406 }
407
408 ui::RenderIntent intent;
409 switch (refreshArgs.outputColorSetting) {
410 case OutputColorSetting::kManaged:
411 case OutputColorSetting::kUnmanaged:
412 intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
413 : ui::RenderIntent::COLORIMETRIC;
414 break;
415 case OutputColorSetting::kEnhanced:
416 intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
417 break;
418 default: // vendor display color setting
419 intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
420 break;
421 }
422
423 ui::ColorMode outMode;
424 ui::Dataspace outDataSpace;
425 ui::RenderIntent outRenderIntent;
426 mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
427 &outRenderIntent);
428
429 return ColorProfile{outMode, outDataSpace, outRenderIntent,
430 refreshArgs.colorSpaceAgnosticDataspace};
431}
432
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800433void Output::beginFrame() {
434 const bool dirty = !getDirtyRegion(false).isEmpty();
435 const bool empty = mOutputLayersOrderedByZ.empty();
436 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
437
438 // If nothing has changed (!dirty), don't recompose.
439 // If something changed, but we don't currently have any visible layers,
440 // and didn't when we last did a composition, then skip it this time.
441 // The second rule does two things:
442 // - When all layers are removed from a display, we'll emit one black
443 // frame, then nothing more until we get new layers.
444 // - When a display is created with a private layer stack, we won't
445 // emit any black frames until a layer is added to the layer stack.
446 const bool mustRecompose = dirty && !(empty && wasEmpty);
447
448 const char flagPrefix[] = {'-', '+'};
449 static_cast<void>(flagPrefix);
450 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
451 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
452 flagPrefix[empty], flagPrefix[wasEmpty]);
453
454 mRenderSurface->beginFrame(mustRecompose);
455
456 if (mustRecompose) {
457 mState.lastCompositionHadVisibleLayers = !empty;
458 }
459}
460
Lloyd Pique66d68602019-02-13 14:23:31 -0800461void Output::prepareFrame() {
462 ATRACE_CALL();
463 ALOGV(__FUNCTION__);
464
465 if (!mState.isEnabled) {
466 return;
467 }
468
469 chooseCompositionStrategy();
470
471 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
472}
473
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800474void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
475 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
476 return;
477 }
478
479 if (mState.isEnabled) {
480 // transform the dirty region into this screen's coordinate space
481 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
482 if (!dirtyRegion.isEmpty()) {
483 base::unique_fd readyFence;
484 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800485 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800486
487 mRenderSurface->queueBuffer(std::move(readyFence));
488 }
489 }
490
491 postFramebuffer();
492
493 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
494
495 prepareFrame();
496}
497
Lloyd Piqued3d69882019-02-28 16:03:46 -0800498void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
499 ATRACE_CALL();
500 ALOGV(__FUNCTION__);
501
502 if (!mState.isEnabled) {
503 return;
504 }
505
506 // Repaint the framebuffer (if needed), getting the optional fence for when
507 // the composition completes.
508 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
509 if (!optReadyFence) {
510 return;
511 }
512
513 // swap buffers (presentation)
514 mRenderSurface->queueBuffer(std::move(*optReadyFence));
515}
516
517std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800518 ATRACE_CALL();
519 ALOGV(__FUNCTION__);
520
521 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
522 mState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800523 base::unique_fd readyFence;
524
Lloyd Pique688abd42019-02-15 15:42:24 -0800525 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800526 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800527 }
528
529 ALOGV("hasClientComposition");
530
531 auto& renderEngine = mCompositionEngine.getRenderEngine();
532 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
533
534 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700535 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800536 clientCompositionDisplay.clip = mState.scissor;
537 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
538 clientCompositionDisplay.orientation = mState.orientation;
539 clientCompositionDisplay.outputDataspace =
540 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
541 clientCompositionDisplay.maxLuminance =
542 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
543
544 // Compute the global color transform matrix.
545 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800546 clientCompositionDisplay.colorTransform = mState.colorTransformMatrix;
Lloyd Pique688abd42019-02-15 15:42:24 -0800547 }
548
549 // Note: Updated by generateClientCompositionRequests
550 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
551
552 // Generate the client composition requests for the layers on this output.
553 std::vector<renderengine::LayerSettings> clientCompositionLayers =
554 generateClientCompositionRequests(supportsProtectedContent,
555 clientCompositionDisplay.clearRegion);
556 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
557
558 // If we the display is secure, protected content support is enabled, and at
559 // least one layer has protected content, we need to use a secure back
560 // buffer.
561 if (mState.isSecure && supportsProtectedContent) {
562 bool needsProtected =
563 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
564 [](auto& layer) {
565 return layer->getLayer().getState().frontEnd.hasProtectedContent;
566 });
567 if (needsProtected != renderEngine.isProtected()) {
568 renderEngine.useProtectedContext(needsProtected);
569 }
570 if (needsProtected != mRenderSurface->isProtected() &&
571 needsProtected == renderEngine.isProtected()) {
572 mRenderSurface->setProtected(needsProtected);
573 }
574 }
575
576 base::unique_fd fd;
577 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
578 if (buf == nullptr) {
579 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
580 "client composition for this frame",
581 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800582 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800583 }
584
585 // We boost GPU frequency here because there will be color spaces conversion
586 // and it's expensive. We boost the GPU frequency so that GPU composition can
587 // finish in time. We must reset GPU frequency afterwards, because high frequency
588 // consumes extra battery.
589 const bool expensiveRenderingExpected =
590 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
591 if (expensiveRenderingExpected) {
592 setExpensiveRenderingExpected(true);
593 }
594
595 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
596 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800597 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800598
599 if (expensiveRenderingExpected) {
600 setExpensiveRenderingExpected(false);
601 }
602
Lloyd Piqued3d69882019-02-28 16:03:46 -0800603 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800604}
605
606std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
607 bool supportsProtectedContent, Region& clearRegion) {
608 std::vector<renderengine::LayerSettings> clientCompositionLayers;
609 ALOGV("Rendering client layers");
610
611 const Region viewportRegion(mState.viewport);
612 const bool useIdentityTransform = false;
613 bool firstLayer = true;
614 // Used when a layer clears part of the buffer.
615 Region dummyRegion;
616
617 for (auto& layer : mOutputLayersOrderedByZ) {
618 const auto& layerState = layer->getState();
619 const auto& layerFEState = layer->getLayer().getState().frontEnd;
620 auto& layerFE = layer->getLayerFE();
621
Lloyd Piquea2468662019-03-07 21:31:06 -0800622 const Region clip(viewportRegion.intersect(layerState.visibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800623 ALOGV("Layer: %s", layerFE.getDebugName());
624 if (clip.isEmpty()) {
625 ALOGV(" Skipping for empty clip");
626 firstLayer = false;
627 continue;
628 }
629
630 bool clientComposition = layer->requiresClientComposition();
631
632 // We clear the client target for non-client composed layers if
633 // requested by the HWC. We skip this if the layer is not an opaque
634 // rectangle, as by definition the layer must blend with whatever is
635 // underneath. We also skip the first layer as the buffer target is
636 // guaranteed to start out cleared.
637 bool clearClientComposition =
638 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
639
640 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
641
642 if (clientComposition || clearClientComposition) {
643 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
644 clip,
645 useIdentityTransform,
646 layer->needsFiltering() || mState.needsFiltering,
647 mState.isSecure,
648 supportsProtectedContent,
649 clientComposition ? clearRegion : dummyRegion,
650 };
651 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700652 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800653 auto& layerSettings = *result;
654 layerSettings.source.buffer.buffer = nullptr;
655 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
656 layerSettings.alpha = half(0.0);
657 layerSettings.disableBlending = true;
658 }
659
660 clientCompositionLayers.push_back(*result);
661 }
662 }
663
664 firstLayer = false;
665 }
666
667 return clientCompositionLayers;
668}
669
670void Output::appendRegionFlashRequests(
671 const Region& flashRegion,
672 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
673 if (flashRegion.isEmpty()) {
674 return;
675 }
676
677 renderengine::LayerSettings layerSettings;
678 layerSettings.source.buffer.buffer = nullptr;
679 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
680 layerSettings.alpha = half(1.0);
681
682 for (const auto& rect : flashRegion) {
683 layerSettings.geometry.boundaries = rect.toFloatRect();
684 clientCompositionLayers.push_back(layerSettings);
685 }
686}
687
688void Output::setExpensiveRenderingExpected(bool) {
689 // The base class does nothing with this call.
690}
691
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800692void Output::postFramebuffer() {
693 ATRACE_CALL();
694 ALOGV(__FUNCTION__);
695
696 if (!getState().isEnabled) {
697 return;
698 }
699
Lloyd Piqued3d69882019-02-28 16:03:46 -0800700 mState.dirtyRegion.clear();
701 mRenderSurface->flip();
702
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800703 auto frame = presentAndGetFrameFences();
704
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700705 mRenderSurface->onPresentDisplayCompleted();
706
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800707 for (auto& layer : getOutputLayersOrderedByZ()) {
708 // The layer buffer from the previous frame (if any) is released
709 // by HWC only when the release fence from this frame (if any) is
710 // signaled. Always get the release fence from HWC first.
711 sp<Fence> releaseFence = Fence::NO_FENCE;
712
713 if (auto hwcLayer = layer->getHwcLayer()) {
714 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
715 releaseFence = f->second;
716 }
717 }
718
719 // If the layer was client composited in the previous frame, we
720 // need to merge with the previous client target acquire fence.
721 // Since we do not track that, always merge with the current
722 // client target acquire fence when it is available, even though
723 // this is suboptimal.
724 // TODO(b/121291683): Track previous frame client target acquire fence.
725 if (mState.usesClientComposition) {
726 releaseFence =
727 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
728 }
729
730 layer->getLayerFE().onLayerDisplayed(releaseFence);
731 }
732
733 // We've got a list of layers needing fences, that are disjoint with
734 // getOutputLayersOrderedByZ. The best we can do is to
735 // supply them with the present fence.
736 for (auto& weakLayer : mReleasedLayers) {
737 if (auto layer = weakLayer.promote(); layer != nullptr) {
738 layer->onLayerDisplayed(frame.presentFence);
739 }
740 }
741
742 // Clear out the released layers now that we're done with them.
743 mReleasedLayers.clear();
744}
745
Lloyd Pique32cbe282018-10-19 13:09:22 -0700746void Output::dirtyEntireOutput() {
747 mState.dirtyRegion.set(mState.bounds);
748}
749
Lloyd Pique66d68602019-02-13 14:23:31 -0800750void Output::chooseCompositionStrategy() {
751 // The base output implementation can only do client composition
752 mState.usesClientComposition = true;
753 mState.usesDeviceComposition = false;
754}
755
Lloyd Pique688abd42019-02-15 15:42:24 -0800756bool Output::getSkipColorTransform() const {
757 return true;
758}
759
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800760compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
761 compositionengine::Output::FrameFences result;
762 if (mState.usesClientComposition) {
763 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
764 }
765 return result;
766}
767
Lloyd Piquefeb73d72018-12-04 17:23:44 -0800768} // namespace impl
769} // namespace android::compositionengine