转自:http://www.eoeandroid.com/thread-29278-1-1.html
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>& 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<OverlayRef> mOverlayRef;
overlay_data_device_t *mOverlayData;
status_t mStatus;
};
Overlay(const sp<OverlayRef>& 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<SurfaceFlinger>& 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);
这里通过 overlayRef::mOverlayHandle 在它的内部保存这 control device 的信息。
从而初始化 data device 的信息。得到 data device。