Android-View绘制原理(11)-HardwareRenderer

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

1. ViewRootImpl

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

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

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

public static ThreadedRenderer create(Context context, boolean translucent, String name) {
        return new ThreadedRenderer(context, translucent, name);
    }

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

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 {
                      ....
                }
              ...
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

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

 synchronized void initUsingContext() {
            if (mContext == null) return;
            initDisplayInfo();
            nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
         
            mContext = null;
        }

调用initDisplayInfo初始化DisplayInfo

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

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的对象

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对象来持有这个指针,

public static RenderNode adopt(long nativePtr) {
        return new RenderNode(nativePtr);
}

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

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 去绘制一帧。

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字段。

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

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方法:

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的构造是这样的:

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

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

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。

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。

 boolean initialize(Surface surface) throws OutOfResourcesException {
        boolean status = !mInitialized;
        mInitialized = true;
        updateEnabledState(surface);
        setSurface(surface);
        return status;
    }

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

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);
    }
   
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

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去

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

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

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

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方法的拦截机制

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
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

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

virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior) = 0;

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

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

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

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

typedef void *EGLSurface;

eglCreateWindowSurface的实现如下

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

	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

struct egl_connection_t {
    ...
    egl_t egl;
    platform_impl_t platform;
    ...
};
extern egl_connection_t gEGLImpl;

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

struct platform_impl_t {
    #include "platform_entries.in"
};

frameworks/native/opengl/libs/platform_entries.in

EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint*)

frameworks/native/opengl/libs/hooks.h

#define EGL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__);

展开就等于:

EGLSurface *(eglCreateWindowSurface)(EGLDisplay, EGLConfig, NativeWindowType, const EGLint *)	

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

   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里,

struct egl_t {
    #include "EGL/egl_entries.in"
};

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

EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint *)

展开之后,结果如下:

EGLSurface *(eglCreateWindowSurface)(EGLDisplay, EGLConfig, NativeWindowType, const EGLint *)

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

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

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.

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绘制搭建好环境。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值