当前位置: 首页 > 工具软件 > Libui > 使用案例 >

Gralloc与上层libui/libsurfaceflinger的关系

丁承德
2023-12-01

如前所述,Gralloc模块主要由 gralloc_module_t 模块,alloc_device_t 设备和 framebuffer_device_t 设备3个结构体来描述。
1. Gralloc模块的主要调用者是ui库中的以下文件:
frameworks/base/libs/ui/FramebufferNativeWindow.cpp


FramebufferNativeWindow的构造函数如下:

    /*
     * This implements the (main) framebuffer management. This class is used
     * mostly by SurfaceFlinger, but also by command line GL application.
     *
     * In fact this is an implementation of ANativeWindow on top of
     * the framebuffer.
     *
     * This implementation is able to manage any number of buffers,
     * defined by NUM_FRAME_BUFFERS (currently set to 2: front
     * and back buffer)
     *
     */
    FramebufferNativeWindow::FramebufferNativeWindow()
        : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
    {
        hw_module_t const* module;
        if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
            int stride;
            int err;
    #ifdef OMAP_ENHANCEMENT
            int i;
    #endif
            err = framebuffer_open(module, &fbDev);                //打开framebuffer设备
            LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
            err = gralloc_open(module, &grDev);                      //打开gralloc设备
            LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
            // bail out if we can't initialize the modules
            if (!fbDev || !grDev)                         //只有framebuffer和gralloc都存在,才能继续运行
                return;
            mUpdateOnDemand = (fbDev->setUpdateRect != 0);    //可选的setUpdateRect
            // initialize the buffer FIFO
    #ifdef OMAP_ENHANCEMENT
            mNumBuffers = NUM_FRAME_BUFFERS;
            mNumFreeBuffers = NUM_FRAME_BUFFERS;
    #else
            mNumBuffers = 2;                //初始化 buffer FIFO,双缓冲,有2块内存。
            mNumFreeBuffers = 2;
    #endif
            mBufferHead = mNumBuffers-1;
    #ifdef OMAP_ENHANCEMENT
            for(i = 0; i < NUM_FRAME_BUFFERS; i++){
                buffers[i] = new NativeBuffer(
                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
            }
            for(i = 0; i < NUM_FRAME_BUFFERS; i++){
                err = grDev->alloc(grDev,
                        fbDev->width, fbDev->height, fbDev->format,
                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
                        i, fbDev->width, fbDev->height, strerror(-err));
                if(err){
                    mNumBuffers = i;
                    mNumFreeBuffers = i;
                    mBufferHead = mNumBuffers-1;
                    break;
                }
           }
    #else
            buffers[0] = new NativeBuffer(         //初始化2个缓冲区          
                    fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
            buffers[1] = new NativeBuffer(
                    fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
            err = grDev->alloc(grDev,              //从gralloc设备中分配内存
                    fbDev->width, fbDev->height, fbDev->format,
                    GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
            LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
                    fbDev->width, fbDev->height, strerror(-err));
            err = grDev->alloc(grDev,
                   fbDev->width, fbDev->height, fbDev->format,
                    GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
            LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
                    fbDev->width, fbDev->height, strerror(-err));
    #endif    
            const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;  //从framebuffer设备中获得常量
            const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
            const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
            const_cast<int&>(ANativeWindow::minSwapInterval) =
                fbDev->minSwapInterval;
            const_cast<int&>(ANativeWindow::maxSwapInterval) =
                fbDev->maxSwapInterval;
        } else {
            LOGE("Couldn't get gralloc module");
        }
        ANativeWindow::setSwapInterval = setSwapInterval;   //处理函数指针
        ANativeWindow::dequeueBuffer = dequeueBuffer;
        ANativeWindow::lockBuffer = lockBuffer;
        ANativeWindow::queueBuffer = queueBuffer;
        ANativeWindow::query = query;
        ANativeWindow::perform = perform;
        ANativeWindow::cancelBuffer = 0;
    #ifdef OMAP_ENHANCEMENT
        LOGE("%d buffers flip-chain implementation enabled\n", mNumBuffers);
    #endif
    }

FramebufferNativeWindow 实际上是Gralloc模块的一层封装,向android本地代码层提供了用于显示的android_native_window_t结构。

2. libui库中的 GraphicBufferAllocator.cpp 用于分配显示缓冲:
    status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
            int usage, buffer_handle_t* handle, int32_t* stride)
    {
        // make sure to not allocate a N x 0 or 0 x N buffer, since this is
        // allowed from an API stand-point allocate a 1x1 buffer instead.
        if (!w || !h)
            w = h = 1;
        // we have a h/w allocator and h/w buffer is requested
        status_t err;
        //mAllocDev 类型为 alloc_device_t,当调用的参数有GRALLOC_USAGE_HW_MASK标志时,有alloc_device_t调用分配一个内存,否则从软件分配一个内存。
        if (usage & GRALLOC_USAGE_HW_MASK) {     
            err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
        } else {
            err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride);
        }
        LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
                w, h, format, usage, err, strerror(-err));
        
        if (err == NO_ERROR) {
            Mutex::Autolock _l(sLock);
            KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
            alloc_rec_t rec;
            rec.w = w;
            rec.h = h;
            rec.s = *stride;
            rec.format = format;
            rec.usage = usage;
            rec.size = h * stride[0] * bytesPerPixel(format);
            list.add(*handle, rec);
        }
        return err;
    }


软件分配内存
    status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h,int format,
            int usage, buffer_handle_t* pHandle, int32_t* pStride)
    {
        int align = 4;
        int bpp = 0;
        switch (format){
            case HAL_PIXEL_FORMAT_RGBA_8888:
            case HAL_PIXEL_FORMAT_RGBX_8888:
            case HAL_PIXEL_FORMAT_BGRA_8888:
                bpp = 4;
                break;
            case HAL_PIXEL_FORMAT_RGB_888:
                bpp = 3;
                break;
            case HAL_PIXEL_FORMAT_RGB_565:
            case HAL_PIXEL_FORMAT_RGBA_5551:
            case HAL_PIXEL_FORMAT_RGBA_4444:
                bpp = 2;
                break;
            default:
                return -EINVAL;
        }
        size_t bpr = (w*bpp +(align-1))& ~(align-1);
        size_t size = bpr * h;
        size_t stride = bpr / bpp;
        size =(size + (PAGE_SIZE-1))& ~(PAGE_SIZE-1);
        int fd = ashmem_create_region("sw-gralloc-buffer",size);
        if (fd< 0) {
            LOGE("ashmem_create_region(size=%d) failed (%s)",
                    size, strerror(-errno));
            return -errno;
        }
        int prot = PROT_READ;
        if (usage& GRALLOC_USAGE_SW_WRITE_MASK)
            prot |= PROT_WRITE;
        if (ashmem_set_prot_region(fd, prot)< 0) {
            LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
                    fd, prot, strerror(-errno));
            close(fd);
            return -errno;
        }
        void*base = mmap(0,size, prot, MAP_SHARED, fd, 0);
        if (base== MAP_FAILED){
            LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
                    fd, size, prot, strerror(-errno));
            close(fd);
            return -errno;
        }
        sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t();
        hnd->fd= fd;
        hnd->size= size;
        hnd->base= intptr_t(base);
        hnd->prot= prot;
        *pStride = stride;
        *pHandle = hnd;
        return NO_ERROR;
    }

3.libui库中的GraphicBufferMapper.cpp文件用于显示缓冲的映射:
    status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
    {
        status_t err;
       //mAllocMod的类型为 gralloc_module_t,可以从Gralloc模块中注册Buffer,也可以从软件注册Buffer
        if (sw_gralloc_handle_t::validate(handle)< 0) {
            err = mAllocMod->registerBuffer(mAllocMod, handle);  
        } else{
            err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle);
        }
        LOGW_IF(err,"registerBuffer(%p) failed %d (%s)",
                handle, err, strerror(-err));
        return err;
    }

4. libui库中的 GraphicBuffer.cpp 定义类GraphicBuffer继承实现了android_native_buffer_t. 这个类是
分配器GraphicBufferAllocator 和映射器 GraphicBufferMapper的调用者。

    GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
            PixelFormat reqFormat, uint32_t reqUsage)
        : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), //调用GraphicBufferMapper
          mInitCheck(NO_ERROR), mIndex(-1)
    {
        width =
        height =
        stride =
        format =
        usage =
        transform = 0;
        handle = NULL;
        mInitCheck = initSize(w, h, reqFormat, reqUsage);
    }

    status_t GraphicBuffer::initSize(uint32_t w, uint32_t h,PixelFormat format,
            uint32_t reqUsage)
    {
        GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); //调用GraphicBufferAllocator
        status_t err = allocator.alloc(w, h, format, reqUsage, &handle,&stride);
        if (err== NO_ERROR){
            this->width= w;
            this->height= h;
            this->format= format;
            this->usage= reqUsage;
        }
        return err;
    }

5. 在图层管理库libSufaceFlinger中, 也有对Gralloc模块的调用部分:
frameworks/base/services/surfaceflinger/LayerBuffer.cpp 中定义了一个Buffer类。其构造函数如下:

    // ============================================================================
    // LayerBuffer::Buffer
    // ============================================================================
    LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers,
            ssize_t offset, size_t bufferSize)
        : mBufferHeap(buffers), mSupportsCopybit(false)
    {
        NativeBuffer& src(mNativeBuffer);
        src.crop.l= 0;                  //剪切区域
        src.crop.t= 0;
        src.crop.r= buffers.w;
        src.crop.b= buffers.h;
        src.img.w= buffers.hor_stride?: buffers.w;      //区域大小和颜色
        src.img.h= buffers.ver_stride?: buffers.h;
        src.img.format= buffers.format;
        src.img.base= (void*)(intptr_t(buffers.heap->base())+ offset);
        src.img.handle= 0;
        gralloc_module_t const * module = LayerBuffer::getGrallocModule();
        if (module&& module->perform){         //根据情况调用perform
            int err = module->perform(module,
                    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
                    buffers.heap->heapID(), bufferSize,
                    offset, buffers.heap->base(),
                    &src.img.handle);
            // we can fail here is the passed buffer is purely software
            mSupportsCopybit = (err == NO_ERROR);
        }
     }

这里调用的perform是gralloc_module_t的一个可选实现的函数指针,如果当前的gralloc模块中实现了该指针,则在这里调用该函数,并使用GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER命令,表示从Buffer中创建一个句柄,可以获得加速效果。
 类似资料: