创建流程
- 应用程序窗口对应一个Surface(Surface.java)
- Surface由每个应用进程的ViewRootImpl持有
- Surface最初初始化为一个空Surface
- Surface的初始化发生在第一次relayoutWindow
css
[View.invalidate]
↓
[逐级传递到 ViewRootImpl]
↓
[ViewRootImpl.scheduleTraversals()]
↓
[插入同步屏障,注册 VSYNC 回调]
↓
[VSYNC 信号到达 → 执行 doTraversal() → performTraversals() → relayoutWindow]
↓
[执行updateBlastSurfaceIfNeeded()]
↓
[创建BLASTBufferQueue → mBlastBufferQueue.createSurface() → mSurface.transferFrom(blastSurface)]
接下来分析Java层BLASTBufferQueue的createSurface创建流程
BLASTBufferQueue.createSurface
- Java层的createSurface对应到jni中的nativeGetSurface
- jni层中,通过BLASTBufferQueue::getSurface获取Surface
- 在BLASTBufferQueue::getSurface中创建并返回了一个BBQSurface
c++
sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
std::lock_guard _lock{mMutex};
sp<IBinder> scHandle = nullptr;
if (includeSurfaceControlHandle && mSurfaceControl) {
scHandle = mSurfaceControl->getHandle();
}
return new BBQSurface(mProducer, true, scHandle, this);
}
- BBQSurface关联了BBQ中的生产者、SurfaceControl、还有BBQ自己本身
- Java层窗口对应的Surface在native层包装的是BBQSurface
将Surface设置给hwui
- 接着上一节,在performTraversals()中创建Surface后,接着会进行更新Surface
c++
private void performTraversals() {
...
} else if ((surfaceReplaced || surfaceSizeChanged || updateSurfaceNeeded)
&& mSurfaceHolder == null
&& mAttachInfo.mThreadedRenderer != null
&& mSurface.isValid()) {
mFullRedrawNeeded = true;
try {
// Need to do updateSurface (which leads to CanvasContext::setSurface and
// re-create the EGLSurface) if either the Surface changed (as indicated by
// generation id), or WindowManager changed the surface size. The latter is
// because on some chips, changing the consumer side's BufferQueue size may
// not take effect immediately unless we create a new EGLSurface.
// Note that frame size change doesn't always imply surface size change (eg.
// drag resizing uses fullscreen surface), need to check surfaceSizeChanged
// flag from WindowManager.
mAttachInfo.mThreadedRenderer.updateSurface(mSurface);
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
mLastPerformTraversalsSkipDrawReason = "oom_update_surface";
return;
}
}
}
- 从java层一层层调用到SkiaPipeline
- 需要注意的一点是在jni层,会将Surface转成ANativeWindow,在hwui模块中只能感知到ANativeWindow的存在
- 在skiapipeline中根据opengl、vulkan后端,区分不同的流程(Android15中已经默认走vulkan)
- (opengl),在SkiaOpenGLPipeline中调用setSurface,然后是EglManager.createSurace将ANativeWindow转成EGLSurface
渲染
还有一条非常隐蔽的线,在SkiaPipeline renderFrame渲染每帧内容时,用的是SkSurface,SkSurface与EGLSurface的关联是源码中看不到的
- 在SkiaPipeline中通过MakeFromBackendRenderTarget创建SkSurface时,需要传入GrBackendRenderTarget(封装了
EGLSurface
的帧缓冲区对象 FBO)