• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <common/trace.h>
19 #include <compositionengine/CompositionEngine.h>
20 #include <compositionengine/CompositionRefreshArgs.h>
21 #include <compositionengine/DisplayCreationArgs.h>
22 #include <compositionengine/DisplaySurface.h>
23 #include <compositionengine/LayerFE.h>
24 #include <compositionengine/impl/Display.h>
25 #include <compositionengine/impl/DisplayColorProfile.h>
26 #include <compositionengine/impl/DumpHelpers.h>
27 #include <compositionengine/impl/OutputLayer.h>
28 #include <compositionengine/impl/RenderSurface.h>
29 
30 // TODO(b/129481165): remove the #pragma below and fix conversion issues
31 #pragma clang diagnostic push
32 #pragma clang diagnostic ignored "-Wconversion"
33 
34 #include "DisplayHardware/HWComposer.h"
35 
36 // TODO(b/129481165): remove the #pragma below and fix conversion issues
37 #pragma clang diagnostic pop // ignored "-Wconversion"
38 
39 #include "PowerAdvisor/PowerAdvisor.h"
40 
41 using aidl::android::hardware::graphics::composer3::Capability;
42 using aidl::android::hardware::graphics::composer3::DisplayCapability;
43 
44 namespace android::compositionengine::impl {
45 
createDisplay(const compositionengine::CompositionEngine & compositionEngine,const compositionengine::DisplayCreationArgs & args)46 std::shared_ptr<Display> createDisplay(
47         const compositionengine::CompositionEngine& compositionEngine,
48         const compositionengine::DisplayCreationArgs& args) {
49     return createDisplayTemplated<Display>(compositionEngine, args);
50 }
51 
52 Display::~Display() = default;
53 
setConfiguration(const compositionengine::DisplayCreationArgs & args)54 void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
55     mIdVariant = args.idVariant;
56     mPowerAdvisor = args.powerAdvisor;
57     mHasPictureProcessing = args.hasPictureProcessing;
58     mMaxLayerPictureProfiles = args.maxLayerPictureProfiles;
59     editState().isSecure = args.isSecure;
60     editState().isProtected = args.isProtected;
61     editState().displaySpace.setBounds(args.pixels);
62     setName(args.name);
63 }
64 
isValid() const65 bool Display::isValid() const {
66     return Output::isValid() && mPowerAdvisor;
67 }
68 
getId() const69 DisplayId Display::getId() const {
70     return asDisplayId(mIdVariant);
71 }
72 
hasSecureLayers() const73 bool Display::hasSecureLayers() const {
74     const auto layers = getOutputLayersOrderedByZ();
75     return std::any_of(layers.begin(), layers.end(), [](const auto& layer) {
76         const auto* state = layer->getLayerFE().getCompositionState();
77         return state && state->isSecure;
78     });
79 }
80 
isSecure() const81 bool Display::isSecure() const {
82     return getState().isSecure;
83 }
84 
setSecure(bool secure)85 void Display::setSecure(bool secure) {
86     editState().isSecure = secure;
87 }
88 
isVirtual() const89 bool Display::isVirtual() const {
90     return !std::holds_alternative<PhysicalDisplayId>(mIdVariant);
91 }
92 
getDisplayId() const93 ftl::Optional<DisplayId> Display::getDisplayId() const {
94     return getId();
95 }
96 
getDisplayIdVariant() const97 ftl::Optional<DisplayIdVariant> Display::getDisplayIdVariant() const {
98     return mIdVariant;
99 }
100 
disconnect()101 void Display::disconnect() {
102     if (mIsDisconnected) {
103         return;
104     }
105 
106     mIsDisconnected = true;
107 
108     if (const auto id = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
109         getCompositionEngine().getHwComposer().disconnectDisplay(*id);
110     }
111 }
112 
setColorTransform(const compositionengine::CompositionRefreshArgs & args)113 void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
114     Output::setColorTransform(args);
115     const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
116     if (mIsDisconnected || !halDisplayId || CC_LIKELY(!args.colorTransformMatrix)) {
117         return;
118     }
119 
120     auto& hwc = getCompositionEngine().getHwComposer();
121     status_t result = hwc.setColorTransform(*halDisplayId, *args.colorTransformMatrix);
122     ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d",
123              to_string(*halDisplayId).c_str(), result);
124 }
125 
setColorProfile(const ColorProfile & colorProfile)126 void Display::setColorProfile(const ColorProfile& colorProfile) {
127     if (colorProfile.mode == getState().colorMode &&
128         colorProfile.dataspace == getState().dataspace &&
129         colorProfile.renderIntent == getState().renderIntent) {
130         return;
131     }
132 
133     if (isVirtual()) {
134         ALOGW("%s: Invalid operation on virtual display", __func__);
135         return;
136     }
137 
138     Output::setColorProfile(colorProfile);
139 
140     const auto physicalId = getDisplayIdVariant().and_then(asPhysicalDisplayId);
141     LOG_FATAL_IF(!physicalId);
142     getCompositionEngine().getHwComposer().setActiveColorMode(*physicalId, colorProfile.mode,
143                                                               colorProfile.renderIntent);
144 }
145 
dump(std::string & out) const146 void Display::dump(std::string& out) const {
147     const char* const type = isVirtual() ? "virtual" : "physical";
148     base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(getId()).c_str(), type,
149                         getName().c_str());
150 
151     out.append("\n   Composition Display State:\n");
152     Output::dumpBase(out);
153 }
154 
createDisplayColorProfile(const DisplayColorProfileCreationArgs & args)155 void Display::createDisplayColorProfile(const DisplayColorProfileCreationArgs& args) {
156     setDisplayColorProfile(compositionengine::impl::createDisplayColorProfile(args));
157 }
158 
createRenderSurface(const RenderSurfaceCreationArgs & args)159 void Display::createRenderSurface(const RenderSurfaceCreationArgs& args) {
160     setRenderSurface(
161             compositionengine::impl::createRenderSurface(getCompositionEngine(), *this, args));
162 }
163 
createClientCompositionCache(uint32_t cacheSize)164 void Display::createClientCompositionCache(uint32_t cacheSize) {
165     cacheClientCompositionRequests(cacheSize);
166 }
167 
createOutputLayer(const sp<compositionengine::LayerFE> & layerFE) const168 std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
169         const sp<compositionengine::LayerFE>& layerFE) const {
170     auto outputLayer = impl::createOutputLayer(*this, layerFE);
171 
172     if (const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
173         outputLayer && !mIsDisconnected && halDisplayId) {
174         auto& hwc = getCompositionEngine().getHwComposer();
175         auto hwcLayer = hwc.createLayer(*halDisplayId);
176         ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
177                  getName().c_str());
178         outputLayer->setHwcLayer(std::move(hwcLayer));
179     }
180     return outputLayer;
181 }
182 
setReleasedLayers(const compositionengine::CompositionRefreshArgs & refreshArgs)183 void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) {
184     Output::setReleasedLayers(refreshArgs);
185 
186     if (mIsDisconnected || isGpuVirtualDisplay() || refreshArgs.layersWithQueuedFrames.empty()) {
187         return;
188     }
189 
190     // For layers that are being removed from a HWC display, and that have
191     // queued frames, add them to a a list of released layers so we can properly
192     // set a fence.
193     compositionengine::Output::ReleasedLayers releasedLayers;
194 
195     // Any non-null entries in the current list of layers are layers that are no
196     // longer going to be visible
197     for (auto* outputLayer : getOutputLayersOrderedByZ()) {
198         if (!outputLayer) {
199             continue;
200         }
201 
202         compositionengine::LayerFE* layerFE = &outputLayer->getLayerFE();
203         const bool hasQueuedFrames =
204                 std::any_of(refreshArgs.layersWithQueuedFrames.cbegin(),
205                             refreshArgs.layersWithQueuedFrames.cend(),
206                             [layerFE](sp<compositionengine::LayerFE> layerWithQueuedFrames) {
207                                 return layerFE == layerWithQueuedFrames.get();
208                             });
209 
210         if (hasQueuedFrames) {
211             releasedLayers.emplace_back(wp<LayerFE>::fromExisting(layerFE));
212         }
213     }
214 
215     setReleasedLayers(std::move(releasedLayers));
216 }
217 
applyDisplayBrightness(bool applyImmediately)218 void Display::applyDisplayBrightness(bool applyImmediately) {
219     if (!getState().displayBrightness) {
220         return;
221     }
222     if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) {
223         auto& hwc = getCompositionEngine().getHwComposer();
224         status_t result = hwc.setDisplayBrightness(*displayId, *getState().displayBrightness,
225                                                    getState().displayBrightnessNits,
226                                                    Hwc2::Composer::DisplayBrightnessOptions{
227                                                            .applyImmediately = applyImmediately})
228                                   .get();
229         ALOGE_IF(result != NO_ERROR, "setDisplayBrightness failed for %s: %d, (%s)",
230                  getName().c_str(), result, strerror(-result));
231     }
232     // Clear out the display brightness now that it's been communicated to composer.
233     editState().displayBrightness.reset();
234 }
235 
beginFrame()236 void Display::beginFrame() {
237     Output::beginFrame();
238 
239     // If we don't have a HWC display, then we are done.
240     const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
241     if (!halDisplayId) {
242         return;
243     }
244 
245     applyDisplayBrightness(false);
246 }
247 
chooseCompositionStrategy(std::optional<android::HWComposer::DeviceRequestedChanges> * outChanges)248 bool Display::chooseCompositionStrategy(
249         std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
250     SFTRACE_FORMAT("%s for %s", __func__, getNamePlusId().c_str());
251     ALOGV(__FUNCTION__);
252 
253     if (mIsDisconnected) {
254         return false;
255     }
256 
257     // If we don't have a HWC display, then we are done.
258     const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
259     if (!halDisplayId) {
260         return false;
261     }
262 
263     // Get any composition changes requested by the HWC device, and apply them.
264     auto& hwc = getCompositionEngine().getHwComposer();
265     const bool requiresClientComposition = anyLayersRequireClientComposition();
266 
267     const TimePoint hwcValidateStartTime = TimePoint::now();
268 
269     if (status_t result = hwc.getDeviceCompositionChanges(*halDisplayId, requiresClientComposition,
270                                                           getState().earliestPresentTime,
271                                                           getState().expectedPresentTime,
272                                                           getState().frameInterval, outChanges);
273         result != NO_ERROR) {
274         ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
275               strerror(-result));
276         return false;
277     }
278 
279     if (isPowerHintSessionEnabled()) {
280         mPowerAdvisor->setHwcValidateTiming(getId(), hwcValidateStartTime, TimePoint::now());
281         if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
282             mPowerAdvisor->setSkippedValidate(*halDisplayId, hwc.getValidateSkipped(*halDisplayId));
283         }
284     }
285 
286     return true;
287 }
288 
applyCompositionStrategy(const std::optional<DeviceRequestedChanges> & changes)289 void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChanges>& changes) {
290     if (changes) {
291         applyChangedTypesToLayers(changes->changedTypes);
292         applyDisplayRequests(changes->displayRequests);
293         applyLayerRequestsToLayers(changes->layerRequests);
294         applyClientTargetRequests(changes->clientTargetProperty);
295         applyLayerLutsToLayers(changes->layerLuts);
296     }
297 
298     // Determine what type of composition we are doing from the final state
299     auto& state = editState();
300     state.usesClientComposition = anyLayersRequireClientComposition();
301     state.usesDeviceComposition = !allLayersRequireClientComposition();
302 }
303 
getSkipColorTransform() const304 bool Display::getSkipColorTransform() const {
305     auto& hwc = getCompositionEngine().getHwComposer();
306     if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
307         return hwc.hasDisplayCapability(*halDisplayId,
308                                         DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
309     }
310 
311     return hwc.hasCapability(Capability::SKIP_CLIENT_COLOR_TRANSFORM);
312 }
313 
allLayersRequireClientComposition() const314 bool Display::allLayersRequireClientComposition() const {
315     const auto layers = getOutputLayersOrderedByZ();
316     return std::all_of(layers.begin(), layers.end(),
317                        [](const auto& layer) { return layer->requiresClientComposition(); });
318 }
319 
applyChangedTypesToLayers(const ChangedTypes & changedTypes)320 void Display::applyChangedTypesToLayers(const ChangedTypes& changedTypes) {
321     if (changedTypes.empty()) {
322         return;
323     }
324 
325     for (auto* layer : getOutputLayersOrderedByZ()) {
326         auto hwcLayer = layer->getHwcLayer();
327         if (!hwcLayer) {
328             continue;
329         }
330 
331         if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
332             layer->applyDeviceCompositionTypeChange(
333                     static_cast<aidl::android::hardware::graphics::composer3::Composition>(
334                             it->second));
335         }
336     }
337 }
338 
applyDisplayRequests(const DisplayRequests & displayRequests)339 void Display::applyDisplayRequests(const DisplayRequests& displayRequests) {
340     auto& state = editState();
341     state.flipClientTarget = (static_cast<uint32_t>(displayRequests) &
342                               static_cast<uint32_t>(hal::DisplayRequest::FLIP_CLIENT_TARGET)) != 0;
343     // Note: HWC2::DisplayRequest::WriteClientTargetToOutput is currently ignored.
344 }
345 
applyLayerRequestsToLayers(const LayerRequests & layerRequests)346 void Display::applyLayerRequestsToLayers(const LayerRequests& layerRequests) {
347     for (auto* layer : getOutputLayersOrderedByZ()) {
348         layer->prepareForDeviceLayerRequests();
349 
350         auto hwcLayer = layer->getHwcLayer();
351         if (!hwcLayer) {
352             continue;
353         }
354 
355         if (auto it = layerRequests.find(hwcLayer); it != layerRequests.end()) {
356             layer->applyDeviceLayerRequest(
357                     static_cast<Hwc2::IComposerClient::LayerRequest>(it->second));
358         }
359     }
360 }
361 
applyClientTargetRequests(const ClientTargetProperty & clientTargetProperty)362 void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty) {
363     if (static_cast<ui::Dataspace>(clientTargetProperty.clientTargetProperty.dataspace) ==
364         ui::Dataspace::UNKNOWN) {
365         return;
366     }
367 
368     editState().dataspace =
369             static_cast<ui::Dataspace>(clientTargetProperty.clientTargetProperty.dataspace);
370     editState().clientTargetBrightness = clientTargetProperty.brightness;
371     editState().clientTargetDimmingStage = clientTargetProperty.dimmingStage;
372     getRenderSurface()->setBufferDataspace(editState().dataspace);
373     getRenderSurface()->setBufferPixelFormat(
374             static_cast<ui::PixelFormat>(clientTargetProperty.clientTargetProperty.pixelFormat));
375 }
376 
applyLayerLutsToLayers(const LayerLuts & layerLuts)377 void Display::applyLayerLutsToLayers(const LayerLuts& layerLuts) {
378     auto& mapper = getCompositionEngine().getHwComposer().getLutFileDescriptorMapper();
379     for (auto* layer : getOutputLayersOrderedByZ()) {
380         auto hwcLayer = layer->getHwcLayer();
381         if (!hwcLayer) {
382             continue;
383         }
384 
385         if (auto lutsIt = layerLuts.find(hwcLayer); lutsIt != layerLuts.end()) {
386             if (auto mapperIt = mapper.find(hwcLayer); mapperIt != mapper.end()) {
387                 layer->applyDeviceLayerLut(::android::base::unique_fd(mapperIt->second.release()),
388                                            lutsIt->second);
389             }
390         }
391     }
392 
393     mapper.clear();
394 }
395 
executeCommands()396 void Display::executeCommands() {
397     const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
398     if (mIsDisconnected || !halDisplayIdOpt) {
399         return;
400     }
401 
402     getCompositionEngine().getHwComposer().executeCommands(*halDisplayIdOpt);
403 }
404 
presentFrame()405 compositionengine::Output::FrameFences Display::presentFrame() {
406     auto fences = impl::Output::presentFrame();
407 
408     const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
409     if (mIsDisconnected || !halDisplayIdOpt) {
410         return fences;
411     }
412 
413     auto& hwc = getCompositionEngine().getHwComposer();
414 
415     const TimePoint startTime = TimePoint::now();
416 
417     if (isPowerHintSessionEnabled() && getState().earliestPresentTime) {
418         mPowerAdvisor->setHwcPresentDelayedTime(*halDisplayIdOpt, *getState().earliestPresentTime);
419     }
420 
421     hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime);
422 
423     if (isPowerHintSessionEnabled()) {
424         mPowerAdvisor->setHwcPresentTiming(*halDisplayIdOpt, startTime, TimePoint::now());
425     }
426 
427     fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
428 
429     // TODO(b/121291683): Change HWComposer call to return entire map
430     for (const auto* layer : getOutputLayersOrderedByZ()) {
431         auto hwcLayer = layer->getHwcLayer();
432         if (!hwcLayer) {
433             continue;
434         }
435 
436         fences.layerFences.emplace(hwcLayer, hwc.getLayerReleaseFence(*halDisplayIdOpt, hwcLayer));
437     }
438 
439     hwc.clearReleaseFences(*halDisplayIdOpt);
440 
441     return fences;
442 }
443 
setExpensiveRenderingExpected(bool enabled)444 void Display::setExpensiveRenderingExpected(bool enabled) {
445     Output::setExpensiveRenderingExpected(enabled);
446 
447     if (mPowerAdvisor && !isGpuVirtualDisplay()) {
448         mPowerAdvisor->setExpensiveRenderingExpected(getId(), enabled);
449     }
450 }
451 
isPowerHintSessionEnabled()452 bool Display::isPowerHintSessionEnabled() {
453     return mPowerAdvisor != nullptr && mPowerAdvisor->usePowerHintSession();
454 }
455 
isPowerHintSessionGpuReportingEnabled()456 bool Display::isPowerHintSessionGpuReportingEnabled() {
457     return mPowerAdvisor != nullptr && mPowerAdvisor->supportsGpuReporting();
458 }
459 
460 // For ADPF GPU v0 this is expected to set start time to when the GPU commands are submitted with
461 // fence returned, i.e. when RenderEngine flushes the commands and returns the draw fence.
setHintSessionGpuStart(TimePoint startTime)462 void Display::setHintSessionGpuStart(TimePoint startTime) {
463     mPowerAdvisor->setGpuStartTime(getId(), startTime);
464 }
465 
setHintSessionGpuFence(std::unique_ptr<FenceTime> && gpuFence)466 void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) {
467     mPowerAdvisor->setGpuFenceTime(getId(), std::move(gpuFence));
468 }
469 
setHintSessionRequiresRenderEngine(bool requiresRenderEngine)470 void Display::setHintSessionRequiresRenderEngine(bool requiresRenderEngine) {
471     mPowerAdvisor->setRequiresRenderEngine(getId(), requiresRenderEngine);
472 }
473 
474 const aidl::android::hardware::graphics::composer3::OverlayProperties*
getOverlaySupport()475 Display::getOverlaySupport() {
476     return &getCompositionEngine().getHwComposer().getOverlaySupport();
477 }
478 
hasPictureProcessing() const479 bool Display::hasPictureProcessing() const {
480     return mHasPictureProcessing;
481 }
482 
getMaxLayerPictureProfiles() const483 int32_t Display::getMaxLayerPictureProfiles() const {
484     return mMaxLayerPictureProfiles;
485 }
486 
finishFrame(GpuCompositionResult && result)487 void Display::finishFrame(GpuCompositionResult&& result) {
488     // We only need to actually compose the display if:
489     // 1) It is being handled by hardware composer, which may need this to
490     //    keep its virtual display state machine in sync, or
491     // 2) There is work to be done (the dirty region isn't empty)
492     if (isGpuVirtualDisplay() && !mustRecompose()) {
493         ALOGV("Skipping display composition");
494         return;
495     }
496 
497     impl::Output::finishFrame(std::move(result));
498 }
499 
supportsOffloadPresent() const500 bool Display::supportsOffloadPresent() const {
501     if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
502         auto& hwc = getCompositionEngine().getHwComposer();
503         return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::MULTI_THREADED_PRESENT);
504     }
505 
506     return false;
507 }
508 
509 } // namespace android::compositionengine::impl
510