硬件渲染器绘制从调用 HardwareRenderer 类 draw 方法实现 View 绘制开始。

frameworks/base/core/java/android/view/ViewRootImpl.java

public final class ViewRootImpl implements ViewParent,        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {    ......    private void draw(boolean fullRedrawNeeded) {        ......        if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {            if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {                ......                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);            } else {                ......            }        }        ......    }    ......}
  1. 更新 RootDisplayList( DisplayList 用于保存属性并在渲染器上执行回放)
  2. 注册动画渲染节点
  3. 同步和绘制帧

先着重分析 1。

frameworks/base/core/java/android/view/ThreadedRenderer.java

public class ThreadedRenderer extends HardwareRenderer {    ......    @Override    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {        attachInfo.mIgnoreDirtyState = true;        final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;        choreographer.mFrameInfo.markDrawStart();        // 1. 更新 RootDisplayList        updateRootDisplayList(view, callbacks);        attachInfo.mIgnoreDirtyState = false;        // 2. 注册动画渲染节点        if (attachInfo.mPendingAnimatingRenderNodes != null) {            final int count = attachInfo.mPendingAnimatingRenderNodes.size();            for (int i = 0; i < count; i++) {                registerAnimatingRenderNode(                        attachInfo.mPendingAnimatingRenderNodes.get(i));            }            attachInfo.mPendingAnimatingRenderNodes.clear();            // We don't need this anymore as subsequent calls to            // ViewRootImpl#attachRenderNodeAnimator will go directly to us.            attachInfo.mPendingAnimatingRenderNodes = null;        }        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;        // 3. 同步和绘制帧        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);        if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {            setEnabled(false);            attachInfo.mViewRootImpl.mSurface.release();            // 由于绘制失败,因此无效。如果仍然需要,则应该获取一个 Surface;            // 如果不再绘制,则不执行任何操作            attachInfo.mViewRootImpl.invalidate();        }        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {            attachInfo.mViewRootImpl.invalidate();        }    }    ......}
  1. 调用 updateViewTreeDisplayList(…) 更新 View 树 DisplayList
  2. 调用渲染节点(RenderNode 类) start(…) 方法获取 DisplayListCanvas 对象
  3. 调用 drawRenderNode(…) 绘制渲染节点
  4. 调用渲染节点 end 方法

frameworks/base/core/java/android/view/ThreadedRenderer.java

public class ThreadedRenderer extends HardwareRenderer {    ......    private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");        updateViewTreeDisplayList(view);        if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {            DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);            try {                final int saveCount = canvas.save();                canvas.translate(mInsetLeft, mInsetTop);                // 在绘制之前回调 onHardwarePreDraw 方法                callbacks.onHardwarePreDraw(canvas);                // 插入 Reorder 屏障                canvas.insertReorderBarrier();                // 绘制渲染节点                canvas.drawRenderNode(view.updateDisplayListIfDirty());                // 插入 Inorder 屏障                canvas.insertInorderBarrier();                // 在绘制后回调 onHardwarePostDraw 方法                callbacks.onHardwarePostDraw(canvas);                canvas.restoreToCount(saveCount);                mRootNodeNeedsUpdate = false;            } finally {                // 调用渲染节点 end 方法                mRootNode.end(canvas);            }        }        Trace.traceEnd(Trace.TRACE_TAG_VIEW);    }    ......}

updateViewTreeDisplayList(…) 设置、清除了一些 flag,然后调用了 View 类 updateDisplayListIfDirty() 方法,如果 View 是脏的更新 DisplayList。

frameworks/base/core/java/android/view/ThreadedRenderer.java

public class ThreadedRenderer extends HardwareRenderer {    ......    private void updateViewTreeDisplayList(View view) {        // 设置 PFLAG_DRAWN 已绘制标志        view.mPrivateFlags |= View.PFLAG_DRAWN;        // 如果设置了 PFLAG_INVALIDATED 无效标志,则赋值 mRecreateDisplayList 为 true        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)                == View.PFLAG_INVALIDATED;        // 清除 PFLAG_INVALIDATED 标志        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;        view.updateDisplayListIfDirty();        view.mRecreateDisplayList = false;    }    ......}

updateDisplayListIfDirty() 获取 View 的 RenderNode,并更新它的 DisplayList(如果需要和支持)。

  1. 调用 dispatchGetDisplayList() 分发获取 DisplayList
  2. 调用 dispatchDraw(…) 派发绘制或者直接调用 draw(…) 绘制

tips:

层类型是 LAYER_TYPE_SOFTWARE 时指示 View 具有软件层。软件层是由位图支持的,即使启用了硬件加速,也可以使用 Android 的软件渲染管道来渲染 View。

软件层有各种各样的用途

当应用程序不使用硬件加速,软件层是有用的应用一个特定的颜色滤镜和/或混合模式和/或半透明的一个 View 和它的所有子 View。

当应用程序使用硬件加速时,软件层用于渲染硬件加速管道不支持的绘图原语。它还可以用于将复杂的视图树缓存到纹理中,并降低绘图操作的复杂性。例如,当一个复杂的视图树被转换成动画时,一个软件层只能用于渲染视图树一次。

当受影响的视图树经常更新时,应该避免软件层。每次更新都需要重新渲染软件层,这可能会很慢(特别是在打开硬件加速时,因为在每次更新后,软件层都要上传到硬件纹理中)。

frameworks/base/core/java/android/view/View.java

@UiThreadpublic class View implements Drawable.Callback, KeyEvent.Callback,        AccessibilityEventSource {    ......    @NonNull    public RenderNode updateDisplayListIfDirty() {        final RenderNode renderNode = mRenderNode;        if (!canHaveDisplayList()) {            // 不能填充 RenderNode            return renderNode;        }        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0                || !renderNode.isValid()                || (mRecreateDisplayList)) {            // 不需要重新创建 DisplayList,只需要告诉孩子 恢复/重新创建 他们的            if (renderNode.isValid()                    && !mRecreateDisplayList) {                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;                mPrivateFlags &= ~PFLAG_DIRTY_MASK;                dispatchGetDisplayList();                return renderNode; // no work needed            }            // 重新创建 DisplayList            mRecreateDisplayList = true;            int width = mRight - mLeft;            int height = mBottom - mTop;            // 获取层类型            int layerType = getLayerType();            // 调用 RenderNode 类 start(...) 方法获取 DisplayListCanvas 对象            final DisplayListCanvas canvas = renderNode.start(width, height);            canvas.setHighContrastText(mAttachInfo.mHighContrastText);            try {                // 获取 HardwareLayer 对象                final HardwareLayer layer = getHardwareLayer();                if (layer != null && layer.isValid()) {                    // 调用 DisplayListCanvas 类 drawHardwareLayer 绘制硬件层                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);                } else if (layerType == LAYER_TYPE_SOFTWARE) {                    // 如果层类型是 LAYER_TYPE_SOFTWARE                     // 创建绘制缓存                    buildDrawingCache(true);                    Bitmap cache = getDrawingCache(true);                    if (cache != null) {                        // 绘制位图                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);                    }                } else {                    // 一般进入此分支                    // 计算滚动                    computeScroll();                    // 应用平移                    canvas.translate(-mScrollX, -mScrollY);                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;                    // 无背景布局的快速路径                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {                        // 派发绘制                        dispatchDraw(canvas);                        if (mOverlay != null && !mOverlay.isEmpty()) {                            mOverlay.getOverlayView().draw(canvas);                        }                    } else {                        draw(canvas);                    }                }            } finally {                // 调用渲染节点 end 方法                renderNode.end(canvas);                setDisplayListProperties(renderNode);            }        } else {            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;            mPrivateFlags &= ~PFLAG_DIRTY_MASK;        }        return renderNode;    }    ......}

dispatchGetDisplayList() 在 View 中是个空方法,根据前面分析,我们传入的是 DecorView。

frameworks/base/core/java/android/view/View.java

@UiThreadpublic class View implements Drawable.Callback, KeyEvent.Callback,        AccessibilityEventSource {    ......    protected void dispatchGetDisplayList() {}    ......}

转入 DecorView 类 dispatchGetDisplayList() 方法实现。实际上也没有重写,最终在 ViewGroup 中找到对应实现,DecorView 继承自 FrameLayout ,FrameLayout 继承自 ViewGroup。

frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java

public class PhoneWindow extends Window implements MenuBuilder.Callback {    ......    private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {        ......    }    ......}

此方法用于使此 ViewGroup 的子 View 恢复或重新创建它们的 DisplayList。当父 ViewGroup 不需要重新创建自己的 DisplayList 时,getDisplayList() 调用它,如果它通过常规的 draw/dispatchDraw 机制,就会发生这种情况。

frameworks/base/core/java/android/view/ViewGroup.java

@UiThreadpublic abstract class ViewGroup extends View implements ViewParent, ViewManager {    ......    @Override    protected void dispatchGetDisplayList() {        final int count = mChildrenCount;        final View[] children = mChildren;        for (int i = 0; i < count; i++) {            final View child = children[i];            if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null)) {                // 重新创建子 View DisplayList                recreateChildDisplayList(child);            }        }        ......    }    ......}

子 View 调用 updateDisplayListIfDirty() 更新自己的 DisplayList。

frameworks/base/core/java/android/view/ViewGroup.java

@UiThreadpublic abstract class ViewGroup extends View implements ViewParent, ViewManager {    ......    private void recreateChildDisplayList(View child) {        child.mRecreateDisplayList = (child.mPrivateFlags & PFLAG_INVALIDATED) != 0;        child.mPrivateFlags &= ~PFLAG_INVALIDATED;        child.updateDisplayListIfDirty();        child.mRecreateDisplayList = false;    }    ......}

现在回到 updateDisplayListIfDirty() 方法。layerType 等于 0,即为 LAYER_TYPE_NONE(指示 View 没有层)。首先调用 dispatchDraw(…) 开始派发绘制。这个方法实现在 ViewGroup 中。这里调用了 drawChild(…) 绘制孩子。

frameworks/base/core/java/android/view/ViewGroup.java

@UiThreadpublic abstract class ViewGroup extends View implements ViewParent, ViewManager {    ......    @Override    protected void dispatchDraw(Canvas canvas) {        boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);        final int childrenCount = mChildrenCount;        final View[] children = mChildren;        int flags = mGroupFlags;        ......        if (usingRenderNodeProperties) canvas.insertReorderBarrier();        final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();        int transientIndex = transientCount != 0 ? 0 : -1;        // 如果没有 HW 加速,只使用预先排序的列表,因为 HW 管道将在内部做绘制重新排序        final ArrayList<View> preorderedList = usingRenderNodeProperties                ? null : buildOrderedChildList();        final boolean customOrder = preorderedList == null                && isChildrenDrawingOrderEnabled();        for (int i = 0; i < childrenCount; i++) {            while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {                final View transientChild = mTransientViews.get(transientIndex);                if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||                        transientChild.getAnimation() != null) {                    // 绘制孩子                    more |= drawChild(canvas, transientChild, drawingTime);                }                transientIndex++;                if (transientIndex >= transientCount) {                    transientIndex = -1;                }            }            int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;            final View child = (preorderedList == null)                    ? children[childIndex] : preorderedList.get(childIndex);            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {                // 绘制孩子                more |= drawChild(canvas, child, drawingTime);            }        }        while (transientIndex >= 0) {            // 在正常视图之后可能会有其他的临时视图            final View transientChild = mTransientViews.get(transientIndex);            if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||                    transientChild.getAnimation() != null) {                // 绘制孩子                more |= drawChild(canvas, transientChild, drawingTime);            }            transientIndex++;            if (transientIndex >= transientCount) {                break;            }        }        ......    }    ......}

绘制此 ViewGroup 的一个子 View。此方法负责将画布置于正确的状态。其内部实现调用了 View 的 draw(…) 方法。

frameworks/base/core/java/android/view/ViewGroup.java

@UiThreadpublic abstract class ViewGroup extends View implements ViewParent, ViewManager {    ......    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {        return child.draw(canvas, this, drawingTime);    }        ......}

View 最终会调用 draw(Canvas canvas) 绘制。

绘制执行几个绘制步骤,这些步骤必须以适当的顺序执行:

  1. 绘制背景
  2. 如有必要,保存画布的图层以准备 fading
  3. 绘制视图的内容
  4. 绘制孩子
  5. 如有必要,绘制 fading 边缘并恢复图层
  6. 绘制装饰(例如滚动条)

frameworks/base/core/java/android/view/View.java

@UiThreadpublic class View implements Drawable.Callback, KeyEvent.Callback,        AccessibilityEventSource {    ......    @CallSuper    public void draw(Canvas canvas) {        final int privateFlags = mPrivateFlags;        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;        // 1.绘制背景        int saveCount;        if (!dirtyOpaque) {            drawBackground(canvas);        }        // 如果可能的话跳过第2步和第5步(一般情况)        final int viewFlags = mViewFlags;        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;        if (!verticalEdges && !horizontalEdges) {            // 3.绘制视图的内容,自定义 View 一般会实现 onDraw 方法            if (!dirtyOpaque) onDraw(canvas);            // 4.绘制孩子            dispatchDraw(canvas);            // Overlay 是内容的一部分,在前景下面绘制            if (mOverlay != null && !mOverlay.isEmpty()) {                mOverlay.getOverlayView().dispatchDraw(canvas);            }            // 6.绘制装饰(前景、滚动条)            onDrawForeground(canvas);            // we're done...            return;        }        /*         * 在这里,我们做完整的例行公事......         * (在这种情况下,速度并不重要,这就是为什么我们重复上面做过的一些测试)         */        boolean drawTop = false;        boolean drawBottom = false;        boolean drawLeft = false;        boolean drawRight = false;        float topFadeStrength = 0.0f;        float bottomFadeStrength = 0.0f;        float leftFadeStrength = 0.0f;        float rightFadeStrength = 0.0f;        // 2.保存画布的图层        int paddingLeft = mPaddingLeft;        final boolean offsetRequired = isPaddingOffsetRequired();        if (offsetRequired) {            paddingLeft += getLeftPaddingOffset();        }        int left = mScrollX + paddingLeft;        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;        int top = mScrollY + getFadeTop(offsetRequired);        int bottom = top + getFadeHeight(offsetRequired);        if (offsetRequired) {            right += getRightPaddingOffset();            bottom += getBottomPaddingOffset();        }        final ScrollabilityCache scrollabilityCache = mScrollCache;        final float fadeHeight = scrollabilityCache.fadingEdgeLength;        int length = (int) fadeHeight;        // clip the fade length if top and bottom fades overlap        // overlapping fades produce odd-looking artifacts        if (verticalEdges && (top + length > bottom - length)) {            length = (bottom - top) / 2;        }        // 如果需要,还可以剪切水平渐变        if (horizontalEdges && (left + length > right - length)) {            length = (right - left) / 2;        }        if (verticalEdges) {            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));            drawTop = topFadeStrength * fadeHeight > 1.0f;            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;        }        if (horizontalEdges) {            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));            drawLeft = leftFadeStrength * fadeHeight > 1.0f;            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));            drawRight = rightFadeStrength * fadeHeight > 1.0f;        }        saveCount = canvas.getSaveCount();        int solidColor = getSolidColor();        if (solidColor == 0) {            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;            if (drawTop) {                canvas.saveLayer(left, top, right, top + length, null, flags);            }            if (drawBottom) {                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);            }            if (drawLeft) {                canvas.saveLayer(left, top, left + length, bottom, null, flags);            }            if (drawRight) {                canvas.saveLayer(right - length, top, right, bottom, null, flags);            }        } else {            scrollabilityCache.setFadeColor(solidColor);        }        // 3.绘制内容        if (!dirtyOpaque) onDraw(canvas);        // 4.绘制孩子        dispatchDraw(canvas);        // 5.绘制 fade 效果并恢复图层        final Paint p = scrollabilityCache.paint;        final Matrix matrix = scrollabilityCache.matrix;        final Shader fade = scrollabilityCache.shader;        if (drawTop) {            matrix.setScale(1, fadeHeight * topFadeStrength);            matrix.postTranslate(left, top);            fade.setLocalMatrix(matrix);            p.setShader(fade);            canvas.drawRect(left, top, right, top + length, p);        }        if (drawBottom) {            matrix.setScale(1, fadeHeight * bottomFadeStrength);            matrix.postRotate(180);            matrix.postTranslate(left, bottom);            fade.setLocalMatrix(matrix);            p.setShader(fade);            canvas.drawRect(left, bottom - length, right, bottom, p);        }        if (drawLeft) {            matrix.setScale(1, fadeHeight * leftFadeStrength);            matrix.postRotate(-90);            matrix.postTranslate(left, top);            fade.setLocalMatrix(matrix);            p.setShader(fade);            canvas.drawRect(left, top, left + length, bottom, p);        }        if (drawRight) {            matrix.setScale(1, fadeHeight * rightFadeStrength);            matrix.postRotate(90);            matrix.postTranslate(right, top);            fade.setLocalMatrix(matrix);            p.setShader(fade);            canvas.drawRect(right - length, top, right, bottom, p);        }        canvas.restoreToCount(saveCount);        // Overlay 是内容的一部分,在前景下面绘制        if (mOverlay != null && !mOverlay.isEmpty()) {            mOverlay.getOverlayView().dispatchDraw(canvas);        }        // 6.绘制装饰(前景、滚动条)        onDrawForeground(canvas);    }    ......}

现在继续分析 RootNode 类 start(…) 方法。

开始为渲染节点记录 DisplayList。在返回的画布上执行的所有操作都被记录并存储在这个 DisplayList 中。调用此方法将标记渲染节点无效,直到调用 end(DisplayListCanvas) 为止。只能重放有效的渲染节点。

  1. 调用 DisplayListCanvas 类静态 obtain(…) 方法返回 DisplayListCanvas 对象
  2. 设置视图端口大小
  3. 绘制前动作,执行任何绘制操作之前调用。对于 DisplayList,dirty 区域应该始终为 null。

frameworks/base/core/java/android/view/RenderNode.java

public class RenderNode {    ......    public DisplayListCanvas start(int width, int height) {        DisplayListCanvas canvas = DisplayListCanvas.obtain(this);        // 设置视图端口大小        canvas.setViewport(width, height);        // 对于 DisplayList,dirty 区域应该始终为 null。        // 绘制前动作,执行任何绘制操作之前调用        canvas.onPreDraw(null);        return canvas;    }    ......}

DisplayListCanvas 类记录绘图操作的 GL 画布的实现。它用于 DisplayList。这个类保存了它所绘制的所有绘制和位图对象的列表,防止当 DisplayList 仍然持有对内存的本地引用时位图的后备内存被释放。

假设画布池中没有 DisplayListCanvas 对象,现在就会 new 一个出来。

frameworks/base/core/java/android/view/DisplayListCanvas.java

public class DisplayListCanvas extends Canvas {    // 记录画布池应该大到足以处理深度嵌套的视图层次结构,因为 DisplayList 是递归生成的。    private static final int POOL_LIMIT = 25;    private static final SynchronizedPool<DisplayListCanvas> sPool =            new SynchronizedPool<DisplayListCanvas>(POOL_LIMIT);    RenderNode mNode;    private int mWidth;    private int mHeight;    static DisplayListCanvas obtain(@NonNull RenderNode node) {        if (node == null) throw new IllegalArgumentException("node cannot be null");        DisplayListCanvas canvas = sPool.acquire();        if (canvas == null) {            canvas = new DisplayListCanvas();        }        canvas.mNode = node;        return canvas;    }    ......}

调用 nCreateDisplayListCanvas() jni 方法并将返回值作为入参传入父类 Canvas 构造器。

frameworks/base/core/java/android/view/DisplayListCanvas.java

public class DisplayListCanvas extends Canvas {    ......    private DisplayListCanvas() {        super(nCreateDisplayListCanvas());        mDensity = 0; // 禁用位图密度缩放    }    private static native long nCreateDisplayListCanvas();    ......}

Canvas 构造函数中仅仅将入参保存在了成员变量 mNativeCanvasWrapper 中。

frameworks/base/graphics/java/android/graphics/Canvas.java

public class DisplayListCanvas extends Canvas {    ......    /**     * 应该只在构造函数中分配(或者在软件画布调用 setBitmap 中分配),在终结器中释放。     * @hide     */    protected long mNativeCanvasWrapper;    ......    public Canvas(long nativeCanvas) {        if (nativeCanvas == 0) {            throw new IllegalStateException();        }        mNativeCanvasWrapper = nativeCanvas;        ......    }    ......}

现在来继续分析 nCreateDisplayListCanvas() 函数本地实现。new 了 DisplayListCanvas 对象,然后将其强转为 jlong 返回,这样就将 Native 层 DisplayListCanvas 对象的引用传回了 Java 层。

frameworks/base/core/jni/android_view_DisplayListCanvas.cpp

static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz) {    return reinterpret_cast<jlong>(new DisplayListCanvas);}

mDisplayListData 成员变量初始化为空指针。

frameworks/base/libs/hwui/DisplayListCanvas.cpp

DisplayListCanvas::DisplayListCanvas()    : mState(*this)    , mResourceCache(ResourceCache::getInstance())    , mDisplayListData(nullptr)    , mTranslateX(0.0f)    , mTranslateY(0.0f)    , mHasDeferredTranslate(false)    , mDeferredBarrierType(kBarrier_None)    , mHighContrastText(false)    , mRestoreSaveCount(-1) {}

onPreDraw(…) 入参是 null,因此会走 else 分支。

frameworks/base/core/java/android/view/DisplayListCanvas.java

public class DisplayListCanvas extends Canvas {    ......    public void onPreDraw(Rect dirty) {        if (dirty != null) {            ......        } else {            nPrepare(mNativeCanvasWrapper);        }    }            private static native void nPrepare(long renderer);    ......}
  1. 将 Java 层保存的 DisplayListCanvas 引用取出
  2. 调用 DisplayListCanvas 对象的 prepare() 方法

frameworks/base/core/jni/android_view_DisplayListCanvas.cpp

static void android_view_DisplayListCanvas_prepare(JNIEnv* env, jobject clazz,        jlong rendererPtr) {    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);    renderer->prepare();}

prepare() 内部实际调用了 prepareDirty(…),只不过入参固定了(见名知其意)。

frameworks/base/libs/hwui/DisplayListCanvas.h

class ANDROID_API DisplayListCanvas: public Canvas, public CanvasStateClient {public:    ......// ----------------------------------------------------------------------------// HWUI 帧状态操作// ----------------------------------------------------------------------------    void prepareDirty(float left, float top, float right, float bottom);    void prepare() { prepareDirty(0.0f, 0.0f, width(), height()); }    ......}

prepareDirty(…) 方法中创建了 DisplayListData 对象,回顾一下,它是用于保存实际数据的(保存 DisplayList 流中使用的命令列表的数据结构)。

frameworks/base/libs/hwui/DisplayListCanvas.cpp

void DisplayListCanvas::prepareDirty(float left, float top,        float right, float bottom) {    LOG_ALWAYS_FATAL_IF(mDisplayListData,            "prepareDirty called a second time during a recording!");    mDisplayListData = new DisplayListData();    ......}

projectionReceiveIndex —— DisplayListOp 的索引。

frameworks/base/libs/hwui/DisplayList.cpp

DisplayListData::DisplayListData()        : projectionReceiveIndex(-1)        , hasDrawOps(false) {}

最后来看 DisplayListCanvas 类 drawRenderNode(…) 方法。此方法表示在此画布上绘制指定的 DisplayList。只有当 android.view.RenderNode#isValid() 返回 true 时,才能绘制 DisplayList。

frameworks/base/core/java/android/view/DisplayListCanvas.java

public class DisplayListCanvas extends Canvas {    ......    public void drawRenderNode(RenderNode renderNode) {        nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());    }    private static native void nDrawRenderNode(long renderer, long renderNode);    ......}
  1. 获取 DisplayListCanvas 对象
  2. 获取 RenderNode 对象
  3. 调用 DisplayListCanvas 类 drawRenderNode 方法绘制渲染节点

frameworks/base/core/jni/android_view_DisplayListCanvas.cpp

static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,        jobject clazz, jlong rendererPtr, jlong renderNodePtr) {    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);    renderer->drawRenderNode(renderNode);}
  1. 创建 DrawRenderNodeOp 对象
  2. 调用 addRenderNodeOp(…) 将 DrawRenderNodeOp 添加到列表

frameworks/base/libs/hwui/DisplayListCanvas.cpp

void DisplayListCanvas::drawRenderNode(RenderNode* renderNode) {    LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(            renderNode,            *mState.currentTransform(),            mState.clipIsSimple());    addRenderNodeOp(op);}

将 DrawRenderNodeOp 对象添加到 DisplayListData 类 Vector 中。

frameworks/base/libs/hwui/DisplayListCanvas.cpp

size_t DisplayListCanvas::addRenderNodeOp(DrawRenderNodeOp* op) {    int opIndex = addDrawOp(op);    int childIndex = mDisplayListData->addChild(op);    // 更新块的子索引    DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop();    chunk.endChildIndex = childIndex + 1;    if (op->renderNode()->stagingProperties().isProjectionReceiver()) {        // 使用暂存属性,因为在 UI 线程上记录        mDisplayListData->projectionReceiveIndex = opIndex;    }    return opIndex;}

最后画时序图总结一下。

Android 源码 图形系统之硬件渲染器绘制_第1张图片

更多相关文章

  1. Android获取窗体信息的Util方法
  2. Android 几种加密解密的方法(仅代码)
  3. Android 实现模拟按键方法一
  4. Android两种轮询的实现方法
  5. Android MonkeyRunner调用方法总结
  6. android home 键的监听方法记录
  7. Android 四种获取屏幕宽度的方法总结

随机推荐

  1. android使用notifyDataSetChanged()方法,a
  2. Android(安卓)封装自己的工具Jar
  3. Android(安卓)P 系统启动-System Server
  4. android设置Webview的滚动条属性
  5. sdut 2162:The Android(安卓)University
  6. Android消息机制
  7. android textview属性
  8. 教你如何创建类似QQ的android弹出菜单
  9. Android中intent如何传递自定义数据类型
  10. Android(安卓)图片Bitmap的剪切