blob: 903ca9891cda4506acd679f47c219780b1c486e5 [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 Piqueef36b002019-01-23 17:52:04 -0800215bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
216 // The layerStackId's must match, and also the layer must not be internal
217 // only when not on an internal output.
218 return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700219}
220
Lloyd Piquecc01a452018-12-04 17:24:00 -0800221compositionengine::OutputLayer* Output::getOutputLayerForLayer(
222 compositionengine::Layer* layer) const {
223 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
224 if (outputLayer && &outputLayer->getLayer() == layer) {
225 return outputLayer.get();
226 }
227 }
228 return nullptr;
229}
230
231std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
Lloyd Pique07e33212018-12-18 16:33:37 -0800232 std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
233 sp<compositionengine::LayerFE> layerFE) {
Lloyd Piquecc01a452018-12-04 17:24:00 -0800234 for (auto& outputLayer : mOutputLayersOrderedByZ) {
235 if (outputLayer && &outputLayer->getLayer() == layer.get()) {
236 return std::move(outputLayer);
237 }
238 }
Lloyd Pique07e33212018-12-18 16:33:37 -0800239 return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800240}
241
242void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
243 mOutputLayersOrderedByZ = std::move(layers);
244}
245
246const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
247 return mOutputLayersOrderedByZ;
248}
249
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800250void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
251 mReleasedLayers = std::move(layers);
252}
253
254Output::ReleasedLayers Output::takeReleasedLayers() {
255 return std::move(mReleasedLayers);
256}
257
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800258void Output::prepare(compositionengine::CompositionRefreshArgs& refreshArgs) {
259 if (CC_LIKELY(!refreshArgs.updatingGeometryThisFrame)) {
260 return;
261 }
262
263 uint32_t zOrder = 0;
264 for (auto& layer : mOutputLayersOrderedByZ) {
265 // Assign a simple Z order sequence to each visible layer.
266 layer->editState().z = zOrder++;
267 }
268}
269
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800270void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800271 updateColorProfile(refreshArgs);
272 updateAndWriteCompositionState(refreshArgs);
273 setColorTransform(refreshArgs);
Lloyd Piqued7b429f2019-03-07 21:11:02 -0800274 beginFrame();
275 prepareFrame();
276 devOptRepaintFlash(refreshArgs);
277 finishFrame(refreshArgs);
278 postFramebuffer();
279}
280
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800281void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
282 for (auto& layer : mOutputLayersOrderedByZ) {
283 layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd,
284 args.updatingGeometryThisFrame);
285 }
286}
287
288void Output::updateAndWriteCompositionState(
289 const compositionengine::CompositionRefreshArgs& refreshArgs) {
290 ATRACE_CALL();
291 ALOGV(__FUNCTION__);
292
293 for (auto& layer : mOutputLayersOrderedByZ) {
294 if (refreshArgs.devOptForceClientComposition) {
295 layer->editState().forceClientComposition = true;
296 }
297
298 layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame);
299
300 // Send the updated state to the HWC, if appropriate.
301 layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
302 }
303}
304
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800305void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
306 setColorProfile(pickColorProfile(refreshArgs));
307}
308
309// Returns a data space that fits all visible layers. The returned data space
310// can only be one of
311// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
312// - Dataspace::DISPLAY_P3
313// - Dataspace::DISPLAY_BT2020
314// The returned HDR data space is one of
315// - Dataspace::UNKNOWN
316// - Dataspace::BT2020_HLG
317// - Dataspace::BT2020_PQ
318ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
319 bool* outIsHdrClientComposition) const {
320 ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
321 *outHdrDataSpace = ui::Dataspace::UNKNOWN;
322
323 for (const auto& layer : mOutputLayersOrderedByZ) {
324 switch (layer->getLayer().getState().frontEnd.dataspace) {
325 case ui::Dataspace::V0_SCRGB:
326 case ui::Dataspace::V0_SCRGB_LINEAR:
327 case ui::Dataspace::BT2020:
328 case ui::Dataspace::BT2020_ITU:
329 case ui::Dataspace::BT2020_LINEAR:
330 case ui::Dataspace::DISPLAY_BT2020:
331 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
332 break;
333 case ui::Dataspace::DISPLAY_P3:
334 bestDataSpace = ui::Dataspace::DISPLAY_P3;
335 break;
336 case ui::Dataspace::BT2020_PQ:
337 case ui::Dataspace::BT2020_ITU_PQ:
338 bestDataSpace = ui::Dataspace::DISPLAY_P3;
339 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
340 *outIsHdrClientComposition =
341 layer->getLayer().getState().frontEnd.forceClientComposition;
342 break;
343 case ui::Dataspace::BT2020_HLG:
344 case ui::Dataspace::BT2020_ITU_HLG:
345 bestDataSpace = ui::Dataspace::DISPLAY_P3;
346 // When there's mixed PQ content and HLG content, we set the HDR
347 // data space to be BT2020_PQ and convert HLG to PQ.
348 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
349 *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
350 }
351 break;
352 default:
353 break;
354 }
355 }
356
357 return bestDataSpace;
358}
359
360compositionengine::Output::ColorProfile Output::pickColorProfile(
361 const compositionengine::CompositionRefreshArgs& refreshArgs) const {
362 if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
363 return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
364 ui::RenderIntent::COLORIMETRIC,
365 refreshArgs.colorSpaceAgnosticDataspace};
366 }
367
368 ui::Dataspace hdrDataSpace;
369 bool isHdrClientComposition = false;
370 ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
371
372 switch (refreshArgs.forceOutputColorMode) {
373 case ui::ColorMode::SRGB:
374 bestDataSpace = ui::Dataspace::V0_SRGB;
375 break;
376 case ui::ColorMode::DISPLAY_P3:
377 bestDataSpace = ui::Dataspace::DISPLAY_P3;
378 break;
379 default:
380 break;
381 }
382
383 // respect hdrDataSpace only when there is no legacy HDR support
384 const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
385 !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
386 if (isHdr) {
387 bestDataSpace = hdrDataSpace;
388 }
389
390 ui::RenderIntent intent;
391 switch (refreshArgs.outputColorSetting) {
392 case OutputColorSetting::kManaged:
393 case OutputColorSetting::kUnmanaged:
394 intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
395 : ui::RenderIntent::COLORIMETRIC;
396 break;
397 case OutputColorSetting::kEnhanced:
398 intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
399 break;
400 default: // vendor display color setting
401 intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
402 break;
403 }
404
405 ui::ColorMode outMode;
406 ui::Dataspace outDataSpace;
407 ui::RenderIntent outRenderIntent;
408 mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
409 &outRenderIntent);
410
411 return ColorProfile{outMode, outDataSpace, outRenderIntent,
412 refreshArgs.colorSpaceAgnosticDataspace};
413}
414
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800415void Output::beginFrame() {
416 const bool dirty = !getDirtyRegion(false).isEmpty();
417 const bool empty = mOutputLayersOrderedByZ.empty();
418 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
419
420 // If nothing has changed (!dirty), don't recompose.
421 // If something changed, but we don't currently have any visible layers,
422 // and didn't when we last did a composition, then skip it this time.
423 // The second rule does two things:
424 // - When all layers are removed from a display, we'll emit one black
425 // frame, then nothing more until we get new layers.
426 // - When a display is created with a private layer stack, we won't
427 // emit any black frames until a layer is added to the layer stack.
428 const bool mustRecompose = dirty && !(empty && wasEmpty);
429
430 const char flagPrefix[] = {'-', '+'};
431 static_cast<void>(flagPrefix);
432 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
433 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
434 flagPrefix[empty], flagPrefix[wasEmpty]);
435
436 mRenderSurface->beginFrame(mustRecompose);
437
438 if (mustRecompose) {
439 mState.lastCompositionHadVisibleLayers = !empty;
440 }
441}
442
Lloyd Pique66d68602019-02-13 14:23:31 -0800443void Output::prepareFrame() {
444 ATRACE_CALL();
445 ALOGV(__FUNCTION__);
446
447 if (!mState.isEnabled) {
448 return;
449 }
450
451 chooseCompositionStrategy();
452
453 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
454}
455
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800456void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
457 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
458 return;
459 }
460
461 if (mState.isEnabled) {
462 // transform the dirty region into this screen's coordinate space
463 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
464 if (!dirtyRegion.isEmpty()) {
465 base::unique_fd readyFence;
466 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800467 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800468
469 mRenderSurface->queueBuffer(std::move(readyFence));
470 }
471 }
472
473 postFramebuffer();
474
475 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
476
477 prepareFrame();
478}
479
Lloyd Piqued3d69882019-02-28 16:03:46 -0800480void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
481 ATRACE_CALL();
482 ALOGV(__FUNCTION__);
483
484 if (!mState.isEnabled) {
485 return;
486 }
487
488 // Repaint the framebuffer (if needed), getting the optional fence for when
489 // the composition completes.
490 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
491 if (!optReadyFence) {
492 return;
493 }
494
495 // swap buffers (presentation)
496 mRenderSurface->queueBuffer(std::move(*optReadyFence));
497}
498
499std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800500 ATRACE_CALL();
501 ALOGV(__FUNCTION__);
502
503 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
504 mState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800505 base::unique_fd readyFence;
506
Lloyd Pique688abd42019-02-15 15:42:24 -0800507 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800508 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800509 }
510
511 ALOGV("hasClientComposition");
512
513 auto& renderEngine = mCompositionEngine.getRenderEngine();
514 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
515
516 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700517 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800518 clientCompositionDisplay.clip = mState.scissor;
519 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
520 clientCompositionDisplay.orientation = mState.orientation;
521 clientCompositionDisplay.outputDataspace =
522 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
523 clientCompositionDisplay.maxLuminance =
524 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
525
526 // Compute the global color transform matrix.
527 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800528 clientCompositionDisplay.colorTransform = mState.colorTransformMatrix;
Lloyd Pique688abd42019-02-15 15:42:24 -0800529 }
530
531 // Note: Updated by generateClientCompositionRequests
532 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
533
534 // Generate the client composition requests for the layers on this output.
535 std::vector<renderengine::LayerSettings> clientCompositionLayers =
536 generateClientCompositionRequests(supportsProtectedContent,
537 clientCompositionDisplay.clearRegion);
538 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
539
540 // If we the display is secure, protected content support is enabled, and at
541 // least one layer has protected content, we need to use a secure back
542 // buffer.
543 if (mState.isSecure && supportsProtectedContent) {
544 bool needsProtected =
545 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
546 [](auto& layer) {
547 return layer->getLayer().getState().frontEnd.hasProtectedContent;
548 });
549 if (needsProtected != renderEngine.isProtected()) {
550 renderEngine.useProtectedContext(needsProtected);
551 }
552 if (needsProtected != mRenderSurface->isProtected() &&
553 needsProtected == renderEngine.isProtected()) {
554 mRenderSurface->setProtected(needsProtected);
555 }
556 }
557
558 base::unique_fd fd;
559 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
560 if (buf == nullptr) {
561 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
562 "client composition for this frame",
563 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800564 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800565 }
566
567 // We boost GPU frequency here because there will be color spaces conversion
568 // and it's expensive. We boost the GPU frequency so that GPU composition can
569 // finish in time. We must reset GPU frequency afterwards, because high frequency
570 // consumes extra battery.
571 const bool expensiveRenderingExpected =
572 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
573 if (expensiveRenderingExpected) {
574 setExpensiveRenderingExpected(true);
575 }
576
577 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
578 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800579 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800580
581 if (expensiveRenderingExpected) {
582 setExpensiveRenderingExpected(false);
583 }
584
Lloyd Piqued3d69882019-02-28 16:03:46 -0800585 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800586}
587
588std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
589 bool supportsProtectedContent, Region& clearRegion) {
590 std::vector<renderengine::LayerSettings> clientCompositionLayers;
591 ALOGV("Rendering client layers");
592
593 const Region viewportRegion(mState.viewport);
594 const bool useIdentityTransform = false;
595 bool firstLayer = true;
596 // Used when a layer clears part of the buffer.
597 Region dummyRegion;
598
599 for (auto& layer : mOutputLayersOrderedByZ) {
600 const auto& layerState = layer->getState();
601 const auto& layerFEState = layer->getLayer().getState().frontEnd;
602 auto& layerFE = layer->getLayerFE();
603
Lloyd Pique56eba802019-08-28 15:45:25 -0700604 const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800605 ALOGV("Layer: %s", layerFE.getDebugName());
606 if (clip.isEmpty()) {
607 ALOGV(" Skipping for empty clip");
608 firstLayer = false;
609 continue;
610 }
611
612 bool clientComposition = layer->requiresClientComposition();
613
614 // We clear the client target for non-client composed layers if
615 // requested by the HWC. We skip this if the layer is not an opaque
616 // rectangle, as by definition the layer must blend with whatever is
617 // underneath. We also skip the first layer as the buffer target is
618 // guaranteed to start out cleared.
619 bool clearClientComposition =
620 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
621
622 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
623
624 if (clientComposition || clearClientComposition) {
625 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
626 clip,
627 useIdentityTransform,
628 layer->needsFiltering() || mState.needsFiltering,
629 mState.isSecure,
630 supportsProtectedContent,
631 clientComposition ? clearRegion : dummyRegion,
632 };
633 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700634 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800635 auto& layerSettings = *result;
636 layerSettings.source.buffer.buffer = nullptr;
637 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
638 layerSettings.alpha = half(0.0);
639 layerSettings.disableBlending = true;
640 }
641
642 clientCompositionLayers.push_back(*result);
643 }
644 }
645
646 firstLayer = false;
647 }
648
649 return clientCompositionLayers;
650}
651
652void Output::appendRegionFlashRequests(
653 const Region& flashRegion,
654 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
655 if (flashRegion.isEmpty()) {
656 return;
657 }
658
659 renderengine::LayerSettings layerSettings;
660 layerSettings.source.buffer.buffer = nullptr;
661 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
662 layerSettings.alpha = half(1.0);
663
664 for (const auto& rect : flashRegion) {
665 layerSettings.geometry.boundaries = rect.toFloatRect();
666 clientCompositionLayers.push_back(layerSettings);
667 }
668}
669
670void Output::setExpensiveRenderingExpected(bool) {
671 // The base class does nothing with this call.
672}
673
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800674void Output::postFramebuffer() {
675 ATRACE_CALL();
676 ALOGV(__FUNCTION__);
677
678 if (!getState().isEnabled) {
679 return;
680 }
681
Lloyd Piqued3d69882019-02-28 16:03:46 -0800682 mState.dirtyRegion.clear();
683 mRenderSurface->flip();
684
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800685 auto frame = presentAndGetFrameFences();
686
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700687 mRenderSurface->onPresentDisplayCompleted();
688
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800689 for (auto& layer : getOutputLayersOrderedByZ()) {
690 // The layer buffer from the previous frame (if any) is released
691 // by HWC only when the release fence from this frame (if any) is
692 // signaled. Always get the release fence from HWC first.
693 sp<Fence> releaseFence = Fence::NO_FENCE;
694
695 if (auto hwcLayer = layer->getHwcLayer()) {
696 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
697 releaseFence = f->second;
698 }
699 }
700
701 // If the layer was client composited in the previous frame, we
702 // need to merge with the previous client target acquire fence.
703 // Since we do not track that, always merge with the current
704 // client target acquire fence when it is available, even though
705 // this is suboptimal.
706 // TODO(b/121291683): Track previous frame client target acquire fence.
707 if (mState.usesClientComposition) {
708 releaseFence =
709 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
710 }
711
712 layer->getLayerFE().onLayerDisplayed(releaseFence);
713 }
714
715 // We've got a list of layers needing fences, that are disjoint with
716 // getOutputLayersOrderedByZ. The best we can do is to
717 // supply them with the present fence.
718 for (auto& weakLayer : mReleasedLayers) {
719 if (auto layer = weakLayer.promote(); layer != nullptr) {
720 layer->onLayerDisplayed(frame.presentFence);
721 }
722 }
723
724 // Clear out the released layers now that we're done with them.
725 mReleasedLayers.clear();
726}
727
Lloyd Pique32cbe282018-10-19 13:09:22 -0700728void Output::dirtyEntireOutput() {
729 mState.dirtyRegion.set(mState.bounds);
730}
731
Lloyd Pique66d68602019-02-13 14:23:31 -0800732void Output::chooseCompositionStrategy() {
733 // The base output implementation can only do client composition
734 mState.usesClientComposition = true;
735 mState.usesDeviceComposition = false;
736}
737
Lloyd Pique688abd42019-02-15 15:42:24 -0800738bool Output::getSkipColorTransform() const {
739 return true;
740}
741
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800742compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
743 compositionengine::Output::FrameFences result;
744 if (mState.usesClientComposition) {
745 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
746 }
747 return result;
748}
749
Lloyd Piquefeb73d72018-12-04 17:23:44 -0800750} // namespace impl
751} // namespace android::compositionengine