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 using aidl::android::hardware::graphics::composer3::Capability;
43 using aidl::android::hardware::graphics::composer3::DisplayCapability;
44
45 namespace android::compositionengine::impl {
46
createDisplay(const compositionengine::CompositionEngine & compositionEngine,const compositionengine::DisplayCreationArgs & args)47 std::shared_ptr<Display> createDisplay(
48 const compositionengine::CompositionEngine& compositionEngine,
49 const compositionengine::DisplayCreationArgs& args) {
50 return createDisplayTemplated<Display>(compositionEngine, args);
51 }
52
53 Display::~Display() = default;
54
setConfiguration(const compositionengine::DisplayCreationArgs & args)55 void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
56 mId = args.id;
57 mPowerAdvisor = args.powerAdvisor;
58 editState().isSecure = args.isSecure;
59 editState().displaySpace.setBounds(args.pixels);
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 VirtualDisplayId::tryCast(mId).has_value();
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 (isVirtual()) {
121 ALOGW("%s: Invalid operation on virtual display", __func__);
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 const char* const type = isVirtual() ? "virtual" : "physical";
135 base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(mId).c_str(), type,
136 getName().c_str());
137
138 out.append("\n Composition Display State:\n");
139 Output::dumpBase(out);
140 }
141
createDisplayColorProfile(const DisplayColorProfileCreationArgs & args)142 void Display::createDisplayColorProfile(const DisplayColorProfileCreationArgs& args) {
143 setDisplayColorProfile(compositionengine::impl::createDisplayColorProfile(args));
144 }
145
createRenderSurface(const RenderSurfaceCreationArgs & args)146 void Display::createRenderSurface(const RenderSurfaceCreationArgs& args) {
147 setRenderSurface(
148 compositionengine::impl::createRenderSurface(getCompositionEngine(), *this, args));
149 }
150
createClientCompositionCache(uint32_t cacheSize)151 void Display::createClientCompositionCache(uint32_t cacheSize) {
152 cacheClientCompositionRequests(cacheSize);
153 }
154
createOutputLayer(const sp<compositionengine::LayerFE> & layerFE) const155 std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
156 const sp<compositionengine::LayerFE>& layerFE) const {
157 auto outputLayer = impl::createOutputLayer(*this, layerFE);
158
159 if (const auto halDisplayId = HalDisplayId::tryCast(mId);
160 outputLayer && !mIsDisconnected && halDisplayId) {
161 auto& hwc = getCompositionEngine().getHwComposer();
162 auto hwcLayer = hwc.createLayer(*halDisplayId);
163 ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
164 getName().c_str());
165 outputLayer->setHwcLayer(std::move(hwcLayer));
166 }
167 return outputLayer;
168 }
169
setReleasedLayers(const compositionengine::CompositionRefreshArgs & refreshArgs)170 void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) {
171 Output::setReleasedLayers(refreshArgs);
172
173 if (mIsDisconnected || GpuVirtualDisplayId::tryCast(mId) ||
174 refreshArgs.layersWithQueuedFrames.empty()) {
175 return;
176 }
177
178 // For layers that are being removed from a HWC display, and that have
179 // queued frames, add them to a a list of released layers so we can properly
180 // set a fence.
181 compositionengine::Output::ReleasedLayers releasedLayers;
182
183 // Any non-null entries in the current list of layers are layers that are no
184 // longer going to be visible
185 for (auto* outputLayer : getOutputLayersOrderedByZ()) {
186 if (!outputLayer) {
187 continue;
188 }
189
190 compositionengine::LayerFE* layerFE = &outputLayer->getLayerFE();
191 const bool hasQueuedFrames =
192 std::any_of(refreshArgs.layersWithQueuedFrames.cbegin(),
193 refreshArgs.layersWithQueuedFrames.cend(),
194 [layerFE](sp<compositionengine::LayerFE> layerWithQueuedFrames) {
195 return layerFE == layerWithQueuedFrames.get();
196 });
197
198 if (hasQueuedFrames) {
199 releasedLayers.emplace_back(layerFE);
200 }
201 }
202
203 setReleasedLayers(std::move(releasedLayers));
204 }
205
applyDisplayBrightness(const bool applyImmediately)206 void Display::applyDisplayBrightness(const bool applyImmediately) {
207 auto& hwc = getCompositionEngine().getHwComposer();
208 const auto halDisplayId = HalDisplayId::tryCast(*getDisplayId());
209 if (const auto physicalDisplayId = PhysicalDisplayId::tryCast(*halDisplayId);
210 physicalDisplayId && getState().displayBrightness) {
211 const status_t result =
212 hwc.setDisplayBrightness(*physicalDisplayId, *getState().displayBrightness,
213 getState().displayBrightnessNits,
214 Hwc2::Composer::DisplayBrightnessOptions{
215 .applyImmediately = applyImmediately})
216 .get();
217 ALOGE_IF(result != NO_ERROR, "setDisplayBrightness failed for %s: %d, (%s)",
218 getName().c_str(), result, strerror(-result));
219 }
220 // Clear out the display brightness now that it's been communicated to composer.
221 editState().displayBrightness.reset();
222 }
223
beginFrame()224 void Display::beginFrame() {
225 Output::beginFrame();
226
227 // If we don't have a HWC display, then we are done.
228 const auto halDisplayId = HalDisplayId::tryCast(mId);
229 if (!halDisplayId) {
230 return;
231 }
232
233 applyDisplayBrightness(false);
234 }
235
chooseCompositionStrategy(std::optional<android::HWComposer::DeviceRequestedChanges> * outChanges)236 bool Display::chooseCompositionStrategy(
237 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
238 ATRACE_CALL();
239 ALOGV(__FUNCTION__);
240
241 if (mIsDisconnected) {
242 return false;
243 }
244
245 // If we don't have a HWC display, then we are done.
246 const auto halDisplayId = HalDisplayId::tryCast(mId);
247 if (!halDisplayId) {
248 return false;
249 }
250
251 const nsecs_t startTime = systemTime();
252
253 // Get any composition changes requested by the HWC device, and apply them.
254 std::optional<android::HWComposer::DeviceRequestedChanges> changes;
255 auto& hwc = getCompositionEngine().getHwComposer();
256 const bool requiresClientComposition = anyLayersRequireClientComposition();
257 if (status_t result =
258 hwc.getDeviceCompositionChanges(*halDisplayId, requiresClientComposition,
259 getState().earliestPresentTime,
260 getState().previousPresentFence,
261 getState().expectedPresentTime, outChanges);
262 result != NO_ERROR) {
263 ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
264 strerror(-result));
265 return false;
266 }
267
268 if (isPowerHintSessionEnabled()) {
269 mPowerAdvisor->setHwcValidateTiming(mId, startTime, systemTime());
270 mPowerAdvisor->setRequiresClientComposition(mId, requiresClientComposition);
271 }
272
273 return true;
274 }
275
applyCompositionStrategy(const std::optional<DeviceRequestedChanges> & changes)276 void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChanges>& changes) {
277 if (changes) {
278 applyChangedTypesToLayers(changes->changedTypes);
279 applyDisplayRequests(changes->displayRequests);
280 applyLayerRequestsToLayers(changes->layerRequests);
281 applyClientTargetRequests(changes->clientTargetProperty);
282 }
283
284 // Determine what type of composition we are doing from the final state
285 auto& state = editState();
286 state.usesClientComposition = anyLayersRequireClientComposition();
287 state.usesDeviceComposition = !allLayersRequireClientComposition();
288 }
289
getSkipColorTransform() const290 bool Display::getSkipColorTransform() const {
291 const auto& hwc = getCompositionEngine().getHwComposer();
292 if (const auto halDisplayId = HalDisplayId::tryCast(mId)) {
293 return hwc.hasDisplayCapability(*halDisplayId,
294 DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
295 }
296
297 return hwc.hasCapability(Capability::SKIP_CLIENT_COLOR_TRANSFORM);
298 }
299
allLayersRequireClientComposition() const300 bool Display::allLayersRequireClientComposition() const {
301 const auto layers = getOutputLayersOrderedByZ();
302 return std::all_of(layers.begin(), layers.end(),
303 [](const auto& layer) { return layer->requiresClientComposition(); });
304 }
305
applyChangedTypesToLayers(const ChangedTypes & changedTypes)306 void Display::applyChangedTypesToLayers(const ChangedTypes& changedTypes) {
307 if (changedTypes.empty()) {
308 return;
309 }
310
311 for (auto* layer : getOutputLayersOrderedByZ()) {
312 auto hwcLayer = layer->getHwcLayer();
313 if (!hwcLayer) {
314 continue;
315 }
316
317 if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
318 layer->applyDeviceCompositionTypeChange(
319 static_cast<aidl::android::hardware::graphics::composer3::Composition>(
320 it->second));
321 }
322 }
323 }
324
applyDisplayRequests(const DisplayRequests & displayRequests)325 void Display::applyDisplayRequests(const DisplayRequests& displayRequests) {
326 auto& state = editState();
327 state.flipClientTarget = (static_cast<uint32_t>(displayRequests) &
328 static_cast<uint32_t>(hal::DisplayRequest::FLIP_CLIENT_TARGET)) != 0;
329 // Note: HWC2::DisplayRequest::WriteClientTargetToOutput is currently ignored.
330 }
331
applyLayerRequestsToLayers(const LayerRequests & layerRequests)332 void Display::applyLayerRequestsToLayers(const LayerRequests& layerRequests) {
333 for (auto* layer : getOutputLayersOrderedByZ()) {
334 layer->prepareForDeviceLayerRequests();
335
336 auto hwcLayer = layer->getHwcLayer();
337 if (!hwcLayer) {
338 continue;
339 }
340
341 if (auto it = layerRequests.find(hwcLayer); it != layerRequests.end()) {
342 layer->applyDeviceLayerRequest(
343 static_cast<Hwc2::IComposerClient::LayerRequest>(it->second));
344 }
345 }
346 }
347
applyClientTargetRequests(const ClientTargetProperty & clientTargetProperty)348 void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty) {
349 if (static_cast<ui::Dataspace>(clientTargetProperty.clientTargetProperty.dataspace) ==
350 ui::Dataspace::UNKNOWN) {
351 return;
352 }
353
354 editState().dataspace =
355 static_cast<ui::Dataspace>(clientTargetProperty.clientTargetProperty.dataspace);
356 editState().clientTargetBrightness = clientTargetProperty.brightness;
357 editState().clientTargetDimmingStage = clientTargetProperty.dimmingStage;
358 getRenderSurface()->setBufferDataspace(editState().dataspace);
359 getRenderSurface()->setBufferPixelFormat(
360 static_cast<ui::PixelFormat>(clientTargetProperty.clientTargetProperty.pixelFormat));
361 }
362
presentAndGetFrameFences()363 compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
364 auto fences = impl::Output::presentAndGetFrameFences();
365
366 const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
367 if (mIsDisconnected || !halDisplayIdOpt) {
368 return fences;
369 }
370
371 auto& hwc = getCompositionEngine().getHwComposer();
372
373 const nsecs_t startTime = systemTime();
374
375 if (isPowerHintSessionEnabled()) {
376 if (!getCompositionEngine().getHwComposer().getComposer()->isSupported(
377 Hwc2::Composer::OptionalFeature::ExpectedPresentTime) &&
378 getState().previousPresentFence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
379 mPowerAdvisor->setHwcPresentDelayedTime(mId, getState().earliestPresentTime);
380 }
381 }
382
383 hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime,
384 getState().previousPresentFence);
385
386 if (isPowerHintSessionEnabled()) {
387 mPowerAdvisor->setHwcPresentTiming(mId, startTime, systemTime());
388 }
389
390 fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
391
392 // TODO(b/121291683): Change HWComposer call to return entire map
393 for (const auto* layer : getOutputLayersOrderedByZ()) {
394 auto hwcLayer = layer->getHwcLayer();
395 if (!hwcLayer) {
396 continue;
397 }
398
399 fences.layerFences.emplace(hwcLayer, hwc.getLayerReleaseFence(*halDisplayIdOpt, hwcLayer));
400 }
401
402 hwc.clearReleaseFences(*halDisplayIdOpt);
403
404 return fences;
405 }
406
setExpensiveRenderingExpected(bool enabled)407 void Display::setExpensiveRenderingExpected(bool enabled) {
408 Output::setExpensiveRenderingExpected(enabled);
409
410 if (mPowerAdvisor && !GpuVirtualDisplayId::tryCast(mId)) {
411 mPowerAdvisor->setExpensiveRenderingExpected(mId, enabled);
412 }
413 }
414
isPowerHintSessionEnabled()415 bool Display::isPowerHintSessionEnabled() {
416 return mPowerAdvisor != nullptr && mPowerAdvisor->usePowerHintSession();
417 }
418
setHintSessionGpuFence(std::unique_ptr<FenceTime> && gpuFence)419 void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) {
420 mPowerAdvisor->setGpuFenceTime(mId, std::move(gpuFence));
421 }
422
finishFrame(const compositionengine::CompositionRefreshArgs & refreshArgs,GpuCompositionResult && result)423 void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs,
424 GpuCompositionResult&& result) {
425 // We only need to actually compose the display if:
426 // 1) It is being handled by hardware composer, which may need this to
427 // keep its virtual display state machine in sync, or
428 // 2) There is work to be done (the dirty region isn't empty)
429 if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) {
430 ALOGV("Skipping display composition");
431 return;
432 }
433
434 impl::Output::finishFrame(refreshArgs, std::move(result));
435
436 if (isPowerHintSessionEnabled()) {
437 auto& hwc = getCompositionEngine().getHwComposer();
438 if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
439 mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId));
440 }
441 }
442 }
443
444 } // namespace android::compositionengine::impl
445