Android硬件加速绘制过程源码分析(四)——离屏硬件缓存HardwareLayer

本文深入探讨Android系统中硬件加速的实现,重点分析硬件层缓存HardwareLayer的工作原理,包括创建、更新及缓存到FBO的过程。同时,对比介绍了软件层缓存如何将View绘制到Bitmap上。
摘要由CSDN通过智能技术生成

      Android在绘制过程中,为了提高一些复杂View的绘制效率,可以对View做缓存。

      Android提供个两种缓存,硬件缓冲和软件缓冲。软件缓冲就是将View缓冲成一个bitmap,而硬件缓冲就是将View缓冲到一个Frame Buffer Object中。详见:

http://blog.csdn.net/mapdigit/article/details/7686962

     我们从View的buildLayer方法开始分析为View建立缓存的过程:

 /**
     * Forces this view's layer to be created and this view to be rendered
     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
     * invoking this method will have no effect.
     *
     * This method can for instance be used to render a view into its layer before
     * starting an animation. If this view is complex, rendering into the layer
     * before starting the animation will avoid skipping frames.
     *
     * @throws IllegalStateException If this view is not attached to a window
     *
     * @see #setLayerType(int, android.graphics.Paint)
     */
    public void buildLayer() {
        if (mLayerType == LAYER_TYPE_NONE) return;

        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo == null) {
            throw new IllegalStateException("This view must be attached to a window first");
        }

        switch (mLayerType) {
            case LAYER_TYPE_HARDWARE:
                if (attachInfo.mHardwareRenderer != null &&
                        attachInfo.mHardwareRenderer.isEnabled() &&
                        attachInfo.mHardwareRenderer.validate()) {
                    getHardwareLayer();
                    // TODO: We need a better way to handle this case
                    // If views have registered pre-draw listeners they need
                    // to be notified before we build the layer. Those listeners
                    // may however rely on other events to happen first so we
                    // cannot just invoke them here until they don't cancel the
                    // current frame
                    if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) {
                        attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates();
                    }
                }
                break;
            case LAYER_TYPE_SOFTWARE:
                buildDrawingCache(true);
                break;
        }
    }

      官方对方法的解释是:强制View创建自己对应的层,并将自己绘制到层上,如果层的类型是LAYER_TYPE_NONE,那么该函数将不起作用。所以该方法要和setLayerType(int layerType, Paint paint)方法配合使用。

public void setLayerType(int layerType, Paint paint) {
        ......
        mLayerType = layerType;
        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
        mLocalDirtyRect = layerDisabled ? null : new Rect();

        invalidateParentCaches();
        invalidate(true);
    }

      我们再回到buildLayer函数,如果我们设置了View的层类型是LAYER_TYPE_HARDWARE,就会调用getHardwareLayer()方法;而如果我们设置了View的层次类型是LAYER_TYPE_SOFTWARE,就会调用buildDrawingCache(true)方法。

一、View的硬件层缓存

      我们先看getHardwareLayer()方法:

/**
     * <p>Returns a hardware layer that can be used to draw this view again
     * without executing its draw method.</p>
     *
     * @return A HardwareLayer ready to render, or null if an error occurred.
     */
    HardwareLayer getHardwareLayer() {
        ......
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
            if (mHardwareLayer == null) {
                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
                        width, height, isOpaque());
                mLocalDirtyRect.set(0, 0, width, height);
            } else {
                ......
            }

            // The layer is not valid if the underlying GPU resources cannot be allocated
            if (!mHardwareLayer.isValid()) {
                return null;
            }

            mHardwareLayer.setLayerPaint(mLayerPaint);
            mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);

            mLocalDirtyRect.setEmpty();
        }

        return mHardwareLayer;
    }

      该方法就是为View创建一个硬件层。首先会判读是否为该View创建过硬件层,如果没有,就会调用mAttachInfo.mHardwareRenderer.createHardwareLayer( width, height, isOpaque())方法创建一个:

@Override
        public HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
            return new GLES20RenderLayer(width, height, isOpa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值