Android SurfaceFlinger 学习之路(十一)(PostView)--附:硬件HWC选取合成类型(Intel)

       这里说点题外话,高通最近势头正猛啊,回拒了博通的恶意收购,又出了骁龙835进军PC市场,拉着AMD一起干英特尔。英特尔在移动设备市场上面还是没有ARM老谋深算,人家简单指令集一路走到底,授权卖指令集或者自己出公版,得到了苹果、三星、高通、MTK等许多大厂的青睐(苹果、高通、三星等厂商都是向ARM买指令集,再自己设计电路,大概是嫌ARM自己的芯片效能不够;然而联发科和其他几家厂商买的是IP(公版)来兜自己的芯片,不自己从头设计电路),细水长流,进过多年顺风打野,最后打出一身神装出来carry。
       反观intel,执着于自己x86架构,也用复杂指令集芯片打入过移动市场,奈何功耗扛不住啊,(充电两小时,装逼5分钟,只是个夸张比喻,勿当真)虽然后来又出了Atom的低功耗处理器,奈何市场已被ARM吞食大半,自己名气也没有打出,最后只能默默凉凉了。
       intel在PC市场上霸主这么多年,实力肯定不是盖的,所以我们这次选个intel在hwc模块的实现来看看(其实是因为TI、高通的实现有些复杂,比较晦涩,三星也倒是比较容易看懂,但是也没有intel代码这么人性化=。=)

HWC选取合成类型

       上面讲到mHwc->prepare(mHwc, mNumDisplays, mLists);对所有显示屏中所有Layer作合成准备(此时也可以开始发送合成的命令码下去,启动硬件合成,但不需要等待完成),hwcomposer需要正确汇报每个Layer的composetype,以告知SurfaceFlinger是否需要额外处理。
       
       实现位于/hardware/intel/img/hwcomposer/common/base/Hwcomposer.cpp,我们找一个公共模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
bool Hwcomposer::prepare(size_t numDisplays,
hwc_display_contents_1_t** displays)
{
bool ret = true;

RETURN_FALSE_IF_NOT_INIT();
ALOGTRACE("display count = %d", numDisplays);

if (!numDisplays || !displays) {
ELOGTRACE("invalid parameters");
return false;
}
//检查显示屏相关信息,处理热插拔消息
mDisplayAnalyzer->analyzeContents(numDisplays, displays);

// disable reclaimed planes
//disable掉所有回收的显示平面
mPlaneManager->disableReclaimedPlanes();

// reclaim all allocated planes if possible
//如果可能,回首所有已经申请过的显示平面
for (size_t i = 0; i < numDisplays; i++) {
if (i >= mDisplayDevices.size()) {
continue;
}
IDisplayDevice *device = mDisplayDevices.itemAt(i);
if (!device) {
VLOGTRACE("device %d doesn't exist", i);
continue;
}
//检查显示屏几何区域是否有变化
device->prePrepare(displays[i]);
}

for (size_t i = 0; i < numDisplays; i++) {
if (i >= mDisplayDevices.size()) {
continue;
}
IDisplayDevice *device = mDisplayDevices.itemAt(i);
if (!device) {
VLOGTRACE("device %d doesn't exist", i);
continue;
}
//最重要的一行:更新HwcLayer,选择合成类型
ret = device->prepare(displays[i]);
if (ret == false) {
ELOGTRACE("failed to do prepare for device %d", i);
continue;
}
}

return ret;
}

       上述就是选取合成类型的步骤:
       1)检查显示屏相关信息,处理热插拔消息;
       2)disable掉所有回收的显示平面;
       3)检查显示屏几何区域是否有变化;
       4)最重要的一行:更新HwcLayer,选择合成类型。

流程细节

       我们分步查看:
       1)检查显示屏相关信息,处理热插拔消息。位于hardware/intel/img/hwcomposer/common/base/DisplayAnalyzer.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void DisplayAnalyzer::analyzeContents(
size_t numDisplays, hwc_display_contents_1_t** displays)
{
// cache and use them only in this context during analysis
mCachedNumDisplays = numDisplays;
mCachedDisplays = displays;
//处理pending的事件
handlePendingEvents();
}
void DisplayAnalyzer::handlePendingEvents()
{
// handle one event per analysis to avoid blocking surface flinger
// some event may take lengthy time to process
Event e;
if (!getEvent(e)) {
return;
}

switch (e.type) {
case HOTPLUG_EVENT:
//处理热插拔
handleHotplugEvent(e.bValue);
break;
}
}
void DisplayAnalyzer::handleHotplugEvent(bool connected)
{
if (connected) {
for (int i = 0; i < mCachedNumDisplays; i++) {
//将合成类型设置成HWC_FRAMEBUFFER
setCompositionType(i, HWC_FRAMEBUFFER, true);
}
}
}

       这就是处理热插拔消息,然后将cache的显示屏合成类型设置成HWC_FRAMEBUFFER,表示用Open GL合成。

       2)disable掉所有回收的显示平面。位于hardware/intel/img/hwcomposer/common/planes/DisplayPlaneManager.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void DisplayPlaneManager::disableReclaimedPlanes()
{
int i, j;
bool ret;

RETURN_VOID_IF_NOT_INIT();

for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
// disable reclaimed planes
if (mReclaimedPlanes[i]) {
for (j = 0; j < mPlaneCount[i]; j++) {
int bit = (1 << j);
if (mReclaimedPlanes[i] & bit) {
DisplayPlane* plane = mPlanes[i].itemAt(j);
// check plane state first
ret = plane->isDisabled();
// reset plane
if (ret)
ret = plane->reset();
if (ret) {
// only merge into free bitmap if it is successfully disabled and reset
// otherwise, plane will be disabled and reset again.
mFreePlanes[i] |=bit;
mReclaimedPlanes[i] &= ~bit;
}
}
}
}
}
}

       disable所有已经回收planes,检查plane是否已经disable,然后将其reset,如果成功了,就合并进入空闲的bitmap,如果没有就要重新disabled and reset。

       3)检查显示屏几何区域是否有变化,遍历每一个显示屏,调用device->prePrepare(displays[i]);我们看一下物理屏幕,位于hardware/intel/img/hwcomposer/common/devices/PhysicalDevice.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool PhysicalDevice::prePrepare(hwc_display_contents_1_t *display)
{
RETURN_FALSE_IF_NOT_INIT();

// for a null list, delete hwc list
if (!mConnected || !display || mBlank) {
if (mLayerList) {
DEINIT_AND_DELETE_OBJ(mLayerList);
}
return true;
}

// check if geometry is changed, if changed delete list
if ((display->flags & HWC_GEOMETRY_CHANGED) && mLayerList) {
DEINIT_AND_DELETE_OBJ(mLayerList);
}
return true;
}

       如果是一个空的hwc list,就将其删除;然后检查几何区域是否变化,如果变了,也要删除hwc list。

       4)最重要的一行:更新HwcLayer,选择合成类型。依然是遍历每一个显示屏,然后调用prepare函数,依然位于hardware/intel/img/hwcomposer/common/devices/PhysicalDevice.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
bool PhysicalDevice::prepare(hwc_display_contents_1_t *display)
{
RETURN_FALSE_IF_NOT_INIT();

if (!mConnected || !display || mBlank)
return true;

// check if geometry is changed
if (display->flags & HWC_GEOMETRY_CHANGED) {
//上一步处理了几何区域变化,上出了hwc list,这一步重新创建
onGeometryChanged(display);
}
if (!mLayerList) {
WLOGTRACE("null HWC layer list");
return true;
}

// update list with new list
//更新hwc list使用重新new的,选取合成类型
return mLayerList->update(display);
}

void PhysicalDevice::onGeometryChanged(hwc_display_contents_1_t *list)
{
if (!list) {
ELOGTRACE("list is NULL");
return;
}

ALOGTRACE("disp = %d, layer number = %d", mType, list->numHwLayers);

// NOTE: should NOT be here
if (mLayerList) {
WLOGTRACE("mLayerList exists");
DEINIT_AND_DELETE_OBJ(mLayerList);
}

// create a new layer list
//上一步处理了几何区域变化,上出了hwc list,这一步重新创建
mLayerList = new HwcLayerList(list, mType);
if (!mLayerList) {
WLOGTRACE("failed to create layer list");
}
}

       上一步处理了几何区域变化,上出了hwc list,这一步重新创建,在onGeometryChanged函数中得以体现。

更新HwcLayerList

       那么选取合成类型就位于mLayerList->update(display);,位于hardware/intel/img/hwcomposer/common/base/HwcLayerList.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
bool HwcLayerList::update(hwc_display_contents_1_t *list)
{
bool ret;

// basic check to make sure the consistance
if (!list) {
ELOGTRACE("null layer list");
return false;
}

if ((int)list->numHwLayers != mLayerCount) {
ELOGTRACE("layer count doesn't match (%d, %d)", list->numHwLayers, mLayerCount);
return false;
}

// update list
mList = list;

bool ok = true;
// update all layers, call each layer's update()
for (int i = 0; i < mLayerCount; i++) {
HwcLayer *hwcLayer = mLayers.itemAt(i);
if (!hwcLayer) {
ELOGTRACE("no HWC layer for layer %d", i);
continue;
}
//更新layer,如果更新返回false,则需要fallback回GLES去合成
if (!hwcLayer->update(&list->hwLayers[i])) {
ok = false;
hwcLayer->setCompositionType(HWC_FORCE_FRAMEBUFFER);
}
}

if (!ok) {
//如果上一步update有返回false的,就要把它fallback回GLES合成
ILOGTRACE("overlay fallback to GLES. flags: %#x", list->flags);
for (int i = 0; i < mLayerCount - 1; i++) {
HwcLayer *hwcLayer = mLayers.itemAt(i);
if (hwcLayer->getPlane() &&
(hwcLayer->getCompositionType() == HWC_OVERLAY ||
hwcLayer->getCompositionType() == HWC_CURSOR_OVERLAY)) {
hwcLayer->setCompositionType(HWC_FRAMEBUFFER);
}
}
//最后一个layer是HWC_FRAMEBUFFER_TARGET合成目标,上面讲过
mLayers.itemAt(mLayerCount - 1)->setCompositionType(HWC_FRAMEBUFFER_TARGET);
//反初始化
deinitialize();
mList = list;
//初始化LayerList每一项
initialize();

// update all layers again after plane re-allocation
//再次更新所有的layer,在plane重新申请之后
for (int i = 0; i < mLayerCount; i++) {
HwcLayer *hwcLayer = mLayers.itemAt(i);
if (!hwcLayer) {
ELOGTRACE("no HWC layer for layer %d", i);
continue;
}

if (!hwcLayer->update(&list->hwLayers[i])) {
DLOGTRACE("fallback to GLES update failed on layer[%d]!\n", i);
}
}
}
//建立只能合成选项,即选择OverLay还是FB
setupSmartComposition();
return true;
}

更新HwcLayer

       这里依然要分步查看:
       Part.1:我们可以看到,选取合成类型为Overlay还是FB就在hwcLayer->update函数,如果返回false,就要fallback回GLES,剩余的都是OverLay。我们看看这个实现,位于hardware/intel/img/hwcomposer/common/base/HwcLayer.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
bool HwcLayer::update(hwc_layer_1_t *layer)
{
// update layer
mLayer = layer;
//创建基本属性,从DataBuffer获取,也可是说是GraphicBuffer
setupAttributes();

// if not a FB layer & a plane was attached update plane's data buffer
//如果不是一个FB layer并且plane已经被连接到更新data buffer
if (mPlane) {
//设置position位置信息
mPlane->setPosition(layer->displayFrame.left,
layer->displayFrame.top,
layer->displayFrame.right - layer->displayFrame.left,
layer->displayFrame.bottom - layer->displayFrame.top);
//设置sourceCrop区域
mPlane->setSourceCrop(layer->sourceCropf.left,
layer->sourceCropf.top,
layer->sourceCropf.right - layer->sourceCropf.left,
layer->sourceCropf.bottom - layer->sourceCropf.top);
//设置矩阵变换
mPlane->setTransform(layer->transform);
//透明度
mPlane->setPlaneAlpha(layer->planeAlpha, layer->blending);
//将layer的句柄设置给plane
bool ret = mPlane->setDataBuffer((uint32_t)layer->handle);
if (ret == true) {
return true;
}
DLOGTRACE("failed to set data buffer, reset handle to 0!!");
mHandle = 0;
if (!mIsProtected) {//如果不是被保护的buffer
//典型的例子:旋转的buffer没有准备好或者句柄为null,就不能用OverLay
// typical case: rotated buffer is not ready or handle is null
return false;
} else {
//被保护的视频需要使用overlay去渲染,return true
// protected video has to be rendered using overlay.
// if buffer is not ready overlay will still be attached to this layer
// but rendering needs to be skipped.
WLOGTRACE("ignoring result of data buffer setting for protected video");
return true;
}
}

return true;
}

       先创建基本属性,从DataBuffer获取,也可是说是GraphicBuffer,我们看看setupAttributes函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
void HwcLayer::setupAttributes()
{ //如果如下属性发生改变,将mUpdated 置为true
if ((mLayer->flags & HWC_SKIP_LAYER) ||
mTransform != mLayer->transform ||
mSourceCropf != mLayer->sourceCropf ||
mDisplayFrame != mLayer->displayFrame ||
mHandle != (uint32_t)mLayer->handle ||
DisplayQuery::isVideoFormat(mFormat)) {
// TODO: same handle does not mean there is always no update
mUpdated = true;
}

// update handle always as it can become "NULL"
// if the given layer is not ready
//如果指定的layer没有准备好,那么handle句柄就会变成null,所以要更新句柄的值
mTransform = mLayer->transform;
mSourceCropf = mLayer->sourceCropf;
mDisplayFrame = mLayer->displayFrame;
mHandle = (uint32_t)mLayer->handle;
//其实属性已经被设置,return
if (mFormat != DataBuffer::FORMAT_INVALID) {
// other attributes have been set.
return;
}
//句柄为null,return
if (mLayer->handle == NULL) {
VLOGTRACE("invalid handle");
return;
}
//获取BufferManager
BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
if (bm == NULL) {
// TODO: this check is redundant
return;
}
//锁定图形缓冲区
DataBuffer *buffer = bm->lockDataBuffer((uint32_t)mLayer->handle);
if (!buffer) {
ELOGTRACE("failed to get buffer");
} else {//获取图形缓冲区属性,并设置给全局变量
mFormat = buffer->getFormat();
mWidth = buffer->getWidth();
mHeight = buffer->getHeight();
mStride = buffer->getStride();
mPriority = (mSourceCropf.right - mSourceCropf.left) * (mSourceCropf.bottom - mSourceCropf.top);
mPriority <<= LAYER_PRIORITY_SIZE_OFFSET;
mPriority |= mIndex;
GraphicBuffer *gBuffer = (GraphicBuffer*)buffer;
mUsage = gBuffer->getUsage();
mIsProtected = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);
if (mIsProtected) {
mPriority |= LAYER_PRIORITY_PROTECTED;
} else if (PlaneCapabilities::isFormatSupported(DisplayPlane::PLANE_OVERLAY, this)) {
mPriority |= LAYER_PRIORITY_OVERLAY;
}
//获取完之后释放
bm->unlockDataBuffer(buffer);
}
}

       这段代码要是参考之前Gralloc模块应该有点印象,就是锁定图形缓冲区,获取图形缓冲区属性,并设置给全局变量,获取完之后释放。
       回到HwcLayer::update,之后判断如果不是一个FB layer并且plane已经被连接到更新data buffer,就要设置position位置信息、设置sourceCrop区域、设置矩阵变换 、透明度。

映射过程

       然后将layer的句柄设置给plane,我们看看这个实现,位于hardware/intel/img/hwcomposer/common/planes/DisplayPlane.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
bool DisplayPlane::setDataBuffer(uint32_t handle)
{
DataBuffer *buffer;
BufferMapper *mapper;
ssize_t index;
bool ret;
bool isCompression;
//获取buffermanager
BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

RETURN_FALSE_IF_NOT_INIT();
ALOGTRACE("handle = %#x", handle);

if (!handle) {
WLOGTRACE("invalid buffer handle");
return false;
}

// do not need to update the buffer handle
//如果不是当前保存句柄,加上CHANGE标签
if (mCurrentDataBuffer != handle)
mUpdateMasks |= PLANE_BUFFER_CHANGED;

// if no update then do Not need set data buffer
if (!mUpdateMasks)
return true;
//锁定缓冲区
buffer = bm->lockDataBuffer(handle);
if (!buffer) {
ELOGTRACE("failed to get buffer");
return false;
}

mIsProtectedBuffer = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);
isCompression = GraphicBuffer::isCompressionBuffer((GraphicBuffer*)buffer);

// map buffer if it's not in cache
//如果映射区域不在缓存cache中,就要重新映射
index = mDataBuffers.indexOfKey(buffer->getKey());
if (index < 0) {
VLOGTRACE("unmapped buffer, mapping...");
//映射buffer,并加入缓存
mapper = mapBuffer(buffer);
if (!mapper) {
ELOGTRACE("failed to map buffer %#x", handle);
bm->unlockDataBuffer(buffer);
return false;
}
} else {
VLOGTRACE("got mapper in saved data buffers and update source Crop");
mapper = mDataBuffers.valueAt(index);
}

// always update source crop to mapper
//更新crop区域
mapper->setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);

mapper->setIsCompression(isCompression);

// unlock buffer after getting mapper
//映射区域之后释放缓冲区
bm->unlockDataBuffer(buffer);
buffer = NULL;
//将映射区域设置给plane
ret = setDataBuffer(*mapper);
if (ret) {//如果成功了,就将handle赋给mCurrentDataBuffer ,并且更新活跃的buffer
mCurrentDataBuffer = handle;
// update active buffers
updateActiveBuffers(mapper);
}
return ret;
}

       核心就是获取显示屏的BufferManager,然后锁定图形缓冲区,然后映射buffer,并加入缓存,映射区域之后释放缓冲区,将映射区域设置给plane。
       映射实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
BufferMapper* DisplayPlane::mapBuffer(DataBuffer *buffer)
{
BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

// invalidate buffer cache if cache is full
//cache满了就要清除
if ((int)mDataBuffers.size() >= mCacheCapacity) {
invalidateBufferCache();
}
//映射plane内存区域
BufferMapper *mapper = bm->map(*buffer);
if (!mapper) {
ELOGTRACE("failed to map buffer");
return NULL;
}

// add it to data buffers
//映射成功后就将这个句柄加入缓存
ssize_t index = mDataBuffers.add(buffer->getKey(), mapper);
if (index < 0) {
ELOGTRACE("failed to add mapper");
bm->unmap(mapper);
return NULL;
}

return mapper;
}
void DisplayPlane::invalidateBufferCache()
{
BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
BufferMapper* mapper;

RETURN_VOID_IF_NOT_INIT();

for (size_t i = 0; i < mDataBuffers.size(); i++) {
mapper = mDataBuffers.valueAt(i);
bm->unmap(mapper);
}

mDataBuffers.clear();
// reset current buffer
mCurrentDataBuffer = 0;
}

       之后将映射区域设置给plane,如果成功了,就将handle赋给mCurrentDataBuffer ,并且更新活跃的buffer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void DisplayPlane::updateActiveBuffers(BufferMapper *mapper)
{
BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

// unmap the first entry (oldest buffer)
if (mActiveBuffers.size() >= MIN_DATA_BUFFER_COUNT) {
BufferMapper *oldest = mActiveBuffers.itemAt(0);
bm->unmap(oldest);
mActiveBuffers.removeAt(0);
}

// queue it to active buffers
if (!isActiveBuffer(mapper)) {
mapper->incRef();
mActiveBuffers.push_back(mapper);
}
}

       也就是移除最老的映射buffer,然后新增加一个最新的。

       如果设置给plane不成功,即没有可用的内存区域或者不匹配,则不能使用OverLay合成,返回false,就要是OpenGL了。

初始化和反初始化

       回到上面HwcLayerList::update,继续往下走。

       然后就是先反初始化deinitialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void HwcLayerList::deinitialize()
{
if (mLayerCount == 0) {
return;
}

DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();
for (int i = 0; i < mLayerCount; i++) {
HwcLayer *hwcLayer = mLayers.itemAt(i);
if (hwcLayer) {
DisplayPlane *plane = hwcLayer->detachPlane();
if (plane) {
planeManager->reclaimPlane(mDisplayIndex, *plane);
}
}
delete hwcLayer;
}

mLayers.clear();
mFBLayers.clear();
mOverlayCandidates.clear();
mSpriteCandidates.clear();
mCursorCandidates.clear();
mZOrderConfig.clear();
mFrameBufferTarget = NULL;
mLayerCount = 0;
}

       反初始化就是清除一些变量。然后是初始化initialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
bool HwcLayerList::initialize()
{
if (!mList || mList->numHwLayers == 0) {
ELOGTRACE("invalid hwc list");
return false;
}
//设置一些变量
mLayerCount = (int)mList->numHwLayers;
mLayers.setCapacity(mLayerCount);
mFBLayers.setCapacity(mLayerCount);
mSpriteCandidates.setCapacity(mLayerCount);
mOverlayCandidates.setCapacity(mLayerCount);
mCursorCandidates.setCapacity(mLayerCount);
mZOrderConfig.setCapacity(mLayerCount);
Hwcomposer& hwc = Hwcomposer::getInstance();

PriorityVector rgbOverlayLayers;
rgbOverlayLayers.setCapacity(mLayerCount);
//根据不同合成类型设置hwcLayer的type
for (int i = 0; i < mLayerCount; i++) {
hwc_layer_1_t *layer = &mList->hwLayers[i];
if (!layer) {
DEINIT_AND_RETURN_FALSE("layer %d is null", i);
}

HwcLayer *hwcLayer = new HwcLayer(i, layer);
if (!hwcLayer) {
DEINIT_AND_RETURN_FALSE("failed to allocate hwc layer %d", i);
}

if (layer->compositionType == HWC_FRAMEBUFFER_TARGET) {//HWC_FRAMEBUFFER_TARGET
hwcLayer->setType(HwcLayer::LAYER_FRAMEBUFFER_TARGET);
mFrameBufferTarget = hwcLayer;
} else if (layer->compositionType == HWC_OVERLAY){
// skipped layer, filtered by Display Analyzer
hwcLayer->setType(HwcLayer::LAYER_SKIPPED);
} else if (layer->compositionType == HWC_FORCE_FRAMEBUFFER) {//HWC_FORCE_FRAMEBUFFER
layer->compositionType = HWC_FRAMEBUFFER;
hwcLayer->setType(HwcLayer::LAYER_FORCE_FB);
// add layer to FB layer list for zorder check during plane assignment
mFBLayers.add(hwcLayer);
} else if (layer->compositionType == HWC_FRAMEBUFFER) {//HWC_FRAMEBUFFER
// by default use GPU composition
//默认由GPU合成
hwcLayer->setType(HwcLayer::LAYER_FB);
mFBLayers.add(hwcLayer);
//检查是否支持cursor overlay
if (checkCursorSupported(hwcLayer)) {
mCursorCandidates.add(hwcLayer);
} else if (checkRgbOverlaySupported(hwcLayer)) {//检查是否支持rgb overlay
rgbOverlayLayers.add(hwcLayer);
} else if (checkSupported(DisplayPlane::PLANE_SPRITE, hwcLayer)) {//检查是否支持PLANE_SPRITE
mSpriteCandidates.add(hwcLayer);
} else if (checkSupported(DisplayPlane::PLANE_OVERLAY, hwcLayer)) {//是否支持PLANE_OVERLAY
mOverlayCandidates.add(hwcLayer);
} else {
// noncandidate layer
}
} else if (layer->compositionType == HWC_SIDEBAND){//HWC_SIDEBAND
hwcLayer->setType(HwcLayer::LAYER_SIDEBAND);
} else {
DEINIT_AND_RETURN_FALSE("invalid composition type %d", layer->compositionType);
}
// add layer to layer list
mLayers.add(hwcLayer);
}

if (mFrameBufferTarget == NULL) {
ELOGTRACE("no frame buffer target?");
return false;
}

// If has layer besides of FB_Target, but no FBLayers, skip plane allocation
// Note: There is case that SF passes down a layerlist with only FB_Target
// layer; we need to have this FB_Target to be flipped as well, otherwise it
// will have the buffer queue blocked. (The buffer hold by driver cannot be
// released if new buffers' flip is skipped).
if ((mFBLayers.size() == 0) && (mLayers.size() > 1)) {
VLOGTRACE("no FB layers, skip plane allocation");
return true;
}

bool hasOverlay = mOverlayCandidates.size() != 0;
while (rgbOverlayLayers.size()) {
HwcLayer *hwcLayer = rgbOverlayLayers.top();
if (hasOverlay) {
mSpriteCandidates.add(hwcLayer);
} else {
mOverlayCandidates.add(hwcLayer);
}
rgbOverlayLayers.removeItemsAt(0);
}

if (!DisplayQuery::forceFbScaling(mDisplayIndex)) {
allocatePlanes();
} else {
// force GLES composition on all layers, then use GPU or hardware
// overlay to scale buffer to match display resolution
assignPrimaryPlane();
}

//dump();
return true;
}

       这一段核心就是根据不同合成类型设置hwcLayer的type,合成类型有HWC_FRAMEBUFFER_TARGET、HWC_FORCE_FRAMEBUFFER、HWC_FRAMEBUFFER、HWC_SIDEBAND,又在HWC_FRAMEBUFFER检测:检查是否支持cursor overlay、检查是否支持rgb overlay、检查是否支持PLANE_SPRITE、是否支持PLANE_OVERLAY,如果支持就要加入OverLay合成。

开始智能合成

       继续回到上面,进行最后一步setupSmartComposition,建立只能合成选项,即选择OverLay还是FB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void HwcLayerList::setupSmartComposition()
{
//默认都是HWC_OVERLAY
uint32_t compositionType = HWC_OVERLAY;
HwcLayer *hwcLayer = NULL;

// setup smart composition only there's no update on all FB layers
//如果所有的FB layer没有更新了就开始建立智能合成
for (size_t i = 0; i < mFBLayers.size(); i++) {
hwcLayer = mFBLayers.itemAt(i);
if (hwcLayer->isUpdated()) {
compositionType = HWC_FRAMEBUFFER;
}
}

VLOGTRACE("smart composition enabled %s",
(compositionType == HWC_OVERLAY) ? "TRUE" : "FALSE");
//开始只能合成,当compositionType == HWC_OVERLAY就是硬件合成,否则其他都是FB模式
for (size_t i = 0; i < mFBLayers.size(); i++) {
hwcLayer = mFBLayers.itemAt(i);
switch (hwcLayer->getType()) {
case HwcLayer::LAYER_FB:
case HwcLayer::LAYER_FORCE_FB:
hwcLayer->setCompositionType(compositionType);
break;
default:
ELOGTRACE("Invalid layer type %d", hwcLayer->getType());
break;
}
}
}

       上面就是开始智能合成,当compositionType == HWC_OVERLAY就是硬件合成,否则其他都是FB模式。

小结

       上述就是hwc硬件选取合成类型的模块,流程分析比较粗略,估计有好多不正确的地方,欢迎大家指正,我好在第一时间修改。

meizi

坚持技术分享,您的支持将鼓励我继续创作!