做了墙漆多久可以入住:读 overlay 部分的一点总结

来源:百度文库 编辑:偶看新闻 时间:2024/05/11 01:20:48
Overlay 分析
1 overlay 代码结构
Overlay 是个相对简单的模块,主要的文件有:
/hardware/libhardware/include/hardware/overlay.h
主要定义了两个 struct, 定义为 data device 和 control device.
提供针对data device  和  control device 的 open 和 close 函数。
这两个函数就是注册到device_module 里面的函数了。

./frameworks/base/include/ui/IOverlay.h
定义了两个类 一个是 IOverlay, 一个是 BnOverlay.
IOverlay 只定义了destroy 一个函数,用于回收 control device资源。
BnOverlay native binder  overlay

./frameworks/base/include/ui/Overlay.h
真正定义 overlay 接口的部分,下面具体介绍

如果我们先不考虑 surface 的话,上面就是比较主要的文件了,下面可以一个一个看一看。
Overlay 使用的driver 是 framebuffer。

2  overlay.h 实现
在 overlay.h 中定义的就是 overlay  的 hal 层了。也是我们需要实现的部分,下面仔细的看一看。
enum {
    OVERLAY_FORMAT_RGBA_8888    = HAL_PIXEL_FORMAT_RGBA_8888,
    OVERLAY_FORMAT_RGB_565      = HAL_PIXEL_FORMAT_RGB_565,
    OVERLAY_FORMAT_BGRA_8888    = HAL_PIXEL_FORMAT_BGRA_8888,
    OVERLAY_FORMAT_YCbCr_422_SP = HAL_PIXEL_FORMAT_YCbCr_422_SP,
    OVERLAY_FORMAT_YCbCr_420_SP = HAL_PIXEL_FORMAT_YCbCr_420_SP,
    OVERLAY_FORMAT_YCbYCr_422_I = HAL_PIXEL_FORMAT_YCbCr_422_I,
    OVERLAY_FORMAT_YCbYCr_420_I = HAL_PIXEL_FORMAT_YCbCr_420_I,
    OVERLAY_FORMAT_CbYCrY_422_I = HAL_PIXEL_FORMAT_CbYCrY_422_I,
    OVERLAY_FORMAT_CbYCrY_420_I = HAL_PIXEL_FORMAT_CbYCrY_420_I,
    OVERLAY_FORMAT_DEFAULT      = 99    // The actual color format is determined
                                        // by the overlay
};
一个enum, 定义了所有支援的format,framebuffer  会根据 format 和 width, height来决定buffer(framebuffer里面用来显示的buffer) 的大小。

typedef struct overlay_t {
    uint32_t            w;
    uint32_t            h;
    int32_t             format;
    uint32_t            w_stride;
    uint32_t            h_stride;
    uint32_t            reserved[3];
    /* returns a reference to this overlay's handle (the caller doesn't
     * take ownership) */
    overlay_handle_t    (*getHandleRef)(struct overlay_t* overlay);
    uint32_t            reserved_procs[7];
} overlay_t;

overlay 的一些信息:
w  width
h   height
format  格式
w_stride h_stride 不知道
getHandleRef  函数返回一个  overlay_handle_t,这个函数很重要。

struct overlay_module_t {
    struct hw_module_t common;
};
定义一个结构体,和 hw_module_t 可以混用的,基本上就是个别名,每一个module  都会对应一个, common 里面会注册一个 open 函数

struct overlay_control_device_t {
    struct hw_device_t common;
    int (*get)(struct overlay_control_device_t *dev, int name);
    overlay_t* (*createOverlay)(struct overlay_control_device_t *dev,
            uint32_t w, uint32_t h, int32_t format);
    void (*destroyOverlay)(struct overlay_control_device_t *dev,
            overlay_t* overlay);
    int (*setPosition)(struct overlay_control_device_t *dev,
            overlay_t* overlay,
            int x, int y, uint32_t w, uint32_t h);
    int (*getPosition)(struct overlay_control_device_t *dev,
            overlay_t* overlay,
            int* x, int* y, uint32_t* w, uint32_t* h);
    int (*setParameter)(struct overlay_control_device_t *dev,
            overlay_t* overlay, int param, int value);
    int (*stage)(struct overlay_control_device_t *dev, overlay_t* overlay);
    int (*commit)(struct overlay_control_device_t *dev, overlay_t* overlay);
};

结构体定义了一个 control device, 成员除了 common都是函数,这些函数就是我们需要去实现的,在实现的时候我们会基于这个结构体扩展出一个 关于 control device的context的结构体,context结构体内部会扩充一些信息并且包含control device 。
Common 每一个device 都必须有,而且必须放到第一位,目的只是为了overlay_control_device_t 和 hw_device_t 做匹配。

int (*get)(struct overlay_control_device_t *dev, int name);
函数为了获取属性,也可以不实现

overlay_t* (*createOverlay)(struct overlay_control_device_t *dev,
            uint32_t w, uint32_t h, int32_t format);
一个很重要的函数,用于生成overlay_t(内部需要做open 等操作,并获取相应的句柄)

void (*destroyOverlay)(struct overlay_control_device_t *dev,
            overlay_t* overlay);
释放资源,分配的handle, 和 control device 的内存。

int (*setPosition)(struct overlay_control_device_t *dev,
            overlay_t* overlay,
            int x, int y, uint32_t w, uint32_t h);
设置overlay 的显示范围。(如果是camera  的 preview, 那么 h, w  要和preview h, w 一致)

int (*getPosition)(struct overlay_control_device_t *dev,
            overlay_t* overlay,
            int* x, int* y, uint32_t* w, uint32_t* h);
获取 overlay  的显示范围。

  int (*setParameter)(struct overlay_control_device_t *dev,
            overlay_t* overlay, int param, int value);
没有实现,可以根据自己的driver ,选择一些参数。

    int (*stage)(struct overlay_control_device_t *dev, overlay_t* overlay);
    int (*commit)(struct overlay_control_device_t *dev, overlay_t* overlay);
framebuffer 中我没有实现这两个函数,不过我看 l4v2 有实现。


struct overlay_data_device_t {
    struct hw_device_t common;
    int (*initialize)(struct overlay_data_device_t *dev,
            overlay_handle_t handle);
    int (*resizeInput)(struct overlay_data_device_t *dev,
            uint32_t w, uint32_t h);
    int (*setCrop)(struct overlay_data_device_t *dev,
            uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
    int (*getCrop)(struct overlay_data_device_t *dev,
       uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
    int (*setParameter)(struct overlay_data_device_t *dev,
            int param, int value);
    int (*dequeueBuffer)(struct overlay_data_device_t *dev,
                 overlay_buffer_t *buf);
    int (*queueBuffer)(struct overlay_data_device_t *dev,
            overlay_buffer_t buffer);
    void* (*getBufferAddress)(struct overlay_data_device_t *dev,
            overlay_buffer_t buffer);
    int (*getBufferCount)(struct overlay_data_device_t *dev);
    int (*getBufferCount)(struct overlay_data_device_t *dev);
};

common   同上

int (*initialize)(struct overlay_data_device_t *dev,
            overlay_handle_t handle);
函数通过 参数handle 来初始化 data device.

int (*resizeInput)(struct overlay_data_device_t *dev,
            uint32_t w, uint32_t h);
函数重新配置显示参数 w, h。 这两个参数生效我这里需要 close 然后重新 open.
很麻烦不知道有没有别的办法了。

int (*setCrop)(struct overlay_data_device_t *dev,
            uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
int (*getCrop)(struct overlay_data_device_t *dev,
       uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
设置显示的区域,和获取显示的区域,当播放的时候,需要这是 坐标和 宽高来定义如何显示这些数据。

int (*dequeueBuffer)(struct overlay_data_device_t *dev,
                 overlay_buffer_t *buf);
int (*queueBuffer)(struct overlay_data_device_t *dev,
            overlay_buffer_t buffer);
l4v2 的driver 用来管理内存。我的是FB 所以我不需要这两个函数。

void* (*getBufferAddress)(struct overlay_data_device_t *dev,
            overlay_buffer_t buffer);
函数返回 framebuffer 内部用于显示的内存。通过 mmap 拿到 内存地址。

以上的两个 data 和 control device是我们需要实现的。

3 Overlay.h 实现
函数实现 的更像是 data device 的功能,和一些外界的接口,我们来看一下。
内部实现的主要的类是  Overlay 和  overlayRef。

OverlayRef 主要需要和surface 配合使用,
通过 Isurface 可以创建出OverlayRef
而 Overlay 是通过OverlayRef 来创建出来的。
下面来看看 Overlay
class Overlay : public virtual RefBase
{
public:
    Overlay(const sp& overlayRef);
    void destroy();
    overlay_handle_t getHandleRef() const;
    status_t dequeueBuffer(overlay_buffer_t* buffer);
    status_t queueBuffer(overlay_buffer_t buffer);
    status_t resizeInput(uint32_t width, uint32_t height);
    status_t setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
    status_t getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
    status_t setParameter(int param, int value);
    void* getBufferAddress(overlay_buffer_t buffer);

    /* get physical informations about the overlay */
    uint32_t getWidth() const;
    uint32_t getHeight() const;
    int32_t getFormat() const;
    int32_t getWidthStride() const;
    int32_t getHeightStride() const;
    int32_t getBufferCount() const;
    status_t getStatus() const;

private:
    virtual ~Overlay();

    sp mOverlayRef;
    overlay_data_device_t *mOverlayData;
    status_t mStatus;
};

Overlay(const sp& overlayRef);
很厉害的设计,通过surface 来控制 overlay  或者 在不使用 overlay 的情况下统一的来管理。
这里就是通过  overlayRef 来创建 overlay , 一旦我们拿到了overlay ,我们就可以通过这个overlay 来获取到 用来显示的address, 向 address 中写入数据,就可以显示我们的图像了。

void destroy();
释放 data device 的资源。 我们通过这里就能看到了,实际上一旦 control device 设置结束之后,我们以后使用 control  device 的机会是没有的。

overlay_handle_t getHandleRef() const;
获取overlay handle,可以根据自己的需要扩展,扩展之后就有很多数据了。

    status_t dequeueBuffer(overlay_buffer_t* buffer);
    status_t queueBuffer(overlay_buffer_t buffer);
配合 linux4vedio2 使用的函数,我的是framebuffer 并不使用。

status_t resizeInput(uint32_t width, uint32_t height);
重新配置overlay 的区域属性。

status_t setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
status_t getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
设置播放的属性。

void* getBufferAddress(overlay_buffer_t buffer);
获取framebuffer  用于显示的内存地址。

    uint32_t getWidth() const;
    uint32_t getHeight() const;
    int32_t getFormat() const;
    int32_t getWidthStride() const;
    int32_t getHeightStride() const;
    int32_t getBufferCount() const;
    status_t getStatus() const;
获取属性的信息。

以上的这些接口是我们以后需要使用的,我们只需要知道如何使用就可以了。



4 与 surface 相关的属性
这个研究了好一会,比较费劲。
首先是这样的:
status_t SurfaceFlinger::readyToRun()
函数在 android 启动的时候就会去调用的函数,在函数的内部有这么一句
DisplayHardware* const hw = new DisplayHardware(this, dpy);
实例化一个DisplayHardware

DisplayHardware:isplayHardware(
        const sp& flinger,
        uint32_t dpy)
    : DisplayHardwareBase(flinger, dpy)
{
    init(dpy);
}
这个是  DisplayHardware 构造函数的实现
我们关心他调用的函数 init。
Init 函数有这么几句
    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
        overlay_control_open(module, &mOverlayEngine);
    }

这个就是我们最关心的,获取到 overlay 的 module 参数,调用 overlay_control_open 获取
control device( mOverlayEngine).
这里就是一切的开始。拥有了control device。

下面就是获取 control  device  的handle 了,通过调用 Isurface的createOverlay。
这个流程是这样的, Isurface->BnOverlay->LayerBuffer->OverlaySource->OverLayChannel
这样就得到了 control  device handle。

我们还需要一个 data device:
data  device  是定义在class Overlay 的一个成员,通过 overlayRef来构造
Overlay(const sp& overlayRef);
这里通过 overlayRef::mOverlayHandle  在它的内部保存这 control device 的信息。
从而初始化  data device 的信息。得到 data device。