• 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/Layer.h>
20 #include <compositionengine/LayerFE.h>
21 #include <compositionengine/Output.h>
22 #include <compositionengine/impl/LayerCompositionState.h>
23 #include <compositionengine/impl/OutputCompositionState.h>
24 #include <compositionengine/impl/OutputLayer.h>
25 #include <compositionengine/impl/OutputLayerCompositionState.h>
26 
27 #include "DisplayHardware/HWComposer.h"
28 
29 namespace android::compositionengine {
30 
31 OutputLayer::~OutputLayer() = default;
32 
33 namespace impl {
34 
35 namespace {
36 
reduce(const FloatRect & win,const Region & exclude)37 FloatRect reduce(const FloatRect& win, const Region& exclude) {
38     if (CC_LIKELY(exclude.isEmpty())) {
39         return win;
40     }
41     // Convert through Rect (by rounding) for lack of FloatRegion
42     return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
43 }
44 
45 } // namespace
46 
createOutputLayer(const CompositionEngine & compositionEngine,std::optional<DisplayId> displayId,const compositionengine::Output & output,std::shared_ptr<compositionengine::Layer> layer,sp<compositionengine::LayerFE> layerFE)47 std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
48         const CompositionEngine& compositionEngine, std::optional<DisplayId> displayId,
49         const compositionengine::Output& output, std::shared_ptr<compositionengine::Layer> layer,
50         sp<compositionengine::LayerFE> layerFE) {
51     auto result = std::make_unique<OutputLayer>(output, layer, layerFE);
52     result->initialize(compositionEngine, displayId);
53     return result;
54 }
55 
OutputLayer(const Output & output,std::shared_ptr<Layer> layer,sp<LayerFE> layerFE)56 OutputLayer::OutputLayer(const Output& output, std::shared_ptr<Layer> layer, sp<LayerFE> layerFE)
57       : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
58 
59 OutputLayer::~OutputLayer() = default;
60 
initialize(const CompositionEngine & compositionEngine,std::optional<DisplayId> displayId)61 void OutputLayer::initialize(const CompositionEngine& compositionEngine,
62                              std::optional<DisplayId> displayId) {
63     if (!displayId) {
64         return;
65     }
66 
67     auto& hwc = compositionEngine.getHwComposer();
68 
69     mState.hwc.emplace(std::shared_ptr<HWC2::Layer>(hwc.createLayer(*displayId),
70                                                     [&hwc, displayId](HWC2::Layer* layer) {
71                                                         hwc.destroyLayer(*displayId, layer);
72                                                     }));
73 }
74 
getOutput() const75 const compositionengine::Output& OutputLayer::getOutput() const {
76     return mOutput;
77 }
78 
getLayer() const79 compositionengine::Layer& OutputLayer::getLayer() const {
80     return *mLayer;
81 }
82 
getLayerFE() const83 compositionengine::LayerFE& OutputLayer::getLayerFE() const {
84     return *mLayerFE;
85 }
86 
getState() const87 const OutputLayerCompositionState& OutputLayer::getState() const {
88     return mState;
89 }
90 
editState()91 OutputLayerCompositionState& OutputLayer::editState() {
92     return mState;
93 }
94 
calculateInitialCrop() const95 Rect OutputLayer::calculateInitialCrop() const {
96     const auto& layerState = mLayer->getState().frontEnd;
97 
98     // apply the projection's clipping to the window crop in
99     // layerstack space, and convert-back to layer space.
100     // if there are no window scaling involved, this operation will map to full
101     // pixels in the buffer.
102 
103     FloatRect activeCropFloat =
104             reduce(layerState.geomLayerBounds, layerState.geomActiveTransparentRegion);
105 
106     const Rect& viewport = mOutput.getState().viewport;
107     const ui::Transform& layerTransform = layerState.geomLayerTransform;
108     const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
109     // Transform to screen space.
110     activeCropFloat = layerTransform.transform(activeCropFloat);
111     activeCropFloat = activeCropFloat.intersect(viewport.toFloatRect());
112     // Back to layer space to work with the content crop.
113     activeCropFloat = inverseLayerTransform.transform(activeCropFloat);
114 
115     // This needs to be here as transform.transform(Rect) computes the
116     // transformed rect and then takes the bounding box of the result before
117     // returning. This means
118     // transform.inverse().transform(transform.transform(Rect)) != Rect
119     // in which case we need to make sure the final rect is clipped to the
120     // display bounds.
121     Rect activeCrop{activeCropFloat};
122     if (!activeCrop.intersect(layerState.geomBufferSize, &activeCrop)) {
123         activeCrop.clear();
124     }
125     return activeCrop;
126 }
127 
calculateOutputSourceCrop() const128 FloatRect OutputLayer::calculateOutputSourceCrop() const {
129     const auto& layerState = mLayer->getState().frontEnd;
130     const auto& outputState = mOutput.getState();
131 
132     if (!layerState.geomUsesSourceCrop) {
133         return {};
134     }
135 
136     // the content crop is the area of the content that gets scaled to the
137     // layer's size. This is in buffer space.
138     FloatRect crop = layerState.geomContentCrop.toFloatRect();
139 
140     // In addition there is a WM-specified crop we pull from our drawing state.
141     Rect activeCrop = calculateInitialCrop();
142     const Rect& bufferSize = layerState.geomBufferSize;
143 
144     int winWidth = bufferSize.getWidth();
145     int winHeight = bufferSize.getHeight();
146 
147     // The bufferSize for buffer state layers can be unbounded ([0, 0, -1, -1])
148     // if display frame hasn't been set and the parent is an unbounded layer.
149     if (winWidth < 0 && winHeight < 0) {
150         return crop;
151     }
152 
153     // Transform the window crop to match the buffer coordinate system,
154     // which means using the inverse of the current transform set on the
155     // SurfaceFlingerConsumer.
156     uint32_t invTransform = layerState.geomBufferTransform;
157     if (layerState.geomBufferUsesDisplayInverseTransform) {
158         /*
159          * the code below applies the primary display's inverse transform to the
160          * buffer
161          */
162         uint32_t invTransformOrient = outputState.orientation;
163         // calculate the inverse transform
164         if (invTransformOrient & HAL_TRANSFORM_ROT_90) {
165             invTransformOrient ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
166         }
167         // and apply to the current transform
168         invTransform =
169                 (ui::Transform(invTransformOrient) * ui::Transform(invTransform)).getOrientation();
170     }
171 
172     if (invTransform & HAL_TRANSFORM_ROT_90) {
173         // If the activeCrop has been rotate the ends are rotated but not
174         // the space itself so when transforming ends back we can't rely on
175         // a modification of the axes of rotation. To account for this we
176         // need to reorient the inverse rotation in terms of the current
177         // axes of rotation.
178         bool is_h_flipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
179         bool is_v_flipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
180         if (is_h_flipped == is_v_flipped) {
181             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
182         }
183         std::swap(winWidth, winHeight);
184     }
185     const Rect winCrop =
186             activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
187 
188     // below, crop is intersected with winCrop expressed in crop's coordinate space
189     float xScale = crop.getWidth() / float(winWidth);
190     float yScale = crop.getHeight() / float(winHeight);
191 
192     float insetL = winCrop.left * xScale;
193     float insetT = winCrop.top * yScale;
194     float insetR = (winWidth - winCrop.right) * xScale;
195     float insetB = (winHeight - winCrop.bottom) * yScale;
196 
197     crop.left += insetL;
198     crop.top += insetT;
199     crop.right -= insetR;
200     crop.bottom -= insetB;
201 
202     return crop;
203 }
204 
calculateOutputDisplayFrame() const205 Rect OutputLayer::calculateOutputDisplayFrame() const {
206     const auto& layerState = mLayer->getState().frontEnd;
207     const auto& outputState = mOutput.getState();
208 
209     // apply the layer's transform, followed by the display's global transform
210     // here we're guaranteed that the layer's transform preserves rects
211     Region activeTransparentRegion = layerState.geomActiveTransparentRegion;
212     const ui::Transform& layerTransform = layerState.geomLayerTransform;
213     const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
214     const Rect& bufferSize = layerState.geomBufferSize;
215     Rect activeCrop = layerState.geomCrop;
216     if (!activeCrop.isEmpty() && bufferSize.isValid()) {
217         activeCrop = layerTransform.transform(activeCrop);
218         if (!activeCrop.intersect(outputState.viewport, &activeCrop)) {
219             activeCrop.clear();
220         }
221         activeCrop = inverseLayerTransform.transform(activeCrop, true);
222         // This needs to be here as transform.transform(Rect) computes the
223         // transformed rect and then takes the bounding box of the result before
224         // returning. This means
225         // transform.inverse().transform(transform.transform(Rect)) != Rect
226         // in which case we need to make sure the final rect is clipped to the
227         // display bounds.
228         if (!activeCrop.intersect(bufferSize, &activeCrop)) {
229             activeCrop.clear();
230         }
231         // mark regions outside the crop as transparent
232         activeTransparentRegion.orSelf(Rect(0, 0, bufferSize.getWidth(), activeCrop.top));
233         activeTransparentRegion.orSelf(
234                 Rect(0, activeCrop.bottom, bufferSize.getWidth(), bufferSize.getHeight()));
235         activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
236         activeTransparentRegion.orSelf(
237                 Rect(activeCrop.right, activeCrop.top, bufferSize.getWidth(), activeCrop.bottom));
238     }
239 
240     // reduce uses a FloatRect to provide more accuracy during the
241     // transformation. We then round upon constructing 'frame'.
242     Rect frame{
243             layerTransform.transform(reduce(layerState.geomLayerBounds, activeTransparentRegion))};
244     if (!frame.intersect(outputState.viewport, &frame)) {
245         frame.clear();
246     }
247     const ui::Transform displayTransform{outputState.transform};
248 
249     return displayTransform.transform(frame);
250 }
251 
calculateOutputRelativeBufferTransform() const252 uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
253     const auto& layerState = mLayer->getState().frontEnd;
254     const auto& outputState = mOutput.getState();
255 
256     /*
257      * Transformations are applied in this order:
258      * 1) buffer orientation/flip/mirror
259      * 2) state transformation (window manager)
260      * 3) layer orientation (screen orientation)
261      * (NOTE: the matrices are multiplied in reverse order)
262      */
263     const ui::Transform& layerTransform = layerState.geomLayerTransform;
264     const ui::Transform displayTransform{outputState.orientation};
265     const ui::Transform bufferTransform{layerState.geomBufferTransform};
266     ui::Transform transform(displayTransform * layerTransform * bufferTransform);
267 
268     if (layerState.geomBufferUsesDisplayInverseTransform) {
269         /*
270          * the code below applies the primary display's inverse transform to the
271          * buffer
272          */
273         uint32_t invTransform = outputState.orientation;
274         // calculate the inverse transform
275         if (invTransform & HAL_TRANSFORM_ROT_90) {
276             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
277         }
278 
279         /*
280          * Here we cancel out the orientation component of the WM transform.
281          * The scaling and translate components are already included in our bounds
282          * computation so it's enough to just omit it in the composition.
283          * See comment in BufferLayer::prepareClientLayer with ref to b/36727915 for why.
284          */
285         transform = ui::Transform(invTransform) * displayTransform * bufferTransform;
286     }
287 
288     // this gives us only the "orientation" component of the transform
289     return transform.getOrientation();
290 } // namespace impl
291 
updateCompositionState(bool includeGeometry)292 void OutputLayer::updateCompositionState(bool includeGeometry) {
293     if (includeGeometry) {
294         mState.displayFrame = calculateOutputDisplayFrame();
295         mState.sourceCrop = calculateOutputSourceCrop();
296         mState.bufferTransform =
297                 static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
298 
299         if ((mLayer->getState().frontEnd.isSecure && !mOutput.getState().isSecure) ||
300             (mState.bufferTransform & ui::Transform::ROT_INVALID)) {
301             mState.forceClientComposition = true;
302         }
303     }
304 }
305 
writeStateToHWC(bool includeGeometry) const306 void OutputLayer::writeStateToHWC(bool includeGeometry) const {
307     // Skip doing this if there is no HWC interface
308     if (!mState.hwc) {
309         return;
310     }
311 
312     auto& hwcLayer = (*mState.hwc).hwcLayer;
313     if (!hwcLayer) {
314         ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
315               mLayerFE->getDebugName(), mOutput.getName().c_str());
316         return;
317     }
318 
319     if (includeGeometry) {
320         // Output dependent state
321 
322         if (auto error = hwcLayer->setDisplayFrame(mState.displayFrame);
323             error != HWC2::Error::None) {
324             ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
325                   mLayerFE->getDebugName(), mState.displayFrame.left, mState.displayFrame.top,
326                   mState.displayFrame.right, mState.displayFrame.bottom, to_string(error).c_str(),
327                   static_cast<int32_t>(error));
328         }
329 
330         if (auto error = hwcLayer->setSourceCrop(mState.sourceCrop); error != HWC2::Error::None) {
331             ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
332                   "%s (%d)",
333                   mLayerFE->getDebugName(), mState.sourceCrop.left, mState.sourceCrop.top,
334                   mState.sourceCrop.right, mState.sourceCrop.bottom, to_string(error).c_str(),
335                   static_cast<int32_t>(error));
336         }
337 
338         if (auto error = hwcLayer->setZOrder(mState.z); error != HWC2::Error::None) {
339             ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), mState.z,
340                   to_string(error).c_str(), static_cast<int32_t>(error));
341         }
342 
343         if (auto error =
344                     hwcLayer->setTransform(static_cast<HWC2::Transform>(mState.bufferTransform));
345             error != HWC2::Error::None) {
346             ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
347                   toString(mState.bufferTransform).c_str(), to_string(error).c_str(),
348                   static_cast<int32_t>(error));
349         }
350 
351         // Output independent state
352 
353         const auto& outputIndependentState = mLayer->getState().frontEnd;
354 
355         if (auto error = hwcLayer->setBlendMode(
356                     static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
357             error != HWC2::Error::None) {
358             ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
359                   toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
360                   static_cast<int32_t>(error));
361         }
362 
363         if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
364             error != HWC2::Error::None) {
365             ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
366                   outputIndependentState.alpha, to_string(error).c_str(),
367                   static_cast<int32_t>(error));
368         }
369 
370         if (auto error =
371                     hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
372             error != HWC2::Error::None) {
373             ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(),
374                   to_string(error).c_str(), static_cast<int32_t>(error));
375         }
376     }
377 }
378 
dump(std::string & out) const379 void OutputLayer::dump(std::string& out) const {
380     using android::base::StringAppendF;
381 
382     StringAppendF(&out, "  - Output Layer %p (Composition layer %p) (%s)\n", this, mLayer.get(),
383                   mLayerFE->getDebugName());
384     mState.dump(out);
385 }
386 
387 } // namespace impl
388 } // namespace android::compositionengine
389