• Android 12(S) 图像显示系统 - SurfaceFlinger GPU合成/CLIENT合成方式 - 随笔1



    必读:

    Android 12(S) 图像显示系统 - 开篇


     

    一、前言

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

    本篇文章,我们先聚焦一点做介绍:用于存储GPU合成后的图形数据的GraphicBuffer是从哪里来的?下面的讲解会围绕这个问题展开。

     

    二、从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,就是用来存储GPU合成后的图形数据的。

     


     

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

    FramebufferSurface的初始化逻辑需要从SurfaceFlinger的初始化谈起,在文章Android 12(S) 图像显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)

    中,曾分析过,SurfaceFlinger::init()中会去注册HWC的回调函数mCompositionEngine->getHwComposer().setCallback(this),当第一次注册callback时,onComposerHalHotplug()会立即在调用registerCallback()的线程中被调用,并跨进程回调到SurfaceFlinger::onComposerHalHotplug。然后一路飞奔:

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

    摘取关键代码如下:

    [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
    void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                             const DisplayDeviceState& state) {
        ......
        sp<compositionengine::DisplaySurface> displaySurface; 
        sp<IGraphicBufferProducer> producer;
        // 创建BufferQueue,获取到生产者和消费者,而且消费者不是SurfaceFlinger哦
        sp<IGraphicBufferProducer> bqProducer;
        sp<IGraphicBufferConsumer> bqConsumer;
        getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);
    
        if (state.isVirtual()) { // 虚拟屏幕,不管它
            const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
            LOG_FATAL_IF(!displayId);
            auto surface = sp<VirtualDisplaySurface>::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<FramebufferSurface>::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<IGraphicBufferConsumer>& 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<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
            const wp<IBinder>& displayToken,
            std::shared_ptr<compositionengine::Display> compositionDisplay,
            const DisplayDeviceState& state,
            const sp<compositionengine::DisplaySurface>& displaySurface, 
            const sp<IGraphicBufferProducer>& 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<DisplayDevice> 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<size_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers))
                        .build());
    
        if (!mFlinger->mDisableClientCompositionCache &&
            SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) {
            mCompositionDisplay->createClientCompositionCache(
                    static_cast<uint32_t>(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);
    }

    本文作者@二的次方  2022-05-10 发布于博客园

    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<android::IProducerListener> 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<android::IProducerListener> 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<android::IBinder> 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<void (android::hardware::Parcel&)>)+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<void (android::hardware::Parcel&)>)+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<void (android::hardware::Parcel&)>)+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<void (android::hardware::Parcel&)>)+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<android::hardware::graphics::composer::V2_4::IComposerCallback> 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<android::hardware::graphics::composer::V2_4::IComposerCallback> 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<android::hardware::graphics::composer::V2_4::IComposerCallback> 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

    注意 本文作者@二的次方  2022-05-10 发布于博客园

    注意 本文作者@二的次方  2022-05-10 发布于博客园

    注意 本文作者@二的次方  2022-05-10 发布于博客园

    这里有一个小细节要留意下,因为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]

     

    四、对上述分析的一个小结和猜想

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

    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<renderengine::ExternalTexture> 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<GraphicBuffer>& outBuffer, sp<Fence>& 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做处理显示。

     


     

     最开始我们提出的问题:用于存储GPU合成后的图形数据的GraphicBuffer是从哪里来的?分析到这里大概应该有讲明白吧

    本文作者@二的次方  2022-05-10 发布于博客园

    五、补充知识点

    5.1 用于GPU合成的GraphicBuffer的数量控制

    通过属性值来控制数量 ro.surface_flinger.max_frame_buffer_acquired_buffers,如何控制的可以看SF的代码

    [/frameworks/native/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop]
    # Controls the number of buffers SurfaceFlinger will allocate for use in FramebufferSurface.
    prop {
        api_name: "max_frame_buffer_acquired_buffers"
        type: Long
        scope: Public
        access: Readonly
        prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
    }

    这个属性值。控制用于GPU合成的FramebufferSurface分配几个GraphicBuffer,,一般是 3 个

     

    5.2 一个疑问

    为什么在allocator出打印出来的Framebuffer的format=1 (PIXEL_FORMAT_RGBA_8888) , 而importer处打印出来的Framebuffer的format=5 (PIXEL_FORMAT_BGRA_8888)  ?

     

    由于对整个体系架构了解还不是很深入,为了找到这个问题的原因,确实费了不少功夫。其实答案在 Gralloc HAL 中。

    我的平台采用的是 Mali GPU,Gralloc HAL使用的是 Open Source Mali GPUs Gralloc Module 为基础的Source code。

    在 Gralloc 的代码实现中有定义一个宏开关 GRALLOC_HWC_FORCE_BGRA_8888 ,打开这个宏的时候,SurfaceFlinger中的 RenderSurface::initialize() 设置的RGBA_8888 会在Gralloc allocate/map时强转为了BGRA_8888来处理。具体的可以开启和关闭这个宏看dumpsys SurfaceFlinger对比

    # When enabled, forces format to BGRA_8888 for FB usage when HWC is in use
    GRALLOC_HWC_FORCE_BGRA_8888?=0

    我的平台对比的信息:

    // 关闭GRALLOC_HWC_FORCE_BGRA_8888这个宏定义,仍是framework设置的RGBA8888
    + name:FramebufferSurface, id:e400000000, size:8.1e+03KiB, w/h:780x438, usage: 0x1b00, req fmt:1, fourcc/mod:875708993/0, dataspace: 0x0, compressed: false
            planes: R/G/B/A:         w/h:780x438, stride:1e00 bytes, size:7e9000
                
    // 打开GRALLOC_HWC_FORCE_BGRA_8888这个宏定义,强制转为了BGRA8888
    + name:FramebufferSurface, id:e200000000, size:8.1e+03KiB, w/h:780x438, usage: 0x1b00, req fmt:1, fourcc/mod:875713089/0, dataspace: 0x0, compressed: false
            planes: B/G/R/A:         w/h:780x438, stride:1e00 bytes, size:7e9000

     

    5.3 用于GPU合成的GraphicBuffer的size(width & height)是由什么决定的?

    答案是当前屏幕的分辨率,也就是 Display的 active mode

    比如我的Android TV平台,设置不同的电视分辨率

    // 720 TV
    GraphicBufferAllocator buffers:
        Handle |        Size |     W (Stride) x H | Layers |   Format |      Usage | Requestor
    0xf2d8e0d0 | 3600.00 KiB | 1280 (1280) x  720 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xf2d937d0 | 3600.00 KiB | 1280 (1280) x  720 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xf2d98050 | 3600.00 KiB | 1280 (1280) x  720 |      1 |        1 | 0x    1b00 | FramebufferSurface
    
    // 1080 TV
    GraphicBufferAllocator buffers:
        Handle |        Size |     W (Stride) x H | Layers |   Format |      Usage | Requestor
    0xf2d81d10 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xf2d83840 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xf2d85ab0 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    
    // 4K TV(限制ro.surface_flinger.max_graphics_height/width)
    GraphicBufferAllocator buffers:
        Handle |        Size |     W (Stride) x H | Layers |   Format |      Usage | Requestor
    0xe8041b40 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xe8045c80 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface
    0xe804fa30 | 8100.00 KiB | 1920 (1920) x 1080 |      1 |        1 | 0x    1b00 | FramebufferSurface

    下面的属性是受平台限制,GPU最大可以支持的合成的size

    console:/ $ getprop | grep max_graphics
    [ro.surface_flinger.max_graphics_height]: [1080]
    [ro.surface_flinger.max_graphics_width]: [1920]

     

    本文作者@二的次方  2022-05-10 发布于博客园

    大概就讲这些吧,之后想到什么问题再补充。

     

  • 相关阅读:
    Transaction - 记一次 Spring 事务联合 Redis 挂了引发的生产事故
    Java函数式编程:深入了解Supplier接口的用法
    PDF如何转Excel?学会这3个方法,1分钟就能实现转换
    C语言--指针初阶
    mysql 安装问题 perl(JSON) is needed by mysql-community-test
    2024年护网行动全国各地面试题汇总(5)作者:————LJS
    猿创征文|【Hive】各种join连接用法
    简易实现QT中的virtualkeyboard及问题总结
    SpringBoot结合dev-tool 实现IDEA项目热部署
    Python---元组---字典---集合
  • 原文地址:https://www.cnblogs.com/roger-yu/p/16230337.html