surfaceflinger中各个layer的排序
surfaceflinger的主要工作就是负责把上层传递下来的各个不同的layer进行composition。
这里,我们来讨论一下各个layer在surfaceflinger中的上下排序关系和相关的代码实现,代码基于android4.3
首先介绍一下两个类,SurfaceFlinger和Client。
简单的说,这两个类的关系可以这么理解:SurfaceFlinger实现了具体的composition的服务,而每一个有UI的程序都需要通过SurfaceFlinger去实现渲染。
这些程序可以通过Client的一些接口来调用SurfaceFlinger以实现这个目的。
Client类中有一个createSurface成员函数
- status_t Client::createSurface(
- const String8& name,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp)
- {
- /*
- * createSurface must be called from the GL thread so that it can
- * have access to the GL context.
- */
- class MessageCreateLayer : public MessageBase {
- SurfaceFlinger* flinger;
- Client* client;
- sp<IBinder>* handle;
- sp<IGraphicBufferProducer>* gbp;
- status_t result;
- const String8& name;
- uint32_t w, h;
- PixelFormat format;
- uint32_t flags;
- public:
- MessageCreateLayer(SurfaceFlinger* flinger,
- const String8& name, Client* client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp)
- : flinger(flinger), client(client),
- handle(handle), gbp(gbp),
- name(name), w(w), h(h), format(format), flags(flags) {
- }
- status_t getResult() const { return result; }
- virtual bool handler() {
- result = flinger->createLayer(name, client, w, h, format, flags,
- handle, gbp);
- return true;
- }
- };
- sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
- name, this, w, h, format, flags, handle, gbp);
- mFlinger->postMessageSync(msg);
- return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
- }
createLayer函数是SurfaceFlinger类的私有函数,但是因为Client是他的友元,所以可以直接调用来创建一个layer。
- private:
- friend class Client;
- friend class DisplayEventConnection;
- friend class Layer;
- friend class SurfaceTextureLayer;
看下createLayer的代码
- status_t SurfaceFlinger::createLayer(
- const String8& name,
- const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
- {
- //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
- if (int32_t(w|h) < 0) {
- ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
- int(w), int(h));
- return BAD_VALUE;
- }
- status_t result = NO_ERROR;
- sp<Layer> layer;
- switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
- case ISurfaceComposerClient::eFXSurfaceNormal:
- result = createNormalLayer(client,
- name, w, h, flags, format,
- handle, gbp, &layer);
- break;
- case ISurfaceComposerClient::eFXSurfaceDim:
- result = createDimLayer(client,
- name, w, h, flags,
- handle, gbp, &layer);
- break;
- default:
- result = BAD_VALUE;
- break;
- }
- if (result == NO_ERROR) {
- addClientLayer(client, *handle, *gbp, layer);
- setTransactionFlags(eTransactionNeeded);
- }
- return result;
- }
这个函数很清晰,主要是调用createNormalLayer和createDimLayer去创建不同的layer。
我们先忽略createDimLayer,只看createNormalLayer的实现
- status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
- {
- // initialize the surfaces
- switch (format) {
- case PIXEL_FORMAT_TRANSPARENT:
- case PIXEL_FORMAT_TRANSLUCENT:
- format = PIXEL_FORMAT_RGBA_8888;
- break;
- case PIXEL_FORMAT_OPAQUE:
- #ifdef NO_RGBX_8888
- format = PIXEL_FORMAT_RGB_565;
- #else
- format = PIXEL_FORMAT_RGBX_8888;
- #endif
- break;
- }
- #ifdef NO_RGBX_8888
- if (format == PIXEL_FORMAT_RGBX_8888)
- format = PIXEL_FORMAT_RGBA_8888;
- #endif
- *outLayer = new Layer(this, client, name, w, h, flags);
- status_t err = (*outLayer)->setBuffers(w, h, format, flags);
- if (err == NO_ERROR) {
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getBufferQueue();
- }
- ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
- return err;
- }
这里主要是创建了一个Layer对象。
- Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags)
- : contentDirty(false),
- sequence(uint32_t(android_atomic_inc(&sSequence))),
- mFlinger(flinger),
- mTextureName(-1U),
- mPremultipliedAlpha(true),
- mName("unnamed"),
- mDebug(false),
- mFormat(PIXEL_FORMAT_NONE),
- mGLExtensions(GLExtensions::getInstance()),
- mOpaqueLayer(true),
- mTransactionFlags(0),
- mQueuedFrames(0),
- mCurrentTransform(0),
- mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mCurrentOpacity(true),
- mRefreshPending(false),
- mFrameLatencyNeeded(false),
- mFiltering(false),
- mNeedsFiltering(false),
- mSecure(false),
- mProtectedByApp(false),
- mHasSurface(false),
- mClientRef(client)
- {
- mCurrentCrop.makeInvalid();
- glGenTextures(1, &mTextureName);
- uint32_t layerFlags = 0;
- if (flags & ISurfaceComposerClient::eHidden)
- layerFlags = layer_state_t::eLayerHidden;
- if (flags & ISurfaceComposerClient::eNonPremultiplied)
- mPremultipliedAlpha = false;
- mName = name;
- mCurrentState.active.w = w;
- mCurrentState.active.h = h;
- mCurrentState.active.crop.makeInvalid();
- mCurrentState.z = 0;
- mCurrentState.alpha = 0xFF;
- mCurrentState.layerStack = 0;
- mCurrentState.flags = layerFlags;
- mCurrentState.sequence = 0;
- mCurrentState.transform.set(0, 0);
- mCurrentState.requested = mCurrentState.active;
- // drawing state & current state are identical
- mDrawingState = mCurrentState;
- }
这里我们主要关注和layer顺序相关的信息
- sequence(uint32_t(android_atomic_inc(&sSequence))),
- mCurrentState.z = 0;
- mCurrentState.layerStack = 0;
这三个变量决定了layer之间的顺序,我来说明一下具体的含义。
首先是layerStack,大家可以把它理解为组的含义。也就是说属于不同组的layer之间互不干扰。
SurfaceFlinger中有一个DisplayDevice类,他表示用来显示的设备,譬如LCD或者是HDMI。
DisplayDevice里也有一个成员变量mLayerStack,在进行composition的时候,只有和这个device的layerstack相同的layer才可能被显示在这个设备上。
第二个是z,其实他就是z-order的意思,表示x,y,z轴的z轴上的顺序。数字越大,表示越在上面,数字越小,表示越在下面。
第三个是sequence,因为sSequence是一个static的变量,所以递加的效果就是为每一个layer设置一个唯一且递增的序列号。
概念介绍完了,我们继续看代码,看看到底是不是这样。
创建完layer之后,createLayer会调用addClientLayer把这个layer的信息添加到当前的状态信息里去。
- void SurfaceFlinger::addClientLayer(const sp<Client>& client,
- const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbc,
- const sp<Layer>& lbc)
- {
- // attach this layer to the client
- client->attachLayer(handle, lbc);
- // add this layer to the current state list
- Mutex::Autolock _l(mStateLock);
- mCurrentState.layersSortedByZ.add(lbc);
- mGraphicBufferProducerList.add(gbc->asBinder());
- }
layersSortedByZ变量很重要,surfaceflinger真正渲染的时候就是靠它来知道哪个layer在上哪个在下的。
这里的add函数就负责把layer放进去
- ssize_t SortedVectorImpl::add(const void* item)
- {
- size_t order;
- ssize_t index = _indexOrderOf(item, &order);
- if (index < 0) {
- index = VectorImpl::insertAt(item, order, 1);
- } else {
- index = VectorImpl::replaceAt(item, index);
- }
- return index;
- }
- ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
- {
- // binary search
- ssize_t err = NAME_NOT_FOUND;
- ssize_t l = 0;
- ssize_t h = size()-1;
- ssize_t mid;
- const void* a = arrayImpl();
- const size_t s = itemSize();
- while (l <= h) {
- mid = l + (h - l)/2;
- const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
- const int c = do_compare(curr, item);
- if (c == 0) {
- err = l = mid;
- break;
- } else if (c < 0) {
- l = mid + 1;
- } else {
- h = mid - 1;
- }
- }
- if (order) *order = l;
- return err;
- }
- int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
- const void* rhs) const
- {
- // sort layers per layer-stack, then by z-order and finally by sequence
- const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs));
- const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs));
- uint32_t ls = l->currentState().layerStack;
- uint32_t rs = r->currentState().layerStack;
- if (ls != rs)
- return ls - rs;
- uint32_t lz = l->currentState().z;
- uint32_t rz = r->currentState().z;
- if (lz != rz)
- return lz - rz;
- return l->sequence - r->sequence;
- }
连着贴了3个函数,其主要作用就是判断这个layer要插在layersSortedByZ的什么位置。
从do_compare我们可以看出,和我刚才分析的是一样的。
第一步是比较layerstack,不同的layerstack分开。
然后再比较z,最后假设这些都一样,就比较唯一的layer序列号。
但是至今为止,layerStack和z都还只是初始化时的0,所以在创建layer的时候,只是把他根据序列号放进layersSortedByZ而已,其实他的顺序还是没有设置的。
下面我们就要去找找看到底在哪里设置了这些。
大家应该都知道bootanimation吧,就是开机负责绘制闪啊闪的android字样的那个程序。
在里面我找到了这样的代码
- // create the native surface
- sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
- dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
- SurfaceComposerClient::openGlobalTransaction();
- control->setLayer(0x40000000);
- SurfaceComposerClient::closeGlobalTransaction();
前面的createSurface我们在前面已经分析完成了。
下面就是setLayer了,这个0x40000000到底是设置了什么那?
我们一步步往下看
- status_t SurfaceControl::setLayer(int32_t layer) {
- status_t err = validate();
- if (err < 0) return err;
- const sp<SurfaceComposerClient>& client(mClient);
- return client->setLayer(mHandle, layer);
- }
- status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
- return getComposer().setLayer(this, id, z);
- }
- status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t z) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
- s->what |= layer_state_t::eLayerChanged;
- s->z = z;
- return NO_ERROR;
- }
可以看到,这个layer变量最终变成了z,存进了layer_state_t结构体内。
这个结构体是哪来的?在看看getLayerStateLocked
- layer_state_t* Composer::getLayerStateLocked(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) {
- ComposerState s;
- s.client = client->mClient;
- s.state.surface = id;
- ssize_t index = mComposerStates.indexOf(s);
- if (index < 0) {
- // we don't have it, add an initialized layer_state to our list
- index = mComposerStates.add(s);
- }
- ComposerState* const out = mComposerStates.editArray();
- return &(out[index].state);
- }
原来是从mComposerStates里找来的啊。
这些代码看上去是在做相关的操作,但是设置还没有具体生效。
下面我们看看SurfaceComposerClient::closeGlobalTransaction()的作用
- void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
- Composer::closeGlobalTransaction(synchronous);
- }
- void Composer::closeGlobalTransactionImpl(bool synchronous) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- Vector<ComposerState> transaction;
- Vector<DisplayState> displayTransaction;
- uint32_t flags = 0;
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- mForceSynchronous |= synchronous;
- if (!mTransactionNestCount) {
- ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
- "call to openGlobalTransaction().");
- } else if (--mTransactionNestCount) {
- return;
- }
- transaction = mComposerStates;
- mComposerStates.clear();
- displayTransaction = mDisplayStates;
- mDisplayStates.clear();
- if (mForceSynchronous) {
- flags |= ISurfaceComposer::eSynchronous;
- }
- if (mAnimation) {
- flags |= ISurfaceComposer::eAnimation;
- }
- if (mTransition) {
- flags |= ISurfaceComposer::eTransition;
- }
- if (mOrientationEnd) {
- flags |= ISurfaceComposer::eOrientationEnd;
- }
- mForceSynchronous = false;
- mAnimation = false;
- }
- sm->setTransactionState(transaction, displayTransaction, flags);
- }
mComposerStates被赋值给transaction,然后通过sm->setTransactionState传递下去。
- void SurfaceFlinger::setTransactionState(
- const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays,
- uint32_t flags)
- {
- ......
- count = state.size();
- for (size_t i=0 ; i<count ; i++) {
- const ComposerState& s(state[i]);
- // Here we need to check that the interface we're given is indeed
- // one of our own. A malicious client could give us a NULL
- // IInterface, or one of its own or even one of our own but a
- // different type. All these situations would cause us to crash.
- //
- // NOTE: it would be better to use RTTI as we could directly check
- // that we have a Client*. however, RTTI is disabled in Android.
- if (s.client != NULL) {
- sp<IBinder> binder = s.client->asBinder();
- if (binder != NULL) {
- String16 desc(binder->getInterfaceDescriptor());
- if (desc == ISurfaceComposerClient::descriptor) {
- sp<Client> client( static_cast<Client *>(s.client.get()) );
- transactionFlags |= setClientStateLocked(client, s.state);
- }
- }
- }
- }
- ......
- }
- uint32_t SurfaceFlinger::setClientStateLocked(
- const sp<Client>& client,
- const layer_state_t& s)
- {
- uint32_t flags = 0;
- sp<Layer> layer(client->getLayerUser(s.surface));
- if (layer != 0) {
- const uint32_t what = s.what;
- if (what & layer_state_t::ePositionChanged) {
- if (layer->setPosition(s.x, s.y))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eLayerChanged) {
- // NOTE: index needs to be calculated before we update the state
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayer(s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- ......
- }
- }
- bool Layer::setLayer(uint32_t z) {
- if (mCurrentState.z == z)
- return false;
- mCurrentState.sequence++;
- mCurrentState.z = z;
- setTransactionFlags(eTransactionNeeded);
- return true;
- }
可以看到,只要设置的z值和之前的不同,setLayer就会返回true。
然后mCurrentState.layersSortedByZ.removeAt和mCurrentState.layersSortedByZ.add就会被执行。
至此,layer的真正z-order就确定好了。
surfaceflinger中各个layer的排序的更多相关文章
- 回调函数及数组中sort()方法实现排序的原理
1.回调函数:把一个方法A当一个参数值传递到另外一个函数B中,在B执行的过程当中我们随时根据需求让A方法执行: 什么是回调 :它是异步编程基本的方法,需要异步处理的时候一般采用后续传递的方式,将后 ...
- 【HOW】如何对Reporting Services表格中数据按字段排序
Reporting Services中可以设置排序的地方非常多,有很多地方从其字面意思上好像是对表格数据的排序,但实际都不管用.在多次尝试后,得到如下的有效设置方式: 1. 鼠标右键单击要排序字段的内 ...
- Atitit.现实生活中最好使用的排序方法-----ati排序法总结
Atitit.现实生活中最好使用的排序方法-----ati排序法总结 1. 现在的问题 1 2. 排序的类别::插入排序//交换排序//选择排序(每次最小/大排在相应的位置 )//归并排序//基数排 ...
- 2dx解析cocosbuilder中使用layer时的缺陷
2dx解析cocosbuilder中使用layer时的缺陷 cocos2d-x 3.7 cocosbuilder中的layer通常会用到触摸属性: 但是在2dx解析布局文件的时候,却很多属性都没解析: ...
- OpenLayers中的Layer概念和实践--Openlayers调用WMS服务
整理转自:http://hi.baidu.com/lixuweiok/item/c406a4e6a6d390e7fa42ba4b 本章我认为是这本书的真正开端,终于开始讲一些有意思的东西了.. 在这一 ...
- [原]Java面试题-将字符串中数字提取出来排序后输出
[Title][原]Java面试题-将字符串中数字提取出来排序后输出 [Date]2013-09-15 [Abstract]很简单的面试题,要求现场在纸上写出来. [Keywords]面试.Java. ...
- 对list集合中的对象进行排序(转载)
原文链接:http://blog.csdn.net/veryisjava/article/details/51675036 Collections对List集合中的数据进行排序 有时候需要对集合中的元 ...
- java 对list中对象按属性排序
实体对象类 --略 排序类----实现Comparator接口,重写compare方法 package com.tang.list; import java.util.Comparator; publ ...
- C++ STL中Map的相关排序操作:按Key排序和按Value排序 - 编程小径 - 博客频道 - CSDN.NET
C++ STL中Map的相关排序操作:按Key排序和按Value排序 - 编程小径 - 博客频道 - CSDN.NET C++ STL中Map的相关排序操作:按Key排序和按Value排序 分类: C ...
随机推荐
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
- HTTP协议的请求和响应学习
本篇作为学习servlet的前提,http协议是学习JavaWeb开发的基石,不深入了解http协议,就不能说掌握了JavaWeb开发. HTTP协议有两个版本:HTTP1.0和HTTP1.1,那么有 ...
- Oracle左连接、右连接示例
建表: create table a ( id ), name ) ); create table b ( name ), age ) ); create table c ( name ), dept ...
- J2EE SSH学习(二)安装Eclipse插件和第一个Eclipse项目
(一)安装Eclipse插件 Eclipse有很多功能很强大的插件,我现在作为一个菜鸟只知道插件的功能通常都很牛叉实用或者很有趣,那么该怎么安装Eclipse插件呢? 我使用的是Eclipse 4.3 ...
- 华为OJ培训主题 比赛统计
题目例如以下: 比赛情况统计 有一个游戏平台,各个參赛队伍(以唯一的TeamID来标识)之间进行单循环的对抗赛,两个队伍之间仅仅举行一场比赛,比赛以得分的多少定胜负.须要完毕一个统计赛况的程序,可以随 ...
- Tomcat详细用法学习(一)
在之前有关Tomcat的随笔<Tomcat免安装版的环境变量配置以及Eclipse下的Tomcat配置和测试>和<其他主机连接本地主机Tomcat会出现的防火墙问题>中已经详细 ...
- csdn发博文验证码缺陷
csdn验证码的长处: 一,差点儿没有浪费人脑人力,却要花去机器人非常多cpu csdn发博文验证码却有非常大缺陷: 一.验证码的内容终于结果是简单的数字,能够穷举尽的,也就是说不怕被封号的话全然能够 ...
- UVA 11054 Wine trading in Gergovia 葡萄酒交易 贪心+模拟
题意:一题街道上很多酒店,交易葡萄酒,正数为卖出葡萄酒,负数为需要葡萄酒,总需求量和总售出量是相等的,从一家店到另外一家店需要路费(路费=距离×运算量),假设每家店线性排列且相邻两店之间距离都是1,求 ...
- iOS高效开源类库
因为iOS SDK相对比较底层,所以开发者就得受累多做一些体力活.不过幸运的是,有很多第三方的类库可以用来简化很多不必要的工作.笔者整理了一下在本人学习过程中用到的一些比较有用Objective-C开 ...
- ZOJ 3529 A Game Between Alice and Bob(博弈论-sg函数)
ZOJ 3529 - A Game Between Alice and Bob Time Limit:5000MS Memory Limit:262144KB 64bit IO For ...