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