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

Commit 3f085429 authored by Chris Craik's avatar Chris Craik
Browse files

Clip TouchFeedbackDrawable effect to receiver Outline

Projected RenderNodes are now wrapped with a ClipRect or masked
SaveLayer, so that they are clipped to the outline of the projection
receiver surface.

Change-Id: I1d4afc1bb5d638d650bc0b1dac51a498f216773e
parent fbb54b83
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
        jlong rendererPtr, jlong paintPtr, jint saveFlags) {
    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
    return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
            paint, saveFlags);
}
@@ -302,7 +302,7 @@ static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
        jlong rendererPtr, jint alpha, jint saveFlags) {
    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
    return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
            alpha, saveFlags);
}
@@ -356,7 +356,7 @@ static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
        jlong rendererPtr, jobject rect) {
    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());

    env->CallVoidMethod(rect, gRectClassInfo.set,
            int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
@@ -870,8 +870,7 @@ static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
    return reinterpret_cast<jlong>(renderer->finishRecording());
}

static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
        jobject clazz) {
static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
    return reinterpret_cast<jlong>(new DisplayListRenderer);
}

+3 −4
Original line number Diff line number Diff line
@@ -362,8 +362,7 @@ public class TouchFeedbackDrawable extends LayerDrawable {
                // first. This will merge SRC_OVER (directly) onto the canvas.
                if (!projected && rippleRestoreCount < 0) {
                    rippleRestoreCount = canvas.saveLayer(bounds.left, bounds.top,
                            bounds.right, bounds.bottom, null, 0);
                    canvas.clipRect(bounds);
                            bounds.right, bounds.bottom, null);
                }

                drewRipples |= ripple.draw(canvas, getRipplePaint());
@@ -381,7 +380,7 @@ public class TouchFeedbackDrawable extends LayerDrawable {
        if (drewRipples && !projected && rippleRestoreCount >= 0) {
            final PorterDuffXfermode xfermode = mState.getTintXfermode();
            canvas.saveLayer(bounds.left, bounds.top,
                    bounds.right, bounds.bottom, getMaskingPaint(xfermode), 0);
                    bounds.right, bounds.bottom, getMaskingPaint(xfermode));
        }

        Drawable mask = null;
@@ -399,7 +398,7 @@ public class TouchFeedbackDrawable extends LayerDrawable {
        if (mask != null && drewRipples) {
            // TODO: This will also mask the lower layer, which is bad.
            canvas.saveLayer(bounds.left, bounds.top, bounds.right,
                    bounds.bottom, getMaskingPaint(DST_IN), 0);
                    bounds.bottom, getMaskingPaint(DST_IN));
            mask.draw(canvas);
        }

+4 −1
Original line number Diff line number Diff line
@@ -29,7 +29,10 @@
namespace android {
namespace uirenderer {

DisplayListData::DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {
DisplayListData::DisplayListData()
        : projectionReceiveIndex(-1)
        , functorCount(0)
        , hasDrawOps(false) {
}

DisplayListData::~DisplayListData() {
+20 −3
Original line number Diff line number Diff line
@@ -318,12 +318,19 @@ private:
class SaveLayerOp : public StateOp {
public:
    SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
            : mArea(left, top, right, bottom), mPaint(&mCachedPaint), mFlags(flags) {
            : mArea(left, top, right, bottom)
            , mPaint(&mCachedPaint)
            , mFlags(flags)
            , mConvexMask(NULL) {
        mCachedPaint.setAlpha(alpha);
    }

    SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
            : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
            : mArea(left, top, right, bottom)
            , mPaint(paint)
            , mFlags(flags)
            , mConvexMask(NULL)
    {}

    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
            bool useQuickReject) {
@@ -338,7 +345,8 @@ public:
    }

    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mPaint, mFlags);
        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
                mPaint, mFlags, mConvexMask);
    }

    virtual void output(int level, uint32_t logFlags) const {
@@ -350,6 +358,11 @@ public:

    int getFlags() { return mFlags; }

    // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
    void setMask(const SkPath* convexMask) {
        mConvexMask = convexMask;
    }

private:
    bool isSaveLayerAlpha() const {
        SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
@@ -361,6 +374,10 @@ private:
    const SkPaint* mPaint;
    SkPaint mCachedPaint;
    int mFlags;

    // Convex path, points at data in RenderNode, valid for the duration of the frame only
    // Only used for masking the SaveLayer which wraps projected RenderNodes
    const SkPath* mConvexMask;
};

class TranslateOp : public StateOp {
+4 −9
Original line number Diff line number Diff line
@@ -184,20 +184,15 @@ status_t DisplayListRenderer::drawDisplayList(RenderNode* displayList,
    // dirty is an out parameter and should not be recorded,
    // it matters only when replaying the display list

    // TODO: To be safe, the display list should be ref-counted in the
    //       resources cache, but we rely on the caller (UI toolkit) to
    //       do the right thing for now
    if (displayList->stagingProperties().isProjectionReceiver()) {
        // use staging property, since recording on UI thread
        mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
    }

    DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
            flags, *currentTransform());
    addDrawOp(op);
    mDisplayListData->addChild(op);

    if (displayList->stagingProperties().isProjectionReceiver()) {
        // use staging property, since recording on UI thread
        mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1;
    }

    return DrawGlInfo::kStatusDone;
}

Loading