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