我正在参与创作者训练营第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()中被初始化。结构办法做了如下初始化:
- 在结构办法中会创立Java和native层两个 根RenderNode节点。
- 创立native层的RenderProxy目标,持有 RenderThread 单例线程的引证。
- 给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树重建总结
- 经过ThreadedRenderer.updateRootDisplayList(),根据view树来构建对应的RenderNode 树(一个view对应一个node) 。每个node中包括了当时view的制作指令,如drawXXXop,假如有子view还会包括drawRenderNodeOp指令。 这些Op又称为统称为displayList。
- 调用node.beginRecording()开端记载,得到java层的RecordingCanvas 目标,一起得到native层的 SkiaRecordingCanvas目标当时view开端执行draw(canvas) ,以及自己的子view的draw(canvas)办法,终究都是调用canvas的api,记载到RecordingCanvas中
- 调用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的绑定