android gralloc源码分析

1、gralloc模块通过struct private_module_t来描述

struct private_module_t {
   
   
    gralloc_module_t base;

    private_handle_t* framebuffer;
    uint32_t flags;
    uint32_t numBuffers;
    uint32_t bufferMask;
    pthread_mutex_t lock;
    buffer_handle_t currentBuffer;
    int pmem_master;
    void* pmem_master_base;

    struct fb_var_screeninfo info;
    struct fb_fix_screeninfo finfo;
    float xdpi;
    float ydpi;
    float fps;
};

该结构的成员记录了gralloc模块的各个参数,主要为模块自己使用。
应用程序操作的图形缓冲区的数据结构通过struct private_handle_t来描述

#ifdef __cplusplus
struct private_handle_t : public native_handle {
   
   
#else
struct private_handle_t {
   
   
    struct native_handle nativeHandle;
#endif

    enum {
   
   
        PRIV_FLAGS_FRAMEBUFFER = 0x00000001
    };

    // file-descriptors
    int     fd;
    // ints
    int     magic;
    int     flags;
    int     size;
    int     offset;
	
	/*图形缓冲区或帧缓冲的起始虚拟地址*/
    // FIXME: the attributes below should be out-of-line
    uint64_t base __attribute__((aligned(8)));
    int     pid;

#ifdef __cplusplus
    static inline int sNumInts() {
   
   
        return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds);
    }
    static const int sNumFds = 1;
    static const int sMagic = 0x3141592;

    private_handle_t(int fd, int size, int flags) :
        fd(fd), magic(sMagic), flags(flags), size(size), offset(0),
        base(0), pid(getpid())
    {
   
   
        version = sizeof(native_handle);
        numInts = sNumInts();
        numFds = sNumFds;
    }
    ~private_handle_t() {
   
   
        magic = 0;
    }

    static int validate(const native_handle* h) {
   
   
        const private_handle_t* hnd = (const private_handle_t*)h;
        if (!h || h->version != sizeof(native_handle) ||
                h->numInts != sNumInts() || h->numFds != sNumFds ||
                hnd->magic != sMagic)
        {
   
   
            ALOGE("invalid gralloc handle (at %p)", h);
            return -EINVAL;
        }
        return 0;
    }
#endif
};

图形缓冲区的操作接口用struct gralloc_module_t来描述

typedef struct gralloc_module_t {
   
   
    struct hw_module_t common;
    
    /*
     * (*registerBuffer)() must be called before a buffer_handle_t that has not
     * been created with (*alloc_device_t::alloc)() can be used.
     * 
     * This is intended to be used with buffer_handle_t's that have been
     * received in this process through IPC.
     * 
     * This function checks that the handle is indeed a valid one and prepares
     * it for use with (*lock)() and (*unlock)().
     * 
     * It is not necessary to call (*registerBuffer)() on a handle created 
     * with (*alloc_device_t::alloc)().
     * 
     * returns an error if this buffer_handle_t is not valid.
     */
    int (*registerBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);

    /*
     * (*unregisterBuffer)() is called once this handle is no longer needed in
     * this process. After this call, it is an error to call (*lock)(),
     * (*unlock)(), or (*registerBuffer)().
     * 
     * This function doesn't close or free the handle itself; this is done
     * by other means, usually through libcutils's native_handle_close() and
     * native_handle_free(). 
     * 
     * It is an error to call (*unregisterBuffer)() on a buffer that wasn't
     * explicitly registered first.
     */
    int (*unregisterBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);
    
    /*
     * The (*lock)() method is called before a buffer is accessed for the 
     * specified usage. This call may block, for instance if the h/w needs
     * to finish rendering or if CPU caches need to be synchronized.
     * 
     * The caller promises to modify only pixels in the area specified 
     * by (l,t,w,h).
     * 
     * The content of the buffer outside of the specified area is NOT modified
     * by this call.
     *
     * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address
     * of the buffer in virtual memory.
     *
     * Note calling (*lock)() on HAL_PIXEL_FORMAT_YCbCr_*_888 buffers will fail
     * and return -EINVAL.  These buffers must be locked with (*lock_ycbcr)()
     * instead.
     *
     * THREADING CONSIDERATIONS:
     *
     * It is legal for several different threads to lock a buffer from 
     * read access, none of the threads are blocked.
     * 
     * However, locking a buffer simultaneously for write or read/write is
     * undefined, but:
     * - shall not result in termination of the process
     * - shall not block the caller
     * It is acceptable to return an error or to leave the buffer's content
     * into an indeterminate state.
     *
     * If the buffer was created with a usage mask incompatible with the
     * requested usage flags here, -EINVAL is returned. 
     * 
     */
    
    int (*lock)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr);

    
    /*
     * The (*unlock)() method must be called after all changes to the buffer
     * are completed.
     */
    
    int (*unlock)(struct gralloc_module_t const* module,
            buffer_handle_t handle);


    /* reserved for future use */
    int (*perform)(struct gralloc_module_t const* module,
            int operation, ... );

    /*
     * The (*lock_ycbcr)() method is like the (*lock)() method, with the
     * difference that it fills a struct ycbcr with a description of the buffer
     * layout, and zeroes out the reserved fields.
     *
     * If the buffer format is not compatible with a flexible YUV format (e.g.
     * the buffer layout cannot be represented with the ycbcr struct), it
     * will return -EINVAL.
     *
     * This method must work on buffers with HAL_PIXEL_FORMAT_YCbCr_*_888
     * if supported by the device, as well as with any other format that is
     * requested by the multimedia codecs when they are configured with a
     * flexible-YUV-compatible color-format with android native buffers.
     *
     * Note that this method may also be called on buffers of other formats,
     * including non-YUV formats.
     *
     * Added in GRALLOC_MODULE_API_VERSION_0_2.
     */

    int (*lock_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            
<think>我们正在讨论的是为高通SM8350平台在LineageOS中配置Gralloc(图形分配器)的问题。用户提到在`hardware/qcom-caf/sm8350/display/gralloc`目录下缺少`Android.bp`文件,并且不确定如何处理`gralloc.qcom`的定义,同时参考了SM8250的处理方式。 根据用户提供的引用[1]:Gralloc模块的命名规范是`gralloc.$(TARGET_BOARD_PLATFORM)`,并且它是一个共享库(`BUILD_SHARED_LIBRARY`),依赖于`libmemalloc.so`。 在LineageOS中,对于高通平台,通常使用CAF(Code Aurora Forum)的硬件支持。用户已经确认平台标识符为`sm8350`(即TARGET_BOARD_PLATFORM=sm8350)。 问题焦点:在SM8350的gralloc目录中缺少`Android.bp`文件,而用户看到SM8250有类似定义。用户想知道应该删除还是添加`gralloc.qcom`的定义。 分析: 1. 在LineageOS中,高通平台的图形栈通常使用CAF分支。对于较新的平台(如SM8350),可能已经迁移到Android.bp(Soong构建系统)而不是旧的Android.mk。 2. 用户发现SM8350的gralloc目录下没有`Android.bp`,而SM8250有。这可能是由于平台差异或代码迁移状态不同。 3. 用户需要确保Gralloc模块被正确构建并命名为`gralloc.sm8350`。 解决方案: - 如果SM8350的gralloc目录中没有`Android.bp`,我们应该参考同平台其他目录或类似平台(如SM8250)的配置,创建一个合适的`Android.bp`。 - 在`Android.bp`中定义模块名称为`gralloc.$(TARGET_BOARD_PLATFORM)`,即`gralloc.sm8350`。 - 如果该目录下存在旧的`Android.mk`,我们可以将其转换为`Android.bp`,或者直接使用Soong的blueprint语法编写。 步骤: 1. 检查SM8350的gralloc目录中是否有`Android.mk`。如果有,我们可以将其转换为`Android.bp`(使用androidmk工具)或者手动编写。 2. 参考SM8250的`Android.bp`(如果存在)来编写SM8350的`Android.bp`。 3. 确保模块名称正确,并且源文件和依赖项配置正确。 示例(基于SM8250的`Android.bp`): 假设SM8250的`hardware/qcom-caf/sm8250/display/gralloc/Android.bp`内容如下(示例): ```bp cc_library_shared { name: "gralloc.$(TARGET_BOARD_PLATFORM)", defaults: ["display-commonsys-intf-defaults"], vendor: true, srcs: [ "gr_utils.cpp", "gr_ion_alloc.cpp", "gr_allocator.cpp", "gr_buf_mgr.cpp", ], shared_libs: [ "libhidlbase", "libhidltransport", "libqdMetaData", "liblog", "libcutils", "libhardware", "libutils", "libsync", "libdl", "libgrallocutils", "libgralloc.qti", "libui", ], header_libs: [ "gralloc_headers", "display_headers", "libhardware_headers", "libutils_headers", ], export_include_dirs: ["."], } ``` 我们可以为SM8350创建类似的`Android.bp`,注意调整源文件列表和依赖库(根据SM8350的实际情况)。 4. 如果SM8350的gralloc实现与SM8250相同,那么可以直接复制并修改模块名(将`sm8250`改为`sm8350`)。但要注意,不同平台的源文件和依赖可能略有不同,需要检查。 5. 在设备的makefile(如`lineage_p3q.mk`)中,确保添加了`gralloc.sm8350`模块: ```makefile PRODUCT_PACKAGES += \ ... \ gralloc.sm8350 ``` 6. 如果该目录下既没有`Android.mk`也没有`Android.bp`,那么可能需要检查CAF源码是否完整,或者是否因为平台较新而尚未迁移。在这种情况下,可能需要从CAF的相应分支获取。 关于用户提到的`gralloc.qcom`:这是一个旧的通用名称,现在应该使用平台特定的名称(如`gralloc.sm8350`)。因此,在设备makefile中不应该再使用`gralloc.qcom`,而应该使用`gralloc.$(TARGET_BOARD_PLATFORM)`。 结论: - 不需要删除`gralloc.qcom`的定义(因为可能不存在于SM8350的配置中),而是确保使用平台特定的名称。 - 为SM8350的gralloc目录添加一个`Android.bp`文件(参考SM8250的写法,并做适当调整)。 最后,编译并验证。</think>### 为 SM8350 平台配置 Gralloc 的解决方案 #### 1. **理解 Gralloc 模块命名规则 高通平台的 Gralloc 模块命名规范为:`gralloc.$(TARGET_BOARD_PLATFORM)`。对于 SM8350 设备,正确命名应为 **`gralloc.sm8350`**[^1]。 `gralloc.qcom` 是旧版通用命名,已不再推荐使用。 #### 2. **处理缺失的 Android.bp 文件 在 `hardware/qcom-caf/sm8350/display/gralloc` 目录中: - **若 Android.bp 缺失**:需从 SM8250 移植模板 - **若 Android.bp 存在但未定义模块**:需手动添加定义 ```bp # 文件路径: hardware/qcom-caf/sm8350/display/gralloc/Android.bp cc_library_shared { name: "gralloc.sm8350", // 关键命名格式 srcs: [ "gr_utils.cpp", "gr_ion_alloc.cpp", // 其他平台特有源文件 ], shared_libs: [ "liblog", "libcutils", "libhardware", "libqdutils", "libqdMetaData", "libsync", "libgrallocutils", ], cflags: [ "-DLOG_TAG=\"gralloc\"", "-D__QTI_DISPLAY_GRALLOC__", "-Wno-unused-parameter" ], vendor: true, } ``` #### 3. **设备树配置修正 在设备 makefile 中确保正确引用: ```makefile # 文件路径: device/<vendor>/<device>/device.mk PRODUCT_PACKAGES += \ android[email protected] \ android[email protected] \ gralloc.sm8350 // 平台特定实现 ``` #### 4. **关键配置标志 在 `BoardConfig.mk` 中设置: ```makefile TARGET_BOARD_PLATFORM := sm8350 TARGET_USES_GRALLOC4 := true // Android 12+ 必须 BOARD_USES_QCOM_HARDWARE := true // 启用高通私有扩展 ``` #### 5. **与 SM8250 的差异处理 | 配置项 | SM8250 方案 | SM8350 适配方案 | |----------------|---------------------------|-------------------------------| | 模块命名 | gralloc.kona | gralloc.sm8350 | | HAL 版本 | TARGET_USES_GRALLOC3 | TARGET_USES_GRALLOC4 | | 内存分配器 | ION 分配器 | 新增 DMABUF 支持 | | DRM 处理 | 基础保护 | 增强型硬件保护层 | #### 6. **编译验证 ```bash # 检查模块是否包含 make -j1 showcommands | grep "gralloc.sm8350" # 编译后验证库文件 ls out/target/product/<device>/system/lib64/hw/ | grep gralloc.sm8350 ``` 预期输出:`gralloc.sm8350.so` > **注意**:若遇到 `gralloc.qcom` 残留引用,需全局搜索并替换为 `gralloc.sm8350`,这是新版 LineageOS 的强制要求[^1]。 ### 常见问题解决 **Q:编译报错 "gralloc.sm8350 undefined symbol"** A:检查 `Android.bp` 中的 `shared_libs` 是否包含所有依赖库,特别是 `libgrallocutils` 和 `libqdMetaData` **Q:图形缓冲区分配失败** A:在 `gralloc_priv.h` 中启用调试日志: ```cpp #define DEBUG_LOG 1 // 添加此宏定义 ``` **Q:DRM 内容显示异常** A:在 `BoardConfig.mk` 添加: ```makefile TARGET_USES_PROTECTED_BUFFERS := true ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值