概述
SurfaceFlinger整合layer的过程
2012-11-22
Linux_Dri...
转自http://blog.csdn.net/andyhuabing/article/details/7293639
代码路径:./services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger 属于system_server进程,在system_init.cpp中利用SurfaceFlinger::instantiate()启动,在此加入到service manager中,所以本身提供service服务功能。
首先看下SurfaceFlinger的类声明:
class SurfaceFlinger :
public BinderService<SurfaceFlinger>,
public BnSurfaceComposer,
protected Thread
从接口可以看出使用Binder与客户端通讯,并且继承线程 Thread 类,则循环执行threadLoop。完成系统中的各个Layer-Surface进行混合,然后将一帧帧混合好的图像传送到显示framebuffer中。
其主线程工作流程图如下:
下面就这以上图五步将代码一一过一遍:
1、waitForEvent() 等待什么事情呢?
void SurfaceFlinger::waitForEvent()
{
while (true) {
......
sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
......
if (msg != 0) {
switch (msg->what) {
//等的就是这个消息事件哟。。。。
case MessageQueue::INVALIDATE:
// invalidate message, just return to the main loop
return;
}
}
}
}
原来是等待收到MessageQueue::INVALIDATE重绘消息才退回到主线程,那么这个消息由谁来发送呢?
请看下面代码:
void SurfaceFlinger::signalEvent() {
mEventQueue.invalidate();
}
void SurfaceFlinger::signal() const {
// this is the IPC call
const_cast<SurfaceFlinger*>(this)->signalEvent();
}
这是就是发送消息的点,这个函数signalEvent由谁来调用呢?其个这个发起都是上一节说的,在释放Surface对应的显示缓冲区需要显示时调用:
unlockAndPost() --> queueBuffer() --> mClient.signalServer() --> SurfaceFlinger::signal()
2、handlePageFlip()
该阶段会遍历各个Layer,在每个Layer中,取得并锁住该Layer的frontBuffer,然后利用frontBuffer 中的图像数据生成该Layer的2D贴图(Texture),并且计算更新区域,为后续的混合操作做准备。
void SurfaceFlinger::handlePageFlip()
{
//调用 lockPageFlip
visibleRegions |= lockPageFlip(currentLayers);
//取得屏幕的区域
const Region screenRegion(hw.bounds());
if (visibleRegions) {
Region opaqueRegion;
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
.....
mWormholeRegion = screenRegion.subtract(opaqueRegion);
}
.....
//调用 unlockPageFlip
unlockPageFlip(currentLayers);
}
上面的调用实际上是一对函数:lockPageFlip & lockPageFlip,那么主要干些啥呢?
bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
{
bool recomputeVisibleRegions = false;
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
//逐个 layer 进行处理
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
layer->lockPageFlip(recomputeVisibleRegions);
}
return recomputeVisibleRegions;
}
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
SharedBufferServer* lcblk(sharedClient.get());
// 获取当前可用的 frontbuffer 索引号
ssize_t buf = lcblk->retireAndLock();
// 计算当前的脏区域
sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
if (newFrontBuffer != NULL) {
// get the dirty region
// compute the posted region
const Region dirty(lcblk->getDirtyRegion(buf));
mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
....
// 如果有脏区域需要重绘,则生成 OpenGL ES 纹理贴图
reloadTexture( mPostedDirtyRegion );
}
void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
{
const GraphicPlane& plane(graphicPlane(0));
const Transform& planeTransform(plane.transform());
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
//进行区域的清理工作
layer->unlockPageFlip(planeTransform, mDirtyRegion);
}
}
void Layer::unlockPageFlip(
const Transform& planeTransform, Region& outDirtyRegion)
{
Region dirtyRegion(mPostedDirtyRegion);
if (!dirtyRegion.isEmpty()) {
mPostedDirtyRegion.clear();
....
if (visibleRegionScreen.isEmpty()) {
// an invisible layer should not hold a freeze-lock
// (because it may never be updated and therefore never release it)
mFreezeLock.clear();
}
}
以上的工作就是按照 Zorder 序计算自已屏幕上的可显示区域:
1、以自己的W,H给出自己初始的可见区域
2、减去自己上面窗口所覆盖的区域
3、handleRepaint
每个Layer的数据都准备好了,并且各个脏区域也计算ok,下步就是根据 Zorder 序从底部将数据绘制到主Surface上
void SurfaceFlinger::handleRepaint()
{
// compute the invalid region
mInvalidRegion.orSelf(mDirtyRegion);
....
// compose all surfaces
composeSurfaces(mDirtyRegion);
// clear the dirty regions
mDirtyRegion.clear();
}
void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
...
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
// 这就是绘图核心函数
layer->draw(clip);
}
}
}
void Layer::onDraw(const Region& clip) const
---> drawWithOpenGL(clip, tex); 基本上都是OpenGL ES 操作函数
while (it != end) {
const Rect& r = *it++;
const GLint sy = fbHeight - (r.top + r.height());
// 裁剪
glScissor(r.left, sy, r.width(), r.height());
// 画矩形
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
4、unlockClients()
释放 handlePageFlip 占用的 frontbuffer 索引号,以便客户端可以继续在新的surface画图
void SurfaceFlinger::unlockClients()
{
...
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer = layers[i];
layer->finishPageFlip();
}
}
-->
SharedBufferServer* lcblk(sharedClient.get());
status_t err = lcblk->unlock( buf );
5、postFramebuffer()
现在已经将所有的Layer图层数据合成完成,最后就是输入到屏幕上显示了
void SurfaceFlinger::postFramebuffer()
{
//调用此函数将混合后的图像传递到屏幕中进行显示
hw.flip(mInvalidRegion);
...
}
void DisplayHardware::flip(const Region& dirty) const
{
// 显示图像吧。。。。。
eglSwapBuffers(dpy, surface);
代码路径:./services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger 属于system_server进程,在system_init.cpp中利用SurfaceFlinger::instantiate()启动,在此加入到service manager中,所以本身提供service服务功能。
首先看下SurfaceFlinger的类声明:
class SurfaceFlinger :
public BinderService<SurfaceFlinger>,
public BnSurfaceComposer,
protected Thread
从接口可以看出使用Binder与客户端通讯,并且继承线程 Thread 类,则循环执行threadLoop。完成系统中的各个Layer-Surface进行混合,然后将一帧帧混合好的图像传送到显示framebuffer中。
其主线程工作流程图如下:
下面就这以上图五步将代码一一过一遍:
1、waitForEvent() 等待什么事情呢?
void SurfaceFlinger::waitForEvent()
{
while (true) {
......
sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
......
if (msg != 0) {
switch (msg->what) {
//等的就是这个消息事件哟。。。。
case MessageQueue::INVALIDATE:
// invalidate message, just return to the main loop
return;
}
}
}
}
原来是等待收到MessageQueue::INVALIDATE重绘消息才退回到主线程,那么这个消息由谁来发送呢?
请看下面代码:
void SurfaceFlinger::signalEvent() {
mEventQueue.invalidate();
}
void SurfaceFlinger::signal() const {
// this is the IPC call
const_cast<SurfaceFlinger*>(this)->signalEvent();
}
这是就是发送消息的点,这个函数signalEvent由谁来调用呢?其个这个发起都是上一节说的,在释放Surface对应的显示缓冲区需要显示时调用:
unlockAndPost() --> queueBuffer() --> mClient.signalServer() --> SurfaceFlinger::signal()
2、handlePageFlip()
该阶段会遍历各个Layer,在每个Layer中,取得并锁住该Layer的frontBuffer,然后利用frontBuffer 中的图像数据生成该Layer的2D贴图(Texture),并且计算更新区域,为后续的混合操作做准备。
void SurfaceFlinger::handlePageFlip()
{
//调用 lockPageFlip
visibleRegions |= lockPageFlip(currentLayers);
//取得屏幕的区域
const Region screenRegion(hw.bounds());
if (visibleRegions) {
Region opaqueRegion;
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
.....
mWormholeRegion = screenRegion.subtract(opaqueRegion);
}
.....
//调用 unlockPageFlip
unlockPageFlip(currentLayers);
}
上面的调用实际上是一对函数:lockPageFlip & lockPageFlip,那么主要干些啥呢?
bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
{
bool recomputeVisibleRegions = false;
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
//逐个 layer 进行处理
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
layer->lockPageFlip(recomputeVisibleRegions);
}
return recomputeVisibleRegions;
}
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
SharedBufferServer* lcblk(sharedClient.get());
// 获取当前可用的 frontbuffer 索引号
ssize_t buf = lcblk->retireAndLock();
// 计算当前的脏区域
sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
if (newFrontBuffer != NULL) {
// get the dirty region
// compute the posted region
const Region dirty(lcblk->getDirtyRegion(buf));
mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
....
// 如果有脏区域需要重绘,则生成 OpenGL ES 纹理贴图
reloadTexture( mPostedDirtyRegion );
}
void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
{
const GraphicPlane& plane(graphicPlane(0));
const Transform& planeTransform(plane.transform());
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
//进行区域的清理工作
layer->unlockPageFlip(planeTransform, mDirtyRegion);
}
}
void Layer::unlockPageFlip(
const Transform& planeTransform, Region& outDirtyRegion)
{
Region dirtyRegion(mPostedDirtyRegion);
if (!dirtyRegion.isEmpty()) {
mPostedDirtyRegion.clear();
....
if (visibleRegionScreen.isEmpty()) {
// an invisible layer should not hold a freeze-lock
// (because it may never be updated and therefore never release it)
mFreezeLock.clear();
}
}
以上的工作就是按照 Zorder 序计算自已屏幕上的可显示区域:
1、以自己的W,H给出自己初始的可见区域
2、减去自己上面窗口所覆盖的区域
3、handleRepaint
每个Layer的数据都准备好了,并且各个脏区域也计算ok,下步就是根据 Zorder 序从底部将数据绘制到主Surface上
void SurfaceFlinger::handleRepaint()
{
// compute the invalid region
mInvalidRegion.orSelf(mDirtyRegion);
....
// compose all surfaces
composeSurfaces(mDirtyRegion);
// clear the dirty regions
mDirtyRegion.clear();
}
void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
...
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
// 这就是绘图核心函数
layer->draw(clip);
}
}
}
void Layer::onDraw(const Region& clip) const
---> drawWithOpenGL(clip, tex); 基本上都是OpenGL ES 操作函数
while (it != end) {
const Rect& r = *it++;
const GLint sy = fbHeight - (r.top + r.height());
// 裁剪
glScissor(r.left, sy, r.width(), r.height());
// 画矩形
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
4、unlockClients()
释放 handlePageFlip 占用的 frontbuffer 索引号,以便客户端可以继续在新的surface画图
void SurfaceFlinger::unlockClients()
{
...
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer = layers[i];
layer->finishPageFlip();
}
}
-->
SharedBufferServer* lcblk(sharedClient.get());
status_t err = lcblk->unlock( buf );
5、postFramebuffer()
现在已经将所有的Layer图层数据合成完成,最后就是输入到屏幕上显示了
void SurfaceFlinger::postFramebuffer()
{
//调用此函数将混合后的图像传递到屏幕中进行显示
hw.flip(mInvalidRegion);
...
}
void DisplayHardware::flip(const Region& dirty) const
{
// 显示图像吧。。。。。
eglSwapBuffers(dpy, surface);
}
最后
以上就是高大便当为你收集整理的SurfaceFlinger整合layer的过程的全部内容,希望文章能够帮你解决SurfaceFlinger整合layer的过程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复