原创文章,转载注明出处,多谢合作。
接上篇,本篇了解下绑定Surface到RenderThread的过程.
从ViewRootmpl的setView中的requestLayout()开始:
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
接着看 mTraversalRunnable , 这是向Choreographer注册的postRunnable回调
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
performTraversals()正式开始UI处理流程
private void performTraversals() {
...
boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
if (layoutRequested) {//满足重新layout的需求
...
/ /预测量阶段, 此阶段将会调用performMeasure计算出View树为显示其内容所需的尺寸,即期望的窗口尺寸.
windowSizeMayChange |= measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);
}
...
/ /根据预测量的结果,通过IWindowSession.relayout()方法向WMS请求调整窗口的尺寸等属性,这将引发WMS对窗口进行重新布局,并将布局结果返回给ViewRootImpl
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
if (!hadSurface) {//首次冷启动hadSurface为 false
if (mAttachInfo.mThreadedRenderer != null) { //之前ThreadedRenderer已经初始化好了
hwInitialized = mAttachInfo.mThreadedRenderer.initialize(mSurface);
}
}
...
if (!mStopped || mReportNextDraw) {
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);//以窗口的实际尺寸对View树进行最终测量
}
...
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);//View树布局
if (didLayout) {
performLayout(lp, mWidth, mHeight);
...
}
...
boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
if (!cancelDraw && !newSurface) {
...
performDraw();//开始绘制处理
...
}
...
}
这里surface绑定流程是从mThreadedRenderer.initialize开始的:
/frameworks/base/core/java/android/view/ThreadedRenderer.java
boolean initialize(Surface surface) throws OutOfResourcesException {
boolean status = !mInitialized;
mInitialized = true;
updateEnabledState(surface);
nInitialize(mNativeProxy, surface);
return status;
}
updateEnabledState 设置了一个Enabled标记
private void updateEnabledState(Surface surface) {
if (surface == null || !surface.isValid()) {
setEnabled(false); //首次启动走这
} else {
setEnabled(mInitialized);
}
}
另外还有个nInitialize 它是个Native方法:
/frameworks/base/core/jni/android_view_ThreadedRenderer.cpp
static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jsurface) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
proxy->initialize(surface);
}
获取java层创建的Surface ,然后走RenderProxy initialize
void RenderProxy::initialize(const sp<Surface>& surface) {
mRenderThread.queue().post(
[ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf));
...
});
}
这里mContext 是CanvasContext 由它执行 setSurface
void CanvasContext::setSurface(sp<Surface>&& surface) {
ATRACE_CALL(); //这里就是systrace中的setSurface label
mNativeSurface = std::move(surface);
ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Srgb;
bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
mFrameNumber = -1;
if (hasSurface) {
mHaveNewSurface = true;
mSwapHistory.clear();
} else {
mRenderThread.removeFrameCallback(this);
mGenerationID++;
}
}
上篇我们讲过, 9.0走的是SkiaGL , 因此mRenderPipeline对应的是SkiaOpenGLPipeline.
frameworks/base/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
ColorMode colorMode) {
if (mEglSurface != EGL_NO_SURFACE) {
mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
}
if (surface) {
const bool wideColorGamut = colorMode == ColorMode::WideColorGamut;
mEglSurface = mEglManager.createSurface(surface, wideColorGamut);
}
if (mEglSurface != EGL_NO_SURFACE) {
const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
return true;
}
return false;
}
接着看EglManager.createSurface方法
frameworks/base/libs/hwui/renderthread/EglManager.cpp
EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) {
initialize();//创建EGLContext
...
//通过eglCreateWindowSurface创建EGLSurface
EGLSurface surface = eglCreateWindowSurface(
mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
...
return surface;
}
这个方法先看initialize()
void EglManager::initialize() {
if (hasEglContext()) return;
ATRACE_NAME("Creating EGLContext");//对应systrace中的Creating EGLContext label
...
loadConfigs();
createContext();
createPBufferSurface();
makeCurrent(mPBufferSurface);
DeviceInfo::initialize();
mRenderThread.renderState().onGLContextCreated();
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
#ifdef HWUI_GLES_WRAP_ENABLED
debug::GlesDriver* driver = debug::GlesDriver::get();
sk_sp<const GrGLInterface> glInterface(driver->getSkiaInterface());
#else
sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
#endif
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
options.fDisableDistanceFieldPaths = true;
mRenderThread.cacheManager().configureContext(&options);
sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
LOG_ALWAYS_FATAL_IF(!grContext.get());
mRenderThread.setGrContext(grContext);
}
}
这里主要是创建了EGLContext以及PBufferSurface.
再回过头来看EglManager::createSurface的eglCreateWindowSurface部分,它简单说就是创建EGLSurface.
再稍微跟下eglCreateWindowSurface这个方法:
external/swiftshader/src/OpenGL/libEGL/main.cpp
EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
{
return egl::CreateWindowSurface(dpy, config, window, attrib_list);
}
最后调用libEGL.cpp的CreateWindowSurface:
external/swiftshader/src/OpenGL/libEGL/libEGL.cpp
EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
{
TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType win = %p, "
"const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
egl::Display *display = egl::Display::get(dpy);
if(!validateConfig(display, config))
{
return EGL_NO_SURFACE;
}
if(!display->isValidWindow(window))
{
return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
return display->createWindowSurface(window, config, attrib_list);
}
从这部分看,最终调用的是OpenGL库的方法了,这里暂时不求甚解,继续跟着主线走。
注:
EGLSurface: 它是一个 EGL 分配的离屏缓冲区 (称为 "pbuffer") 或由操作系统分配的窗口。由 eglCreateWindowSurface() 调用创建。接收一个 "窗口对象" 作为参数,在 Android 上它可以是一个 SurfaceView,SurfaceTexture,SurfaceHolder 或 Surface -- 所有在底层具有 BufferQueue 的东西。当你执行这个调用时,EGL 创建一个新的 EGLSurface 对象,将它与窗口对象的 BufferQueue 的生产者接口连接。从那时起,向那个 EGLSurface 渲染将使得一个缓冲区被取出,向其中渲染,并放回以由消费者使用。
EGL创建EGLSurface有三个方法:eglCreateWindowSurface()、eglCreatePbufferSurface()和eglCreatePixmapSurface() 分别创建WindowSurface、PbufferSurface、PixmapSurface.
- WindowSurface 在屏幕上的一块显示区的封装,渲染后即显示在界面上。
- PbufferSurface 在显存中开辟一个空间,将渲染后的数据(帧)存放在这里。
- PixmapSurface 以位图的形式存放在内存中,据说各平台的支持不是很好。
OpenGL操作的最终目标实际上是帧缓存(Frame Buffer)后面的各种表现形式则是EGL对Frame Buffer的封装.
最后总结一张流程图:
绑定Surface到RenderThread整体流程
网友评论