blob: 87df85846fe46c44c6f8a5591419f050404cbc18 [file] [log] [blame]
Lloyd Pique45a165a2018-10-19 11:54:47 -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 Pique32cbe282018-10-19 13:09:22 -070017#include <android-base/stringprintf.h>
Lloyd Pique45a165a2018-10-19 11:54:47 -070018#include <compositionengine/CompositionEngine.h>
Lloyd Piqued3d69882019-02-28 16:03:46 -080019#include <compositionengine/CompositionRefreshArgs.h>
Lloyd Pique45a165a2018-10-19 11:54:47 -070020#include <compositionengine/DisplayCreationArgs.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070021#include <compositionengine/DisplaySurface.h>
Lloyd Piquedf336d92019-03-07 21:38:42 -080022#include <compositionengine/LayerFE.h>
Lloyd Pique45a165a2018-10-19 11:54:47 -070023#include <compositionengine/impl/Display.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070024#include <compositionengine/impl/DisplayColorProfile.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070025#include <compositionengine/impl/DumpHelpers.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080026#include <compositionengine/impl/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070027#include <compositionengine/impl/RenderSurface.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080028#include <utils/Trace.h>
Lloyd Pique45a165a2018-10-19 11:54:47 -070029
30#include "DisplayHardware/HWComposer.h"
Lloyd Pique688abd42019-02-15 15:42:24 -080031#include "DisplayHardware/PowerAdvisor.h"
Lloyd Pique45a165a2018-10-19 11:54:47 -070032
33namespace android::compositionengine::impl {
34
Lloyd Pique35fca9d2019-02-13 14:24:11 -080035std::shared_ptr<Display> createDisplay(
Lloyd Pique45a165a2018-10-19 11:54:47 -070036 const compositionengine::CompositionEngine& compositionEngine,
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070037 const compositionengine::DisplayCreationArgs& args) {
38 return createDisplayTemplated<Display>(compositionEngine, args);
Lloyd Pique45a165a2018-10-19 11:54:47 -070039}
40
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070041Display::Display(const DisplayCreationArgs& args)
42 : mIsVirtual(args.isVirtual), mId(args.displayId), mPowerAdvisor(args.powerAdvisor) {}
Lloyd Pique45a165a2018-10-19 11:54:47 -070043
44Display::~Display() = default;
45
46const std::optional<DisplayId>& Display::getId() const {
47 return mId;
48}
49
50bool Display::isSecure() const {
Lloyd Pique32cbe282018-10-19 13:09:22 -070051 return getState().isSecure;
Lloyd Pique45a165a2018-10-19 11:54:47 -070052}
53
54bool Display::isVirtual() const {
55 return mIsVirtual;
56}
57
58void Display::disconnect() {
59 if (!mId) {
60 return;
61 }
62
Lloyd Pique32cbe282018-10-19 13:09:22 -070063 auto& hwc = getCompositionEngine().getHwComposer();
Lloyd Pique45a165a2018-10-19 11:54:47 -070064 hwc.disconnectDisplay(*mId);
65 mId.reset();
66}
67
Lloyd Pique3eb1b212019-03-07 21:15:40 -080068void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
69 Output::setColorTransform(args);
70
71 if (!mId || CC_LIKELY(!args.colorTransformMatrix)) {
72 return;
73 }
Lloyd Pique32cbe282018-10-19 13:09:22 -070074
75 auto& hwc = getCompositionEngine().getHwComposer();
Lloyd Pique3eb1b212019-03-07 21:15:40 -080076 status_t result = hwc.setColorTransform(*mId, *args.colorTransformMatrix);
Lloyd Pique32cbe282018-10-19 13:09:22 -070077 ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d",
78 mId ? to_string(*mId).c_str() : "", result);
79}
80
Lloyd Pique6a3b4462019-03-07 20:58:12 -080081void Display::setColorProfile(const ColorProfile& colorProfile) {
82 const ui::Dataspace targetDataspace =
83 getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
84 colorProfile.colorSpaceAgnosticDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -080085
Lloyd Pique6a3b4462019-03-07 20:58:12 -080086 if (colorProfile.mode == getState().colorMode &&
87 colorProfile.dataspace == getState().dataspace &&
88 colorProfile.renderIntent == getState().renderIntent &&
89 targetDataspace == getState().targetDataspace) {
Lloyd Pique32cbe282018-10-19 13:09:22 -070090 return;
91 }
92
93 if (mIsVirtual) {
94 ALOGW("%s: Invalid operation on virtual display", __FUNCTION__);
95 return;
96 }
97
Lloyd Pique6a3b4462019-03-07 20:58:12 -080098 Output::setColorProfile(colorProfile);
Lloyd Pique32cbe282018-10-19 13:09:22 -070099
100 auto& hwc = getCompositionEngine().getHwComposer();
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800101 hwc.setActiveColorMode(*mId, colorProfile.mode, colorProfile.renderIntent);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700102}
103
104void Display::dump(std::string& out) const {
105 using android::base::StringAppendF;
106
107 StringAppendF(&out, " Composition Display State: [\"%s\"]", getName().c_str());
108
109 out.append("\n ");
110
111 dumpVal(out, "isVirtual", mIsVirtual);
112 if (mId) {
113 dumpVal(out, "hwcId", to_string(*mId));
114 } else {
115 StringAppendF(&out, "no hwcId, ");
116 }
117
118 out.append("\n");
119
120 Output::dumpBase(out);
121}
122
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700123void Display::createDisplayColorProfile(const DisplayColorProfileCreationArgs& args) {
124 setDisplayColorProfile(compositionengine::impl::createDisplayColorProfile(args));
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700125}
126
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700127void Display::createRenderSurface(const RenderSurfaceCreationArgs& args) {
128 setRenderSurface(
129 compositionengine::impl::createRenderSurface(getCompositionEngine(), *this, args));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700130}
131
Lloyd Piquedf336d92019-03-07 21:38:42 -0800132std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
133 const std::shared_ptr<compositionengine::Layer>& layer,
134 const sp<compositionengine::LayerFE>& layerFE) const {
135 auto result = Output::createOutputLayer(layer, layerFE);
136
137 if (result && mId) {
138 auto& hwc = getCompositionEngine().getHwComposer();
139 auto displayId = *mId;
140 // Note: For the moment we ensure it is safe to take a reference to the
141 // HWComposer implementation by destroying all the OutputLayers (and
142 // hence the HWC2::Layers they own) before setting a new HWComposer. See
143 // for example SurfaceFlinger::updateVrFlinger().
144 // TODO(b/121291683): Make this safer.
145 auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(displayId),
146 [&hwc, displayId](HWC2::Layer* layer) {
147 hwc.destroyLayer(displayId, layer);
148 });
149 ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
150 getName().c_str());
151 result->setHwcLayer(std::move(hwcLayer));
152 }
153 return result;
154}
155
Lloyd Piquec29e4c62019-03-07 21:48:19 -0800156void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) {
157 Output::setReleasedLayers(refreshArgs);
158
159 if (!mId || refreshArgs.layersWithQueuedFrames.empty()) {
160 return;
161 }
162
163 // For layers that are being removed from a HWC display, and that have
164 // queued frames, add them to a a list of released layers so we can properly
165 // set a fence.
166 compositionengine::Output::ReleasedLayers releasedLayers;
167
168 // Any non-null entries in the current list of layers are layers that are no
169 // longer going to be visible
170 for (auto& layer : getOutputLayersOrderedByZ()) {
171 if (!layer) {
172 continue;
173 }
174
175 sp<compositionengine::LayerFE> layerFE(&layer->getLayerFE());
176 const bool hasQueuedFrames =
177 std::find(refreshArgs.layersWithQueuedFrames.cbegin(),
178 refreshArgs.layersWithQueuedFrames.cend(),
179 &layer->getLayer()) != refreshArgs.layersWithQueuedFrames.cend();
180
181 if (hasQueuedFrames) {
182 releasedLayers.emplace_back(layerFE);
183 }
184 }
185
186 setReleasedLayers(std::move(releasedLayers));
187}
188
Lloyd Pique66d68602019-02-13 14:23:31 -0800189void Display::chooseCompositionStrategy() {
190 ATRACE_CALL();
191 ALOGV(__FUNCTION__);
192
193 // Default to the base settings -- client composition only.
194 Output::chooseCompositionStrategy();
195
196 // If we don't have a HWC display, then we are done
197 if (!mId) {
198 return;
199 }
200
201 // Get any composition changes requested by the HWC device, and apply them.
202 std::optional<android::HWComposer::DeviceRequestedChanges> changes;
203 auto& hwc = getCompositionEngine().getHwComposer();
204 if (status_t result = hwc.getDeviceCompositionChanges(*mId, anyLayersRequireClientComposition(),
205 &changes);
206 result != NO_ERROR) {
207 ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
208 strerror(-result));
209 return;
210 }
211 if (changes) {
212 applyChangedTypesToLayers(changes->changedTypes);
213 applyDisplayRequests(changes->displayRequests);
214 applyLayerRequestsToLayers(changes->layerRequests);
215 }
216
217 // Determine what type of composition we are doing from the final state
218 auto& state = editState();
219 state.usesClientComposition = anyLayersRequireClientComposition();
220 state.usesDeviceComposition = !allLayersRequireClientComposition();
221}
222
Lloyd Pique688abd42019-02-15 15:42:24 -0800223bool Display::getSkipColorTransform() const {
224 if (!mId) {
225 return false;
226 }
227
228 auto& hwc = getCompositionEngine().getHwComposer();
229 return hwc.hasDisplayCapability(*mId, HWC2::DisplayCapability::SkipClientColorTransform);
230}
231
Lloyd Pique66d68602019-02-13 14:23:31 -0800232bool Display::anyLayersRequireClientComposition() const {
233 const auto& layers = getOutputLayersOrderedByZ();
234 return std::any_of(layers.cbegin(), layers.cend(),
235 [](const auto& layer) { return layer->requiresClientComposition(); });
236}
237
238bool Display::allLayersRequireClientComposition() const {
239 const auto& layers = getOutputLayersOrderedByZ();
240 return std::all_of(layers.cbegin(), layers.cend(),
241 [](const auto& layer) { return layer->requiresClientComposition(); });
242}
243
244void Display::applyChangedTypesToLayers(const ChangedTypes& changedTypes) {
245 if (changedTypes.empty()) {
246 return;
247 }
248
249 for (auto& layer : getOutputLayersOrderedByZ()) {
250 auto hwcLayer = layer->getHwcLayer();
251 if (!hwcLayer) {
252 continue;
253 }
254
255 if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
256 layer->applyDeviceCompositionTypeChange(
257 static_cast<Hwc2::IComposerClient::Composition>(it->second));
258 }
259 }
260}
261
262void Display::applyDisplayRequests(const DisplayRequests& displayRequests) {
263 auto& state = editState();
264 state.flipClientTarget = (static_cast<uint32_t>(displayRequests) &
265 static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0;
266 // Note: HWC2::DisplayRequest::WriteClientTargetToOutput is currently ignored.
267}
268
269void Display::applyLayerRequestsToLayers(const LayerRequests& layerRequests) {
270 for (auto& layer : getOutputLayersOrderedByZ()) {
271 layer->prepareForDeviceLayerRequests();
272
273 auto hwcLayer = layer->getHwcLayer();
274 if (!hwcLayer) {
275 continue;
276 }
277
278 if (auto it = layerRequests.find(hwcLayer); it != layerRequests.end()) {
279 layer->applyDeviceLayerRequest(
280 static_cast<Hwc2::IComposerClient::LayerRequest>(it->second));
281 }
282 }
283}
284
Lloyd Pique35fca9d2019-02-13 14:24:11 -0800285compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
286 auto result = impl::Output::presentAndGetFrameFences();
287
288 if (!mId) {
289 return result;
290 }
291
292 auto& hwc = getCompositionEngine().getHwComposer();
293 hwc.presentAndGetReleaseFences(*mId);
294
295 result.presentFence = hwc.getPresentFence(*mId);
296
297 // TODO(b/121291683): Change HWComposer call to return entire map
298 for (const auto& layer : getOutputLayersOrderedByZ()) {
299 auto hwcLayer = layer->getHwcLayer();
300 if (!hwcLayer) {
301 continue;
302 }
303
304 result.layerFences.emplace(hwcLayer, hwc.getLayerReleaseFence(*mId, hwcLayer));
305 }
306
307 hwc.clearReleaseFences(*mId);
308
309 return result;
310}
311
Lloyd Pique688abd42019-02-15 15:42:24 -0800312void Display::setExpensiveRenderingExpected(bool enabled) {
313 Output::setExpensiveRenderingExpected(enabled);
314
315 if (mPowerAdvisor && mId) {
316 mPowerAdvisor->setExpensiveRenderingExpected(*mId, enabled);
317 }
318}
319
Lloyd Piqued3d69882019-02-28 16:03:46 -0800320void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
321 // We only need to actually compose the display if:
322 // 1) It is being handled by hardware composer, which may need this to
323 // keep its virtual display state machine in sync, or
324 // 2) There is work to be done (the dirty region isn't empty)
325 if (!mId) {
326 if (getDirtyRegion(refreshArgs.repaintEverything).isEmpty()) {
327 ALOGV("Skipping display composition");
328 return;
329 }
330 }
331
332 impl::Output::finishFrame(refreshArgs);
333}
334
Lloyd Pique45a165a2018-10-19 11:54:47 -0700335} // namespace android::compositionengine::impl