1 /*
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>
19 #include <compositionengine/CompositionRefreshArgs.h>
20 #include <compositionengine/DisplayCreationArgs.h>
21 #include <compositionengine/DisplaySurface.h>
22 #include <compositionengine/LayerFE.h>
23 #include <compositionengine/impl/Display.h>
24 #include <compositionengine/impl/DisplayColorProfile.h>
25 #include <compositionengine/impl/DumpHelpers.h>
26 #include <compositionengine/impl/OutputLayer.h>
27 #include <compositionengine/impl/RenderSurface.h>
28
29 #include <utils/Trace.h>
30
31 // TODO(b/129481165): remove the #pragma below and fix conversion issues
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wconversion"
34
35 #include "DisplayHardware/HWComposer.h"
36
37 // TODO(b/129481165): remove the #pragma below and fix conversion issues
38 #pragma clang diagnostic pop // ignored "-Wconversion"
39
40 #include "DisplayHardware/PowerAdvisor.h"
41
42 namespace android::compositionengine::impl {
43
createDisplay(const compositionengine::CompositionEngine & compositionEngine,const compositionengine::DisplayCreationArgs & args)44 std::shared_ptr<Display> createDisplay(
45 const compositionengine::CompositionEngine& compositionEngine,
46 const compositionengine::DisplayCreationArgs& args) {
47 return createDisplayTemplated<Display>(compositionEngine, args);
48 }
49
50 Display::~Display() = default;
51
setConfiguration(const compositionengine::DisplayCreationArgs & args)52 void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
53 mId = args.id;
54 mIsVirtual = !args.connectionType;
55 mPowerAdvisor = args.powerAdvisor;
56 editState().isSecure = args.isSecure;
57 editState().displaySpace.bounds = Rect(args.pixels);
58 setLayerStackFilter(args.layerStackId,
59 args.connectionType == ui::DisplayConnectionType::Internal);
60 setName(args.name);
61 }
62
isValid() const63 bool Display::isValid() const {
64 return Output::isValid() && mPowerAdvisor;
65 }
66
getId() const67 DisplayId Display::getId() const {
68 return mId;
69 }
70
isSecure() const71 bool Display::isSecure() const {
72 return getState().isSecure;
73 }
74
isVirtual() const75 bool Display::isVirtual() const {
76 return mIsVirtual;
77 }
78
getDisplayId() const79 std::optional<DisplayId> Display::getDisplayId() const {
80 return mId;
81 }
82
disconnect()83 void Display::disconnect() {
84 if (mIsDisconnected) {
85 return;
86 }
87
88 mIsDisconnected = true;
89
90 if (const auto id = HalDisplayId::tryCast(mId)) {
91 getCompositionEngine().getHwComposer().disconnectDisplay(*id);
92 }
93 }
94
setColorTransform(const compositionengine::CompositionRefreshArgs & args)95 void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
96 Output::setColorTransform(args);
97 const auto halDisplayId = HalDisplayId::tryCast(mId);
98 if (mIsDisconnected || !halDisplayId || CC_LIKELY(!args.colorTransformMatrix)) {
99 return;
100 }
101
102 auto& hwc = getCompositionEngine().getHwComposer();
103 status_t result = hwc.setColorTransform(*halDisplayId, *args.colorTransformMatrix);
104 ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d",
105 to_string(mId).c_str(), result);
106 }
107
setColorProfile(const ColorProfile & colorProfile)108 void Display::setColorProfile(const ColorProfile& colorProfile) {
109 const ui::Dataspace targetDataspace =
110 getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
111 colorProfile.colorSpaceAgnosticDataspace);
112
113 if (colorProfile.mode == getState().colorMode &&
114 colorProfile.dataspace == getState().dataspace &&
115 colorProfile.renderIntent == getState().renderIntent &&
116 targetDataspace == getState().targetDataspace) {
117 return;
118 }
119
120 if (mIsVirtual) {
121 ALOGW("%s: Invalid operation on virtual display", __FUNCTION__);
122 return;
123 }
124
125 Output::setColorProfile(colorProfile);
126
127 const auto physicalId = PhysicalDisplayId::tryCast(mId);
128 LOG_FATAL_IF(!physicalId);
129 getCompositionEngine().getHwComposer().setActiveColorMode(*physicalId, colorProfile.mode,
130 colorProfile.renderIntent);
131 }
132
dump(std::string & out) const133 void Display::dump(std::string& out) const {
134 using android::base::StringAppendF;
135
136 StringAppendF(&out, " Composition Display State: [\"%s\"]", getName().c_str());
137
138 out.append("\n ");
139 dumpVal(out, "isVirtual", mIsVirtual);
140 dumpVal(out, "DisplayId", to_string(mId));
141 out.append("\n");
142
143 Output::dumpBase(out);
144 }
145
createDisplayColorProfile(const DisplayColorProfileCreationArgs & args)146 void Display::createDisplayColorProfile(const DisplayColorProfileCreationArgs& args) {
147 setDisplayColorProfile(compositionengine::impl::createDisplayColorProfile(args));
148 }
149
createRenderSurface(const RenderSurfaceCreationArgs & args)150 void Display::createRenderSurface(const RenderSurfaceCreationArgs& args) {
151 setRenderSurface(
152 compositionengine::impl::createRenderSurface(getCompositionEngine(), *this, args));
153 }
154
createClientCompositionCache(uint32_t cacheSize)155 void Display::createClientCompositionCache(uint32_t cacheSize) {
156 cacheClientCompositionRequests(cacheSize);
157 }
158
createOutputLayer(const sp<compositionengine::LayerFE> & layerFE) const159 std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
160 const sp<compositionengine::LayerFE>& layerFE) const {
161 auto outputLayer = impl::createOutputLayer(*this, layerFE);
162
163 if (const auto halDisplayId = HalDisplayId::tryCast(mId);
164 outputLayer && !mIsDisconnected && halDisplayId) {
165 auto& hwc = getCompositionEngine().getHwComposer();
166 auto hwcLayer = hwc.createLayer(*halDisplayId);
167 ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
168 getName().c_str());
169 outputLayer->setHwcLayer(std::move(hwcLayer));
170 }
171 return outputLayer;
172 }
173
setReleasedLayers(const compositionengine::CompositionRefreshArgs & refreshArgs)174 void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) {
175 Output::setReleasedLayers(refreshArgs);
176
177 if (mIsDisconnected || GpuVirtualDisplayId::tryCast(mId) ||
178 refreshArgs.layersWithQueuedFrames.empty()) {
179 return;
180 }
181
182 // For layers that are being removed from a HWC display, and that have
183 // queued frames, add them to a a list of released layers so we can properly
184 // set a fence.
185 compositionengine::Output::ReleasedLayers releasedLayers;
186
187 // Any non-null entries in the current list of layers are layers that are no
188 // longer going to be visible
189 for (auto* outputLayer : getOutputLayersOrderedByZ()) {
190 if (!outputLayer) {
191 continue;
192 }
193
194 compositionengine::LayerFE* layerFE = &outputLayer->getLayerFE();
195 const bool hasQueuedFrames =
196 std::any_of(refreshArgs.layersWithQueuedFrames.cbegin(),
197 refreshArgs.layersWithQueuedFrames.cend(),
198 [layerFE](sp<compositionengine::LayerFE> layerWithQueuedFrames) {
199 return layerFE == layerWithQueuedFrames.get();
200 });
201
202 if (hasQueuedFrames) {
203 releasedLayers.emplace_back(layerFE);
204 }
205 }
206
207 setReleasedLayers(std::move(releasedLayers));
208 }
209
chooseCompositionStrategy()210 void Display::chooseCompositionStrategy() {
211 ATRACE_CALL();
212 ALOGV(__FUNCTION__);
213
214 if (mIsDisconnected) {
215 return;
216 }
217
218 // Default to the base settings -- client composition only.
219 Output::chooseCompositionStrategy();
220
221 // If we don't have a HWC display, then we are done.
222 const auto halDisplayId = HalDisplayId::tryCast(mId);
223 if (!halDisplayId) {
224 return;
225 }
226
227 // Get any composition changes requested by the HWC device, and apply them.
228 std::optional<android::HWComposer::DeviceRequestedChanges> changes;
229 auto& hwc = getCompositionEngine().getHwComposer();
230 if (status_t result =
231 hwc.getDeviceCompositionChanges(*halDisplayId, anyLayersRequireClientComposition(),
232 getState().earliestPresentTime,
233 getState().previousPresentFence, &changes);
234 result != NO_ERROR) {
235 ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
236 strerror(-result));
237 return;
238 }
239 if (changes) {
240 applyChangedTypesToLayers(changes->changedTypes);
241 applyDisplayRequests(changes->displayRequests);
242 applyLayerRequestsToLayers(changes->layerRequests);
243 applyClientTargetRequests(changes->clientTargetProperty);
244 }
245
246 // Determine what type of composition we are doing from the final state
247 auto& state = editState();
248 state.usesClientComposition = anyLayersRequireClientComposition();
249 state.usesDeviceComposition = !allLayersRequireClientComposition();
250 }
251
getSkipColorTransform() const252 bool Display::getSkipColorTransform() const {
253 const auto& hwc = getCompositionEngine().getHwComposer();
254 if (const auto halDisplayId = HalDisplayId::tryCast(mId)) {
255 return hwc.hasDisplayCapability(*halDisplayId,
256 hal::DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
257 }
258
259 return hwc.hasCapability(hal::Capability::SKIP_CLIENT_COLOR_TRANSFORM);
260 }
261
anyLayersRequireClientComposition() const262 bool Display::anyLayersRequireClientComposition() const {
263 const auto layers = getOutputLayersOrderedByZ();
264 return std::any_of(layers.begin(), layers.end(),
265 [](const auto& layer) { return layer->requiresClientComposition(); });
266 }
267
allLayersRequireClientComposition() const268 bool Display::allLayersRequireClientComposition() const {
269 const auto layers = getOutputLayersOrderedByZ();
270 return std::all_of(layers.begin(), layers.end(),
271 [](const auto& layer) { return layer->requiresClientComposition(); });
272 }
273
applyChangedTypesToLayers(const ChangedTypes & changedTypes)274 void Display::applyChangedTypesToLayers(const ChangedTypes& changedTypes) {
275 if (changedTypes.empty()) {
276 return;
277 }
278
279 for (auto* layer : getOutputLayersOrderedByZ()) {
280 auto hwcLayer = layer->getHwcLayer();
281 if (!hwcLayer) {
282 continue;
283 }
284
285 if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
286 layer->applyDeviceCompositionTypeChange(
287 static_cast<Hwc2::IComposerClient::Composition>(it->second));
288 }
289 }
290 }
291
applyDisplayRequests(const DisplayRequests & displayRequests)292 void Display::applyDisplayRequests(const DisplayRequests& displayRequests) {
293 auto& state = editState();
294 state.flipClientTarget = (static_cast<uint32_t>(displayRequests) &
295 static_cast<uint32_t>(hal::DisplayRequest::FLIP_CLIENT_TARGET)) != 0;
296 // Note: HWC2::DisplayRequest::WriteClientTargetToOutput is currently ignored.
297 }
298
applyLayerRequestsToLayers(const LayerRequests & layerRequests)299 void Display::applyLayerRequestsToLayers(const LayerRequests& layerRequests) {
300 for (auto* layer : getOutputLayersOrderedByZ()) {
301 layer->prepareForDeviceLayerRequests();
302
303 auto hwcLayer = layer->getHwcLayer();
304 if (!hwcLayer) {
305 continue;
306 }
307
308 if (auto it = layerRequests.find(hwcLayer); it != layerRequests.end()) {
309 layer->applyDeviceLayerRequest(
310 static_cast<Hwc2::IComposerClient::LayerRequest>(it->second));
311 }
312 }
313 }
314
applyClientTargetRequests(const ClientTargetProperty & clientTargetProperty)315 void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty) {
316 if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
317 return;
318 }
319
320 editState().dataspace = clientTargetProperty.dataspace;
321 getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
322 getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
323 }
324
presentAndGetFrameFences()325 compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
326 auto fences = impl::Output::presentAndGetFrameFences();
327
328 const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
329 if (mIsDisconnected || !halDisplayIdOpt) {
330 return fences;
331 }
332
333 auto& hwc = getCompositionEngine().getHwComposer();
334 hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime,
335 getState().previousPresentFence);
336
337 fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
338
339 // TODO(b/121291683): Change HWComposer call to return entire map
340 for (const auto* layer : getOutputLayersOrderedByZ()) {
341 auto hwcLayer = layer->getHwcLayer();
342 if (!hwcLayer) {
343 continue;
344 }
345
346 fences.layerFences.emplace(hwcLayer, hwc.getLayerReleaseFence(*halDisplayIdOpt, hwcLayer));
347 }
348
349 hwc.clearReleaseFences(*halDisplayIdOpt);
350
351 return fences;
352 }
353
setExpensiveRenderingExpected(bool enabled)354 void Display::setExpensiveRenderingExpected(bool enabled) {
355 Output::setExpensiveRenderingExpected(enabled);
356
357 if (mPowerAdvisor && !GpuVirtualDisplayId::tryCast(mId)) {
358 mPowerAdvisor->setExpensiveRenderingExpected(mId, enabled);
359 }
360 }
361
finishFrame(const compositionengine::CompositionRefreshArgs & refreshArgs)362 void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
363 // We only need to actually compose the display if:
364 // 1) It is being handled by hardware composer, which may need this to
365 // keep its virtual display state machine in sync, or
366 // 2) There is work to be done (the dirty region isn't empty)
367 if (GpuVirtualDisplayId::tryCast(mId) &&
368 getDirtyRegion(refreshArgs.repaintEverything).isEmpty()) {
369 ALOGV("Skipping display composition");
370 return;
371 }
372
373 impl::Output::finishFrame(refreshArgs);
374 }
375
376 } // namespace android::compositionengine::impl
377