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

Commit 967e2bf3 authored by Romain Guy's avatar Romain Guy
Browse files

Preliminary support for clipRect(Rect, Op)

This adds basic support for clip regions. It is currently disabled at compile
time. Enabling clip regions will require setting up a stencil buffer.

Change-Id: I638616a972276e38737f8ac0633692c3845eaa74
parent 0afa7e2d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -12734,9 +12734,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
     * </p>
     *
     * <p>
     * The actual mesurement work of a view is performed in
     * The actual measurement work of a view is performed in
     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
     * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
     * </p>
     *
     *
+14 −0
Original line number Diff line number Diff line
@@ -55,43 +55,51 @@ public:
            void        set(uint32_t w, uint32_t h);
        
            Region&     orSelf(const Rect& rhs);
            Region&     xorSelf(const Rect& rhs);
            Region&     andSelf(const Rect& rhs);
            Region&     subtractSelf(const Rect& rhs);

            // boolean operators, applied on this
            Region&     orSelf(const Region& rhs);
            Region&     xorSelf(const Region& rhs);
            Region&     andSelf(const Region& rhs);
            Region&     subtractSelf(const Region& rhs);

            // boolean operators
    const   Region      merge(const Rect& rhs) const;
    const   Region      mergeExclusive(const Rect& rhs) const;
    const   Region      intersect(const Rect& rhs) const;
    const   Region      subtract(const Rect& rhs) const;

            // boolean operators
    const   Region      merge(const Region& rhs) const;
    const   Region      mergeExclusive(const Region& rhs) const;
    const   Region      intersect(const Region& rhs) const;
    const   Region      subtract(const Region& rhs) const;

            // these translate rhs first
            Region&     translateSelf(int dx, int dy);
            Region&     orSelf(const Region& rhs, int dx, int dy);
            Region&     xorSelf(const Region& rhs, int dx, int dy);
            Region&     andSelf(const Region& rhs, int dx, int dy);
            Region&     subtractSelf(const Region& rhs, int dx, int dy);

            // these translate rhs first
    const   Region      translate(int dx, int dy) const;
    const   Region      merge(const Region& rhs, int dx, int dy) const;
    const   Region      mergeExclusive(const Region& rhs, int dx, int dy) const;
    const   Region      intersect(const Region& rhs, int dx, int dy) const;
    const   Region      subtract(const Region& rhs, int dx, int dy) const;

    // convenience operators overloads
    inline  const Region      operator | (const Region& rhs) const;
    inline  const Region      operator ^ (const Region& rhs) const;
    inline  const Region      operator & (const Region& rhs) const;
    inline  const Region      operator - (const Region& rhs) const;
    inline  const Region      operator + (const Point& pt) const;

    inline  Region&     operator |= (const Region& rhs);
    inline  Region&     operator ^= (const Region& rhs);
    inline  Region&     operator &= (const Region& rhs);
    inline  Region&     operator -= (const Region& rhs);
    inline  Region&     operator += (const Point& pt);
@@ -158,6 +166,9 @@ private:
const Region Region::operator | (const Region& rhs) const {
    return merge(rhs);
}
const Region Region::operator ^ (const Region& rhs) const {
    return mergeExclusive(rhs);
}
const Region Region::operator & (const Region& rhs) const {
    return intersect(rhs);
}
@@ -172,6 +183,9 @@ const Region Region::operator + (const Point& pt) const {
Region& Region::operator |= (const Region& rhs) {
    return orSelf(rhs);
}
Region& Region::operator ^= (const Region& rhs) {
    return xorSelf(rhs);
}
Region& Region::operator &= (const Region& rhs) {
    return andSelf(rhs);
}
+121 −19
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
    transform = &mTransformRoot;
    clipRect = &mClipRectRoot;
    region = NULL;
    clipRegion = NULL;
}

/**
@@ -52,8 +53,21 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
    if (saveFlags & SkCanvas::kClip_SaveFlag) {
        mClipRectRoot.set(*s->clipRect);
        clipRect = &mClipRectRoot;
#if STENCIL_BUFFER_SIZE
        if (s->clipRegion) {
            mClipRegionRoot.merge(*s->clipRegion);
            clipRegion = &mClipRegionRoot;
        } else {
            clipRegion = NULL;
        }
#else
        clipRegion = NULL;
#endif
    } else {
        clipRect = s->clipRect;
#if STENCIL_BUFFER_SIZE
        clipRegion = s->clipRegion;
#endif
    }

    if (s->flags & Snapshot::kFlagFboTarget) {
@@ -68,6 +82,77 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
// Clipping
///////////////////////////////////////////////////////////////////////////////

void Snapshot::ensureClipRegion() {
#if STENCIL_BUFFER_SIZE
    if (!clipRegion) {
        clipRegion = &mClipRegionRoot;
        android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
        clipRegion->set(tmp);
    }
#endif
}

void Snapshot::copyClipRectFromRegion() {
#if STENCIL_BUFFER_SIZE
    if (!clipRegion->isEmpty()) {
        android::Rect bounds(clipRegion->bounds());
        clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom);

        if (clipRegion->isRect()) {
            clipRegion->clear();
            clipRegion = NULL;
        }
    } else {
        clipRect->setEmpty();
        clipRegion = NULL;
    }
#endif
}

bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
    android::Rect tmp(left, top, right, bottom);
    clipRegion->orSelf(tmp);
    copyClipRectFromRegion();
    return true;
#else
    return false;
#endif
}

bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
    android::Rect tmp(left, top, right, bottom);
    clipRegion->xorSelf(tmp);
    copyClipRectFromRegion();
    return true;
#else
    return false;
#endif
}

bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
    android::Rect tmp(left, top, right, bottom);
    clipRegion->andSelf(tmp);
    copyClipRectFromRegion();
    return true;
#else
    return false;
#endif
}

bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
    android::Rect tmp(left, top, right, bottom);
    clipRegion->subtractSelf(tmp);
    copyClipRectFromRegion();
    return true;
#else
    return false;
#endif
}

bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
    Rect r(left, top, right, bottom);
    transform->mapRect(r);
@@ -77,33 +162,47 @@ bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::
bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
    bool clipped = false;

    // NOTE: The unimplemented operations require support for regions
    // Supporting regions would require using a stencil buffer instead
    // of the scissor. The stencil buffer itself is not too expensive
    // (memory cost excluded) but on fillrate limited devices, managing
    // the stencil might have a negative impact on the framerate.
    switch (op) {
        case SkRegion::kDifference_Op:
        case SkRegion::kDifference_Op: {
            ensureClipRegion();
            clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
            break;
        case SkRegion::kIntersect_Op:
        }
        case SkRegion::kIntersect_Op: {
            if (CC_UNLIKELY(clipRegion)) {
                clipped = clipRegionOr(r.left, r.top, r.right, r.bottom);
            } else {
                clipped = clipRect->intersect(r);
                if (!clipped) {
                    clipRect->setEmpty();
                    clipped = true;
                }
            }
            break;
        case SkRegion::kUnion_Op:
        }
        case SkRegion::kUnion_Op: {
            if (CC_UNLIKELY(clipRegion)) {
                clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom);
            } else {
                clipped = clipRect->unionWith(r);
            }
            break;
        case SkRegion::kXOR_Op:
        }
        case SkRegion::kXOR_Op: {
            ensureClipRegion();
            clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
            break;
        case SkRegion::kReverseDifference_Op:
        }
        case SkRegion::kReverseDifference_Op: {
            // TODO!!!!!!!
            break;
        case SkRegion::kReplace_Op:
            clipRect->set(r);
        }
        case SkRegion::kReplace_Op: {
            setClip(r.left, r.top, r.right, r.bottom);
            clipped = true;
            break;
        }
    }

    if (clipped) {
        flags |= Snapshot::kFlagClipSet;
@@ -114,6 +213,10 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {

void Snapshot::setClip(float left, float top, float right, float bottom) {
    clipRect->set(left, top, right, bottom);
    if (clipRegion) {
        clipRegion->clear();
        clipRegion = NULL;
    }
    flags |= Snapshot::kFlagClipSet;
}

@@ -129,8 +232,7 @@ const Rect& Snapshot::getLocalClip() {

void Snapshot::resetClip(float left, float top, float right, float bottom) {
    clipRect = &mClipRectRoot;
    clipRect->set(left, top, right, bottom);
    flags |= Snapshot::kFlagClipSet;
    setClip(left, top, right, bottom);
}

///////////////////////////////////////////////////////////////////////////////
+24 −1
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ public:
    mat4* transform;

    /**
     * Current clip region. The clip is stored in canvas-space coordinates,
     * Current clip rect. The clip is stored in canvas-space coordinates,
     * (screen-space coordinates in the regular case.)
     *
     * This is a reference to a rect owned by this snapshot or another
@@ -189,6 +189,17 @@ public:
     */
    Rect* clipRect;

    /**
     * Current clip region. The clip is stored in canvas-space coordinates,
     * (screen-space coordinates in the regular case.)
     *
     * This is a reference to a region owned by this snapshot or another
     * snapshot. This pointer must not be freed. See ::mClipRegionRoot.
     *
     * This field is used only if STENCIL_BUFFER_SIZE is > 0.
     */
    Region* clipRegion;

    /**
     * The ancestor layer's dirty region.
     *
@@ -198,10 +209,22 @@ public:
    Region* region;

private:
    void ensureClipRegion();
    void copyClipRectFromRegion();

    bool clipRegionOr(float left, float top, float right, float bottom);
    bool clipRegionXor(float left, float top, float right, float bottom);
    bool clipRegionAnd(float left, float top, float right, float bottom);
    bool clipRegionNand(float left, float top, float right, float bottom);

    mat4 mTransformRoot;
    Rect mClipRectRoot;
    Rect mLocalClip;

#if STENCIL_BUFFER_SIZE
    Region mClipRegionRoot;
#endif

}; // class Snapshot

}; // namespace uirenderer
+19 −0
Original line number Diff line number Diff line
@@ -126,6 +126,9 @@ void Region::addRectUnchecked(int l, int t, int r, int b)
Region& Region::orSelf(const Rect& r) {
    return operationSelf(r, op_or);
}
Region& Region::xorSelf(const Rect& r) {
    return operationSelf(r, op_xor);
}
Region& Region::andSelf(const Rect& r) {
    return operationSelf(r, op_and);
}
@@ -143,6 +146,9 @@ Region& Region::operationSelf(const Rect& r, int op) {
Region& Region::orSelf(const Region& rhs) {
    return operationSelf(rhs, op_or);
}
Region& Region::xorSelf(const Region& rhs) {
    return operationSelf(rhs, op_xor);
}
Region& Region::andSelf(const Region& rhs) {
    return operationSelf(rhs, op_and);
}
@@ -165,6 +171,9 @@ Region& Region::translateSelf(int x, int y) {
const Region Region::merge(const Rect& rhs) const {
    return operation(rhs, op_or);
}
const Region Region::mergeExclusive(const Rect& rhs) const {
    return operation(rhs, op_xor);
}
const Region Region::intersect(const Rect& rhs) const {
    return operation(rhs, op_and);
}
@@ -182,6 +191,9 @@ const Region Region::operation(const Rect& rhs, int op) const {
const Region Region::merge(const Region& rhs) const {
    return operation(rhs, op_or);
}
const Region Region::mergeExclusive(const Region& rhs) const {
    return operation(rhs, op_xor);
}
const Region Region::intersect(const Region& rhs) const {
    return operation(rhs, op_and);
}
@@ -205,6 +217,9 @@ const Region Region::translate(int x, int y) const {
Region& Region::orSelf(const Region& rhs, int dx, int dy) {
    return operationSelf(rhs, dx, dy, op_or);
}
Region& Region::xorSelf(const Region& rhs, int dx, int dy) {
    return operationSelf(rhs, dx, dy, op_xor);
}
Region& Region::andSelf(const Region& rhs, int dx, int dy) {
    return operationSelf(rhs, dx, dy, op_and);
}
@@ -222,6 +237,9 @@ Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) {
const Region Region::merge(const Region& rhs, int dx, int dy) const {
    return operation(rhs, dx, dy, op_or);
}
const Region Region::mergeExclusive(const Region& rhs, int dx, int dy) const {
    return operation(rhs, dx, dy, op_xor);
}
const Region Region::intersect(const Region& rhs, int dx, int dy) const {
    return operation(rhs, dx, dy, op_and);
}
@@ -421,6 +439,7 @@ void Region::boolean_operation(int op, Region& dst,
    SkRegion::Op sk_op;
    switch (op) {
        case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break;
        case op_xor: sk_op = SkRegion::kUnion_XOR; name="XOR"; break;
        case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break;
        case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break;
    }
Loading