Android硬件加速绘制过程源码分析(二)——DisplayList录制绘制操作

本文深入探讨Android硬件加速的绘制过程,重点关注DisplayList如何录制绘制操作。从drawBitmap函数开始,解析DisplayList、DisplayListRenderer和DisplayListFinalizer之间的关系,以及View的getDisplayList函数在绘制过程中的作用。通过对各个组件的分析,揭示了Android视图层次结构中绘制操作的记录和存储机制。
摘要由CSDN通过智能技术生成

      View Hierarchy的绘制过程的第一步是DisplayList录制绘制操作。

一、绘制操作是什么?

      DisplayList是将绘制操作保存下来,那我们先看看绘制操作是什么。比如说drawBitmap就是一个绘制操作,Android将它封装成一个DrawBitmapOp

class DrawBitmapOp : public DrawBoundedOp {
public:
    ........
    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
        return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
                getPaint(renderer));
    }
    ........
 };

      drawPath,drawColor,drawRect,drawArc等等都会有这样的Operation对象对应。详见libs\hwui\DisplayListOp.h。
二、DisplayList如何保存绘制操作?

      说DisplayList保存绘制操作其实也不是十分准确。在GLES20DisplayList(DisplayList的实现类)中其实有个内部类DisplayListFinalizer,该类中有个mNativeDisplayList的成员变量,它指向一个C++对象。因为Java中没有指针变量,所以用长整形来保存C++对象的地址。这个本地对象才是真正保存绘制操作的对象。

private static class DisplayListFinalizer {
        final long mNativeDisplayList;

        public DisplayListFinalizer(long nativeDisplayList) {
            mNativeDisplayList = nativeDisplayList;
        }

        @Override
        protected void finalize() throws Throwable {
            try {
                nDestroyDisplayList(mNativeDisplayList);
            } finally {
                super.finalize();
            }
        }
    }

      本地DisplayList对象的头文件在\libs\hwui\DisplayList.h,该对象有个mDisplayListData的成员变量,而DisplayListData中有个displayListOps的成员变量,该变量是个Vector容器类型,保存一个个DisplayListOp对象。

class DisplayListData : public LightRefBase<DisplayListData> {
public:
    LinearAllocator allocator;
    Vector<DisplayListOp*> displayListOps;
......
};

三、从drawBitmap函数到DrawBitmapOp对象的过程。

     Android如何将调用一次drawBitmap的操作转变成DrawBitmapOp对象保存起来?我们从java层canvas.drawBitmap(...)函数开始。canvas的真正类型决定了drawBitmap的不同行为。这里的canvas可能有三种类型Canvas,GLES20Canvas,GLES20RecordingCanvas。如果是Canvas,则我们没有使用硬件加速来加速,具体就不分析了。其实GLES20Canvas和GLES20RecordingCanvas的drawBitmap函数是一样的,因为GLES20RecordingCanvas是继承的GLES20Canvas,而且GLES20RecordingCanvas并没有重写drawBitmap方法:

@Override
    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
        throwIfCannotDraw(bitmap);
        // Shaders are ignored when drawing bitmaps
        int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
        try {
            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
            nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
        } finally {
            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
        }
    }

     我们看到drawBitmap调用了一个本地方法nDrawBitmap方法。该方法的第一个参数传入的是GLES20Canvas的一个成员变量mRenderer,指向一个本地对象(上文已经提过java中如何指向本地对象)。GLES20Canvas和GLES20RecordingCanvas主要的区别就是这个参数。

protected GLES20Canvas(boolean record, boolean translucent) {
        mOpaque = !translucent;

        if (record) {
            mRenderer = nCreateDisplayListRenderer();
        } else {
            mRenderer = nCreateRenderer();
        }

        setupFinalizer();
    }

      在创建GLES20Canvas对象时,record是false,而在创建GLES20RecordingCanvas对象时,record为true。nCreateDisplayListRenderer()和nCreateRenderer()函数的实现都在core\jni\android_view_GLES20Canvas.cpp中:

static jlong android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
    RENDERER_LOGD("Create OpenGLRenderer");
    OpenGLRenderer* renderer = new OpenGLRenderer();
    renderer->initProperties();
    return reinterpret_cast<jlong>(renderer);
}


 

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

      所以GLES20Canvas中mRenderer指向的是一个OpenGLRenderer本地对象,GLES20RecordingCanvas中mRenderer指向的是一个DisplayListRenderer本地对象。我们在回到drawBitmap函数中,它会调用本地方法nDrawBitmap,该函数的实现也在core\jni\android_view_GLES20Canvas.cpp中:


                
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值