qualcomm平台的Gralloc驱动分析

前言:在MSM处理器中,重新实现了Gralloc模块的架构,此Gralloc模块是基于FrameBuffer和Pmem驱动实现的。


一、文件gralloc.cpp

MSM平台中和Gralloc模块相关的文件目录:\hardware\qcom\display\libgralloc\

在文件gralloc.cpp中,使用Gralloc中的结构体private_module_t来扩展里面的结构体private_module_t。结构体private_module_t的实现文件是gtalloc_priv.h,在里面宝海了和上下文有关的信息。下面将简单分析文件gralloc.cpp的实现流程。

在文件gralloc.cpp中首先需要定义结构体HAL_MODULE_INFO_SYM,具体代码如下:

// HAL module initialize
struct private_module_t HAL_MODULE_INFO_SYM = {
    base: {
        common: {
            tag: HARDWARE_MODULE_TAG,
            version_major: 1,
            version_minor: 0,
            id: GRALLOC_HARDWARE_MODULE_ID,
            name: "Graphics Memory Allocator Module",
            author: "The Android Open Source Project",
            methods: &gralloc_module_methods,
            dso: 0,
            reserved: {0},
        },
        registerBuffer: gralloc_register_buffer,
        unregisterBuffer: gralloc_unregister_buffer,
        lock: gralloc_lock,
        unlock: gralloc_unlock,
        perform: gralloc_perform,
        lock_ycbcr: gralloc_lock_ycbcr,
    },
    framebuffer: 0,
    fbFormat: 0,
    flags: 0,
    numBuffers: 0,
    bufferMask: 0,
    lock: PTHREAD_MUTEX_INITIALIZER,
};

上述代码和Gralloc中的代码基本移植,只是增加了结构体private_module_t的perform()函数指针来实现gralloc_perform()。函数gralloc_perform()在文件mapper.cpp中定义,代码如下:

int gralloc_perform(struct gralloc_module_t const* module,
                    int operation, ... )
{
    int res = -EINVAL;
    va_list args;
    if(!module)
        return res;


    va_start(args, operation);
    switch (operation) {
        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
            {
                int fd = va_arg(args, int);
                unsigned int size = va_arg(args, unsigned int);
                unsigned int offset = va_arg(args, unsigned int);
                void* base = va_arg(args, void*);
                int width = va_arg(args, int);
                int height = va_arg(args, int);
                int format = va_arg(args, int);


                native_handle_t** handle = va_arg(args, native_handle_t**);
                private_handle_t* hnd = (private_handle_t*)native_handle_create(
                    private_handle_t::sNumFds, private_handle_t::sNumInts());
                if (hnd) {
                  hnd->magic = private_handle_t::sMagic;
                  hnd->fd = fd;
                  hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
                  hnd->size = size;
                  hnd->offset = offset;
                  hnd->base = uint64_t(base) + offset;
                  hnd->gpuaddr = 0;
                  hnd->width = width;
                  hnd->height = height;
                  hnd->format = format;
                  *handle = (native_handle_t *)hnd;
                  res = 0;
                }
                break;


            }
        case GRALLOC_MODULE_PERFORM_GET_STRIDE:
            {
                int width   = va_arg(args, int);
                int format  = va_arg(args, int);
                int *stride = va_arg(args, int *);
                int alignedw = 0, alignedh = 0;
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
                        0, format, 0, alignedw, alignedh);
                *stride = alignedw;
                res = 0;
            } break;


        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
            {
                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *stride = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }


                int alignedw = 0, alignedh = 0;
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
                *stride = alignedw;


                res = 0;
            } break;


        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
            {
                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *stride = va_arg(args, int *);
                int *height = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }


                int alignedw = 0, alignedh = 0;
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
                *stride = alignedw;
                *height = alignedh;


                res = 0;
            } break;


        case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
            {
                int width   = va_arg(args, int);
                int height  = va_arg(args, int);
                int format  = va_arg(args, int);
                int usage   = va_arg(args, int);
                int *alignedWidth = va_arg(args, int *);
                int *alignedHeight = va_arg(args, int *);
                int *tileEnabled = va_arg(args,int *);
                *tileEnabled = isUBwcEnabled(format, usage) ||
                               isMacroTileEnabled(format, usage);
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
                        height, format, usage, *alignedWidth, *alignedHeight);
                res = 0;
            } break;


        case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *color_space = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
                    *color_space = metadata->colorSpace;
                    res = 0;
                }
            } break;


        case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
                if (!private_handle_t::validate(hnd)) {
                    res = getYUVPlaneInfo(hnd, ycbcr);
                }
            } break;


        case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *map_secure_buffer = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
                    *map_secure_buffer = metadata->mapSecureBuffer;
                    res = 0;
                } else {
                    *map_secure_buffer = 0;
                }
            } break;


        case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *flag = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                if (metadata && (metadata->operation & LINEAR_FORMAT)) {
                    *flag = 0;
                }
                res = 0;
            } break;


        case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
            {
                private_handle_t* hnd = va_arg(args, private_handle_t*);
                void** rgb_data = va_arg(args, void**);
                if (!private_handle_t::validate(hnd)) {
                    res = getRgbDataAddress(hnd, rgb_data);
                }
            } break;


        case GRALLOC_MODULE_PERFORM_GET_IGC:
            {
                private_handle_t* hnd = va_arg(args, private_handle_t*);
                uint32_t *igc = va_arg(args, uint32_t *);
                if (!private_handle_t::validate(hnd) && igc) {
                    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                    if (metadata && (metadata->operation & SET_IGC)) {
                        *igc = metadata->igc;
                        res = 0;
                    }
                }
            } break;


        case GRALLOC_MODULE_PERFORM_SET_IGC:
            {
                private_handle_t* hnd = va_arg(args, private_handle_t*);
                uint32_t igc = va_arg(args, uint32_t);
                if (!private_handle_t::validate(hnd)) {
                    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                    if (metadata) {
                        metadata->igc = (IGC_t) igc;
                        metadata->operation |= SET_IGC;
                        res = 0;
                    }
                }
            } break;


        case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                uint32_t *enable = va_arg(args, uint32_t*);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
            } break;
        default:
            break;
    }
    va_end(args);
    return res;
}

在上述代码中,通过case语句实现了一个命令GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,此命令是在surfaceFlinger中被调用的内容,这是一个可选的功能,在此通过调用Pmem获取内存的大小。


二、文件framebuffer.cpp

在文件\hardware\qcom\display\libgralloc\framebuffer.cpp中实现了QSD8K的framebuffer_devices_t设备驱动,其实现源码和标准的程序类似,区别是增加了更多颜色格式的支持,并且用RGBA8888作为默认的颜色格式。

其中在post中的区别是不支持双缓冲需要的内存复制功能时,不会调用memcopy()来实现,而是滴啊用msm_copy_buffer()来实现。post实现函数的代码如下:

static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
    private_module_t* m =
        reinterpret_cast<private_module_t*>(dev->common.module);
    private_handle_t *hnd = static_cast<private_handle_t*>
        (const_cast<native_handle_t*>(buffer));
    fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
    const unsigned int offset = (unsigned int) (hnd->base -
            m->framebuffer->base);
    m->info.activate = FB_ACTIVATE_VBL;
    m->info.yoffset = (int)(offset / m->finfo.line_length);
    if (ioctl(ctx->fbFd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
        ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
                __FUNCTION__, strerror(errno));
        return -errno;
    }
    return 0;
}


三、文件gralloc.cpp

在文件gralloc.cpp中,实现了函数alloc()、free()、close()。这些函数是MSM的Galloc模块默认的实现函数,和标准函数一有一些区别的。函数gralloc_alloc()是MSM中gralloc_alloc_buffer来分配内存。由此课件这部分的实现和默认galloc模块中是不一样的。实现代码如下:

int gralloc_device_open(const hw_module_t* module, const char* name,
                        hw_device_t** device)
{
    int status = -EINVAL;
    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
        const private_module_t* m = reinterpret_cast<const private_module_t*>(
            module);
        gpu_context_t *dev;
        IAllocController* alloc_ctrl = IAllocController::getInstance();
        dev = new gpu_context_t(m, alloc_ctrl);
        if(!dev)
            return status;

        *device = &dev->common;
        status = 0;
    } else {
        status = fb_device_open(module, name, device);
    }
    return status;
}
由此可见,在qualcomm平台中提高了alloc_device_t设备性能,使用Pmem驱动程序作为内存映射工具,将原来通过ashmem分配和管理的内存部分转移到了Pmem上面。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值