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

Commit 9f935c28 authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Revert "Support alpha for SurfaceView""

parents 092b57fa 3fde6cee
Loading
Loading
Loading
Loading
+67 −59
Original line number Diff line number Diff line
@@ -107,14 +107,6 @@ import java.util.function.Consumer;
 * and scaling a SurfaceView on screen will not cause rendering artifacts. Such
 * artifacts may occur on previous versions of the platform when its window is
 * positioned asynchronously.</p>
 *
 * <p class="note"><strong>Note:</strong> Starting in platform version
 * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, SurfaceView will support arbitrary
 * alpha blending. Prior platform versions ignored alpha values on the SurfaceView if they were
 * between 0 and 1. If the SurfaceView is configured with Z-above, then the alpha is applied
 * directly to the Surface. If the SurfaceView is configured with Z-below, then the alpha is
 * applied to the hole punch directly. Note that when using Z-below, overlapping SurfaceViews
 * may not blend properly as a consequence of not applying alpha to the surface content directly.
 */
public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
    private static final String TAG = "SurfaceView";
@@ -154,7 +146,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    Paint mRoundedViewportPaint;

    int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
    int mRequestedSubLayer = APPLICATION_MEDIA_SUBLAYER;

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    boolean mIsCreating = false;
@@ -186,7 +177,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    @UnsupportedAppUsage
    int mRequestedFormat = PixelFormat.RGB_565;

    float mAlpha = 1f;
    boolean mUseAlpha = false;
    float mSurfaceAlpha = 1f;
    boolean mClipSurfaceToBounds;
    int mBackgroundColor = Color.BLACK;

@@ -343,25 +335,58 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
     * @hide
     */
    public void setUseAlpha() {
        // TODO(b/241474646): Remove me
        return;
        if (!mUseAlpha) {
            mUseAlpha = true;
            updateSurfaceAlpha();
        }
    }

    @Override
    public void setAlpha(float alpha) {
        // Sets the opacity of the view to a value, where 0 means the view is completely transparent
        // and 1 means the view is completely opaque.
        //
        // Note: Alpha value of this view is ignored by default. To enable alpha blending, you need
        // to call setUseAlpha() as well.
        // This view doesn't support translucent opacity if the view is located z-below, since the
        // logic to punch a hole in the view hierarchy cannot handle such case. See also
        // #clearSurfaceViewPort(Canvas)
        if (DEBUG) {
            Log.d(TAG, System.identityHashCode(this)
                    + " setAlpha: alpha=" + alpha);
                    + " setAlpha: mUseAlpha = " + mUseAlpha + " alpha=" + alpha);
        }
        super.setAlpha(alpha);
        updateSurfaceAlpha();
    }

    @Override
    protected boolean onSetAlpha(int alpha) {
        if (Math.round(mAlpha * 255) != alpha) {
            updateSurface();
    private float getFixedAlpha() {
        // Compute alpha value to be set on the underlying surface.
        final float alpha = getAlpha();
        return mUseAlpha && (mSubLayer > 0 || alpha == 0f) ? alpha : 1f;
    }

    private void updateSurfaceAlpha() {
        if (!mUseAlpha || !mHaveFrame || mSurfaceControl == null) {
            return;
        }
        final float viewAlpha = getAlpha();
        if (mSubLayer < 0 && 0f < viewAlpha && viewAlpha < 1f) {
            Log.w(TAG, System.identityHashCode(this)
                    + " updateSurfaceAlpha:"
                    + " translucent color is not supported for a surface placed z-below.");
        }
        final ViewRootImpl viewRoot = getViewRootImpl();
        if (viewRoot == null) {
            return;
        }
        final float alpha = getFixedAlpha();
        if (alpha != mSurfaceAlpha) {
            final Transaction transaction = new Transaction();
            transaction.setAlpha(mSurfaceControl, alpha);
            viewRoot.applyTransactionOnDraw(transaction);
            damageInParent();
            mSurfaceAlpha = alpha;
        }
        return true;
    }

    private void performDrawFinished() {
@@ -509,15 +534,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        invalidate();
    }

    @Override
    public boolean hasOverlappingRendering() {
        // SurfaceViews only alpha composite by modulating the Surface alpha for Z-above, or
        // applying alpha on the hole punch for Z-below - no deferral to a layer is necessary.
        return false;
    }

    private void clearSurfaceViewPort(Canvas canvas) {
        final float alpha = getAlpha();
        if (mCornerRadius > 0f) {
            canvas.getClipBounds(mTmpRect);
            if (mClipSurfaceToBounds && mClipBounds != null) {
@@ -529,11 +546,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                    mTmpRect.right,
                    mTmpRect.bottom,
                    mCornerRadius,
                    mCornerRadius,
                    alpha
                    mCornerRadius
            );
        } else {
            canvas.punchHole(0f, 0f, getWidth(), getHeight(), 0f, 0f, alpha);
            canvas.punchHole(0f, 0f, getWidth(), getHeight(), 0f, 0f);
        }
    }

@@ -636,10 +652,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        } else {
            subLayer = APPLICATION_MEDIA_SUBLAYER;
        }
        if (mRequestedSubLayer == subLayer) {
        if (mSubLayer == subLayer) {
            return false;
        }
        mRequestedSubLayer = subLayer;
        mSubLayer = subLayer;

        if (!allowDynamicChange) {
            return false;
@@ -651,8 +667,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        if (viewRoot == null) {
            return true;
        }

        updateSurface();
        final Transaction transaction = new SurfaceControl.Transaction();
        updateRelativeZ(transaction);
        viewRoot.applyTransactionOnDraw(transaction);
        invalidate();
        return true;
    }
@@ -705,7 +722,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    }

    private void releaseSurfaces(boolean releaseSurfacePackage) {
        mAlpha = 1f;
        mSurfaceAlpha = 1f;

        synchronized (mSurfaceControlLock) {
            mSurface.destroy();
            if (mBlastBufferQueue != null) {
@@ -752,7 +770,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    }

    private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
            boolean creating, boolean sizeChanged, boolean hintChanged, boolean relativeZChanged,
            boolean creating, boolean sizeChanged, boolean hintChanged,
            Transaction surfaceUpdateTransaction) {
        boolean realSizeChanged = false;

@@ -782,20 +800,14 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                surfaceUpdateTransaction.hide(mSurfaceControl);
            }



            updateBackgroundVisibility(surfaceUpdateTransaction);
            updateBackgroundColor(surfaceUpdateTransaction);
            if (isAboveParent()) {
                float alpha = getAlpha();
            if (mUseAlpha) {
                float alpha = getFixedAlpha();
                surfaceUpdateTransaction.setAlpha(mSurfaceControl, alpha);
            }

            if (relativeZChanged) {
                if (!isAboveParent()) {
                    // If we're moving from z-above to z-below, then restore the surface alpha back to 1
                    // and let the holepunch drive visibility and blending.
                    surfaceUpdateTransaction.setAlpha(mSurfaceControl, 1.f);
                }
                updateRelativeZ(surfaceUpdateTransaction);
                mSurfaceAlpha = alpha;
            }

            surfaceUpdateTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
@@ -861,7 +873,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        } finally {
            mSurfaceLock.unlock();
        }

        return realSizeChanged;
    }

@@ -895,10 +906,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        int myHeight = mRequestedHeight;
        if (myHeight <= 0) myHeight = getHeight();

        final float alpha = getAlpha();
        final float alpha = getFixedAlpha();
        final boolean formatChanged = mFormat != mRequestedFormat;
        final boolean visibleChanged = mVisible != mRequestedVisible;
        final boolean alphaChanged = mAlpha != alpha;
        final boolean alphaChanged = mSurfaceAlpha != alpha;
        final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged)
                && mRequestedVisible;
        final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
@@ -910,17 +921,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            || getHeight() != mScreenRect.height();
        final boolean hintChanged = (viewRoot.getBufferTransformHint() != mTransformHint)
                && mRequestedVisible;
        final boolean relativeZChanged = mSubLayer != mRequestedSubLayer;

        if (creating || formatChanged || sizeChanged || visibleChanged
                || alphaChanged || windowVisibleChanged || positionChanged
                || layoutSizeChanged || hintChanged || relativeZChanged) {
        if (creating || formatChanged || sizeChanged || visibleChanged ||
                (mUseAlpha && alphaChanged) || windowVisibleChanged ||
                positionChanged || layoutSizeChanged || hintChanged) {

            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                    + "Changes: creating=" + creating
                    + " format=" + formatChanged + " size=" + sizeChanged
                    + " visible=" + visibleChanged + " alpha=" + alphaChanged
                    + " hint=" + hintChanged
                    + " mUseAlpha=" + mUseAlpha
                    + " visible=" + visibleChanged
                    + " left=" + (mWindowSpaceLeft != mLocation[0])
                    + " top=" + (mWindowSpaceTop != mLocation[1]));
@@ -932,10 +943,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                mSurfaceWidth = myWidth;
                mSurfaceHeight = myHeight;
                mFormat = mRequestedFormat;
                mAlpha = alpha;
                mLastWindowVisibility = mWindowVisibility;
                mTransformHint = viewRoot.getBufferTransformHint();
                mSubLayer = mRequestedSubLayer;

                mScreenRect.left = mWindowSpaceLeft;
                mScreenRect.top = mWindowSpaceTop;
@@ -959,7 +968,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                }

                final boolean redrawNeeded = sizeChanged || creating || hintChanged
                        || (mVisible && !mDrawFinished) || alphaChanged || relativeZChanged;
                        || (mVisible && !mDrawFinished);
                boolean shouldSyncBuffer =
                        redrawNeeded && viewRoot.wasRelayoutRequested() && viewRoot.isInLocalSync();
                SyncBufferTransactionCallback syncBufferTransactionCallback = null;
@@ -970,9 +979,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                            syncBufferTransactionCallback::onTransactionReady);
                }

                final boolean realSizeChanged = performSurfaceTransaction(viewRoot, translator,
                        creating, sizeChanged, hintChanged, relativeZChanged,
                        surfaceUpdateTransaction);
                final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
                        translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);

                try {
                    SurfaceHolder.Callback[] callbacks = null;
+3 −4
Original line number Diff line number Diff line
@@ -670,9 +670,8 @@ public abstract class BaseCanvas {
    /**
     * @hide
     */
    public void punchHole(float left, float top, float right, float bottom, float rx, float ry,
            float alpha) {
        nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, alpha);
    public void punchHole(float left, float top, float right, float bottom, float rx, float ry) {
        nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry);
    }

    /**
@@ -824,5 +823,5 @@ public abstract class BaseCanvas {
            float hOffset, float vOffset, int flags, long nativePaint);

    private static native void nPunchHole(long renderer, float left, float top, float right,
            float bottom, float rx, float ry, float alpha);
            float bottom, float rx, float ry);
}
+3 −4
Original line number Diff line number Diff line
@@ -610,9 +610,8 @@ public class BaseRecordingCanvas extends Canvas {
     * @hide
     */
    @Override
    public void punchHole(float left, float top, float right, float bottom, float rx, float ry,
            float alpha) {
        nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, alpha);
    public void punchHole(float left, float top, float right, float bottom, float rx, float ry) {
        nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry);
    }

    @FastNative
@@ -743,5 +742,5 @@ public class BaseRecordingCanvas extends Canvas {

    @FastNative
    private static native void nPunchHole(long renderer, float left, float top, float right,
            float bottom, float rx, float ry, float alpha);
            float bottom, float rx, float ry);
}
+3 −5
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@

#include "CanvasProperty.h"
#include "NinePatchUtils.h"
#include "SkBlendMode.h"
#include "VectorDrawable.h"
#include "hwui/Bitmap.h"
#include "hwui/MinikinUtils.h"
@@ -252,11 +251,10 @@ const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {
    return (rec && rec->saveCount == currentSaveCount) ? rec : nullptr;
}

void SkiaCanvas::punchHole(const SkRRect& rect, float alpha) {
void SkiaCanvas::punchHole(const SkRRect& rect) {
    SkPaint paint = SkPaint();
    paint.setColor(SkColors::kBlack);
    paint.setAlphaf(alpha);
    paint.setBlendMode(SkBlendMode::kDstOut);
    paint.setColor(0);
    paint.setBlendMode(SkBlendMode::kClear);
    mCanvas->drawRRect(rect, paint);
}

+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ public:
        LOG_ALWAYS_FATAL("SkiaCanvas does not support enableZ");
    }

    virtual void punchHole(const SkRRect& rect, float alpha) override;
    virtual void punchHole(const SkRRect& rect) override;

    virtual void setBitmap(const SkBitmap& bitmap) override;

Loading