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

Commit 16ecda53 authored by Chris Craik's avatar Chris Craik
Browse files

Update view's alpha and layer docs

bug:8501661

Makes the performance issues and interaction with layer type/paint
more clear.

Additionally, corrects change from 47ab7d66
to still allow displayList alpha to override layer paint

Change-Id: Ic94d75865700820489370461cd8ac9f9077a8d90
parent 0102443c
Loading
Loading
Loading
Loading
+21 −17
Original line number Original line Diff line number Diff line
@@ -9485,17 +9485,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
     * completely transparent and 1 means the view is completely opaque.</p>
     * completely transparent and 1 means the view is completely opaque.</p>
     *
     *
     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
     * performance implications, especially for large views. It is best to use the alpha property
     * sparingly and transiently, as in the case of fading animations.</p>
     *
     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
     * strongly recommended for performance reasons to either override
     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
     *
     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
     * responsible for applying the opacity itself. Otherwise, calling this method is
     * responsible for applying the opacity itself.</p>
     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
     * setting a hardware layer.</p>
     *
     *
     * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
     * <p>Note that if the view is backed by a
     * performance implications. It is generally best to use the alpha property sparingly and
     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
     * transiently, as in the case of fading animations.</p>
     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
     * 1.0 will supercede the alpha of the layer paint.</p>
     *
     *
     * @param alpha The opacity of the view.
     * @param alpha The opacity of the view.
     *
     *
     * @see #hasOverlappingRendering()
     * @see #setLayerType(int, android.graphics.Paint)
     * @see #setLayerType(int, android.graphics.Paint)
     *
     *
     * @attr ref android.R.styleable#View_alpha
     * @attr ref android.R.styleable#View_alpha
@@ -12365,13 +12374,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * </ul>
     * </ul>
     *
     *
     * <p>If this view has an alpha value set to < 1.0 by calling
     * <p>If this view has an alpha value set to < 1.0 by calling
     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
     * by this view's alpha value.</p>
     * equivalent to setting a hardware layer on this view and providing a paint with
     * the desired alpha value.</p>
     *
     *
     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
     * for more information on when and how to use layers.</p>
     * for more information on when and how to use layers.</p>
     *
     *
     * @param layerType The type of layer to use with this view, must be one of
     * @param layerType The type of layer to use with this view, must be one of
@@ -12441,11 +12448,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
     * </ul>
     * </ul>
     *
     *
     * <p>If this view has an alpha value set to < 1.0 by calling
     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
     * alpha value of the layer's paint is superceded by this view's alpha value.</p>
     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
     * equivalent to setting a hardware layer on this view and providing a paint with
     * the desired alpha value.</p>
     *
     *
     * @param paint The paint used to compose the layer. This argument is optional
     * @param paint The paint used to compose the layer. This argument is optional
     *        and can be null. It is ignored when the layer type is
     *        and can be null. It is ignored when the layer type is
+7 −2
Original line number Original line Diff line number Diff line
@@ -352,7 +352,9 @@ void DisplayList::outputViewProperties(const int level) {
        }
        }
    }
    }
    if (mAlpha < 1) {
    if (mAlpha < 1) {
        if (mCaching || !mHasOverlappingRendering) {
        if (mCaching) {
            ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mAlpha);
        } else if (!mHasOverlappingRendering) {
            ALOGD("%*sScaleAlpha %.2f", level * 2, "", mAlpha);
            ALOGD("%*sScaleAlpha %.2f", level * 2, "", mAlpha);
        } else {
        } else {
            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
@@ -400,7 +402,9 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler,
        }
        }
    }
    }
    if (mAlpha < 1) {
    if (mAlpha < 1) {
        if (mCaching || !mHasOverlappingRendering) {
        if (mCaching) {
            renderer.setOverrideLayerAlpha(mAlpha);
        } else if (!mHasOverlappingRendering) {
            renderer.scaleAlpha(mAlpha);
            renderer.scaleAlpha(mAlpha);
        } else {
        } else {
            // TODO: should be able to store the size of a DL at record time and not
            // TODO: should be able to store the size of a DL at record time and not
@@ -513,6 +517,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level)
    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
    handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
    handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
    renderer.restoreToCount(restoreTo);
    renderer.restoreToCount(restoreTo);
    renderer.setOverrideLayerAlpha(1.0f);
}
}


}; // namespace uirenderer
}; // namespace uirenderer
+20 −5
Original line number Original line Diff line number Diff line
@@ -114,6 +114,7 @@ OpenGLRenderer::OpenGLRenderer():
        mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
        mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
    mDrawModifiers.mShader = NULL;
    mDrawModifiers.mShader = NULL;
    mDrawModifiers.mColorFilter = NULL;
    mDrawModifiers.mColorFilter = NULL;
    mDrawModifiers.mOverrideLayerAlpha = 1.0f;
    mDrawModifiers.mHasShadow = false;
    mDrawModifiers.mHasShadow = false;
    mDrawModifiers.mHasDrawFilter = false;
    mDrawModifiers.mHasDrawFilter = false;


@@ -1074,7 +1075,7 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
            layer->setFilter(GL_LINEAR, true);
            layer->setFilter(GL_LINEAR, true);
        }
        }


        float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha;
        float alpha = getLayerAlpha(layer);
        bool blend = layer->isBlend() || alpha < 1.0f;
        bool blend = layer->isBlend() || alpha < 1.0f;
        drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
        drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
                layer->getTexture(), alpha, layer->getMode(), blend,
                layer->getTexture(), alpha, layer->getMode(), blend,
@@ -1112,7 +1113,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
            rects = safeRegion.getArray(&count);
            rects = safeRegion.getArray(&count);
        }
        }


        const float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha;
        const float alpha = getLayerAlpha(layer);
        const float texX = 1.0f / float(layer->getWidth());
        const float texX = 1.0f / float(layer->getWidth());
        const float texY = 1.0f / float(layer->getHeight());
        const float texY = 1.0f / float(layer->getHeight());
        const float height = rect.getHeight();
        const float height = rect.getHeight();
@@ -2237,7 +2238,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const
        float left, float top, float right, float bottom, SkPaint* paint) {
        float left, float top, float right, float bottom, SkPaint* paint) {
    int alpha;
    int alpha;
    SkXfermode::Mode mode;
    SkXfermode::Mode mode;
    getAlphaAndModeDirect(paint, &alpha, &mode);
    getAlphaAndMode(paint, &alpha, &mode);


    return drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
    return drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
            left, top, right, bottom, alpha, mode);
            left, top, right, bottom, alpha, mode);
@@ -2990,7 +2991,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
        if (layer->region.isRect()) {
        if (layer->region.isRect()) {
            composeLayerRect(layer, layer->regionRect);
            composeLayerRect(layer, layer->regionRect);
        } else if (layer->mesh) {
        } else if (layer->mesh) {
            const float a = layer->getAlpha() / 255.0f * mSnapshot->alpha;
            const float a = getLayerAlpha(layer);
            setupDraw();
            setupDraw();
            setupDrawWithTexture();
            setupDrawWithTexture();
            setupDrawColor(a, a, a, a);
            setupDrawColor(a, a, a, a);
@@ -3446,10 +3447,24 @@ void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, flo
    TextureVertex::setUV(v++, u2, v2);
    TextureVertex::setUV(v++, u2, v2);
}
}


void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const {
    getAlphaAndModeDirect(paint, alpha,  mode);
    getAlphaAndModeDirect(paint, alpha,  mode);
    if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) {
        // if drawing a layer, ignore the paint's alpha
        *alpha = mDrawModifiers.mOverrideLayerAlpha;
    }
    *alpha *= mSnapshot->alpha;
    *alpha *= mSnapshot->alpha;
}
}


float OpenGLRenderer::getLayerAlpha(Layer* layer) const {
    float alpha;
    if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) {
        alpha = mDrawModifiers.mOverrideLayerAlpha;
    } else {
        alpha = layer->getAlpha() / 255.0f;
    }
    return alpha * mSnapshot->alpha;
}

}; // namespace uirenderer
}; // namespace uirenderer
}; // namespace android
}; // namespace android
+16 −4
Original line number Original line Diff line number Diff line
@@ -51,6 +51,7 @@ namespace uirenderer {
struct DrawModifiers {
struct DrawModifiers {
    SkiaShader* mShader;
    SkiaShader* mShader;
    SkiaColorFilter* mColorFilter;
    SkiaColorFilter* mColorFilter;
    float mOverrideLayerAlpha;


    // Drop shadow
    // Drop shadow
    bool mHasShadow;
    bool mHasShadow;
@@ -275,6 +276,9 @@ public:
    virtual void resetPaintFilter();
    virtual void resetPaintFilter();
    virtual void setupPaintFilter(int clearBits, int setBits);
    virtual void setupPaintFilter(int clearBits, int setBits);


    // If this value is set to < 1.0, it overrides alpha set on layer (see drawBitmap, drawLayer)
    void setOverrideLayerAlpha(float alpha) { mDrawModifiers.mOverrideLayerAlpha = alpha; }

    SkPaint* filterPaint(SkPaint* paint);
    SkPaint* filterPaint(SkPaint* paint);


    bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
    bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
@@ -283,7 +287,6 @@ public:
    const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
    const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
    void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
    void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }


    // TODO: what does this mean? no perspective? no rotate?
    ANDROID_API bool isCurrentTransformSimple() {
    ANDROID_API bool isCurrentTransformSimple() {
        return mSnapshot->transform->isSimple();
        return mSnapshot->transform->isSimple();
    }
    }
@@ -325,7 +328,8 @@ public:
    /**
    /**
     * Gets the alpha and xfermode out of a paint object. If the paint is null
     * Gets the alpha and xfermode out of a paint object. If the paint is null
     * alpha will be 255 and the xfermode will be SRC_OVER. This method does
     * alpha will be 255 and the xfermode will be SRC_OVER. This method does
     * not multiply the paint's alpha by the current snapshot's alpha.
     * not multiply the paint's alpha by the current snapshot's alpha, and does
     * not replace the alpha with the overrideLayerAlpha
     *
     *
     * @param paint The paint to extract values from
     * @param paint The paint to extract values from
     * @param alpha Where to store the resulting alpha
     * @param alpha Where to store the resulting alpha
@@ -450,13 +454,21 @@ protected:


    /**
    /**
     * Gets the alpha and xfermode out of a paint object. If the paint is null
     * Gets the alpha and xfermode out of a paint object. If the paint is null
     * alpha will be 255 and the xfermode will be SRC_OVER.
     * alpha will be 255 and the xfermode will be SRC_OVER. Accounts for both
     * snapshot alpha, and overrideLayerAlpha
     *
     *
     * @param paint The paint to extract values from
     * @param paint The paint to extract values from
     * @param alpha Where to store the resulting alpha
     * @param alpha Where to store the resulting alpha
     * @param mode Where to store the resulting xfermode
     * @param mode Where to store the resulting xfermode
     */
     */
    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const;

    /**
     * Gets the alpha from a layer, accounting for snapshot alpha and overrideLayerAlpha
     *
     * @param layer The layer from which the alpha is extracted
     */
    inline float getLayerAlpha(Layer* layer) const;


    /**
    /**
     * Safely retrieves the mode from the specified xfermode. If the specified
     * Safely retrieves the mode from the specified xfermode. If the specified