Android下SF合成流程重学习之GPU合成

2024-04-10 1271阅读

    Android下SF合成流程重学习之GPU合成

引言

SurfaceFlinger中的图层选择GPU合成(CLIENT合成方式)时,会把待合成的图层Layers通过renderengine(SkiaGLRenderEngine)绘制到一块GraphicBuffer中,然后把这块GraphicBuffer图形缓存通过调用setClientTarget传递给HWC模块,HWC进一步处理后把这个GraphicBuffer中的图像呈现到屏幕上。

本篇文章,我们先聚焦如下量点做介绍:

  • 用于存储GPU合成后的图形数据的GraphicBuffer是从哪里来的?
  • GPU合成中,SF执行的主要逻辑是什么?

    Android下SF合成流程重学习之GPU合成

    Android下SF合成流程重学习之GPU合成


    一.从dumpsys SurfaceFlinger中的信息谈起

    如果你查看过dumpsys SurfaceFlinger的信息,也许你注意过一些GraphicBufferAllocator/GraphicBufferMapper打印出的一些信息,这些信息记录了所有通过Gralloc模块allocate和import的图形缓存的信息。

    如下是在我的平台下截取的dumpsys SurfaceFlinger部分信息:

    GraphicBufferAllocator buffers:
        Handle |        Size |     W (Stride) x H | Layers |   Format |      Usage | Requestor
    0xf3042b90 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xf3042f30 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xf3046020 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    Total allocated by GraphicBufferAllocator (estimate): 24300.00 KB
    Imported gralloc buffers:
    + name:FramebufferSurface, id:e100000000, size:8.3e+03KiB, w/h:780x438, usage: 0x40001b00, req fmt:5, fourcc/mod:875713089/576460752303423505, dataspace: 0x0, compressed: true
    	planes: B/G/R/A:	 w/h:780x440, stride:1e00 bytes, size:818000
    + name:FramebufferSurface, id:e100000001, size:8.3e+03KiB, w/h:780x438, usage: 0x40001b00, req fmt:5, fourcc/mod:875713089/576460752303423505, dataspace: 0x0, compressed: true
    	planes: B/G/R/A:	 w/h:780x440, stride:1e00 bytes, size:818000
    + name:FramebufferSurface, id:e100000002, size:8.3e+03KiB, w/h:780x438, usage: 0x40001b00, req fmt:5, fourcc/mod:875713089/576460752303423505, dataspace: 0x0, compressed: true
    	planes: B/G/R/A:	 w/h:780x440, stride:1e00 bytes, size:818000
    Total imported by gralloc: 5e+04KiB
    

    上面的信息中可以看到一些儿冥冥之中貌似、似乎、好像很有意思的字眼:FramebufferSurface。

    作为Requestor的FramebufferSurface去请求分配了三块图形缓存,还规定了width、height、format、usage等信息。

    如上你看到的这3块GraphicBuffer,就是用来存储CPU合成后的图形数据的。


    二.SF为GPU合成做的准备

    俗话说的好,不打没有准备的仗。SF也是如此,为了做好GPU的合成,SF会在启动的时候就搭建好EGL环境,为后续GPU合成做好准备。具体逻辑如下:

    文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::init() {
        ALOGI(  "SurfaceFlinger's main thread ready to run. "
                "Initializing graphics H/W...");
        Mutex::Autolock _l(mStateLock);
        // Get a RenderEngine for the given display / config (can't fail)
        // TODO(b/77156734): We need to stop casting and use HAL types when possible.
        // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
        // 创建RenderEngine对象
        mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(
                renderengine::RenderEngineCreationArgs::Builder()
                    .setPixelFormat(static_cast(defaultCompositionPixelFormat))
                    .setImageCacheSize(maxFrameBufferAcquiredBuffers)
                    .setUseColorManagerment(useColorManagement)
                    .setEnableProtectedContext(enable_protected_contents(false))
                    .setPrecacheToneMapperShaderOnly(false)
                    .setSupportsBackgroundBlur(mSupportsBlur)
                    .setContextPriority(useContextPriority
                            ? renderengine::RenderEngine::ContextPriority::HIGH
                            : renderengine::RenderEngine::ContextPriority::MEDIUM)
                    .build()));
    文件:frameworks/native/libs/renderengine/RenderEngine.cpp
    std::unique_ptr RenderEngine::create(const RenderEngineCreationArgs& args) {
        char prop[PROPERTY_VALUE_MAX];
         // 如果PROPERTY_DEBUG_RENDERENGINE_BACKEND 属性不设,则默认是gles类型
        property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
        if (strcmp(prop, "gles") == 0) {
            ALOGD("RenderEngine GLES Backend");
            // 创建GLESRenderEngine对象
            return renderengine::gl::GLESRenderEngine::create(args);
        }
        ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
        return renderengine::gl::GLESRenderEngine::create(args);
    }
    文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
    std::unique_ptr GLESRenderEngine::create(const RenderEngineCreationArgs& args) {
        // initialize EGL for the default display
        // 获得EGLDisplay
        EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (!eglInitialize(display, nullptr, nullptr)) {
            LOG_ALWAYS_FATAL("failed to initialize EGL");
        }
         // 查询EGL版本信息
        const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
        if (!eglVersion) {
            checkGlError(__FUNCTION__, __LINE__);
            LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
        }
        //查询EGL支持哪些拓展
        const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
        if (!eglExtensions) {
            checkGlError(__FUNCTION__, __LINE__);
            LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
        }
        //根据支持的拓展设置属性,目前来看所有的属性都为true
        GLExtensions& extensions = GLExtensions::getInstance();
        extensions.initWithEGLStrings(eglVersion, eglExtensions);
        // The code assumes that ES2 or later is available if this extension is
        // supported.
        EGLConfig config = EGL_NO_CONFIG;
        if (!extensions.hasNoConfigContext()) {
            config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
        }
        bool useContextPriority =
                extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH;
        EGLContext protectedContext = EGL_NO_CONTEXT;
        if (args.enableProtectedContext && extensions.hasProtectedContent()) {
            protectedContext = createEglContext(display, config, nullptr, useContextPriority,
                                                Protection::PROTECTED);
            ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
        }
        // 创建非protect的EglContext
        EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
                                           Protection::UNPROTECTED);
        LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
        EGLSurface dummy = EGL_NO_SURFACE;
         // 支持该属性,不走if逻辑
        if (!extensions.hasSurfacelessContext()) {
            dummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
                                                 Protection::UNPROTECTED);
            LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
        }
        // eglMakeCurrent 将 EGLDisplay和EglContext 绑定
        EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
        LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
        ...
        std::unique_ptr engine;
        switch (version) {
            case GLES_VERSION_1_0:
            case GLES_VERSION_1_1:
                LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
                break;
            case GLES_VERSION_2_0:
            case GLES_VERSION_3_0:
                // GLESRenderEngine 初始化
                engine = std::make_unique(args, display, config, ctxt, dummy,
             protectedContext, protectedDummy);
                break;
        }
    ...
    }
    GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
                                       EGLConfig config, EGLContext ctxt, EGLSurface dummy,
                                       EGLContext protectedContext, EGLSurface protectedDummy)
          : renderengine::impl::RenderEngine(args),
            mEGLDisplay(display),
            mEGLConfig(config),
            mEGLContext(ctxt),
            mDummySurface(dummy),
            mProtectedEGLContext(protectedContext),
            mProtectedDummySurface(protectedDummy),
            mVpWidth(0),
            mVpHeight(0),
            mFramebufferImageCacheSize(args.imageCacheSize),
            mUseColorManagement(args.useColorManagement) {
        // 查询可支持最大的纹理尺寸和视图大小
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
        glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
        //像素数据按4字节对齐
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glPixelStorei(GL_PACK_ALIGNMENT, 4);
        ...
          // 色彩空间相关设置,遇到具体场景再分析
         if (mUseColorManagement) {
            const ColorSpace srgb(ColorSpace::sRGB());
            const ColorSpace displayP3(ColorSpace::DisplayP3());
            const ColorSpace bt2020(ColorSpace::BT2020());
            // no chromatic adaptation needed since all color spaces use D65 for their white points.
            mSrgbToXyz = mat4(srgb.getRGBtoXYZ());
            mDisplayP3ToXyz = mat4(displayP3.getRGBtoXYZ());
            mBt2020ToXyz = mat4(bt2020.getRGBtoXYZ());
            mXyzToSrgb = mat4(srgb.getXYZtoRGB());
            mXyzToDisplayP3 = mat4(displayP3.getXYZtoRGB());
            mXyzToBt2020 = mat4(bt2020.getXYZtoRGB());
            // Compute sRGB to Display P3 and BT2020 transform matrix.
            // NOTE: For now, we are limiting output wide color space support to
            // Display-P3 and BT2020 only.
            mSrgbToDisplayP3 = mXyzToDisplayP3 * mSrgbToXyz;
            mSrgbToBt2020 = mXyzToBt2020 * mSrgbToXyz;
            // Compute Display P3 to sRGB and BT2020 transform matrix.
            mDisplayP3ToSrgb = mXyzToSrgb * mDisplayP3ToXyz;
            mDisplayP3ToBt2020 = mXyzToBt2020 * mDisplayP3ToXyz;
            // Compute BT2020 to sRGB and Display P3 transform matrix
            mBt2020ToSrgb = mXyzToSrgb * mBt2020ToXyz;
            mBt2020ToDisplayP3 = mXyzToDisplayP3 * mBt2020ToXyz;
        }
        ...
         // 涉及到有模糊的layer,具体场景再分析
        if (args.supportsBackgroundBlur) {
            mBlurFilter = new BlurFilter(*this);
            checkErrors("BlurFilter creation");
        }
        // 创建ImageManager 线程,这个线程是管理输入的mEGLImage
        mImageManager = std::make_unique(this);
        mImageManager->initThread();
        //创建GLFramebuffer
        mDrawingBuffer = createFramebuffer();
        ...
    }
        
    文件:frameworks/native/libs/renderengine/gl/GLFramebuffer.cpp
    // 创建了一个纹理ID mTextureName,和 fb ID mFramebufferName
    GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine)
          : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
        glGenTextures(1, &mTextureName);
        glGenFramebuffers(1, &mFramebufferName);
    }
    

    通过上述的代码我们可以看到在启动之初就搭建好了EGL环境,并将当前线程与context绑定,为后面使用gl命令做好准备,然后创建了ImageManager 线程,这个线程是管理输入Buffer的EGLImage,然后创建了GLFrameBuffer,用来操作输出的buffer。

    并且有一点我们需要特别注意,在在创建BufferQueueLayer时就已经对各个layer创建了纹理ID,为后面走GPU合成做准备。如下:

    文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::string name,
     uint32_t w, uint32_t h, uint32_t flags,
     LayerMetadata metadata, PixelFormat& format,
     sp* handle,
     sp* gbp,
     sp* outLayer) {
        ...
        
        args.textureName = getNewTexture();
        ...
    }
    uint32_t SurfaceFlinger::getNewTexture() {
        {
            std::lock_guard lock(mTexturePoolMutex);
            if (!mTexturePool.empty()) {
                uint32_t name = mTexturePool.back();
                mTexturePool.pop_back();
                ATRACE_INT("TexturePoolSize", mTexturePool.size());
                return name;
            }
            // The pool was too small, so increase it for the future
            ++mTexturePoolSize;
        }
        // The pool was empty, so we need to get a new texture name directly using a
        // blocking call to the main thread
        // 每个layer,调用glGenTextures 生成纹理ID,schedule运行在sf主线程
        return schedule([this] {
                   uint32_t name = 0;
                   getRenderEngine().genTextures(1, &name);
                   return name;
               })
                .get();
    }
    

    三.创建与初始化FramebufferSurface的流程

    FramebufferSurface的初始化逻辑需要从SurfaceFlinger的初始化谈起,我们知道在SurfaceFlinger::init()中会去注册HWC的回调函数mCompositionEngine->getHwComposer().setCallback(this),当第一次注册callback时,onComposerHalHotplug()会立即在调用registerCallback()的线程中被调用,并跨进程回调到SurfaceFlinger::onComposerHalHotplug。然后一路飞奔:

    Android下SF合成流程重学习之GPU合成

    在SurfaceFlinger::processDisplayAdded这个方法中去创建了BufferQueue和FramebufferSurface,简单理解为连接上了显示屏幕(Display),那就要给准备一个BufferQueue,以便GPU合成UI等图层时,可以向这个BufferQueue索要GraphicBuffer来存储合成后的图形数据,再呈现到屏幕上去(我的傻瓜式理解)

    摘取关键代码如下:

    [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
    void SurfaceFlinger::processDisplayAdded(const wp& displayToken,
                                             const DisplayDeviceState& state) {
        ......
        sp displaySurface;
        sp producer;
        // 创建BufferQueue,获取到生产者和消费者,而且消费者不是SurfaceFlinger哦
        sp bqProducer;
        sp bqConsumer;
        getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);
        if (state.isVirtual()) { // 虚拟屏幕,不管它
            const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
            LOG_FATAL_IF(!displayId);
            auto surface = sp::make(getHwComposer(), *displayId, state.surface,
            bqProducer, bqConsumer, state.displayName);
            displaySurface = surface;
            producer = std::move(surface);
        } else { // 看这个case
            ALOGE_IF(state.surface != nullptr,
                     "adding a supported display, but rendering "
                     "surface is provided (%p), ignoring it",
                     state.surface.get());
            const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());
            LOG_FATAL_IF(!displayId);
            // 创建了FramebufferSurface对象,FramebufferSurface继承自compositionengine::DisplaySurface
            // FramebufferSurface是作为消费者的角色工作的,消费SF GPU合成后的图形数据
            displaySurface =
                    sp::make(getHwComposer(), *displayId, bqConsumer,
                                                 state.physical->activeMode->getSize(),
                                                 ui::Size(maxGraphicsWidth, maxGraphicsHeight));
            producer = bqProducer;
        }
        LOG_FATAL_IF(!displaySurface);
        // 创建DisplayDevice,其又去创建RenderSurface,作为生产者角色工作,displaySurface就是FramebufferSurface对象
        const auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay),
            state, displaySurface, producer);
        mDisplays.emplace(displayToken, display);
        ......
    }
    

    瞅一瞅 FramebufferSuraface的构造函数,没啥复杂的,就是一些设置,初始化一些成员。

    FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
                                           const sp& consumer,
                                           const ui::Size& size, const ui::Size& maxSize)
          : ConsumerBase(consumer),
            mDisplayId(displayId),
            mMaxSize(maxSize),
            mCurrentBufferSlot(-1),
            mCurrentBuffer(),
            mCurrentFence(Fence::NO_FENCE),
            mHwc(hwc),
            mHasPendingRelease(false),
            mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
            mPreviousBuffer() {
        ALOGV("Creating for display %s", to_string(displayId).c_str());
        mName = "FramebufferSurface";
        mConsumer->setConsumerName(mName); // 设置消费者的名字是 "FramebufferSurface"
        mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |  // 设置usage
                                           GRALLOC_USAGE_HW_RENDER |
                                           GRALLOC_USAGE_HW_COMPOSER);
        const auto limitedSize = limitSize(size);
        mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height); // 设置buffer 大小
        mConsumer->setMaxAcquiredBufferCount(
                SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
    }
    

    再进到SurfaceFlinger::setupNewDisplayDeviceInternal中看看相关的逻辑:

    [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
    sp SurfaceFlinger::setupNewDisplayDeviceInternal(
            const wp& displayToken,
            std::shared_ptr compositionDisplay,
            const DisplayDeviceState& state,
            const sp& displaySurface,
            const sp& producer) {
        ......
        creationArgs.displaySurface = displaySurface;  // displaySurface就是FramebufferSurface对象   
        // producer是前面processDisplayAdded中创建的
        auto nativeWindowSurface = getFactory().createNativeWindowSurface(producer);
        auto nativeWindow = nativeWindowSurface->getNativeWindow();
        creationArgs.nativeWindow = nativeWindow;
        ....
        // 前面一大坨代码是在初始话creationArgs,这些参数用来创建DisplayDevice
        // creationArgs.nativeWindow会把前面创建的producer关联到了DisplayDevice
        sp display = getFactory().createDisplayDevice(creationArgs);
        // 后面一大坨,对display进行了些设置
        if (!state.isVirtual()) {
            display->setActiveMode(state.physical->activeMode->getId());
            display->setDeviceProductInfo(state.physical->deviceProductInfo);
        }
        ....
    }
    

    接下来就是 DisplayDevice 的构造函数了,里面主要是创建了RenderSurface对象,然后对其进行初始化

    [/frameworks/native/services/surfaceflinger/DisplayDevice.cpp]
    DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)
          : mFlinger(args.flinger),
            mHwComposer(args.hwComposer),
            mDisplayToken(args.displayToken),
            mSequenceId(args.sequenceId),
            mConnectionType(args.connectionType),
            mCompositionDisplay{args.compositionDisplay},
            mPhysicalOrientation(args.physicalOrientation),
            mSupportedModes(std::move(args.supportedModes)),
            mIsPrimary(args.isPrimary) {
        mCompositionDisplay->editState().isSecure = args.isSecure;
        // 创建RenderSurface,args.nativeWindow 即为producer,指向生产者
        mCompositionDisplay->createRenderSurface(
                compositionengine::RenderSurfaceCreationArgsBuilder()
                        .setDisplayWidth(ANativeWindow_getWidth(args.nativeWindow.get()))
                        .setDisplayHeight(ANativeWindow_getHeight(args.nativeWindow.get()))
                        .setNativeWindow(std::move(args.nativeWindow))
                        .setDisplaySurface(std::move(args.displaySurface)) // displaySurface就是FramebufferSurface对象
                        .setMaxTextureCacheSize(
                                static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers))
                        .build());
        if (!mFlinger->mDisableClientCompositionCache &&
            SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) {
            mCompositionDisplay->createClientCompositionCache(
                    static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers));
        }
        mCompositionDisplay->createDisplayColorProfile(
                compositionengine::DisplayColorProfileCreationArgs{args.hasWideColorGamut,
                    std::move(args.hdrCapabilities),
                    args.supportedPerFrameMetadata,
                    args.hwcColorModes});
        if (!mCompositionDisplay->isValid()) {
            ALOGE("Composition Display did not validate!");
        }
        // 初始化RenderSurface
        mCompositionDisplay->getRenderSurface()->initialize();
        setPowerMode(args.initialPowerMode);
        // initialize the display orientation transform.
        setProjection(ui::ROTATION_0, Rect::INVALID_RECT, Rect::INVALID_RECT);
    }
    

    RenderSurface作为生产者的角色工作,构造函数如下,留意启成员displaySurface就是SurfaceFlinger中创建的FramebufferSurface对象

    也就是 作为生产者的RenderSurface中持有 消费者的引用 displaySurface,可以呼叫FramebufferSurface的方法。

    [ /frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp]
    RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display& display,
                                 const RenderSurfaceCreationArgs& args)
          : mCompositionEngine(compositionEngine),
            mDisplay(display),
            mNativeWindow(args.nativeWindow),
            mDisplaySurface(args.displaySurface),  // displaySurface就是FramebufferSurface对象
            mSize(args.displayWidth, args.displayHeight),
            mMaxTextureCacheSize(args.maxTextureCacheSize) {
        LOG_ALWAYS_FATAL_IF(!mNativeWindow);
    }
    

    我们看看他的RenderSurface::initialize()方法

    [/frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp]
    void RenderSurface::initialize() {
        ANativeWindow* const window = mNativeWindow.get();
        int status = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
        ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status);
        status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
        ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status);
        status = native_window_set_usage(window, DEFAULT_USAGE);
        ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status);
    }
    

    上述方法也很简单,就是作为producer去和BufferQueue建立connect,并设置format为RGBA_8888,设置usage为GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE

    为了验证上述分析的流程是正确的,我在BufferQueueProducer::connect中加log来打印调用栈的信息,如下,是不是和分析的一样啊

    11-13 00:52:58.497   227   227 D BufferQueueProducer: connect[1303] /vendor/bin/hw/android.hardware.graphics.composer@2.4-service start
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#00 pc 0005e77f  /system/lib/libgui.so (android::BufferQueueProducer::connect(android::sp const&, int, bool, android::IGraphicBufferProducer::QueueBufferOutput*)+1282)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#01 pc 000a276b  /system/lib/libgui.so (android::Surface::connect(int, android::sp const&, bool)+138)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#02 pc 0009de41  /system/lib/libgui.so (android::Surface::hook_perform(ANativeWindow*, int, ...)+128)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#03 pc 00121b1d  /system/bin/surfaceflinger (android::compositionengine::impl::RenderSurface::initialize()+12)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#04 pc 00083cc5  /system/bin/surfaceflinger (android::DisplayDevice::DisplayDevice(android::DisplayDeviceCreationArgs&)+1168)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#05 pc 000d8bed  /system/bin/surfaceflinger (android::SurfaceFlinger::processDisplayAdded(android::wp const&, android::DisplayDeviceState const&)+4440)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#06 pc 000d0db5  /system/bin/surfaceflinger (android::SurfaceFlinger::processDisplayChangesLocked()+2436)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#07 pc 000cef6b  /system/bin/surfaceflinger (android::SurfaceFlinger::processDisplayHotplugEventsLocked()+6422)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#08 pc 000d2c7f  /system/bin/surfaceflinger (android::SurfaceFlinger::onComposerHalHotplug(unsigned long long, android::hardware::graphics::composer::V2_1::IComposerCallback::Connection)+334)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#09 pc 0009afab  /system/bin/surfaceflinger (_ZN7android12_GLOBAL__N_122ComposerCallbackBridge9onHotplugEyNS_8hardware8graphics8composer4V2_117IComposerCallback10ConnectionE$d689f7ac1c60e4abeed02ca92a51bdcd+20)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#10 pc 0001bb97  /system/lib/android.hardware.graphics.composer@2.1.so (android::hardware::graphics::composer::V2_1::BnHwComposerCallback::_hidl_onHotplug(android::hidl::base::V1_0::BnHwBase*, android::hardware::Parcel const&, android::hardware::Parcel*, std::__1::function)+166)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#11 pc 000275e9  /system/lib/android.hardware.graphics.composer@2.4.so (android::hardware::graphics::composer::V2_4::BnHwComposerCallback::onTransact(unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int, std::__1::function)+228)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#12 pc 00054779  /system/lib/libhidlbase.so (android::hardware::BHwBinder::transact(unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int, std::__1::function)+96)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#13 pc 0004fc67  /system/lib/libhidlbase.so (android::hardware::IPCThreadState::transact(int, unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int)+2174)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#14 pc 0004f2e5  /system/lib/libhidlbase.so (android::hardware::BpHwBinder::transact(unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int, std::__1::function)+36)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#15 pc 0002bdf1  /system/lib/android.hardware.graphics.composer@2.4.so (android::hardware::graphics::composer::V2_4::BpHwComposerClient::_hidl_registerCallback_2_4(android::hardware::IInterface*, android::hardware::details::HidlInstrumentor*, android::sp const&)+296)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#16 pc 0002ed8d  /system/lib/android.hardware.graphics.composer@2.4.so (android::hardware::graphics::composer::V2_4::BpHwComposerClient::registerCallback_2_4(android::sp const&)+34)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#17 pc 00085627  /system/bin/surfaceflinger (android::Hwc2::impl::Composer::registerCallback(android::sp const&)+98)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#18 pc 00092d63  /system/bin/surfaceflinger (android::impl::HWComposer::setCallback(android::HWC2::ComposerCallback*)+2206)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#19 pc 000cd35b  /system/bin/surfaceflinger (android::SurfaceFlinger::init()+438)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#20 pc 000feb03  /system/bin/surfaceflinger (main+862)
    11-13 00:52:58.581   227   227 E BufferQueueProducer: stackdump:#21 pc 0003253b  /apex/com.android.runtime/lib/bionic/libc.so (__libc_init+54)
    11-13 00:52:58.582   227   227 D BufferQueueProducer: connect[1307] /vendor/bin/hw/android.hardware.graphics.composer@2.4-service end
    

    这里有一个小细节要留意下,因为SurfaceFlinger::onComposerHalHotplug是HWC回调过来的,所以代码执行是在android.hardware.graphics.composer@2.4-service这个进程中的。

    BufferQueueProducer::connect中记录的mConnectedPid就是composer service的PID

    [ /frameworks/native/libs/gui/BufferQueueProducer.cpp]
    mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
    

    在dump BufferQueue的信息时,根据PID获取的 producer name 也就是 android.hardware.graphics.composer@2.4-service

    [/frameworks/native/libs/gui/BufferQueueCore.cpp]
    void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
        ...
        getProcessName(mConnectedPid, producerProcName);
        getProcessName(pid, consumerProcName);
        ....
    }
    

    如下是我的平台dumpsys SurfaceFlinger的信息打印出来的Composition RenderSurface State的信息,看看是不是和代码的设置都有对应起来:

    mConsumerName=FramebufferSurface
    producer=[342:/vendor/bin/hw/android.hardware.graphics.composer@2.4-service]
    consumer=[223:/system/bin/surfaceflinger])
    

    format/size/usage也都可以对应到代码的设置

       Composition RenderSurface State:
       size=[1920 1080] ANativeWindow=0xef2c3278 (format 1) flips=605
      FramebufferSurface: dataspace: Default(0)
       mAbandoned=0
       - BufferQueue mMaxAcquiredBufferCount=2 mMaxDequeuedBufferCount=1
         mDequeueBufferCannotBlock=0 mAsyncMode=0
         mQueueBufferCanDrop=0 mLegacyBufferDrop=1
         default-size=[1920x1080] default-format=1      transform-hint=00 frame-counter=580
         mTransformHintInUse=00 mAutoPrerotation=0
       FIFO(0):
       (mConsumerName=FramebufferSurface, mConnectedApi=1, mConsumerUsageBits=6656, mId=df00000000, producer=[342:/vendor/bin/hw/android.hardware.graphics.composer@2.4-service], consumer=[223:/system/bin/surfaceflinger])
       Slots:
        >[01:0xeec82110] state=ACQUIRED 0xef4429c0 frame=2 [1920x1080:1920,  1]
        >[02:0xeec806f0] state=ACQUIRED 0xef443100 frame=580 [1920x1080:1920,  1]
         [00:0xeec81f00] state=FREE     0xef440580 frame=579 [1920x1080:1920,  1]
    

    四.关于RenderSurface和FramebufferSurface小结

    Android下SF合成流程重学习之GPU合成

    上述内容中出现的一些字眼,不禁令人”瞎想连篇“

    SurfaceFlinger创建了BufferQueue ==> Producer & Consumer

    创建了RenderSurface作为生产者,它持有Producer

    创建了FramebufferSurface作为消费者,它持有Consumer

    前面分析BufferQueue的工作原理时,有讲过:

    生产者不断的dequeueBuffer & queueBuffer ; 而消费者不断的acquireBuffer & releaseBuffer ,这样图像缓存就在 生产者 – BufferQueue – 消费者 间流转起来了。

    看看作为生产者的RenderSurface中方法:

    [/frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h]
    /**
     * Encapsulates everything for composing to a render surface with RenderEngine
     */
    class RenderSurface {
        ....
        // Allocates a buffer as scratch space for GPU composition
        virtual std::shared_ptr dequeueBuffer(
                base::unique_fd* bufferFence) = 0;
        // Queues the drawn buffer for consumption by HWC. readyFence is the fence
        // which will fire when the buffer is ready for consumption.
        virtual void queueBuffer(base::unique_fd readyFence) = 0;
        ...
    };
    

    熟悉的味道:

    dequeueBuffer : 分配一个缓冲区作为GPU合成的暂存空间

    queueBuffer : 入队列已绘制好的图形缓存供HWC使用

    同样如果去查看作为消费者的FramebufferSurface也会看到acquireBuffer & releaseBuffer的调用,如下:

    [/frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp]
    status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
            sp& outBuffer, sp& outFence,
            Dataspace& outDataspace) {
        Mutex::Autolock lock(mMutex);
        BufferItem item;
        status_t err = acquireBufferLocked(&item, 0); // 获取待显示的buffer
        ...
        status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace); // 传递给HWC进一步处理显示
        return NO_ERROR;
    }
    

    所以,最后我们大概会有这样一种逻辑处理流程:

    • 当需要GPU合成时,会通过生产者RenderSurface::dequeueBuffer请求一块图形缓存,然后GPU就合成/绘图,把数据保存到这块图形缓存中,通过RenderSurface::queueBuffer提交这块缓存

    • 调用mDisplaySurface->advanceFrame()通知消费者来消费:

      FramebufferSurface::advanceFrame ==>FramebufferSurface::nextBuffer ==> acquireBufferLocked
      
    • 去请求可用的图形缓存,这个buffer中存储有GPU合成的结果,然后通过setClientTarget把这个buffer传递给HWC做处理显示。


      五.SF处理GPU合成流程分析

      还记得我们前面分析到的Output::prepareFrame吗,其如果存在GPU合成,会执行如下的相关逻辑:

      Output::prepareFrame()
          Display::chooseCompositionStrategy
              Output::chooseCompositionStrategy()
              hwc.getDeviceCompositionChanges
              
              
      status_t HWComposer::getDeviceCompositionChanges(
              DisplayId displayId, bool frameUsesClientComposition,
              std::optional* outChanges) {
          
          ...
          if (!frameUsesClientComposition) {
              sp outPresentFence;
              uint32_t state = UINT32_MAX;
              /**
               * @brief 
               * 如果所有的layer都能走device合成
               * 则在hwc里面直接present,若有不支持
               * device合成的情况,则走GPU合成,会走validate逻辑
               */
              error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
              if (!hasChangesError(error)) {
                  RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
              }
              if (state == 1) { //Present Succeeded.
                  //present成功,数据直接提交给了hwc
                  std::unordered_map releaseFences;
                  error = hwcDisplay->getReleaseFences(&releaseFences);
                  displayData.releaseFences = std::move(releaseFences);
                  displayData.lastPresentFence = outPresentFence;
                  displayData.validateWasSkipped = true;
                  displayData.presentError = error;
                  return NO_ERROR;
              }
              // Present failed but Validate ran.
          } else {
              error = hwcDisplay->validate(&numTypes, &numRequests);
          }
          ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
          if (!hasChangesError(error)) {
              RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
          }
          android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
          changedTypes.reserve(numTypes);
          error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
          RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
          auto displayRequests = static_cast(0);
          android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
          layerRequests.reserve(numRequests);
          error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
          RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
          DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
          error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
          outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
      std::move(layerRequests),
      std::move(clientTargetProperty)});
          //接收hwc反馈回来的,主要是支持device和gpu合成的情况
          error = hwcDisplay->acceptChanges();
          RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
          return NO_ERROR;
      }
      

      前面我们也分析到了Output::finishFrame,其中的composeSurfaces是GPU合成的核心:

      void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
          ...
          auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
          if (!optReadyFence) {
              return;
          }
          // swap buffers (presentation)
          mRenderSurface->queueBuffer(std::move(*optReadyFence));
      }
      

      Android下SF合成流程重学习之GPU合成

      Android下SF合成流程重学习之GPU合成

      5.1 Output::composeSurfaces

      这里我们先重点来看composeSurfaces这个函数,看下走GPU合成的逻辑:

      文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
      std::optional Output::composeSurfaces(
              const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
      ...
          base::unique_fd fd;
          sp buf;
          // If we aren't doing client composition on this output, but do have a
          // flipClientTarget request for this frame on this output, we still need to
          // dequeue a buffer.
          if (hasClientComposition || outputState.flipClientTarget) {
              // dequeueBuffer一块Buffer,这块Buffer作为输出
              buf = mRenderSurface->dequeueBuffer(&fd);
              if (buf == nullptr) {
                  ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
                        "client composition for this frame",
                        mName.c_str());
                  return {};
              }
          }
          base::unique_fd readyFence;
          // GPU合成时不返回
          if (!hasClientComposition) {
              setExpensiveRenderingExpected(false);
              return readyFence;
          }
          ALOGV("hasClientComposition");
           // 设置clientCompositionDisplay,这个是display相关参数
          renderengine::DisplaySettings clientCompositionDisplay;
          clientCompositionDisplay.physicalDisplay = outputState.destinationClip;
          clientCompositionDisplay.clip = outputState.sourceClip;
          clientCompositionDisplay.orientation = outputState.orientation;
          clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
             ? outputState.dataspace
                  : ui::Dataspace::UNKNOWN;
          clientCompositionDisplay.maxLuminance =
                  mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
          // Compute the global color transform matrix.
          if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
              clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
          }
          // Note: Updated by generateClientCompositionRequests
          clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
          // Generate the client composition requests for the layers on this output.
          // 设置clientCompositionLayers , 这个是layer的相关参数
          std::vector clientCompositionLayers =
                  generateClientCompositionRequests(supportsProtectedContent,
                                                    clientCompositionDisplay.clearRegion,
                                                    clientCompositionDisplay.outputDataspace);
          appendRegionFlashRequests(debugRegion, clientCompositionLayers);
          // Check if the client composition requests were rendered into the provided graphic buffer. If
          // so, we can reuse the buffer and avoid client composition.
          // 如果cache里有相同的Buffer,则不需要重复draw一次
          if (mClientCompositionRequestCache) {
              if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay,
          clientCompositionLayers)) {
                  outputCompositionState.reusedClientComposition = true;
                  setExpensiveRenderingExpected(false);
                  return readyFence;
              }
              mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay,
                                                  clientCompositionLayers);
          }
          // We boost GPU frequency here because there will be color spaces conversion
          // or complex GPU shaders and it's expensive. We boost the GPU frequency so that
          // GPU composition can finish in time. We must reset GPU frequency afterwards,
          // because high frequency consumes extra battery.
          // 针对有模糊layer和有复杂颜色空间转换的场景,给GPU进行提频
          const bool expensiveBlurs =
                  refreshArgs.blursAreExpensive && mLayerRequestingBackgroundBlur != nullptr;
          const bool expensiveRenderingExpected =
                  clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3 || expensiveBlurs;
          if (expensiveRenderingExpected) {
              setExpensiveRenderingExpected(true);
          }
          // 将clientCompositionLayers 里面的内容插入到clientCompositionLayerPointers,实质内容相同
          std::vector clientCompositionLayerPointers;
          clientCompositionLayerPointers.reserve(clientCompositionLayers.size());
          std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
                         std::back_inserter(clientCompositionLayerPointers),
                         [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* {
                             return &settings;
                         });
          const nsecs_t renderEngineStart = systemTime();
          // GPU合成,主要逻辑在drawLayers里面
          status_t status =
                  renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers,
                                          buf->getNativeBuffer(), /*useFramebufferCache=*/true,
                                          std::move(fd), &readyFence);
         ...
      }
      std::vector Output::generateClientCompositionRequests(
              bool supportsProtectedContent, Region& clearRegion, ui::Dataspace outputDataspace) {
          std::vector clientCompositionLayers;
          ALOGV("Rendering client layers");
          const auto& outputState = getState();
          const Region viewportRegion(outputState.viewport);
          const bool useIdentityTransform = false;
          bool firstLayer = true;
          // Used when a layer clears part of the buffer.
          Region dummyRegion;
          for (auto* layer : getOutputLayersOrderedByZ()) {
              const auto& layerState = layer->getState();
              const auto* layerFEState = layer->getLayerFE().getCompositionState();
              auto& layerFE = layer->getLayerFE();
              const Region clip(viewportRegion.intersect(layerState.visibleRegion));
              ALOGV("Layer: %s", layerFE.getDebugName());
              if (clip.isEmpty()) {
                  ALOGV("  Skipping for empty clip");
                  firstLayer = false;
                  continue;
              }
              const bool clientComposition = layer->requiresClientComposition();
              // We clear the client target for non-client composed layers if
              // requested by the HWC. We skip this if the layer is not an opaque
              // rectangle, as by definition the layer must blend with whatever is
              // underneath. We also skip the first layer as the buffer target is
              // guaranteed to start out cleared.
              const bool clearClientComposition =
                      layerState.clearClientTarget && layerFEState->isOpaque && !firstLayer;
              ALOGV("  Composition type: client %d clear %d", clientComposition, clearClientComposition);
              // If the layer casts a shadow but the content casting the shadow is occluded, skip
              // composing the non-shadow content and only draw the shadows.
              const bool realContentIsVisible = clientComposition &&
                      !layerState.visibleRegion.subtract(layerState.shadowRegion).isEmpty();
              if (clientComposition || clearClientComposition) {
                  compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
                          clip,
                          useIdentityTransform,
                          layer->needsFiltering() || outputState.needsFiltering,
                          outputState.isSecure,
                          supportsProtectedContent,
                          clientComposition ? clearRegion : dummyRegion,
                          outputState.viewport,
                          outputDataspace,
                          realContentIsVisible,
                          !clientComposition, /* clearContent  */
                  };
                  std::vector results =
                          layerFE.prepareClientCompositionList(targetSettings);
                  if (realContentIsVisible && !results.empty()) {
                      layer->editState().clientCompositionTimestamp = systemTime();
                  }
                  clientCompositionLayers.insert(clientCompositionLayers.end(),
                                                 std::make_move_iterator(results.begin()),
                                                 std::make_move_iterator(results.end()));
                  results.clear();
              }
              firstLayer = false;
          }
          return clientCompositionLayers;
      }
      

      输入的Buffer是通过BufferLayer的prepareClientComposition 函数设到RenderEngine里面的,如下:

      文件:frameworks/native/services/surfaceflinger/BufferLayer.cpp
      std::optional BufferLayer::prepareClientComposition(
              compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) {
          ATRACE_CALL();
          std::optional result =
                  Layer::prepareClientComposition(targetSettings);
           ...
          const State& s(getDrawingState());
          // 应用queue过来的Buffer
          layer.source.buffer.buffer = mBufferInfo.mBuffer;
          layer.source.buffer.isOpaque = isOpaque(s);
           // acquire fence
          layer.source.buffer.fence = mBufferInfo.mFence;
          // 创建BufferQueueLayer时创建的texture ID
          layer.source.buffer.textureName = mTextureName;
          ...
      }
      

      至此,SurfaceFlinger调到RenderEngine里面,SurfaceFlinger的display和outputlayer的信息传到了RenderEngine,这些都是GPU合成需要的信息,然后来看下drawLayers的流程。

      5.2 GLESRenderEngine::drawLayers

      Android下SF合成流程重学习之GPU合成

      文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
      status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                                            const std::vector& layers,
                                            ANativeWindowBuffer* const buffer,
                                            const bool useFramebufferCache, base::unique_fd&& bufferFence,
                                            base::unique_fd* drawFence) {
          ATRACE_CALL();
          if (layers.empty()) {
              ALOGV("Drawing empty layer stack");
              return NO_ERROR;
          }
           // 要等前一帧的release fence
          if (bufferFence.get() >= 0) {
              // Duplicate the fence for passing to waitFence.
              base::unique_fd bufferFenceDup(dup(bufferFence.get()));
              if (bufferFenceDup setNativeWindowBuffer(buffer, mEngine.isProtected(),
             useFramebufferCache)
                      ? mEngine.bindFrameBuffer(mFramebuffer)
                      : NO_MEMORY;
          }
          ~BindNativeBufferAsFramebuffer() {
              mFramebuffer->setNativeWindowBuffer(nullptr, false, /*arbitrary*/ true);
              mEngine.unbindFrameBuffer(mFramebuffer);
          }
          status_t getStatus() const { return mStatus; }
      private:
          RenderEngine& mEngine;
          Framebuffer* mFramebuffer;
          status_t mStatus;
      };
      文件: frameworks/native/libs/renderengine/gl/GLFramebuffer.cpp
      bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
                                                const bool useFramebufferCache) {
          ATRACE_CALL();
          if (mEGLImage != EGL_NO_IMAGE_KHR) {
              if (!usingFramebufferCache) {
                  eglDestroyImageKHR(mEGLDisplay, mEGLImage);
                  DEBUG_EGL_IMAGE_TRACKER_DESTROY();
              }
              mEGLImage = EGL_NO_IMAGE_KHR;
              mBufferWidth = 0;
              mBufferHeight = 0;
          }
          if (nativeBuffer) {
              mEGLImage = mEngine.createFramebufferImageIfNeeded(nativeBuffer, isProtected,
                  useFramebufferCache);
              if (mEGLImage == EGL_NO_IMAGE_KHR) {
                  return false;
              }
              usingFramebufferCache = useFramebufferCache;
              mBufferWidth = nativeBuffer->width;
              mBufferHeight = nativeBuffer->height;
          }
          return true;
      }
      文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
      GLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
                    bool isProtected,
                    bool useFramebufferCache) {
          // buffer类型转换,将ANativeWindowBuffer 转换成 GraphicsBuffer
          sp graphicBuffer = GraphicBuffer::from(nativeBuffer);
            //使用cache,如果有一样的image,就直接返回
           if (useFramebufferCache) {
              std::lock_guard lock(mFramebufferImageCacheMutex);
              for (const auto& image : mFramebufferImageCache) {
                  if (image.first == graphicBuffer->getId()) {
                      return image.second;
                  }
              }
          }
          EGLint attributes[] = {
                  isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
                  isProtected ? EGL_TRUE : EGL_NONE,
                  EGL_NONE,
          };
          // 将dequeue出来的buffer作为参数创建 EGLImage
          EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                                                nativeBuffer, attributes);
          if (useFramebufferCache) {
              if (image != EGL_NO_IMAGE_KHR) {
                  std::lock_guard lock(mFramebufferImageCacheMutex);
                  if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
                      EGLImageKHR expired = mFramebufferImageCache.front().second;
                      mFramebufferImageCache.pop_front();
                      eglDestroyImageKHR(mEGLDisplay, expired);
                      DEBUG_EGL_IMAGE_TRACKER_DESTROY();
                  }
                   // 把image放到mFramebufferImageCache 里面
                  mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
              }
          }
          if (image != EGL_NO_IMAGE_KHR) {
              DEBUG_EGL_IMAGE_TRACKER_CREATE();
          }
          return image;
      }
      status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
          ATRACE_CALL();                
          GLFramebuffer* glFramebuffer = static_cast(framebuffer);
          // 上一步创建的EGLImage
          EGLImageKHR eglImage = glFramebuffer->getEGLImage();
           // 创建RenderEngine 时就已经创建好的 texture id和 fb id
          uint32_t textureName = glFramebuffer->getTextureName();
          uint32_t framebufferName = glFramebuffer->getFramebufferName();
          // Bind the texture and turn our EGLImage into a texture
          // 绑定texture,后面的操作将作用在这上面
          glBindTexture(GL_TEXTURE_2D, textureName);
           // 根据EGLImage 创建一个 2D texture
          glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage); 
          // Bind the Framebuffer to render into
          glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
          // 将纹理附着在帧缓存上面,渲染到farmeBuffer
          glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
          uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
          ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
                   glStatus);
          return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
      }
      

      首先将dequeue出来的buffer通过eglCreateImageKHR做成image,然后通过glEGLImageTargetTexture2DOES根据image创建一个2D的纹理,再通过glFramebufferTexture2D把纹理附着在帧缓存上面。setViewportAndProjection 设置视图和投影矩阵。

      文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
      status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                                            const std::vector& layers,
                                            ANativeWindowBuffer* const buffer,
                                            const bool useFramebufferCache, base::unique_fd&& bufferFence,
                                            base::unique_fd* drawFence) {
               ...
               // 设置顶点和纹理坐标的size
               Mesh mesh = Mesh::Builder()
                              .setPrimitive(Mesh::TRIANGLE_FAN)
                              .setVertices(4 /* count */, 2 /* size */)
                              .setTexCoords(2 /* size */)
                              .setCropCoords(2 /* size */)
                              .build();
               for (auto const layer : layers) {
                //遍历outputlayer
                   ...
                //获取layer的大小
              const FloatRect bounds = layer->geometry.boundaries;
              Mesh::VertexArray position(mesh.getPositionArray());
              // 设置顶点的坐标,逆时针方向
              position[0] = vec2(bounds.left, bounds.top);
              position[1] = vec2(bounds.left, bounds.bottom);
              position[2] = vec2(bounds.right, bounds.bottom);
              position[3] = vec2(bounds.right, bounds.top);
               //设置crop的坐标
              setupLayerCropping(*layer, mesh);
              // 设置颜色矩阵
              setColorTransform(display.colorTransform * layer->colorTransform);
              ...
              // Buffer相关设置
              if (layer->source.buffer.buffer != nullptr) {
                  disableTexture = false;
                  isOpaque = layer->source.buffer.isOpaque;
                   // layer的buffer,理解为输入的buffer
                  sp gBuf = layer->source.buffer.buffer;
                  // textureName是创建BufferQueuelayer时生成的,用来标识这个layer,
                  // fence是acquire fence
                  bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf,
                                            layer->source.buffer.fence);
                  ...
                  // 设置纹理坐标,也是逆时针
                  renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray());
                  texCoords[0] = vec2(0.0, 0.0);
                  texCoords[1] = vec2(0.0, 1.0);
                  texCoords[2] = vec2(1.0, 1.0);
                  texCoords[3] = vec2(1.0, 0.0);
                 // 设置纹理的参数,glTexParameteri
                  setupLayerTexturing(texture);
              }
      status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
            const sp& buffer,
            const sp& bufferFence) {
          if (buffer == nullptr) {
              return BAD_VALUE;
          }
          ATRACE_CALL();
          bool found = false;
          {
              // 在ImageCache里面找有没有相同的buffer
              std::lock_guard lock(mRenderingMutex);
              auto cachedImage = mImageCache.find(buffer->getId());
              found = (cachedImage != mImageCache.end());
          }
          // If we couldn't find the image in the cache at this time, then either
          // SurfaceFlinger messed up registering the buffer ahead of time or we got
          // backed up creating other EGLImages.
          if (!found) {
              //如果ImageCache里面没有则需要重新创建一个EGLImage,创建输入的EGLImage是在ImageManager线程里面,利用notify唤醒机制
              status_t cacheResult = mImageManager->cache(buffer);
              if (cacheResult != NO_ERROR) {
                  return cacheResult;
              }
          }
          ...
              // 把EGLImage转换成纹理,类型为GL_TEXTURE_EXTERNAL_OES
              bindExternalTextureImage(texName, *cachedImage->second);
              mTextureView.insert_or_assign(texName, buffer->getId());
          }
      }
      void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
          ATRACE_CALL();
          const GLImage& glImage = static_cast(image);
          const GLenum target = GL_TEXTURE_EXTERNAL_OES;
           //绑定纹理,纹理ID为texName
          glBindTexture(target, texName);
          if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
              // 把EGLImage转换成纹理,纹理ID为texName
              glEGLImageTargetTexture2DOES(target, static_cast(glImage.getEGLImage()));
          }
      }
      

      Android下SF合成流程重学习之GPU合成

      Android下SF合成流程重学习之GPU合成

      至此,将输入和输出的Buffer都生成了纹理对应,以及设置了纹理的坐标和顶点的坐标,接下来就要使用shader进行绘制了。

      文件:frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
      void GLESRenderEngine::drawMesh(const Mesh& mesh) {
          ATRACE_CALL();
          if (mesh.getTexCoordsSize()) {
              //开启顶点着色器属性,,目的是能在顶点着色器中访问顶点的属性数据
              glEnableVertexAttribArray(Program::texCoords);
             // 给顶点着色器传纹理的坐标
              glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE,
                                    mesh.getByteStride(), mesh.getTexCoords());
          }
          //给顶点着色器传顶点的坐标
          glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
                                mesh.getByteStride(), mesh.getPositions());
          ...
          // 创建顶点和片段着色器,将顶点属性设和一些常量参数设到shader里面
          ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
                                                 managedState);
          ...
          // 调GPU去draw
          glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
          ...
      }
      文件:frameworks/native/libs/renderengine/gl/ProgramCache.cpp
      void ProgramCache::useProgram(EGLContext context, const Description& description) {
          //设置key值,根据不同的key值创建不同的shader
          Key needs(computeKey(description));    
          // look-up the program in the cache
          auto& cache = mCaches[context];
          auto it = cache.find(needs);
          if (it == cache.end()) {
              // we didn't find our program, so generate one...
              nsecs_t time = systemTime();
              // 如果cache里面没有相同的program则重新创建一个
              it = cache.emplace(needs, generateProgram(needs)).first;
              time = systemTime() - time;
              ALOGV(">>> generated new program for context %p: needs=%08X, time=%u ms (%zu programs)",
                    context, needs.mKey, uint32_t(ns2ms(time)), cache.size());
          }   
          
          // here we have a suitable program for this description
          std::unique_ptr& program = it->second;
          if (program->isValid()) {
              program->use();
              program->setUniforms(description);
          }
      }
      std::unique_ptr ProgramCache::generateProgram(const Key& needs) {
          ATRACE_CALL();
          // 创建顶点着色器
          String8 vs = generateVertexShader(needs);
          // 创建片段着色器
          String8 fs = generateFragmentShader(needs);
           // 链接和编译着色器
          return std::make_unique(needs, vs.string(), fs.string());
      }
      String8 ProgramCache::generateVertexShader(const Key& needs) {
          Formatter vs;
          if (needs.hasTextureCoords()) {
               // attribute属性通过glVertexAttribPointer设置,varying 表示输出给片段着色器的数据
              vs 
              vs 
          Formatter fs;
          if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
              fs 
              fs 
              fs 
              fs 
                  // 输出像素的颜色值
                  fs 
          // 编译顶点和片段着色器
          GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
          GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
          // 创建programID
          GLuint programId = glCreateProgram();
          // 将顶点和片段着色器链接到programe
          glAttachShader(programId, vertexId);
          glAttachShader(programId, fragmentId);
          // 将着色器里面的属性和自定义的属性变量绑定
          glBindAttribLocation(programId, position, "position");
          glBindAttribLocation(programId, texCoords, "texCoords");
          glBindAttribLocation(programId, cropCoords, "cropCoords");
          glBindAttribLocation(programId, shadowColor, "shadowColor");
          glBindAttribLocation(programId, shadowParams, "shadowParams");
          glLinkProgram(programId);
          GLint status;
          glGetProgramiv(programId, GL_LINK_STATUS, &status);
          ...
              mProgram = programId;
              mVertexShader = vertexId;
              mFragmentShader = fragmentId;
              mInitialized = true;
              //获得着色器里面uniform变量的位置
              mProjectionMatrixLoc = glGetUniformLocation(programId, "projection");
              mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
              ...
              // set-up the default values for our uniforms
              glUseProgram(programId);
              glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
              glEnableVertexAttribArray(0);
      }
      void Program::use() {
          // Program生效
          glUseProgram(mProgram);
      } 
      void Program::setUniforms(const Description& desc) {
          // TODO: we should have a mechanism here to not always reset uniforms that
          // didn't change for this program.
          // 根据uniform的位置,给uniform变量设置,设到shader里面
          if (mSamplerLoc = 0) {
              glUniform1i(mSamplerLoc, 0);
              glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.texture.getMatrix().asArray());
          }
         ...
             glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.projectionMatrix.asArray());
          }
      
          ATRACE_CALL();
          if (!GLExtensions::getInstance().hasNativeFenceSync()) {
              return base::unique_fd();
          }
          // 创建一个EGLSync对象,用来标识GPU是否绘制完
          EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
          if (sync == EGL_NO_SYNC_KHR) {
              ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
              return base::unique_fd();
          }
          // native fence fd will not be populated until flush() is done.
          // 将gl command命令全部刷给GPU
          glFlush();
          // get the fence fd
           //获得android 使用的fence fd
          base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
          eglDestroySyncKHR(mEGLDisplay, sync);
          if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
              ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
          }
          // Only trace if we have a valid fence, as current usage falls back to
          // calling finish() if the fence fd is invalid.
          if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer) && fenceFd.get() = 0) {
              mFlushTracer-queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
          }
          return fenceFd;
      }
      
          ATRACE_CALL();
          ALOGV(__FUNCTION__);
          if (!getState().isEnabled) {
              return;
          }
          // Repaint the framebuffer (if needed), getting the optional fence for when
          // the composition completes.
          auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
          if (!optReadyFence) {
              return;
          }
          // swap buffers (presentation)
          mRenderSurface-queueBuffer(std::move(*optReadyFence));
      }
      文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
      void RenderSurface::queueBuffer(base::unique_fd readyFence) {
          auto& state = mDisplay.getState();
               ...
          
              if (mGraphicBuffer == nullptr) {
                  ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str());
              } else {
                  status_t result =
                          // mGraphicBuffer-getNativeBuffer() 是GPU输出的Buffer,可以理解为GPU将内容合成到该Buffer上
                          mNativeWindow-queueBuffer(mNativeWindow.get(),
      mGraphicBuffer-getNativeBuffer(), dup(readyFence));
                  if (result != NO_ERROR) {
                      ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(),
                            result);
                      // We risk blocking on dequeueBuffer if the primary display failed
                      // to queue up its buffer, so crash here.
                      if (!mDisplay.isVirtual()) {
                          LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result);
                      } else {
                          mNativeWindow-cancelBuffer(mNativeWindow.get(),
       mGraphicBuffer-getNativeBuffer(), dup(readyFence));
                      }
                  }
                  mGraphicBuffer = nullptr;
              }
          }
          // 消费Buffer
          status_t result = mDisplaySurface-advanceFrame();
          if (result != NO_ERROR) {
              ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result);
          }
      }
      文件:frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
      status_t FramebufferSurface::advanceFrame() {
          uint32_t slot = 0;
          sp
              ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
                      strerror(-result), result);
          }
          return result;
      }
      status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
              sp
          Mutex::Autolock lock(mMutex);
          BufferItem item;
          // acquire Buffer
          status_t err = acquireBufferLocked(&item, 0);
          ...
          if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
              item.mSlot != mCurrentBufferSlot) {
              mHasPendingRelease = true;
              mPreviousBufferSlot = mCurrentBufferSlot;
              mPreviousBuffer = mCurrentBuffer;
          }
          //更新当前的Buffer和fence信息
          mCurrentBufferSlot = item.mSlot;
          mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
          mCurrentFence = item.mFence;
          outFence = item.mFence;
          mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer);
          outDataspace = static_cast
              ALOGE("error posting framebuffer: %d", result);
              return result;
          }
          return NO_ERROR;
      }
      
          ATRACE_CALL();
          ALOGV(__FUNCTION__);
         ...
          auto frame = presentAndGetFrameFences();
          mRenderSurface-onPresentDisplayCompleted();
          ...
      }
         
      文件:frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
      status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
          ATRACE_CALL();
          
          RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
              
          auto& displayData = mDisplayData[displayId];
          auto& hwcDisplay = displayData.hwcDisplay;
          
           ...
          // GPU合成时执行present,返回present fence
          auto error = hwcDisplay-present(&displayData.lastPresentFence);
          RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
          std::unordered_map
          if (mHasPendingRelease) {
              sp
                  // 更新BufferSlot的 fence
                  status_t result = addReleaseFence(mPreviousBufferSlot,
                          mPreviousBuffer, fence);
                  ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
                          " fence: %s (%d)", strerror(-result), result);
              }
              // 释放之前的Buffer
              status_t result = releaseBufferLocked(mPreviousBufferSlot, mPreviousBuffer);
              ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
                      " %s (%d)", strerror(-result), result);
          
              mPreviousBuffer.clear();
              mHasPendingRelease = false;
          }
      }
      
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]