Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     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 
     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 
     75 const compositionengine::Output& OutputLayer::getOutput() const {
     76     return mOutput;
     77 }
     78 
     79 compositionengine::Layer& OutputLayer::getLayer() const {
     80     return *mLayer;
     81 }
     82 
     83 compositionengine::LayerFE& OutputLayer::getLayerFE() const {
     84     return *mLayerFE;
     85 }
     86 
     87 const OutputLayerCompositionState& OutputLayer::getState() const {
     88     return mState;
     89 }
     90 
     91 OutputLayerCompositionState& OutputLayer::editState() {
     92     return mState;
     93 }
     94 
     95 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 
    128 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 
    205 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 
    252 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 
    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 
    306 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 
    379 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