• 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 <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