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

Commit 80d61161 authored by Dan Stoza's avatar Dan Stoza
Browse files

SF: Switch computeBounds to return FloatRect

Switches Layer::computeBounds to return a FloatRect instead of a Rect.

During the computation of the bounds, we apply the layer transformation
to its nominal dimensions, clip it against its bounds (which are either
its parents bounds or the screen bounds), and apply the inverse of the
layer transformation.

Previously, the intermediate position (after transformation/clip, but
before inverse transformation) was stored as Rect, which is to say that
it was truncated to integer coordinates. After applying the inverse
transformation, this loss of precision can cause glitches where a layer
that should be clipped against, e.g., the side of the screen no longer
creates a watertight seal against that side.

In order to fix this, we now store the intermediate value as a FloatRect
and propagate float precision back through computeBounds. The callers of
computeBounds tend to then immediately apply the transform again, at
which point it is safe to round back to integer.

Bug: 64070729
Bug: 66431327
Bug: 69935057
Test: Modified android.view.cts.SurfaceViewSyncTest#
      testSurfaceViewBigScale no longer produces bogus display frames
Change-Id: If5987ca4ad76657f9670a5f59258f896180352e2
parent da9904d6
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -27,6 +27,17 @@ public:
    float getWidth() const { return right - left; }
    float getWidth() const { return right - left; }
    float getHeight() const { return bottom - top; }
    float getHeight() const { return bottom - top; }


    FloatRect intersect(const FloatRect& other) const {
        return {
            // Inline to avoid tromping on other min/max defines or adding a
            // dependency on STL
            (left > other.left) ? left : other.left,
            (top > other.top) ? top : other.top,
            (right < other.right) ? right : other.right,
            (bottom < other.bottom) ? bottom : other.bottom
        };
    }

    float left = 0.0f;
    float left = 0.0f;
    float top = 0.0f;
    float top = 0.0f;
    float right = 0.0f;
    float right = 0.0f;
+9 −0
Original line number Original line Diff line number Diff line
@@ -69,6 +69,15 @@ public:
        bottom = rb.y;
        bottom = rb.y;
    }
    }


    inline explicit Rect(const FloatRect& floatRect) {
        // Ideally we would use std::round, but we don't want to add an STL
        // dependency here, so we use an approximation
        left = static_cast<int32_t>(floatRect.left + 0.5f);
        top = static_cast<int32_t>(floatRect.top + 0.5f);
        right = static_cast<int32_t>(floatRect.right + 0.5f);
        bottom = static_cast<int32_t>(floatRect.bottom + 0.5f);
    }

    void makeInvalid();
    void makeInvalid();


    inline void clear() {
    inline void clear() {
+3 −2
Original line number Original line Diff line number Diff line
@@ -787,16 +787,17 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT
     * minimal value)? Or, we could make GL behave like HWC -- but this feel
     * minimal value)? Or, we could make GL behave like HWC -- but this feel
     * like more of a hack.
     * like more of a hack.
     */
     */
    Rect win(computeBounds());
    const Rect bounds{computeBounds()}; // Rounds from FloatRect


    Transform t = getTransform();
    Transform t = getTransform();
    Rect win = bounds;
    if (!s.finalCrop.isEmpty()) {
    if (!s.finalCrop.isEmpty()) {
        win = t.transform(win);
        win = t.transform(win);
        if (!win.intersect(s.finalCrop, &win)) {
        if (!win.intersect(s.finalCrop, &win)) {
            win.clear();
            win.clear();
        }
        }
        win = t.inverse().transform(win);
        win = t.inverse().transform(win);
        if (!win.intersect(computeBounds(), &win)) {
        if (!win.intersect(bounds, &win)) {
            win.clear();
            win.clear();
        }
        }
    }
    }
+20 −8
Original line number Original line Diff line number Diff line
@@ -285,6 +285,14 @@ static Rect reduce(const Rect& win, const Region& exclude) {
    return Region(win).subtract(exclude).getBounds();
    return Region(win).subtract(exclude).getBounds();
}
}


static FloatRect reduce(const FloatRect& win, const Region& exclude) {
    if (CC_LIKELY(exclude.isEmpty())) {
        return win;
    }
    // Convert through Rect (by rounding) for lack of FloatRegion
    return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
}

Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
    const Layer::State& s(getDrawingState());
    const Layer::State& s(getDrawingState());
    Rect win(s.active.w, s.active.h);
    Rect win(s.active.w, s.active.h);
@@ -323,12 +331,12 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
    return win;
    return win;
}
}


Rect Layer::computeBounds() const {
FloatRect Layer::computeBounds() const {
    const Layer::State& s(getDrawingState());
    const Layer::State& s(getDrawingState());
    return computeBounds(s.activeTransparentRegion);
    return computeBounds(s.activeTransparentRegion);
}
}


Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
    const Layer::State& s(getDrawingState());
    const Layer::State& s(getDrawingState());
    Rect win(s.active.w, s.active.h);
    Rect win(s.active.w, s.active.h);


@@ -345,14 +353,16 @@ Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
    }
    }


    Transform t = getTransform();
    Transform t = getTransform();

    FloatRect floatWin = win.toFloatRect();
    if (p != nullptr) {
    if (p != nullptr) {
        win = t.transform(win);
        floatWin = t.transform(floatWin);
        win.intersect(bounds, &win);
        floatWin = floatWin.intersect(bounds.toFloatRect());
        win = t.inverse().transform(win);
        floatWin = t.inverse().transform(floatWin);
    }
    }


    // subtract the transparent region and snap to the bounds
    // subtract the transparent region and snap to the bounds
    return reduce(win, activeTransparentRegion);
    return reduce(floatWin, activeTransparentRegion);
}
}


Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const {
Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const {
@@ -528,7 +538,9 @@ void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z
                Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom));
                Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom));
    }
    }


    Rect frame(t.transform(computeBounds(activeTransparentRegion)));
    // computeBounds returns a FloatRect to provide more accuracy during the
    // transformation. We then round upon constructing 'frame'.
    Rect frame{t.transform(computeBounds(activeTransparentRegion))};
    if (!s.finalCrop.isEmpty()) {
    if (!s.finalCrop.isEmpty()) {
        if (!frame.intersect(s.finalCrop, &frame)) {
        if (!frame.intersect(s.finalCrop, &frame)) {
            frame.clear();
            frame.clear();
@@ -807,7 +819,7 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh,
    const Layer::State& s(getDrawingState());
    const Layer::State& s(getDrawingState());
    const Transform renderAreaTransform(renderArea.getTransform());
    const Transform renderAreaTransform(renderArea.getTransform());
    const uint32_t height = renderArea.getHeight();
    const uint32_t height = renderArea.getHeight();
    Rect win = computeBounds();
    FloatRect win = computeBounds();


    vec2 lt = vec2(win.left, win.top);
    vec2 lt = vec2(win.left, win.top);
    vec2 lb = vec2(win.left, win.bottom);
    vec2 lb = vec2(win.left, win.bottom);
+3 −2
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
#include <utils/String8.h>
#include <utils/String8.h>
#include <utils/Timers.h>
#include <utils/Timers.h>


#include <ui/FloatRect.h>
#include <ui/FrameStats.h>
#include <ui/FrameStats.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <ui/PixelFormat.h>
@@ -303,8 +304,8 @@ public:
    }
    }


    void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const;
    void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const;
    Rect computeBounds(const Region& activeTransparentRegion) const;
    FloatRect computeBounds(const Region& activeTransparentRegion) const;
    Rect computeBounds() const;
    FloatRect computeBounds() const;


    int32_t getSequence() const { return sequence; }
    int32_t getSequence() const { return sequence; }


Loading