blob: 8b156f8e090bbb25bddca13e639335f54a35845d [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
117void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace,
Lloyd Piquef5275482019-01-29 18:42:42 -0800118 ui::RenderIntent renderIntent,
119 ui::Dataspace colorSpaceAgnosticDataspace) {
120 ui::Dataspace targetDataspace =
121 getDisplayColorProfile()->getTargetDataspace(mode, dataspace,
122 colorSpaceAgnosticDataspace);
123
Lloyd Piqueef958122019-02-05 18:00:12 -0800124 if (mState.colorMode == mode && mState.dataspace == dataspace &&
Lloyd Piquef5275482019-01-29 18:42:42 -0800125 mState.renderIntent == renderIntent && mState.targetDataspace == targetDataspace) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800126 return;
127 }
128
Lloyd Pique32cbe282018-10-19 13:09:22 -0700129 mState.colorMode = mode;
130 mState.dataspace = dataspace;
131 mState.renderIntent = renderIntent;
Lloyd Piquef5275482019-01-29 18:42:42 -0800132 mState.targetDataspace = targetDataspace;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700133
Lloyd Pique31cb2942018-10-19 17:23:03 -0700134 mRenderSurface->setBufferDataspace(dataspace);
135
Lloyd Pique32cbe282018-10-19 13:09:22 -0700136 ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
137 decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(),
138 renderIntent);
Lloyd Piqueef958122019-02-05 18:00:12 -0800139
140 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700141}
142
143void Output::dump(std::string& out) const {
144 using android::base::StringAppendF;
145
146 StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str());
147
148 out.append("\n ");
149
150 dumpBase(out);
151}
152
153void Output::dumpBase(std::string& out) const {
154 mState.dump(out);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700155
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700156 if (mDisplayColorProfile) {
157 mDisplayColorProfile->dump(out);
158 } else {
159 out.append(" No display color profile!\n");
160 }
161
Lloyd Pique31cb2942018-10-19 17:23:03 -0700162 if (mRenderSurface) {
163 mRenderSurface->dump(out);
164 } else {
165 out.append(" No render surface!\n");
166 }
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800167
Lloyd Pique207def92019-02-28 16:09:52 -0800168 android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800169 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
170 if (!outputLayer) {
171 continue;
172 }
173 outputLayer->dump(out);
174 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700175}
176
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700177compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
178 return mDisplayColorProfile.get();
179}
180
181void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
182 mDisplayColorProfile = std::move(mode);
183}
184
185void Output::setDisplayColorProfileForTest(
186 std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
187 mDisplayColorProfile = std::move(mode);
188}
189
Lloyd Pique31cb2942018-10-19 17:23:03 -0700190compositionengine::RenderSurface* Output::getRenderSurface() const {
191 return mRenderSurface.get();
192}
193
194void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
195 mRenderSurface = std::move(surface);
196 mState.bounds = Rect(mRenderSurface->getSize());
197
198 dirtyEntireOutput();
199}
200
201void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
202 mRenderSurface = std::move(surface);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700203}
204
205const OutputCompositionState& Output::getState() const {
206 return mState;
207}
208
209OutputCompositionState& Output::editState() {
210 return mState;
211}
212
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000213Region Output::getDirtyRegion(bool repaintEverything) const {
214 Region dirty(mState.viewport);
215 if (!repaintEverything) {
216 dirty.andSelf(mState.dirtyRegion);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700217 }
218 return dirty;
219}
220
Lloyd Piqueef36b002019-01-23 17:52:04 -0800221bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
222 // The layerStackId's must match, and also the layer must not be internal
223 // only when not on an internal output.
224 return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700225}
226
Lloyd Piquecc01a452018-12-04 17:24:00 -0800227compositionengine::OutputLayer* Output::getOutputLayerForLayer(
228 compositionengine::Layer* layer) const {
229 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
230 if (outputLayer && &outputLayer->getLayer() == layer) {
231 return outputLayer.get();
232 }
233 }
234 return nullptr;
235}
236
237std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
Lloyd Pique07e33212018-12-18 16:33:37 -0800238 std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
239 sp<compositionengine::LayerFE> layerFE) {
Lloyd Piquecc01a452018-12-04 17:24:00 -0800240 for (auto& outputLayer : mOutputLayersOrderedByZ) {
241 if (outputLayer && &outputLayer->getLayer() == layer.get()) {
242 return std::move(outputLayer);
243 }
244 }
Lloyd Pique07e33212018-12-18 16:33:37 -0800245 return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800246}
247
248void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
249 mOutputLayersOrderedByZ = std::move(layers);
250}
251
252const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
253 return mOutputLayersOrderedByZ;
254}
255
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800256void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
257 mReleasedLayers = std::move(layers);
258}
259
260Output::ReleasedLayers Output::takeReleasedLayers() {
261 return std::move(mReleasedLayers);
262}
263
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800264void Output::beginFrame() {
265 const bool dirty = !getDirtyRegion(false).isEmpty();
266 const bool empty = mOutputLayersOrderedByZ.empty();
267 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
268
269 // If nothing has changed (!dirty), don't recompose.
270 // If something changed, but we don't currently have any visible layers,
271 // and didn't when we last did a composition, then skip it this time.
272 // The second rule does two things:
273 // - When all layers are removed from a display, we'll emit one black
274 // frame, then nothing more until we get new layers.
275 // - When a display is created with a private layer stack, we won't
276 // emit any black frames until a layer is added to the layer stack.
277 const bool mustRecompose = dirty && !(empty && wasEmpty);
278
279 const char flagPrefix[] = {'-', '+'};
280 static_cast<void>(flagPrefix);
281 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
282 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
283 flagPrefix[empty], flagPrefix[wasEmpty]);
284
285 mRenderSurface->beginFrame(mustRecompose);
286
287 if (mustRecompose) {
288 mState.lastCompositionHadVisibleLayers = !empty;
289 }
290}
291
Lloyd Pique66d68602019-02-13 14:23:31 -0800292void Output::prepareFrame() {
293 ATRACE_CALL();
294 ALOGV(__FUNCTION__);
295
296 if (!mState.isEnabled) {
297 return;
298 }
299
300 chooseCompositionStrategy();
301
302 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
303}
304
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800305void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
306 if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
307 return;
308 }
309
310 if (mState.isEnabled) {
311 // transform the dirty region into this screen's coordinate space
312 const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
313 if (!dirtyRegion.isEmpty()) {
314 base::unique_fd readyFence;
315 // redraw the whole screen
Lloyd Piqued3d69882019-02-28 16:03:46 -0800316 static_cast<void>(composeSurfaces(dirtyRegion));
Lloyd Piquef8cf14d2019-02-28 16:03:12 -0800317
318 mRenderSurface->queueBuffer(std::move(readyFence));
319 }
320 }
321
322 postFramebuffer();
323
324 std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
325
326 prepareFrame();
327}
328
Lloyd Piqued3d69882019-02-28 16:03:46 -0800329void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
330 ATRACE_CALL();
331 ALOGV(__FUNCTION__);
332
333 if (!mState.isEnabled) {
334 return;
335 }
336
337 // Repaint the framebuffer (if needed), getting the optional fence for when
338 // the composition completes.
339 auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
340 if (!optReadyFence) {
341 return;
342 }
343
344 // swap buffers (presentation)
345 mRenderSurface->queueBuffer(std::move(*optReadyFence));
346}
347
348std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800349 ATRACE_CALL();
350 ALOGV(__FUNCTION__);
351
352 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
353 mState.usesClientComposition};
Lloyd Piqued3d69882019-02-28 16:03:46 -0800354 base::unique_fd readyFence;
355
Lloyd Pique688abd42019-02-15 15:42:24 -0800356 if (!hasClientComposition) {
Lloyd Piqued3d69882019-02-28 16:03:46 -0800357 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800358 }
359
360 ALOGV("hasClientComposition");
361
362 auto& renderEngine = mCompositionEngine.getRenderEngine();
363 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
364
365 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700366 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800367 clientCompositionDisplay.clip = mState.scissor;
368 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
369 clientCompositionDisplay.orientation = mState.orientation;
370 clientCompositionDisplay.outputDataspace =
371 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
372 clientCompositionDisplay.maxLuminance =
373 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
374
375 // Compute the global color transform matrix.
376 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
377 clientCompositionDisplay.colorTransform = mState.colorTransformMat;
378 }
379
380 // Note: Updated by generateClientCompositionRequests
381 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
382
383 // Generate the client composition requests for the layers on this output.
384 std::vector<renderengine::LayerSettings> clientCompositionLayers =
385 generateClientCompositionRequests(supportsProtectedContent,
386 clientCompositionDisplay.clearRegion);
387 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
388
389 // If we the display is secure, protected content support is enabled, and at
390 // least one layer has protected content, we need to use a secure back
391 // buffer.
392 if (mState.isSecure && supportsProtectedContent) {
393 bool needsProtected =
394 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
395 [](auto& layer) {
396 return layer->getLayer().getState().frontEnd.hasProtectedContent;
397 });
398 if (needsProtected != renderEngine.isProtected()) {
399 renderEngine.useProtectedContext(needsProtected);
400 }
401 if (needsProtected != mRenderSurface->isProtected() &&
402 needsProtected == renderEngine.isProtected()) {
403 mRenderSurface->setProtected(needsProtected);
404 }
405 }
406
407 base::unique_fd fd;
408 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
409 if (buf == nullptr) {
410 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
411 "client composition for this frame",
412 mName.c_str());
Lloyd Piqued3d69882019-02-28 16:03:46 -0800413 return std::nullopt;
Lloyd Pique688abd42019-02-15 15:42:24 -0800414 }
415
416 // We boost GPU frequency here because there will be color spaces conversion
417 // and it's expensive. We boost the GPU frequency so that GPU composition can
418 // finish in time. We must reset GPU frequency afterwards, because high frequency
419 // consumes extra battery.
420 const bool expensiveRenderingExpected =
421 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
422 if (expensiveRenderingExpected) {
423 setExpensiveRenderingExpected(true);
424 }
425
426 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
427 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
Lloyd Piqued3d69882019-02-28 16:03:46 -0800428 &readyFence);
Lloyd Pique688abd42019-02-15 15:42:24 -0800429
430 if (expensiveRenderingExpected) {
431 setExpensiveRenderingExpected(false);
432 }
433
Lloyd Piqued3d69882019-02-28 16:03:46 -0800434 return readyFence;
Lloyd Pique688abd42019-02-15 15:42:24 -0800435}
436
437std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
438 bool supportsProtectedContent, Region& clearRegion) {
439 std::vector<renderengine::LayerSettings> clientCompositionLayers;
440 ALOGV("Rendering client layers");
441
442 const Region viewportRegion(mState.viewport);
443 const bool useIdentityTransform = false;
444 bool firstLayer = true;
445 // Used when a layer clears part of the buffer.
446 Region dummyRegion;
447
448 for (auto& layer : mOutputLayersOrderedByZ) {
449 const auto& layerState = layer->getState();
450 const auto& layerFEState = layer->getLayer().getState().frontEnd;
451 auto& layerFE = layer->getLayerFE();
452
Lloyd Pique56eba802019-08-28 15:45:25 -0700453 const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800454 ALOGV("Layer: %s", layerFE.getDebugName());
455 if (clip.isEmpty()) {
456 ALOGV(" Skipping for empty clip");
457 firstLayer = false;
458 continue;
459 }
460
461 bool clientComposition = layer->requiresClientComposition();
462
463 // We clear the client target for non-client composed layers if
464 // requested by the HWC. We skip this if the layer is not an opaque
465 // rectangle, as by definition the layer must blend with whatever is
466 // underneath. We also skip the first layer as the buffer target is
467 // guaranteed to start out cleared.
468 bool clearClientComposition =
469 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
470
471 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
472
473 if (clientComposition || clearClientComposition) {
474 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
475 clip,
476 useIdentityTransform,
477 layer->needsFiltering() || mState.needsFiltering,
478 mState.isSecure,
479 supportsProtectedContent,
480 clientComposition ? clearRegion : dummyRegion,
481 };
482 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700483 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800484 auto& layerSettings = *result;
485 layerSettings.source.buffer.buffer = nullptr;
486 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
487 layerSettings.alpha = half(0.0);
488 layerSettings.disableBlending = true;
489 }
490
491 clientCompositionLayers.push_back(*result);
492 }
493 }
494
495 firstLayer = false;
496 }
497
498 return clientCompositionLayers;
499}
500
501void Output::appendRegionFlashRequests(
502 const Region& flashRegion,
503 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
504 if (flashRegion.isEmpty()) {
505 return;
506 }
507
508 renderengine::LayerSettings layerSettings;
509 layerSettings.source.buffer.buffer = nullptr;
510 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
511 layerSettings.alpha = half(1.0);
512
513 for (const auto& rect : flashRegion) {
514 layerSettings.geometry.boundaries = rect.toFloatRect();
515 clientCompositionLayers.push_back(layerSettings);
516 }
517}
518
519void Output::setExpensiveRenderingExpected(bool) {
520 // The base class does nothing with this call.
521}
522
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800523void Output::postFramebuffer() {
524 ATRACE_CALL();
525 ALOGV(__FUNCTION__);
526
527 if (!getState().isEnabled) {
528 return;
529 }
530
Lloyd Piqued3d69882019-02-28 16:03:46 -0800531 mState.dirtyRegion.clear();
532 mRenderSurface->flip();
533
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800534 auto frame = presentAndGetFrameFences();
535
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700536 mRenderSurface->onPresentDisplayCompleted();
537
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800538 for (auto& layer : getOutputLayersOrderedByZ()) {
539 // The layer buffer from the previous frame (if any) is released
540 // by HWC only when the release fence from this frame (if any) is
541 // signaled. Always get the release fence from HWC first.
542 sp<Fence> releaseFence = Fence::NO_FENCE;
543
544 if (auto hwcLayer = layer->getHwcLayer()) {
545 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
546 releaseFence = f->second;
547 }
548 }
549
550 // If the layer was client composited in the previous frame, we
551 // need to merge with the previous client target acquire fence.
552 // Since we do not track that, always merge with the current
553 // client target acquire fence when it is available, even though
554 // this is suboptimal.
555 // TODO(b/121291683): Track previous frame client target acquire fence.
556 if (mState.usesClientComposition) {
557 releaseFence =
558 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
559 }
560
561 layer->getLayerFE().onLayerDisplayed(releaseFence);
562 }
563
564 // We've got a list of layers needing fences, that are disjoint with
565 // getOutputLayersOrderedByZ. The best we can do is to
566 // supply them with the present fence.
567 for (auto& weakLayer : mReleasedLayers) {
568 if (auto layer = weakLayer.promote(); layer != nullptr) {
569 layer->onLayerDisplayed(frame.presentFence);
570 }
571 }
572
573 // Clear out the released layers now that we're done with them.
574 mReleasedLayers.clear();
575}
576
Lloyd Pique32cbe282018-10-19 13:09:22 -0700577void Output::dirtyEntireOutput() {
578 mState.dirtyRegion.set(mState.bounds);
579}
580
Lloyd Pique66d68602019-02-13 14:23:31 -0800581void Output::chooseCompositionStrategy() {
582 // The base output implementation can only do client composition
583 mState.usesClientComposition = true;
584 mState.usesDeviceComposition = false;
585}
586
Lloyd Pique688abd42019-02-15 15:42:24 -0800587bool Output::getSkipColorTransform() const {
588 return true;
589}
590
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800591compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
592 compositionengine::Output::FrameFences result;
593 if (mState.usesClientComposition) {
594 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
595 }
596 return result;
597}
598
Lloyd Piquefeb73d72018-12-04 17:23:44 -0800599} // namespace impl
600} // namespace android::compositionengine