Android View绘制原理 - HardwareRenderer

前面的文章介绍了绘制的主要流程和基础组件,包括Vsync的主要流程,Surface的创建流程,Canvas相关的组件,现在可以开始绘制了。前面的文章已经分析过,现在默认是开启硬件加速的,因此会使用HardwareRenderer来进行绘制,涉及的内容较多,本文仅介绍HardwareRenderer的初始化流程。

1. ViewRootImpl

HardwareRendererder的初始化是再ViewRootImpl在完成的,再setView方法中,会调用enableHardwareAcceleration方法:

java 复制代码
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
                if (mSurfaceHolder == null) {
                    enableHardwareAcceleration(attrs);  
                }
}
java 复制代码
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
        ...
                mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent, attrs.getTitle().toString());
                ...
    }

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

java 复制代码
public static ThreadedRenderer create(Context context, boolean translucent, String name) {
        return new ThreadedRenderer(context, translucent, name);
    }

当relayoutWindow完成后,初始化了BlastBufferQueue,然后通过这个queue创建出了一个新的Surface,然后复制给到ViewRootImpl的mSurface,从而mSurface变成可用状态。

java 复制代码
private void performTraversals() {
               ...
                relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
               ...
                if (surfaceCreated) {
                   ...
                    if (mAttachInfo.mThreadedRenderer != null) {
                           ...
                            hwInitialized = mAttachInfo.mThreadedRenderer.initialize(mSurface);
                            if (hwInitialized && (host.mPrivateFlags  & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                                // Don't pre-allocate if transparent regions
                                // are requested as they may not be needed
                                mAttachInfo.mThreadedRenderer.allocateBuffers();
                            }
                           ...
                    }
                } else {
                      ....
                }
              ...
java 复制代码
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException {
      ...
        int relayoutResult = mWindowSession.relayout(mWindow, params,,,,);
       
        if (mSurfaceControl.isValid()) {
          
                final Surface blastSurface = getOrCreateBLASTSurface();
                // If blastSurface == null that means it hasn't changed since the last time we
                // called. In this situation, avoid calling transferFrom as we would then
                // inc the generation ID and cause EGL resources to be recreated.
                if (blastSurface != null) {
                    mSurface.transferFrom(blastSurface);
                }
            }
            if (mAttachInfo.mThreadedRenderer != null) {
                 ...
                mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
            }
        } 
         ...
    }

performTraversals 这里有两个步骤

  • 调用relayoutWindow去生成有效的SurfaceControl,然后调用AttachInfo.mThreadedRenderer.setSurfaceControl方法设置到mThreadedRenderer
  • relayout结束后,生成有效的Surface,然后调用mThreadedRenderer.initialize进行初始化,接着调用了allocateBuffers来分图形缓存。因此初始化中,我们主来分析这几个方法。

2. ThreadedRenderer构造方法

ThreadedRenderer继承自HardwareRenderer,因此构造方法直接进入HardwareRenderer的构造方法
frameworks/base/graphics/java/android/graphics/HardwareRenderer.java

java 复制代码
public HardwareRenderer() {
        ProcessInitializer.sInstance.initUsingContext();
        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
        mRootNode.setClipToBounds(false);
        mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
        if (mNativeProxy == 0) {
            throw new OutOfMemoryError("Unable to create hardware renderer");
        }
        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
        ProcessInitializer.sInstance.init(mNativeProxy);
    }

这里调用了很多的native函数来进行初始化

2.1 ProcessInitializer.sInstance.initUsingContext

java 复制代码
 synchronized void initUsingContext() {
            if (mContext == null) return;
            initDisplayInfo();
            nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
         
            mContext = null;
        }

调用initDisplayInfo初始化DisplayInfo

java 复制代码
private void initDisplayInfo() {
        
            DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
           
            Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
           
            Mode activeMode = display.getMode();
            nInitDisplayInfo(activeMode.getPhysicalWidth(), activeMode.getPhysicalHeight(),
                    display.getRefreshRate(), wideColorDataspace.mNativeDataspace,
                    display.getAppVsyncOffsetNanos(), display.getPresentationDeadlineNanos());

            mDisplayInitialized = true;
        }

获取默认显示器,然后调用nInitDisplayInfo,传入的物理宽度,长度,刷新率等信息。
frameworks/base/libs/hwui/jni/android_graphics_HardwareRenderer.cpp

java 复制代码
static void android_view_ThreadedRenderer_initDisplayInfo(JNIEnv*, jclass, jint physicalWidth,
                                                          jint physicalHeight, jfloat refreshRate,
                                                          jint wideColorDataspace,
                                                          jlong appVsyncOffsetNanos,
                                                          jlong presentationDeadlineNanos) {
    DeviceInfo::setWidth(physicalWidth);
    DeviceInfo::setHeight(physicalHeight);
    DeviceInfo::setRefreshRate(refreshRate);
    DeviceInfo::setWideColorDataspace(static_cast<ADataSpace>(wideColorDataspace));
    DeviceInfo::setAppVsyncOffsetNanos(appVsyncOffsetNanos);
    DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
}

将显示器的信息保存到DeviceInfo,因此在底层后续就可以知道显示器的这些信息。

2.2 初始化RootRenderNode

调用jni方法nCreateRootRenderNode来生成RootRenderNode的对象

java 复制代码
static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
    RootRenderNode* node = new RootRenderNode(std::make_unique<JvmErrorReporter>(env));
    node->incStrong(0);
    node->setName("RootRenderNode");
    return reinterpret_cast<jlong>(node);
}

生成一个RootRenderNode对象,并返回其指针给java层,java层构造一个RenderNode对象来持有这个指针,

java 复制代码
public static RenderNode adopt(long nativePtr) {
        return new RenderNode(nativePtr);
}

将这个对象赋值给mRootNode。RenderNode的构造方法如下:

java 复制代码
private RenderNode(long nativePtr) {
        mNativeRenderNode = nativePtr;
        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
        mAnimationHost = null;
    }

2.3 创建RenderProxy

调用nCreateProxy来创建一个RenderProxy,RenderProxy是向上提供API,其内部真正起作用的是RenderThread 和DrawFrameTask, RenderProxy的大部分方法都会通过向ReaderThread的工作队列里添加任务去执行,或者通过DrawFrameTask 去绘制一帧。

java 复制代码
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
        jboolean translucent, jlong rootRenderNodePtr) {
    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
    ContextFactoryImpl factory(rootRenderNode);
    RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
    return (jlong) proxy;
}

构造出RenderProxy对象,然后将这个指针保存到HardwareRender的mNativeProxy字段。

java 复制代码
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
                         IContextFactory* contextFactory)
        : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
    mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
        return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
    });
    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode,
                              pthread_gettid_np(pthread_self()), getRenderThreadTid());
}

构造RenderProxy的时候,会初始化RenderThread 和CanvasContext. 创建CanvasContext的时候,调用了mRenderThread.queue().runSync方法,这个类似Handler的runWithScissors,需要lamda执行完才返回。最后将renderThread,canvasContex和rootRenderNode设置到mDrawFrameTask。

2.4 创建RenderThread

RenderThread是一个无限循环的线程,它有一个queue来接受任务,有任务来时唤醒线程进行执行。这在HardwareRender初始化时需要将RenderThread初始化。这是一个单例对象,通过RenderThread::getInstance()来获取创建好的对象。
frameworks/base/libs/hwui/renderthread/RenderThread.cpp

java 复制代码
RenderThread& RenderThread::getInstance() {
    [[clang::no_destroy]] static sp<RenderThread> sInstance = []() {
        sp<RenderThread> thread = sp<RenderThread>::make();
        thread->start("RenderThread");
        return thread;
    }();
    gHasRenderThreadInstance = true;
    return *sInstance;
}

RenderThread::RenderThread()
        : ThreadBase()
        , mVsyncSource(nullptr)
        , mVsyncRequested(false)
        , mFrameCallbackTaskPending(false)
        , mRenderState(nullptr)
        , mEglManager(nullptr)
        , mFunctorManager(WebViewFunctorManager::instance())
        , mGlobalProfileData(mJankDataMutex) {
    Properties::load();
}

RenderThread继承自ThreadBase,当调用start启动线程的时候,会执行threadLoop方法:

java 复制代码
bool RenderThread::threadLoop() {
    setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
    Looper::setForThread(mLooper);
    if (gOnStartHook) {
        gOnStartHook("RenderThread");
    }
    initThreadLocals();

    while (true) {
        waitForWork();
        processQueue();
        ...
    }

    return false;
}

此时RenderThread就绪,等待Queue里出现任务。

2.5 创建CanvasContext

上面介绍了CanvasContext的构造是这样的:

java 复制代码
mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
        return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
    });

最终调用的是一个create方法:

java 复制代码
CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
                                     RenderNode* rootRenderNode, IContextFactory* contextFactory) {
    auto renderType = Properties::getRenderPipelineType();

    switch (renderType) {
        case RenderPipelineType::SkiaGL:
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
        case RenderPipelineType::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;
}

它首先根据系统属性配置,如果是使用SkialGL绘制的话,生成一个SkiaOpenGLPipeline对象,如果使用SkiaVulkan的话,就创建一个SkiaVulkanPipeline,当pipeline创建好后,用于生成CanvasContext。

java 复制代码
CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
                             IContextFactory* contextFactory,
                             std::unique_ptr<IRenderPipeline> renderPipeline)
        : mRenderThread(thread)
        , mGenerationID(0)
        , mOpaque(!translucent)
        , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
        , mJankTracker(&thread.globalProfileData())
        , mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
        , mContentDrawBounds(0, 0, 0, 0)
        , mRenderPipeline(std::move(renderPipeline)) {
    rootRenderNode->makeRoot();
    mRenderNodes.emplace_back(rootRenderNode);
    mProfiler.setDensity(DeviceInfo::getDensity());
}

这样CanvasContext就拥有了绘制的能力,比如RenderThread提供异步的绘制能力,mRenderPipeline提供图形绘制能力,rootRenderNode提供绘制内容。因此CanvasContext融合了绘制所需要各种的组件。

到这里HardwareRender的构造就完成了,它创建了底层的RenderProxy,启动了RenderThread,以及初始化了CanvaContext以及RenderPipeline。

3 HardwareRender的初始化

前面以及介绍了,HardwareRender对象创好出来之后,需要进行初始化,为其提供绘制所需的Surface。

java 复制代码
 boolean initialize(Surface surface) throws OutOfResourcesException {
        boolean status = !mInitialized;
        mInitialized = true;
        updateEnabledState(surface);
        setSurface(surface);
        return status;
    }

这里调用setSurface方法来这设置,从而进入到这个native方法

java 复制代码
public void setSurface(@Nullable Surface surface, boolean discardBuffer) {
        if (surface != null && !surface.isValid()) {
            throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
        }
        nSetSurface(mNativeProxy, surface, discardBuffer);
    }
   
java 复制代码
static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject jsurface, jboolean discardBuffer) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    ANativeWindow* window = nullptr;
    if (jsurface) {
        window = fromSurface(env, jsurface);
    }
    bool enableTimeout = true;
    if (discardBuffer) {
        // Currently only Surface#lockHardwareCanvas takes this path
        enableTimeout = false;
        proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
    }
    proxy->setSurface(window, enableTimeout);
    if (window) {
        ANativeWindow_release(window);
    }
}

在这里我们看到将一个Surface转换成了一个ANativeWindow,我们前面介绍过,Surface是继承自ANativeWindow的,而fromSurface函数是定义window.h的方法ANativeWindow_fromSurface ,它只是作了一个类型转换,其实返回的就还是Surface本身。
frameworks/base/native/android/native_window_jni.cpp

java 复制代码
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) {
    sp<ANativeWindow> win = android_view_Surface_getNativeWindow(env, surface);
    if (win != NULL) {
        ANativeWindow_acquire(win.get());
    }
    return win.get();
}

ANativeWindow_acquire 和ANativeWindow_release 是分别作引用计数的增加和减少。在转换成了ANativeWinwodw之后,设置到proxy去

java 复制代码
void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
   if (window) { ANativeWindow_acquire(window); }
   mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
       mContext->setSurface(win, enableTimeout);
       if (win) { ANativeWindow_release(win); }
   });
}

通过王renderThread的队列中post一个任务来,将ANativeWindow 设置的到CanvasContext

java 复制代码
void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
   ATRACE_CALL();

   if (window) {
       mNativeSurface = std::make_unique<ReliableSurface>(window);
       mNativeSurface->init();
       if (enableTimeout) {
           // TODO: Fix error handling & re-shorten timeout
           ANativeWindow_setDequeueTimeout(window, 4000_ms);
       }
   } else {
       mNativeSurface = nullptr;
   }
   setupPipelineSurface();
}

在这里先 创建一个ReliableSurface来包装window,接着调用init进行初始化,enableTimeout为true,于是设置dequeue的超时为4秒钟,然后在调用setupPipelineSurface开启绘制流水线。我们来一步步分析一下

3.1 ReliableSurface

它的构造很简单
frameworks/base/libs/hwui/renderthread/ReliableSurface.cpp

java 复制代码
ReliableSurface::ReliableSurface(ANativeWindow* window) : mWindow(window) {
    LOG_ALWAYS_FATAL_IF(!mWindow, "Error, unable to wrap a nullptr");
    ANativeWindow_acquire(mWindow);
}

赋值给mWindow,然后增加引用计数

3.2 ReliableSurface.init

java 复制代码
void ReliableSurface::init() {
    int result = ANativeWindow_setCancelBufferInterceptor(mWindow, hook_cancelBuffer, this);
    LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set cancelBuffer interceptor: error = %d",
                        result);

    result = ANativeWindow_setDequeueBufferInterceptor(mWindow, hook_dequeueBuffer, this);
    LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set dequeueBuffer interceptor: error = %d",
                        result);

    result = ANativeWindow_setQueueBufferInterceptor(mWindow, hook_queueBuffer, this);
    LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set queueBuffer interceptor: error = %d",
                        result);

    result = ANativeWindow_setPerformInterceptor(mWindow, hook_perform, this);
    LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set perform interceptor: error = %d",
                        result);

    result = ANativeWindow_setQueryInterceptor(mWindow, hook_query, this);
    LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set query interceptor: error = %d",
                        result);
}

它init为ANativeWindow设置了5个拦截器,这个连接器在Surface本身的hook函数中执行,所以dequeueBuffer, queueBuffer,perform 和query方法都会转到到ReliableSurface来执行,我们分析一下hook_dequeueBuffer方法的拦截机制

java 复制代码
int ReliableSurface::hook_dequeueBuffer(ANativeWindow* window,
                                        ANativeWindow_dequeueBufferFn dequeueBuffer, void* data,
                                        ANativeWindowBuffer** buffer, int* fenceFd) {
    ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
    {
        std::lock_guard _lock{rs->mMutex};
        if (rs->mReservedBuffer) {
            *buffer = rs->mReservedBuffer;
            *fenceFd = rs->mReservedFenceFd.release();
            rs->mReservedBuffer = nullptr;
            return OK;
        }
    }

    int result = dequeueBuffer(window, buffer, fenceFd);
    if (result != OK) {
        ALOGW("dequeueBuffer failed, error = %d; switching to fallback", result);
        *buffer = rs->acquireFallbackBuffer(result);
        *fenceFd = -1;
        return *buffer ? OK : INVALID_OPERATION;
    } else {
        std::lock_guard _lock{rs->mMutex};
        rs->mHasDequeuedBuffer = true;
    }
    return OK;
}
  • data 是注册回调的时候,传入的this,因此可以转回ReliableSurface。
  • 调用dequeueBuffer方法,这个dequeueBuffer方法是surface中在调用这个拦截器是传入的方法指针dequeueBufferInternal。
    frameworks/native/libs/gui/Surface.cpp
java 复制代码
int Surface::hook_dequeueBuffer(ANativeWindow* window,
        ANativeWindowBuffer** buffer, int* fenceFd) {
    Surface* c = getSelf(window);
    {
        std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex);
        if (c->mDequeueInterceptor != nullptr) {
            auto interceptor = c->mDequeueInterceptor;
            auto data = c->mDequeueInterceptorData;
            return interceptor(window, Surface::dequeueBufferInternal, data, buffer, fenceFd);
        }
    }
    return c->dequeueBuffer(buffer, fenceFd);
}

因此其实还是调用到了Surface的dequeueBufferInternal来执行dequeueBuffer。只不过这里经过了ReliableSurface一层封装,记录一下mHasDequeuedBuffer = true。

3.3 setupPipelineSurface

这一步将ANativeWindow设置到pipeline

java 复制代码
void CanvasContext::setupPipelineSurface() {
    bool hasSurface = mRenderPipeline->setSurface(
            mNativeSurface ? mNativeSurface->getNativeWindow() : nullptr, mSwapBehavior);
   ...
}

mRenderPipeline的类型是SkiaPipeline,而SkiaPipeline是继承自IRenderPipeline,setSurface也是定义在IRenderPipeline
frameworks/base/libs/hwui/renderthread/IRenderPipeline.h

java 复制代码
virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior) = 0;

实现的是根据系统属性设置的,可能是SkiaOpenGLPipeline和SkiaVulkanPipeline,我们分析一下SkiaOpenGLPipeline

frameworks/base/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp

java 复制代码
bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior) {
    if (mEglSurface != EGL_NO_SURFACE) {
        mEglManager.destroySurface(mEglSurface);
        mEglSurface = EGL_NO_SURFACE;
    }

    if (surface) {
        mRenderThread.requireGlContext();
        auto newSurface = mEglManager.createSurface(surface, mColorMode, mSurfaceColorSpace);
        if (!newSurface) {
            return false;
        }
        mEglSurface = newSurface.unwrap();
    }

    if (mEglSurface != EGL_NO_SURFACE) {
        const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
        mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
        return true;
    }

    return false;
}

mRenderThread.requireGlContext(); 将会为RenderThread创建好使用OpenGL进行GPU绘制的上下文

接着调用mEglManager的createSurface方法,传入ANativeWindow,生成一个EGLSurface。EGL 是OpenGL 与 Android 窗口的桥接。

frameworks/base/libs/hwui/renderthread/EglManager.cpp

java 复制代码
Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
                                                     ColorMode colorMode,
                                                     sk_sp<SkColorSpace> colorSpace) {
    ...
    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, config, window, attribs);
    if (surface == EGL_NO_SURFACE) {
        return Error<EGLint>{eglGetError()};
    }

    ...
    return surface;
}

ELGSurface是一个指针
frameworks/native/opengl/include/EGL/eglext.h

java 复制代码
typedef void *EGLSurface;

eglCreateWindowSurface的实现如下

frameworks/native/opengl/libs/EGL/eglApi.cpp

java 复制代码
    EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window,
                                  const EGLint* attrib_list) {
    clearError();

    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglCreateWindowSurface(dpy, config, window, attrib_list);
}

egl_connection_t的定义在这个头文件:

frameworks/native/opengl/libs/EGL/egldefs.h

java 复制代码
struct egl_connection_t {
    ...
    egl_t egl;
    platform_impl_t platform;
    ...
};
extern egl_connection_t gEGLImpl;

platform又是另外一个结构体类型platform_impl_t

java 复制代码
struct platform_impl_t {
    #include "platform_entries.in"
};

frameworks/native/opengl/libs/platform_entries.in

java 复制代码
EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint*)

frameworks/native/opengl/libs/hooks.h

java 复制代码
#define EGL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__);

展开就等于:

java 复制代码
EGLSurface *(eglCreateWindowSurface)(EGLDisplay, EGLConfig, NativeWindowType, const EGLint *)   

这个函数的实现在这里
frameworks/native/opengl/libs/EGL/egl_platform_entries.cpp

java 复制代码
   static const implementation_map_t sPlatformImplMap[] = {
        ...
       { "eglCreateWindowSurface", (EGLFuncPointer)&eglCreateWindowSurfaceImpl },
       ...
   }

   EGLSurface eglCreateWindowSurfaceImpl(EGLDisplay dpy, EGLConfig config, NativeWindowType window,
                                      const EGLint* attrib_list) {
    egl_connection_t* cnx = nullptr;
    egl_display_t* dp = validate_display_connection(dpy, &cnx);
    if (dp) {
        return eglCreateWindowSurfaceTmpl<
                EGLint, PFNEGLCREATEWINDOWSURFACEPROC>(dp, cnx, config, window, attrib_list,
                                                       cnx->egl.eglCreateWindowSurface);
    }
    return EGL_NO_SURFACE;
}

继续调用了eglCreateWindowSurfaceTmpl来生成EGLSurface。 这个函数的最后一个参数cnx->egl.eglCreateWindowSurface是一个方法指针。在上面的代码有列出,其中cnx->egl是一个egl_t类型的结构体,定义也是在hooks里,

java 复制代码
struct egl_t {
    #include "EGL/egl_entries.in"
};

frameworks/native/opengl/libs/EGL/egl_entries.in```

java 复制代码
EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint *)

展开之后,结果如下:

java 复制代码
EGLSurface *(eglCreateWindowSurface)(EGLDisplay, EGLConfig, NativeWindowType, const EGLint *)

因此调用eglCreateWindowSurfaceTmpl方法的最后一个参数就是这个函数。我看一下这个函数

frameworks/native/opengl/libs/EGL/egl_platform_entries.cpp

java 复制代码
template <typename AttrType, typename CreateFuncType>
EGLSurface eglCreateWindowSurfaceTmpl(egl_display_t* dp, egl_connection_t* cnx, EGLConfig config,
                                      ANativeWindow* window, const AttrType* attrib_list,
                                      CreateFuncType createWindowSurfaceFunc) {
   ...
    window->query(window, NATIVE_WINDOW_IS_VALID, &value);
    if (!value) {
        return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    }

    ....
    int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
    ...
    int err = native_window_set_buffers_format(window, format);
    ....
    window->setSwapInterval(window, 1);

    EGLSurface surface = createWindowSurfaceFunc(iDpy, config, window, attrib_list);
    if (surface != EGL_NO_SURFACE) {
        egl_surface_t* s = new egl_surface_t(dp, config, window, surface,
                                             getReportedColorSpace(colorSpace), cnx);
        return s;
    }

    // EGLSurface creation failed
    if (!cnx->useAngle) {
        native_window_set_buffers_format(window, 0);
        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
    }
    return EGL_NO_SURFACE;
}

这里先对window作了一些操作,比如native_window_api_connect, 它会执行Surface的perform方法,最后调用到Surface的connect方法,但是因为现在BufferQueue是由App进程自己管理了,因此connect里并没有IPC的调用。最后执行createWindowSurfaceFunc函数来生成EGLSurface,然后包装成egl_surface_t_返回去。_createWindowSurfaceFunc * 是来自于cnx->egl. 这个egl是全局的,它是在初始化时,加载EGL驱动的时候赋值的,具体的逻辑比较复杂,所以它的内容就不再此处展开了。

frameworks/native/opengl/libs/EGL/egl_object.h.

java 复制代码
class egl_surface_t : public egl_object_t {
      ...
      egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
                  EGLint colorSpace, egl_connection_t const* cnx);

这里可以看到egl_surface_t的定义,因为EGLSurface仅仅是一个指针,因此可以返回这个对象,同时我们也知道了后面使用的EGLSurface本质上是一个egl_surface_t对象。

4 总结

HardrwareRender的初始化需要从Java层传入Surface,这个Surface在C层将以ANativeWindow的形式被使用。 在初始化后,C

层会创建一个RenderProxy,启动一个RenderThread以及创建CanvasContext,它包含一个RenderPipeline,RenderPipeline通过EGLManager生成EGLSuface,它的类型只一个指针,实际指向一个egl_surface_t结构体,最终这个EGLSurfacec实际持有这个Surface对象,从而为后面通过EGL绘制搭建好环境。

👀关注公众号:Android老皮!!!欢迎大家来找我探讨交流👀

相关推荐
三少爷的鞋7 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)11 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码13 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程13 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程18 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程18 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓18 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程18 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer