Android 从Android3.0(API Level 11)开始就支持了硬件加速,在target api >= 14会默认开启,利用GPU代替CPU绘制,软加速是利用Skia,而硬件加速是利用OpenGL绘制。缺点是增加了内存占用。

本文只是在java层去看硬件加速,没有深究jni层如何绘制。

  • RenderNode 每个View都有一个RenderNode与之对应

  • RenderThread jin层会创建一个对应的线程,loop循环接收RenderNode

  • DisplayList jin层将DisplayListCanvas的操作转化到DisplayList

  • DisplayListCanvas java层上canvas缓存所有绘制操作,设置到RenderNode中

基本流程:

  1. UI线程负责构建操作DisplayList
  2. RenderThread线程利用OpenGL去绘制DisplayList的操作

参考之前的文章《View/ViewGroup 绘制流程和疑惑(一)》 可以了解整个View/ViewGroup/ViewRootImpl整体的绘制流程。

硬件加速的绘制流程基本上是一致的,只不过在draw流程上有不同的分歧点。

我们知道,子View的invalidate标记dirty区域,借由着ViewParent的invalidateChildInParent(int[] location, Rect dirty),到顶层的DecorView,最后触发了ViewRootImpl的invalidateChildInParent(),引起schedualTraversals()。

在文章《Android 屏幕刷新机制》讲过Vsync信号到来的时候,才会引起ViewRootImpl的preformTraversals()流程到draw()。


ThreadedRender初始化

在添加窗口WindowManagerGlobal.addView()会调用ViewRootlImpl的setView()

// WindowManagerGlobalpublic void addView(View view, ViewGroup.LayoutParams params,            Display display, Window parentWindow) {root.setView(view, wparams, panelParentView);}public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {if (mSurfaceHolder == null) {enableHardwareAcceleration(attrs);    }}private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {        mAttachInfo.mHardwareAccelerated = false;        mAttachInfo.mHardwareAccelerationRequested = false;        // 根据标记位,判断是否要硬件加速        final boolean hardwareAccelerated =                (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;        if (hardwareAccelerated) {            // 是否支持硬件加速:判断是否支持OpenGL            if (!ThreadedRenderer.isAvailable()) {                return;            }            if (!ThreadedRenderer.sRendererDisabled                    || (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {                if (mAttachInfo.mThreadedRenderer != null) {                    mAttachInfo.mThreadedRenderer.destroy();                }                // 创建ThreadedRender                mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,                        attrs.getTitle().toString());                          }        }    }public static ThreadedRenderer create(Context context, boolean translucent, String name) {    ThreadedRenderer renderer = null;    if (isAvailable()) {        renderer = new ThreadedRenderer(context, translucent, name);    }    return renderer;}ThreadedRenderer(Context context, boolean translucent, String name) {    // jni 创建 RenderNode    long rootNodePtr = nCreateRootRenderNode();    // 赋值给根布局的RenderNode    mRootNode = RenderNode.adopt(rootNodePtr);    // 创建ThreadProxy用来向RenderThread线程提交操作    mNativeProxy = nCreateProxy(translucent, rootNodePtr);}

View的RenderNode初始化

// View.javapublic View(Context context) {mRenderNode = RenderNode.create(getClass().getName(), this);}public static RenderNode create(String name, @Nullable View owningView) {    return new RenderNode(name, owningView);}private RenderNode(String name, View owningView) {    mNativeRenderNode = nCreate(name);    NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);    mOwningView = owningView;}

Draw() 流程

private void draw(boolean fullRedrawNeeded) {    Surface surface = mSurface;    final Rect dirty = mDirty;    if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {        // 硬件加速        if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {            boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;            mInvalidateRootRequested = false;            if (invalidateRoot) {                mAttachInfo.mThreadedRenderer.invalidateRoot();            }            mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);        } else {        // 软件加速            if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {                return;            }        }}

硬件加速:mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this)

软件加速:drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)

// ThreadedRender// view指向的DecorViewvoid draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {    attachInfo.mIgnoreDirtyState = true;    final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;    choreographer.mFrameInfo.markDrawStart();    updateRootDisplayList(view, callbacks);int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);}// 更新所有RenderNode 创建DisplayListCanvas赋值到RenderNodeprivate void updateRootDisplayList(View view, DrawCallbacks callbacks) {    updateViewTreeDisplayList(view);    if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {        DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);        try {            final int saveCount = canvas.save();            canvas.translate(mInsetLeft, mInsetTop);            callbacks.onPreDraw(canvas);            canvas.insertReorderBarrier();            canvas.drawRenderNode(view.updateDisplayListIfDirty());            canvas.insertInorderBarrier();            callbacks.onPostDraw(canvas);            canvas.restoreToCount(saveCount);            mRootNodeNeedsUpdate = false;        } finally {            mRootNode.end(canvas);        }    }}//private void updateViewTreeDisplayList(View view) {    ...    view.updateDisplayListIfDirty();}

RenderedThread从DecorView开始,往所有的ViewGroup/View更新RenderNode

// View.javapublic RenderNode updateDisplayListIfDirty() {    final RenderNode renderNode = mRenderNode;    final DisplayListCanvas canvas = renderNode.start(width, height);    canvas.setHighContrastText(mAttachInfo.mHighContrastText);try {        if (layerType == LAYER_TYPE_SOFTWARE) {            buildDrawingCache(true);            Bitmap cache = getDrawingCache(true);            if (cache != null) {                canvas.drawBitmap(cache, 0, 0, mLayerPaint);            }        } else {           // 如果是ViewGroup,自身不用绘制,直接递归子View           if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {               dispatchDraw(canvas);           } else {               draw(canvas);           }        }     } finally {        renderNode.end(canvas);        setDisplayListProperties(renderNode);     }     return renderNode;}public void end(DisplayListCanvas canvas) {    long displayList = canvas.finishRecording();    nSetDisplayList(mNativeRenderNode, displayList);    canvas.recycle();}

从RenderNode获取DisplayListCanvas,将所有操作写入到DisplayListCanvas,最后交给RenderNode,完成构建DisplayList。最后调用nSyncAndDrawFrame

参考:
https://www.jianshu.com/p/7bf306c09c7e
https://www.jb51.net/article/143618.htm

更多相关文章

  1. Android网络编程 HttpUrlConnection HttpClient AsyncTask
  2. android(18)_数据存储与访问_SQLite数据库_使用SQLiteDatabase操
  3. Handler、Looper与MessageQueue源码分析
  4. Error pulling origin: error: Your local changes to the follo
  5. Android(安卓)suspend底层流程解析
  6. 深入了解View实现原理以及自定义View详解
  7. 用Kotlin写响应式编程RxAndroid
  8. Google ZXing系列讲解(三)——ZXing 目录结构与主体流程
  9. Android网络请求库——android-async-http

随机推荐

  1. Android海康监控视频调用demo
  2. Android中TabHost的原理及使用
  3. Android(安卓)记录一次开发微信分享功能
  4. Android面试时的问题,实现半透明的popupw
  5. Android(安卓)给Button加个监听
  6. Android(安卓)程式开发:(二十)内容提供者 —
  7. MPAndroidChart 3.0——BarChart(一)
  8. Android(安卓)BaseActivity和BaseFragmen
  9. 动画---放缩,旋转,移动,渐变
  10. android apk如何引用系统framework.jar,s