blob: 6878e99b72010a9f36a88c5a8cc1fe2beb416758 [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
17#include <android-base/stringprintf.h>
18#include <compositionengine/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070019#include <compositionengine/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080020#include <compositionengine/LayerFE.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070021#include <compositionengine/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070022#include <compositionengine/impl/Output.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080023#include <compositionengine/impl/OutputLayer.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070024#include <ui/DebugUtils.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080025#include <utils/Trace.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070026
Lloyd Piquefeb73d72018-12-04 17:23:44 -080027namespace android::compositionengine {
28
29Output::~Output() = default;
30
31namespace impl {
Lloyd Pique32cbe282018-10-19 13:09:22 -070032
33Output::Output(const CompositionEngine& compositionEngine)
34 : mCompositionEngine(compositionEngine) {}
35
36Output::~Output() = default;
37
38const CompositionEngine& Output::getCompositionEngine() const {
39 return mCompositionEngine;
40}
41
42bool Output::isValid() const {
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070043 return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
44 mRenderSurface->isValid();
Lloyd Pique32cbe282018-10-19 13:09:22 -070045}
46
47const std::string& Output::getName() const {
48 return mName;
49}
50
51void Output::setName(const std::string& name) {
52 mName = name;
53}
54
55void Output::setCompositionEnabled(bool enabled) {
56 if (mState.isEnabled == enabled) {
57 return;
58 }
59
60 mState.isEnabled = enabled;
61 dirtyEntireOutput();
62}
63
64void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame,
65 const Rect& viewport, const Rect& scissor, bool needsFiltering) {
66 mState.transform = transform;
67 mState.orientation = orientation;
68 mState.scissor = scissor;
69 mState.frame = frame;
70 mState.viewport = viewport;
71 mState.needsFiltering = needsFiltering;
72
73 dirtyEntireOutput();
74}
75
Lloyd Pique31cb2942018-10-19 17:23:03 -070076// TODO(lpique): Rename setSize() once more is moved.
77void Output::setBounds(const ui::Size& size) {
78 mRenderSurface->setDisplaySize(size);
79 // TODO(lpique): Rename mState.size once more is moved.
80 mState.bounds = Rect(mRenderSurface->getSize());
Lloyd Pique32cbe282018-10-19 13:09:22 -070081
82 dirtyEntireOutput();
83}
84
Lloyd Piqueef36b002019-01-23 17:52:04 -080085void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
86 mState.layerStackId = layerStackId;
87 mState.layerStackInternal = isInternal;
Lloyd Pique32cbe282018-10-19 13:09:22 -070088
89 dirtyEntireOutput();
90}
91
92void Output::setColorTransform(const mat4& transform) {
Lloyd Pique77f79a22019-04-29 15:55:40 -070093 if (mState.colorTransformMat == transform) {
94 return;
95 }
96
Lloyd Pique32cbe282018-10-19 13:09:22 -070097 const bool isIdentity = (transform == mat4());
Lloyd Piqueef958122019-02-05 18:00:12 -080098 const auto newColorTransform =
Lloyd Pique32cbe282018-10-19 13:09:22 -070099 isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
Lloyd Piqueef958122019-02-05 18:00:12 -0800100
Lloyd Piqueef958122019-02-05 18:00:12 -0800101 mState.colorTransform = newColorTransform;
Alec Mouric7e8ce82019-04-02 12:28:05 -0700102 mState.colorTransformMat = transform;
Lloyd Piqueef958122019-02-05 18:00:12 -0800103
104 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700105}
106
107void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace,
Lloyd Piquef5275482019-01-29 18:42:42 -0800108 ui::RenderIntent renderIntent,
109 ui::Dataspace colorSpaceAgnosticDataspace) {
110 ui::Dataspace targetDataspace =
111 getDisplayColorProfile()->getTargetDataspace(mode, dataspace,
112 colorSpaceAgnosticDataspace);
113
Lloyd Piqueef958122019-02-05 18:00:12 -0800114 if (mState.colorMode == mode && mState.dataspace == dataspace &&
Lloyd Piquef5275482019-01-29 18:42:42 -0800115 mState.renderIntent == renderIntent && mState.targetDataspace == targetDataspace) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800116 return;
117 }
118
Lloyd Pique32cbe282018-10-19 13:09:22 -0700119 mState.colorMode = mode;
120 mState.dataspace = dataspace;
121 mState.renderIntent = renderIntent;
Lloyd Piquef5275482019-01-29 18:42:42 -0800122 mState.targetDataspace = targetDataspace;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700123
Lloyd Pique31cb2942018-10-19 17:23:03 -0700124 mRenderSurface->setBufferDataspace(dataspace);
125
Lloyd Pique32cbe282018-10-19 13:09:22 -0700126 ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
127 decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(),
128 renderIntent);
Lloyd Piqueef958122019-02-05 18:00:12 -0800129
130 dirtyEntireOutput();
Lloyd Pique32cbe282018-10-19 13:09:22 -0700131}
132
133void Output::dump(std::string& out) const {
134 using android::base::StringAppendF;
135
136 StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str());
137
138 out.append("\n ");
139
140 dumpBase(out);
141}
142
143void Output::dumpBase(std::string& out) const {
144 mState.dump(out);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700145
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700146 if (mDisplayColorProfile) {
147 mDisplayColorProfile->dump(out);
148 } else {
149 out.append(" No display color profile!\n");
150 }
151
Lloyd Pique31cb2942018-10-19 17:23:03 -0700152 if (mRenderSurface) {
153 mRenderSurface->dump(out);
154 } else {
155 out.append(" No render surface!\n");
156 }
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800157
Lloyd Pique207def92019-02-28 16:09:52 -0800158 android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
Lloyd Pique37c2c9b2018-12-04 17:25:10 -0800159 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
160 if (!outputLayer) {
161 continue;
162 }
163 outputLayer->dump(out);
164 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700165}
166
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700167compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
168 return mDisplayColorProfile.get();
169}
170
171void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
172 mDisplayColorProfile = std::move(mode);
173}
174
175void Output::setDisplayColorProfileForTest(
176 std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
177 mDisplayColorProfile = std::move(mode);
178}
179
Lloyd Pique31cb2942018-10-19 17:23:03 -0700180compositionengine::RenderSurface* Output::getRenderSurface() const {
181 return mRenderSurface.get();
182}
183
184void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
185 mRenderSurface = std::move(surface);
186 mState.bounds = Rect(mRenderSurface->getSize());
187
188 dirtyEntireOutput();
189}
190
191void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
192 mRenderSurface = std::move(surface);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700193}
194
195const OutputCompositionState& Output::getState() const {
196 return mState;
197}
198
199OutputCompositionState& Output::editState() {
200 return mState;
201}
202
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000203Region Output::getDirtyRegion(bool repaintEverything) const {
204 Region dirty(mState.viewport);
205 if (!repaintEverything) {
206 dirty.andSelf(mState.dirtyRegion);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700207 }
208 return dirty;
209}
210
Lloyd Piqueef36b002019-01-23 17:52:04 -0800211bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
212 // The layerStackId's must match, and also the layer must not be internal
213 // only when not on an internal output.
214 return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700215}
216
Lloyd Piquecc01a452018-12-04 17:24:00 -0800217compositionengine::OutputLayer* Output::getOutputLayerForLayer(
218 compositionengine::Layer* layer) const {
219 for (const auto& outputLayer : mOutputLayersOrderedByZ) {
220 if (outputLayer && &outputLayer->getLayer() == layer) {
221 return outputLayer.get();
222 }
223 }
224 return nullptr;
225}
226
227std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
Lloyd Pique07e33212018-12-18 16:33:37 -0800228 std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
229 sp<compositionengine::LayerFE> layerFE) {
Lloyd Piquecc01a452018-12-04 17:24:00 -0800230 for (auto& outputLayer : mOutputLayersOrderedByZ) {
231 if (outputLayer && &outputLayer->getLayer() == layer.get()) {
232 return std::move(outputLayer);
233 }
234 }
Lloyd Pique07e33212018-12-18 16:33:37 -0800235 return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800236}
237
238void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
239 mOutputLayersOrderedByZ = std::move(layers);
240}
241
242const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
243 return mOutputLayersOrderedByZ;
244}
245
Lloyd Piquec7ef21b2019-01-29 18:43:00 -0800246void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
247 mReleasedLayers = std::move(layers);
248}
249
250Output::ReleasedLayers Output::takeReleasedLayers() {
251 return std::move(mReleasedLayers);
252}
253
Lloyd Piqued0a92a02019-02-19 17:47:26 -0800254void Output::beginFrame() {
255 const bool dirty = !getDirtyRegion(false).isEmpty();
256 const bool empty = mOutputLayersOrderedByZ.empty();
257 const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
258
259 // If nothing has changed (!dirty), don't recompose.
260 // If something changed, but we don't currently have any visible layers,
261 // and didn't when we last did a composition, then skip it this time.
262 // The second rule does two things:
263 // - When all layers are removed from a display, we'll emit one black
264 // frame, then nothing more until we get new layers.
265 // - When a display is created with a private layer stack, we won't
266 // emit any black frames until a layer is added to the layer stack.
267 const bool mustRecompose = dirty && !(empty && wasEmpty);
268
269 const char flagPrefix[] = {'-', '+'};
270 static_cast<void>(flagPrefix);
271 ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__,
272 mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
273 flagPrefix[empty], flagPrefix[wasEmpty]);
274
275 mRenderSurface->beginFrame(mustRecompose);
276
277 if (mustRecompose) {
278 mState.lastCompositionHadVisibleLayers = !empty;
279 }
280}
281
Lloyd Pique66d68602019-02-13 14:23:31 -0800282void Output::prepareFrame() {
283 ATRACE_CALL();
284 ALOGV(__FUNCTION__);
285
286 if (!mState.isEnabled) {
287 return;
288 }
289
290 chooseCompositionStrategy();
291
292 mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
293}
294
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800295void Output::postFramebuffer() {
296 ATRACE_CALL();
297 ALOGV(__FUNCTION__);
298
299 if (!getState().isEnabled) {
300 return;
301 }
302
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800303 auto frame = presentAndGetFrameFences();
304
Lloyd Pique7d90ba52019-08-08 11:57:53 -0700305 mRenderSurface->onPresentDisplayCompleted();
306
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800307 for (auto& layer : getOutputLayersOrderedByZ()) {
308 // The layer buffer from the previous frame (if any) is released
309 // by HWC only when the release fence from this frame (if any) is
310 // signaled. Always get the release fence from HWC first.
311 sp<Fence> releaseFence = Fence::NO_FENCE;
312
313 if (auto hwcLayer = layer->getHwcLayer()) {
314 if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
315 releaseFence = f->second;
316 }
317 }
318
319 // If the layer was client composited in the previous frame, we
320 // need to merge with the previous client target acquire fence.
321 // Since we do not track that, always merge with the current
322 // client target acquire fence when it is available, even though
323 // this is suboptimal.
324 // TODO(b/121291683): Track previous frame client target acquire fence.
325 if (mState.usesClientComposition) {
326 releaseFence =
327 Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
328 }
329
330 layer->getLayerFE().onLayerDisplayed(releaseFence);
331 }
332
333 // We've got a list of layers needing fences, that are disjoint with
334 // getOutputLayersOrderedByZ. The best we can do is to
335 // supply them with the present fence.
336 for (auto& weakLayer : mReleasedLayers) {
337 if (auto layer = weakLayer.promote(); layer != nullptr) {
338 layer->onLayerDisplayed(frame.presentFence);
339 }
340 }
341
342 // Clear out the released layers now that we're done with them.
343 mReleasedLayers.clear();
344}
345
Lloyd Pique32cbe282018-10-19 13:09:22 -0700346void Output::dirtyEntireOutput() {
347 mState.dirtyRegion.set(mState.bounds);
348}
349
Lloyd Pique66d68602019-02-13 14:23:31 -0800350void Output::chooseCompositionStrategy() {
351 // The base output implementation can only do client composition
352 mState.usesClientComposition = true;
353 mState.usesDeviceComposition = false;
354}
355
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800356compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
357 compositionengine::Output::FrameFences result;
358 if (mState.usesClientComposition) {
359 result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
360 }
361 return result;
362}
363
Lloyd Piquefeb73d72018-12-04 17:23:44 -0800364} // namespace impl
365} // namespace android::compositionengine