blob: 10534f4de321a5304cfea8c0519f92f45d71abfd [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
316 composeSurfaces(dirtyRegion, &readyFence);
317
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 Pique688abd42019-02-15 15:42:24 -0800329bool Output::composeSurfaces(const Region& debugRegion, base::unique_fd* readyFence) {
330 ATRACE_CALL();
331 ALOGV(__FUNCTION__);
332
333 const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
334 mState.usesClientComposition};
335 if (!hasClientComposition) {
336 return true;
337 }
338
339 ALOGV("hasClientComposition");
340
341 auto& renderEngine = mCompositionEngine.getRenderEngine();
342 const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
343
344 renderengine::DisplaySettings clientCompositionDisplay;
Lloyd Pique810b0302019-08-14 16:09:32 -0700345 clientCompositionDisplay.physicalDisplay = mState.scissor;
Lloyd Pique688abd42019-02-15 15:42:24 -0800346 clientCompositionDisplay.clip = mState.scissor;
347 clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
348 clientCompositionDisplay.orientation = mState.orientation;
349 clientCompositionDisplay.outputDataspace =
350 mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
351 clientCompositionDisplay.maxLuminance =
352 mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
353
354 // Compute the global color transform matrix.
355 if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
356 clientCompositionDisplay.colorTransform = mState.colorTransformMat;
357 }
358
359 // Note: Updated by generateClientCompositionRequests
360 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
361
362 // Generate the client composition requests for the layers on this output.
363 std::vector<renderengine::LayerSettings> clientCompositionLayers =
364 generateClientCompositionRequests(supportsProtectedContent,
365 clientCompositionDisplay.clearRegion);
366 appendRegionFlashRequests(debugRegion, clientCompositionLayers);
367
368 // If we the display is secure, protected content support is enabled, and at
369 // least one layer has protected content, we need to use a secure back
370 // buffer.
371 if (mState.isSecure && supportsProtectedContent) {
372 bool needsProtected =
373 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
374 [](auto& layer) {
375 return layer->getLayer().getState().frontEnd.hasProtectedContent;
376 });
377 if (needsProtected != renderEngine.isProtected()) {
378 renderEngine.useProtectedContext(needsProtected);
379 }
380 if (needsProtected != mRenderSurface->isProtected() &&
381 needsProtected == renderEngine.isProtected()) {
382 mRenderSurface->setProtected(needsProtected);
383 }
384 }
385
386 base::unique_fd fd;
387 sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
388 if (buf == nullptr) {
389 ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
390 "client composition for this frame",
391 mName.c_str());
392 return false;
393 }
394
395 // We boost GPU frequency here because there will be color spaces conversion
396 // and it's expensive. We boost the GPU frequency so that GPU composition can
397 // finish in time. We must reset GPU frequency afterwards, because high frequency
398 // consumes extra battery.
399 const bool expensiveRenderingExpected =
400 clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
401 if (expensiveRenderingExpected) {
402 setExpensiveRenderingExpected(true);
403 }
404
405 renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
406 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
407 readyFence);
408
409 if (expensiveRenderingExpected) {
410 setExpensiveRenderingExpected(false);
411 }
412
413 return true;
414}
415
416std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
417 bool supportsProtectedContent, Region& clearRegion) {
418 std::vector<renderengine::LayerSettings> clientCompositionLayers;
419 ALOGV("Rendering client layers");
420
421 const Region viewportRegion(mState.viewport);
422 const bool useIdentityTransform = false;
423 bool firstLayer = true;
424 // Used when a layer clears part of the buffer.
425 Region dummyRegion;
426
427 for (auto& layer : mOutputLayersOrderedByZ) {
428 const auto& layerState = layer->getState();
429 const auto& layerFEState = layer->getLayer().getState().frontEnd;
430 auto& layerFE = layer->getLayerFE();
431
Lloyd Pique56eba802019-08-28 15:45:25 -0700432 const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion));
Lloyd Pique688abd42019-02-15 15:42:24 -0800433 ALOGV("Layer: %s", layerFE.getDebugName());
434 if (clip.isEmpty()) {
435 ALOGV(" Skipping for empty clip");
436 firstLayer = false;
437 continue;
438 }
439
440 bool clientComposition = layer->requiresClientComposition();
441
442 // We clear the client target for non-client composed layers if
443 // requested by the HWC. We skip this if the layer is not an opaque
444 // rectangle, as by definition the layer must blend with whatever is
445 // underneath. We also skip the first layer as the buffer target is
446 // guaranteed to start out cleared.
447 bool clearClientComposition =
448 layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
449
450 ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
451
452 if (clientComposition || clearClientComposition) {
453 compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
454 clip,
455 useIdentityTransform,
456 layer->needsFiltering() || mState.needsFiltering,
457 mState.isSecure,
458 supportsProtectedContent,
459 clientComposition ? clearRegion : dummyRegion,
460 };
461 if (auto result = layerFE.prepareClientComposition(targetSettings)) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700462 if (!clientComposition) {
Lloyd Pique688abd42019-02-15 15:42:24 -0800463 auto& layerSettings = *result;
464 layerSettings.source.buffer.buffer = nullptr;
465 layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
466 layerSettings.alpha = half(0.0);
467 layerSettings.disableBlending = true;
468 }
469
470 clientCompositionLayers.push_back(*result);
471 }
472 }
473
474 firstLayer = false;
475 }
476
477 return clientCompositionLayers;
478}
479
480void Output::appendRegionFlashRequests(
481 const Region& flashRegion,
482 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
483 if (flashRegion.isEmpty()) {
484 return;
485 }
486
487 renderengine::LayerSettings layerSettings;
488 layerSettings.source.buffer.buffer = nullptr;
489 layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
490 layerSettings.alpha = half(1.0);
491
492 for (const auto& rect : flashRegion) {
493 layerSettings.geometry.boundaries = rect.toFloatRect();
494 clientCompositionLayers.push_back(layerSettings);
495 }
496}
497
498void Output::setExpensiveRenderingExpected(bool) {
499 // The base class does nothing with this call.
500}
501
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800502void Output::postFramebuffer() {
503 ATRACE_CALL();
504 ALOGV(__FUNCTION__);
505
506 if (!getState().isEnabled) {
507 return;
508 }
509
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800510 auto frame = presentAndGetFrameFences();
511
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700512 mRenderSurface->onPresentDisplayCompleted();
513
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800514 for (auto& layer : getOutputLayersOrderedByZ()) {
515 // The layer buffer from the previous frame (if any) is released
516 // by HWC only when the release fence from this frame (if any) is
517 // signaled. Always get the release fence from HWC first.
518 sp<Fence> releaseFence = Fence::NO_FENCE;
519
520 if (auto hwcLayer = layer->getHwcLayer()) {
521 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
522 releaseFence = f->second;
523 }
524 }
525
526 // If the layer was client composited in the previous frame, we
527 // need to merge with the previous client target acquire fence.
528 // Since we do not track that, always merge with the current
529 // client target acquire fence when it is available, even though
530 // this is suboptimal.
531 // TODO(b/121291683): Track previous frame client target acquire fence.
532 if (mState.usesClientComposition) {
533 releaseFence =
534 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
535 }
536
537 layer->getLayerFE().onLayerDisplayed(releaseFence);
538 }
539
540 // We've got a list of layers needing fences, that are disjoint with
541 // getOutputLayersOrderedByZ. The best we can do is to
542 // supply them with the present fence.
543 for (auto& weakLayer : mReleasedLayers) {
544 if (auto layer = weakLayer.promote(); layer != nullptr) {
545 layer->onLayerDisplayed(frame.presentFence);
546 }
547 }
548
549 // Clear out the released layers now that we're done with them.
550 mReleasedLayers.clear();
551}
552
Lloyd Pique32cbe282018-10-19 13:09:22 -0700553void Output::dirtyEntireOutput() {
554 mState.dirtyRegion.set(mState.bounds);
555}
556
Lloyd Pique66d68602019-02-13 14:23:31 -0800557void Output::chooseCompositionStrategy() {
558 // The base output implementation can only do client composition
559 mState.usesClientComposition = true;
560 mState.usesDeviceComposition = false;
561}
562
Lloyd Pique688abd42019-02-15 15:42:24 -0800563bool Output::getSkipColorTransform() const {
564 return true;
565}
566
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800567compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
568 compositionengine::Output::FrameFences result;
569 if (mState.usesClientComposition) {
570 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
571 }
572 return result;
573}
574
Lloyd Piquefeb73d72018-12-04 17:23:44 -0800575} // namespace impl
576} // namespace android::compositionengine