我正在参与创作者训练营第6期,点击了解活动概况

硬件烘托中采用AttachInfo的mThreadRenderer.draw办法传入view,attachinfo和ViewRootImpl开端硬件烘托

private boolean draw(boolean fullRedrawNeeded) {
    if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
        if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
            // 硬件烘托
            mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
        } else {
            // 软件烘托
        }
    }
}

ThreadRender的初始化

resume的时分会调用ViewRootImpl的setView办法创立windowSession和WMS通讯,之后会调用enbleHardwareAccleration办法判断是否开启硬件烘托

>ViewRootImpl.java
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
     // ...
      else if (!ThreadedRenderer.sRendererDisabled
                    || (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
     // 进程默许 开启硬件制作         
     mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
                        attrs.getTitle().toString());
     // ...
     }                   
}
>ThreadedRenderer.java 
  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) {
        // 调用父类的结构
        super();
        setName(name);
        setOpaque(!translucent);
        // ...
    }
>HardwareRenderer.java 
//     父类的结构
 public HardwareRenderer() {
        // 创立一个Java层的 根RootNode 节点
        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
        mRootNode.setClipToBounds(false);
        // 创立一个 native层的 RenderProxy 目标,  用来和RenderThread线程通讯
        mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
        if (mNativeProxy == 0) {
            throw new OutOfMemoryError("Unable to create hardware renderer");
        }
        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
        // 往AMS设置 renderThread的线程tid
        ProcessInitializer.sInstance.init(mNativeProxy);
    }
  public static RenderNode adopt(long nativePtr) {
        //创立Java层的RenderNode, 持有native层的node 引证 
        return new RenderNode(nativePtr);
    }

调用父类的结构办法流程如下:

  • ncreateRootRenderNode会创立,native层的RootRenderNode目标,并设置node的name为RootRenderNode
  • 接着创立一个Java层的根RootNode节点持有natve层的node引证
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
        jboolean translucent, jlong rootRenderNodePtr) {
     // 获取之前创立的  rootRenderNode
    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
    // 创立 ContextFactoryImpl 目标
    ContextFactoryImpl factory(rootRenderNode);
    // new 一个 RenderProxy目标
    RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
    return (jlong) proxy;
}
// RenderProxy 的结构函数
>frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
                         IContextFactory* contextFactory)
         //mRenderThread 赋值。一个运用只会具有一个RenderThread线程
        : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
        //往RenderThread的行列中post一个消息创立CanvasContext目标
    mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
        // 在RenderThread线程中,创立CanvasContext目标。用所以链接OpenGL/Vulkan和graphicBuffer缓冲区的关键
        //终究要运用这个contetx保存的surface的GraphBuffer进行烘托
        return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
    });
    // mDrawFrameTask 设置context 
    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode,
                              pthread_gettid_np(pthread_self()), getRenderThreadTid());
}
>frameworks/base/libs/hwui/renderthread/CanvasContext.cpp
CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
                                     RenderNode* rootRenderNode, IContextFactory* contextFactory) {
    // 依据烘托管道的装备
    auto renderType = Properties::getRenderPipelineType();
    switch (renderType) {
        case RenderPipelineType::SkiaGL:
            // skiaOpenGl烘托管道
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
        case RenderPipelineType::SkiaVulkan:
            // skiaVulkan烘托管道
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
        default:
            LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
            break;
    }
    return nullptr;
}
  • nCreateProxy办法传入native的rootRenderNode,使用之前创立的rootRenderNode创立ContextFactoryImpl目标,紧接着创立一个RenderProxy目标(用于和)
  • Renderproxy目标的结构函数中获取到RenderThread单例线程,然后在这个线程中去创立CanvasContext目标(链接OpenGL/Vulkan和graphicBuffer缓冲区的关键)。

RenderThread的第一个drawFrameTask任务便是去创立CanvasContext

创立过程会依据烘托管道装备去创立不同的canvascontext。t比如skiaOpenGl烘托管道仍是skiaVulkan烘托管道;接着给drawFarmeTask设置上面创立的context。

  • 将创立出来的RenderProxy传入到AMS中,也便是像AMS设置renderThread的线程tid

小结:

ThreadedRenderer 在ViewRootImpl的setView()中被初始化。结构办法做了如下初始化:

  1. 在结构办法中会创立Java和native层两个 根RenderNode节点。
  2. 创立native层的RenderProxy目标,持有 RenderThread 单例线程的引证。
  3. 给RenderThread线程,设置烘托的上下文。依据装备该CanvasContext采用的是管道:SkiaOpenGLPipeline 或许 SkiaVulkanPipeline。

Java层的都是renderNode节点目标,只要native层才能够创立rootRenderNode目标。在setView初始化的时分会创立native层的rootrenderNode之后创立一个rendernode绑定这个native的rootRenderNode

RenderNode

>View.java
public View(Context context) {
        mContext = context;
        mResources = context != null ? context.getResources() : null;
        // ...
        // 生成一个 RenderNode节点
        mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
}
> RenderNode.java
/** @hide */
public static RenderNode create(String name, @Nullable AnimationHost animationHost) {
    return new RenderNode(name, animationHost);
}
//结构办法 
 private RenderNode(String name, AnimationHost animationHost) {
        // 调用native办法 生成
        mNativeRenderNode = nCreate(name);
        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
        mAnimationHost = animationHost;
    }
>frameworks/base/libs/hwui/jni/android_graphics_RenderNode.cpp
static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) {
    // 创立一个 renderNode节点 
    RenderNode* renderNode = new RenderNode();
    renderNode->incStrong(0);
    if (name != NULL) {
        const char* textArray = env->GetStringUTFChars(name, NULL);
        renderNode->setName(textArray);
        env->ReleaseStringUTFChars(name, textArray);
    }
    return reinterpret_cast<jlong>(renderNode);
}

RenderNode有两个结构办法。一个是根View专用的接受native层的RootRenderNode目标;还有一个是一般的除了根View用的接受View名字的结构办法。第二种终究是调用的nCreate创立的c层的RenderNode绑定

RenderNode 是依据view树来树立的。每一个View对应一个RenderNode节点。

一个RenderNode节点包括了当时view的制作指令drawOp( 如 drawLines->drawLinesOp), 一起还包括制作子RenderNode节点的指令:DrawRenderNodeOp。因此,可看成一颗RenderNode树。 每一个drawXXXOp指令都有对应的OpenGL/Vulkan 指令与之对应。

RecordingCanvas

RecordingCanvas 用来记载 View树 中的硬件加速制作动作drawOp。对应native层的 SkiaRecordingCanvas。 主要功能都是由 native来完结。 经过obtain()办法来获得一个 RecordingCanvas

obtain办法需求传入RenderNode目标和宽高信息来创立RecordingCanvas,第一次经过new创立之后进行修改器node宽高内部特点不再进行创立。RecordingCanvas结构办法中终究在c层创立了一个SkiaRecordingCanvas也便是和java层的RecordingCanvas对应

ThreadedRenderer.draw()

void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
    // 构建View的 drawXXXOp树 
    updateRootDisplayList(view, callbacks);
    // 通知 RenderThread  线程 开端制作
    int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
}

updateRootDisplayList

> ThreadedRenderer.java
private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
    Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
    //构建View的drawXXXop树也便是displayList制作指令
    //更新传入view对应的 RenderNode中的displayList(drawOp树)
    updateViewTreeDisplayList(view);
    // ...
    // 当根节点重绘时需求从头核算drawOp树
    if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
        // 从RecordingCanvas缓存池中,获取一个 RecordingCanvas 目标,包括了当时RenderNode、width、height信息
        RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
        try {
            final int saveCount = canvas.save();
            canvas.translate(mInsetLeft, mInsetTop);
            callbacks.onPreDraw(canvas);
            canvas.enableZ();
            // 回来view对应的node,开端制作RenderNode
            canvas.drawRenderNode(view.updateDisplayListIfDirty());
            canvas.disableZ();
            callbacks.onPostDraw(canvas);
            canvas.restoreToCount(saveCount);
            mRootNodeNeedsUpdate = false;
        } finally {
            // 完毕制作,加入到Nodes集合 
            mRootNode.endRecording();
        }
    }
    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
>RenderNode.java
public @NonNull RecordingCanvas beginRecording(int width, int height) {
    // 一个 RenderNode节点 只能有一个 RecordingCanvas目标 
    if (mCurrentRecordingCanvas != null) {
        throw new IllegalStateException(
                "Recording currently in progress - missing #endRecording() call?");
    }
    mCurrentRecordingCanvas = RecordingCanvas.obtain(this, width, height);
    return mCurrentRecordingCanvas;
}

updateViewTreeDisplayList 更新View树的DisplayList

private void updateViewTreeDisplayList(View view) {
    view.mPrivateFlags |= View.PFLAG_DRAWN;
    view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
            == View.PFLAG_INVALIDATED;
    view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
    // 调用了view的 updateDisplayListIfDirty
    view.updateDisplayListIfDirty();
    view.mRecreateDisplayList = false;
}

传入View获取到对应RenderNode中的displayList;假如根节点需求更新并且具有drawOp指令需求获取到根节点的RecordingCanvas目标(包括当时node宽高信息)并调用drawRenderNode进行更新view的displayList( updateDisplayListIfDirty )终究调用rootnode的endRecording加入到nodes集合中

updateDisplayListIfDirty
public RenderNode updateDisplayListIfDirty() {
    // 拿到对应的 renderNode
    final RenderNode renderNode = mRenderNode;
    if (!canHaveDisplayList()) {
        // can't populate RenderNode, don't try
        return renderNode;
    }
    if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
            || !renderNode.hasDisplayList()
            || (mRecreateDisplayList)) {
        // Don't need to recreate the display list, just need to tell our
        // children to restore/recreate theirs
        // 假如当时view的缓存可用,则重用drawOp展示列表。告知子view去重建displayList
        if (renderNode.hasDisplayList()
                && !mRecreateDisplayList) {
            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
            // 分发子view去 重建displayList
            dispatchGetDisplayList();
            return renderNode; // no work needed
        }
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        int layerType = getLayerType();
        // 假如走到这儿表明缓存不可用需求drawOp树重建,开端记载drawOp
        //获取RecordingCanvas后续draw的时分是制作到这块canvas的
        final RecordingCanvas canvas = renderNode.beginRecording(width, height);
        try {
            if (layerType == LAYER_TYPE_SOFTWARE) {
               // 假如当时view具有LAYER_TYPE_SOFTWARE类型,及时开了硬件加速,也只会运用
               //Android软件烘托管道来制作。
                buildDrawingCache(true);
                Bitmap cache = getDrawingCache(true);
                if (cache != null) {
                    canvas.drawBitmap(cache, 0, 0, mLayerPaint);
                }
            } else {
                // Fast path for layouts with no backgrounds
                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                    // 假如自身不需求制作,则分发到子view,让子view去完结制作
                    dispatchDraw(canvas);
                    drawAutofilledHighlight(canvas);
                    if (mOverlay != null && !mOverlay.isEmpty()) {
                        mOverlay.getOverlayView().draw(canvas);
                    }
                    if (debugDraw()) {
                        debugDrawFocus(canvas);
                    }
                } else {
                    //查看下行代码解释
                    draw(canvas);
                }
            }
        } finally {
            // 完毕记载drawOp
            renderNode.endRecording();
            setDisplayListProperties(renderNode);
        }
    } else {
        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
    }
    return renderNode;
}
// draw 办法 
public void draw(Canvas canvas) {
     /*
      * Draw traversal performs several drawing steps which must be executed
      * in the appropriate order:
      *
      *      1. Draw the background
      *      2. If necessary, save the canvas' layers to prepare for fading
      *      3. Draw view's content
      *      4. Draw children
      *      5. If necessary, draw the fading edges and restore layers
      *      6. Draw decorations (scrollbars for instance)
      */
     }
}    

和根View相同调用updateDisplayListIfDirty;假如当时View缓存可用则重用drawOp列表。分发子View去重建displayList;假如缓存不可用表明需求重建DrawOp树

重建DrawOp树的过程起始点

重建DrawOp树的过程起始点便是renderNode.beginRecording获取到RecordingCanvas记载制作指令

重建DrawOp树记载制作指令

调用 draw办法内部会将指令添加到RecordingCanvas(实质是native层的SkiaCanvas) 中(六个顺序背景,内容等)

重建DrawOp树完毕将canvas记载的DisplayList回来给java层
> RenderNode.java
public void endRecording() {
    if (mCurrentRecordingCanvas == null) {
        throw new IllegalStateException(
                "No recording in progress, forgot to call #beginRecording()?");
    }
    RecordingCanvas canvas = mCurrentRecordingCanvas;
    mCurrentRecordingCanvas = null;
    // 1 完毕制作动作记载,调用到native,回来native层的SkiaDisplayList目标的引证
    long displayList = canvas.finishRecording();
    //释放displayList
    nSetDisplayList(mNativeRenderNode, displayList);
    canvas.recycle();
}
> nSetDisplayList
> frameworks/base/core/jni/android_view_RenderNode.cpp
static void android_view_RenderNode_setDisplayList(JNIEnv* env,
        jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
    renderNode->setStagingDisplayList(newData);
}
> frameworks/base/libs/hwui/RenderNode.cpp
void RenderNode::setStagingDisplayList(DisplayList* displayList) {
      //
    mValid = (displayList != nullptr);
    mNeedsDisplayListSync = true;
    //释放之前的 displayList
    delete mStagingDisplayList;
    // 赋值新的 displayList
    mStagingDisplayList = displayList;
}

RecordingCanvasrenderNode.endRecording()完毕记载drawOP树 node调用endRecording(),内部终究调用的是native层的 SkiaRecordingCanvas的finishRecording()办法,回来 displayList目标的引证给java层。

DrawOp树重建总结
  1. 经过ThreadedRenderer.updateRootDisplayList(),根据view树来构建对应的RenderNode 树(一个view对应一个node) 。每个node中包括了当时view的制作指令,如drawXXXop,假如有子view还会包括drawRenderNodeOp指令。 这些Op又称为统称为displayList。
  2. 调用node.beginRecording()开端记载,得到java层的RecordingCanvas 目标,一起得到native层的 SkiaRecordingCanvas目标当时view开端执行draw(canvas) ,以及自己的子view的draw(canvas)办法,终究都是调用canvas的api,记载到RecordingCanvas中
  3. 调用node.endRecording()完毕制作, RenderNode.endRecording()做了两件事:调用native层 SkiaRecordingCanvas的finishRecording(),完毕记载,一起回来displayList的引证到java层

至此,一切的制作指令都存储到了对应的node中。

canvas.drawRenderNode制作Node

上一步中只是更新了一切RenderNodenode中的displayList,也便是完结了canvas.drawRenderNode(view.updateDisplayListIfDirty())中view.updateDisplayListIfDirty()的部分,接下来便是调用drawRenderNode来对displayList进行制作

canva.drawNode实质上是调用native层的Skiacanvas的drawRenderNode办法

public void drawRenderNode(@NonNull RenderNode renderNode) {
     // 其实便是调用native的 canvas->drawRenderNode(...
    nDrawRenderNode(mNativeCanvasWrapper, renderNode.mNativeRenderNode);
}
>frameworks/base/core/jni/android_view_DisplayListCanvas.cpp
static void android_view_DisplayListCanvas_drawRenderNode(jlong canvasPtr, jlong renderNodePtr) {
    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    canvas->drawRenderNode(renderNode);
}
>frameworks/base/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
    // mChildNodes 是 std::deque<RenderNodeDrawable>类型。 
    //把renderNode转换成drawable目标,创立一个 RenderNodeDrawable目标,存入行列中
    mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
    // 取出 RenderNodeDrawable 目标
    //RenderNodeDrawable 封装了一个node目标,让node能够被记载为 一系列的 skia 制作指令。
    auto& renderNodeDrawable = mDisplayList->mChildNodes.back();
    // 开端制作 
    drawDrawable(&renderNodeDrawable);
    // use staging property, since recording on UI thread
    if (renderNode->stagingProperties().isProjectionReceiver()) {
        mDisplayList->mProjectionReceiver = &renderNodeDrawable;
    }
}
// 开端制作
>frameworks/base/libs/hwui/SkiaCanvas.h
void drawDrawable(SkDrawable* drawable) { 
   //mCanvas 是 SKCanvas目标
   mCanvas->drawDrawable(drawable); 
}
// 此时现已到了skia引擎库
>external/skia/src/core/SkCanvas.cpp
void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
    // 持续调用
    this->onDrawDrawable(dr, matrix);
}
void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
    // drawable bounds are no longer reliable (e.g. android displaylist)
    // so don't use them for quick-reject
    if (this->predrawNotify()) {
        this->topDevice()->drawDrawable(this, dr, matrix);
    }
}
SkBaseDevice* SkCanvas::topDevice() const {
    SkASSERT(fMCRec->fDevice);
    return fMCRec->fDevice;
}
topDevice() 回来的是 SkDevice目标。
>external/skia/src/core/SkDevice.cpp  
void SkBaseDevice::drawDrawable(SkCanvas* canvas, SkDrawable* drawable, const SkMatrix* matrix) {
    //able是 SKDrawable类型,上面传入的详细完结类是 RenderNodeDrawable 
    drawable->draw(canvas, matrix);
}
> external/skia/src/core/SkDrawable.cpp
void SkDrawable::draw(SkCanvas* canvas, const SkMatrix* matrix) {
    SkAutoCanvasRestore acr(canvas, true);
    if (matrix) {
      //结合skia的 matrix 
        canvas->concat(*matrix);
    }
    // onDraw是一个抽象办法,详细完结的是xxxDrawable,而这儿传入的是 RenderNodeDrawable
    this->onDraw(canvas);
    if ((false)) {
        draw_bbox(canvas, this->getBounds());
    }
}
RenderNodeDrawable
>frameworks/base/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
void RenderNodeDrawable::onDraw(SkCanvas* canvas) {
    // negative and positive Z order are drawn out of order, if this render node drawable is in
    // a reordering section
    if ((!mInReorderingSection) || MathUtils::isZero(mRenderNode->properties().getZ())) {
        this->forceDraw(canvas);
    }
}
void RenderNodeDrawable::forceDraw(SkCanvas* canvas) const {
    RenderNode* renderNode = mRenderNode.get();
    //最重要的是这句,将displayList转换为SkiaDl语法
    SkiaDisplayList* displayList = renderNode->getDisplayList().asSkiaDl();
    displayList->mProjectedOutline = nullptr;
}
renderNode转换成RenderNodeDrawable目标

将renderNode转换成drawable目标创立一个RenderNodeDrawable目标,存入行列中

RenderNodeDrawable 封装了一个node目标,让node能够被记载为 一系列的 skia 制作指令。

RenderNodeDrawable中将node转换成skia指令

这时分现已到了SkiaCanvas内部,调用SkCanvas的drawAble一切的制作DrawOp指令终究都会转换成skia制作指令

DrawFrameTask::drawFrame()

接着就开端进入到同步过程了。把renderNode同步到烘托线程也便是调用renderProxy的syncAndDrawFrame,其内部会调用mDrawFrameTask.drawFrame办法

// post到 RenderTHread 线程
postAndWait();其终究会调用到下一行:
//往烘托线程的行列中 post任务进去 ,回调run办法。
mRenderThread->queue().post([this]() { run(); });

也便是会往RenderThread的行列中post自己,终究会调用DrawFrmaeTask的run办法。

// run办法:
void DrawFrameTask::run() {
    bool canUnblockUiThread;
    bool canDrawThisFrame;
    {
        // 结构一个 treeInfo 目标 
        TreeInfo info(TreeInfo::MODE_FULL, *mContext);
        // 遍历renderNode结合,转变为TreeInfo 信息
        canUnblockUiThread = syncFrameState(info);
    }
    //赋值 CanvasContext 目标
    CanvasContext* context = mContext;
    // ... 
    nsecs_t dequeueBufferDuration = 0;
    if (CC_LIKELY(canDrawThisFrame)) {
         // 调用canvasContext的draw办法开端制作 
        dequeueBufferDuration = context->draw();
    }
}
//syncFrameState办法
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
    // 预备eglcontext 上下文,用来链接OpenGL和 GraphicBuffer之间的桥梁
    bool canDraw = mContext->makeCurrent();
    for (size_t i = 0; i < mLayers.size(); i++) {
        mLayers[i]->apply();
    }
}
// makeCurrent()办法的详细完结为 SkiaOpenGLPipeline或许 SkiaVulkanPipeline。
>frameworks/base/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
    // 调用 mEglManager 来初始化
    if (!mEglManager.makeCurrent(mEglSurface, &error)) {
        return MakeCurrentResult::AlreadyCurrent;
    }
    return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded;
}
>frameworks/base/libs/hwui/renderthread/EglManager.cpp 
bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut, bool force) {
    if (!force && isCurrent(surface)) return false;
    if (surface == EGL_NO_SURFACE) {
        // Ensure we always have a valid surface & context
        // 确保surface有用
        surface = mPBufferSurface;
    }
    //egl模块给OpenGL供给Surface和eglContext
    if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
        ...
    }
    return true;
}

run办法中会创立一个TreeInfo目标遍历renderNode转换成TreeInfo,接着调用makeCurrent初始化eglContext上下文(用来链接opengl和graphicbuffer的桥梁),主要是绑定surface让egl模块给opengl供给surface窗口和eglcontext上下文。经过EglManager的 makeCurrent()终于让OpenGL和本地窗口surface 联系了起来。因此,经过CanvasContext.draw() 就能够完结OpenGL/Vulkan制作,终究经过Skia/Vulkan 引擎(SkiaOpenGLPipeline/SkiaVulkanPipeline)把数据烘托到缓冲区GraphicBuffer中

CanvasContext介绍

CanvasContext 效果用于管理当时制作区域。每个RenderThread目标有一个 CanvasContext。 管理全局EGL context和当时制作区域surface。

绑定Surface

在ViewRootImpl的 setView办法,假如是硬件制作则会恳求Buffer,经过mAttachInfo.mThreadRender.alloateBuffers()

//mAttachInfo.mThreadRender.alloateBuffers
public void allocateBuffers() {
    // JNI办法
     nAllocateBuffers(mNativeProxy);
}
private static native void nAllocateBuffers(long nativeProxy);
>frameworks/base/core/jni/android_view_ThreadedRenderer.cpp 
static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,jlong proxyPtr) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    //调用RenderProxy的allocateBuffers
    proxy->allocateBuffers();
}
>frameworks/base/libs/hwui/renderthread/RenderProxy.cpp 
void RenderProxy::allocateBuffers() {
    // post到renderThread线程中
    //run办法中会调用CanvasContext.allocateBuffers()
    mRenderThread.queue().post([=]() { mContext->allocateBuffers(); });
} 
>frameworks/base/libs/hwui/renderthread/CanvasContext.cpp
void CanvasContext::allocateBuffers() {
    if (mNativeSurface && Properties::isDrawingEnabled()) {
        // ANativeWindow的hook办法
        ANativeWindow_tryAllocateBuffers(mNativeSurface->getNativeWindow());
    }
}
void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) {
    if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) {
        return;
    }
    // 终究调用到 ANativeWindow的perform函数,surface的hook_perform钩子函数也会回调
    window->perform(window, NATIVE_WINDOW_ALLOCATE_BUFFERS);
}

在 Surface 中会进行申请buffer终究仍是和软件制作相同buffer是经过GraphBufferProducer进行申请的。恳求到buffer后会调用ThreadProxy的init办法调用context.setSurface完结canvascontext和Surface的绑定