Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6035634d authored by Vishnu Nair's avatar Vishnu Nair
Browse files

SF: Add support for boundless layers 1/2

Size is currently used to bound a layer and its child layers. There are scenarios where we do not
want to restrict a layer or its children to any specific size. For example
1. Have a color layer fill the bounds of its parent.
2. Have a layer apply a transform (ROTATION) to all child layers without cropping them.
Currently this is achieved by providing a large enough size so that the layer or its children do
not get cropped incorrectly.

This change modifies computeBounds and computeScreenBounds to ignore a layer's size. We calculate
the bounds by using the layer's buffer size and/or crop. Then we pass the bounds to the parent
layer to crop to its bounds. If the layer has no bounds, we pass the child bounds forward. If
we are also at the bottom of the hierarchy, such as a boundless color layer, then our bounds are
set to the parent bounds.

In WM, we set the layer's crop property in places where we relied on layer size.

Bug: 114413815
Test: go/wm-smoke
Test: mmma frameworks/native/services/surfaceflinger/tests/ && \
mmma frameworks/native/libs/gui/tests/ && adb sync data && \
adb shell /data/nativetest64/libgui_test/libgui_test && \
adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \
adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \
adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \
echo "ALL TESTS PASSED"

Change-Id: I962c0c7639f6c863fc16b8acd16f077f040f8de4
parent 6bdb3cac
Loading
Loading
Loading
Loading
+30 −0
Original line number Original line Diff line number Diff line
@@ -667,6 +667,36 @@ uint64_t BufferLayer::getHeadFrameNumber() const {
    }
    }
}
}


Rect BufferLayer::getBufferSize(const State& s) const {
    // If we have a sideband stream, or we are scaling the buffer then return the layer size since
    // we cannot determine the buffer size.
    if ((s.sidebandStream != nullptr) ||
        (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) {
        return Rect(getActiveWidth(s), getActiveHeight(s));
    }

    if (mActiveBuffer == nullptr) {
        return Rect::INVALID_RECT;
    }

    uint32_t bufWidth = mActiveBuffer->getWidth();
    uint32_t bufHeight = mActiveBuffer->getHeight();

    // Undo any transformations on the buffer and return the result.
    if (mCurrentTransform & ui::Transform::ROT_90) {
        std::swap(bufWidth, bufHeight);
    }

    if (getTransformToDisplayInverse()) {
        uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
        if (invTransform & ui::Transform::ROT_90) {
            std::swap(bufWidth, bufHeight);
        }
    }

    return Rect(bufWidth, bufHeight);
}

} // namespace android
} // namespace android


#if defined(__gl_h_)
#if defined(__gl_h_)
+2 −0
Original line number Original line Diff line number Diff line
@@ -186,6 +186,8 @@ private:
    mutable renderengine::Texture mTexture;
    mutable renderengine::Texture mTexture;


    bool mRefreshPending{false};
    bool mRefreshPending{false};

    Rect getBufferSize(const State& s) const override;
};
};


} // namespace android
} // namespace android
+4 −2
Original line number Original line Diff line number Diff line
@@ -35,7 +35,9 @@ const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{
};
};
// clang-format on
// clang-format on


BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {
    mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
}
BufferStateLayer::~BufferStateLayer() = default;
BufferStateLayer::~BufferStateLayer() = default;


// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
@@ -394,7 +396,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse
        }
        }
    }
    }


    if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
    if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
        (s.active.w != bufferWidth || s.active.h != bufferHeight)) {
        (s.active.w != bufferWidth || s.active.h != bufferHeight)) {
        ALOGE("[%s] rejecting buffer: "
        ALOGE("[%s] rejecting buffer: "
              "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
              "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
+63 −50
Original line number Original line Diff line number Diff line
@@ -265,39 +265,12 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) {
    return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
    return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
}
}


Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
Rect Layer::computeScreenBounds() const {
    const State& s(getDrawingState());
    FloatRect bounds = computeBounds();
    Rect win(getActiveWidth(s), getActiveHeight(s));

    Rect crop = getCrop(s);
    if (!crop.isEmpty()) {
        win.intersect(crop, &win);
    }

    ui::Transform t = getTransform();
    ui::Transform t = getTransform();
    win = t.transform(win);
    // Transform to screen space.

    bounds = t.transform(bounds);
    const sp<Layer>& p = mDrawingParent.promote();
    return Rect{bounds};
    // Now we need to calculate the parent bounds, so we can clip ourselves to those.
    // When calculating the parent bounds for purposes of clipping,
    // we don't need to constrain the parent to its transparent region.
    // The transparent region is an optimization based on the
    // buffer contents of the layer, but does not affect the space allocated to
    // it by policy, and thus children should be allowed to extend into the
    // parent's transparent region. In fact one of the main uses, is to reduce
    // buffer allocation size in cases where a child window sits behind a main window
    // (by marking the hole in the parent window as a transparent region)
    if (p != nullptr) {
        Rect bounds = p->computeScreenBounds(false);
        bounds.intersect(win, &win);
    }

    if (reduceTransparentRegion) {
        auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s));
        win = reduce(win, screenTransparentRegion);
    }

    return win;
}
}


FloatRect Layer::computeBounds() const {
FloatRect Layer::computeBounds() const {
@@ -307,32 +280,72 @@ FloatRect Layer::computeBounds() const {


FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
    const State& s(getDrawingState());
    const State& s(getDrawingState());
    Rect win(getActiveWidth(s), getActiveHeight(s));
    Rect bounds = getCroppedBufferSize(s);

    FloatRect floatBounds = bounds.toFloatRect();
    Rect crop = getCrop(s);
    if (bounds.isValid()) {
    if (!crop.isEmpty()) {
        // Layer has bounds. Pass in our bounds as a special case. Then pass on to our parents so
        win.intersect(crop, &win);
        // that they can clip it.
    }
        floatBounds = cropChildBounds(floatBounds);

    } else {
        // Layer does not have bounds, so we fill to our parent bounds. This is done by getting our
        // parent bounds and inverting the transform to get the maximum bounds we can have that
        // will fit within our parent bounds.
        const auto& p = mDrawingParent.promote();
        const auto& p = mDrawingParent.promote();
    FloatRect floatWin = win.toFloatRect();
    FloatRect parentBounds = floatWin;
        if (p != nullptr) {
        if (p != nullptr) {
        // We pass an empty Region here for reasons mirroring that of the case described in
            ui::Transform t = s.active_legacy.transform;
        // the computeScreenBounds reduceTransparentRegion=false case.
            // When calculating the parent bounds for purposes of clipping, we don't need to
        parentBounds = p->computeBounds(Region());
            // constrain the parent to its transparent region. The transparent region is an
            // optimization based on the buffer contents of the layer, but does not affect the
            // space allocated to it by policy, and thus children should be allowed to extend into
            // the parent's transparent region.
            // One of the main uses is a parent window with a child sitting behind the parent
            // window, marked by a transparent region. When computing the parent bounds from the
            // parent's perspective we pass in the transparent region to reduce buffer allocation
            // size. When computing the parent bounds from the child's perspective, we pass in an
            // empty transparent region in order to extend into the the parent bounds.
            floatBounds = p->computeBounds(Region());
            // Transform back to layer space.
            floatBounds = t.inverse().transform(floatBounds);
        }
    }
    }


    ui::Transform t = s.active_legacy.transform;
    // Subtract the transparent region and snap to the bounds.
    return reduce(floatBounds, activeTransparentRegion);
}

FloatRect Layer::cropChildBounds(const FloatRect& childBounds) const {
    const State& s(getDrawingState());
    Rect bounds = getCroppedBufferSize(s);
    FloatRect croppedBounds = childBounds;

    // If the layer has bounds, then crop the passed in child bounds and pass
    // it to our parents so they can crop it as well. If the layer has no bounds,
    // then pass on the child bounds.
    if (bounds.isValid()) {
        croppedBounds = croppedBounds.intersect(bounds.toFloatRect());
    }


    const auto& p = mDrawingParent.promote();
    if (p != nullptr) {
    if (p != nullptr) {
        floatWin = t.transform(floatWin);
        // Transform to parent space and allow parent layer to crop the
        floatWin = floatWin.intersect(parentBounds);
        // child bounds as well.
        floatWin = t.inverse().transform(floatWin);
        ui::Transform t = s.active_legacy.transform;
        croppedBounds = t.transform(croppedBounds);
        croppedBounds = p->cropChildBounds(croppedBounds);
        croppedBounds = t.inverse().transform(croppedBounds);
    }
    return croppedBounds;
}
}


    // subtract the transparent region and snap to the bounds
Rect Layer::getCroppedBufferSize(const State& s) const {
    return reduce(floatWin, activeTransparentRegion);
    Rect size = getBufferSize(s);
    Rect crop = getCrop(s);
    if (!crop.isEmpty() && size.isValid()) {
        size.intersect(crop, &size);
    } else if (!crop.isEmpty()) {
        size = crop;
    }
    return size;
}
}


Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
+22 −1
Original line number Original line Diff line number Diff line
@@ -575,7 +575,7 @@ public:
    ssize_t removeChild(const sp<Layer>& layer);
    ssize_t removeChild(const sp<Layer>& layer);
    sp<Layer> getParent() const { return mCurrentParent.promote(); }
    sp<Layer> getParent() const { return mCurrentParent.promote(); }
    bool hasParent() const { return getParent() != nullptr; }
    bool hasParent() const { return getParent() != nullptr; }
    Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
    Rect computeScreenBounds() const;
    bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
    bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
    bool setChildRelativeLayer(const sp<Layer>& childLayer,
    bool setChildRelativeLayer(const sp<Layer>& childLayer,
            const sp<IBinder>& relativeToHandle, int32_t relativeZ);
            const sp<IBinder>& relativeToHandle, int32_t relativeZ);
@@ -785,6 +785,27 @@ private:
                                       const LayerVector::Visitor& visitor);
                                       const LayerVector::Visitor& visitor);
    LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
    LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
                                          const std::vector<Layer*>& layersInTree);
                                          const std::vector<Layer*>& layersInTree);

    /**
     * Retuns the child bounds in layer space cropped to its bounds as well all its parent bounds.
     * The cropped bounds must be transformed back from parent layer space to child layer space by
     * applying the inverse of the child's transformation.
     */
    FloatRect cropChildBounds(const FloatRect& childBounds) const;

    /**
     * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
     * INVALID_RECT if the layer has no buffer and no crop.
     * A layer with an invalid buffer size and no crop is considered to be boundless. The layer
     * bounds are constrained by its parent bounds.
     */
    Rect getCroppedBufferSize(const Layer::State& s) const;

    /**
     * Returns active buffer size in the correct orientation. Buffer size is determined by undoing
     * any buffer transformations. If the layer has no buffer then return INVALID_RECT.
     */
    virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; }
};
};


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
Loading