Surface在C++层的创建源码解析
Surface在C++层的创建源码解析
源码为:android4.4.4
1、创建SurfaceComposerClient绘图客户端
// create a client to surfaceflinger sp<SurfaceComposerClient> client = new SurfaceComposerClient(); //创建SurfaceFlinger的本地代理 |
展开SurfaceComposerClient源码:frameworks\native\libs\gui\SurfaceComposerClient.cpp
SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT), mComposer(Composer::getInstance()) // Composer::getInstance() 应该是一个单例模式 { } |
mStatus: 为status_t类型变量 , mComposer:为Composer&的引用
Composer类为SurfaceComposerClient类的友元类。
Composer::getInstance()获取一个Composer对象赋值给mComposer。
现在client对象的两个变量mStatus和mComposer都有值了。
2、通过client对象获取屏幕信息
DisplayInfo display; //获取屏幕的宽高等信息 client->getDisplayInfo(client->getBuiltInDisplay(HWC_DISPLAY_PRIMARY), &display); |
将获取到的屏幕信息存放发哦display这个结构体里。
看看client->getBuiltInDisplay(HWC_DISPLAY_PRIMARY)这个是什么意思。
sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) { return Composer::getInstance().getBuiltInDisplay(id); } //调用Composer的getBuiltInDisplay方法 |
sp<IBinder> Composer::getBuiltInDisplay(int32_t id) { return ComposerService::getComposerService()->getBuiltInDisplay(id); }//再次调用ComposerService对象的getBuiltInDisplay方法 |
client-> getBuiltInDisplay最终获取到一个Ibinder对象
再看看client->getDisplayInfo这个方法
status_t SurfaceComposerClient::getDisplayInfo( const sp<IBinder>& display, DisplayInfo* info) { return ComposerService::getComposerService()->getDisplayInfo(display, info); } |
根据HWC_DISPLAY_PRIMARY获取Ibinder对象,根据Binder对象获取ComposerSeveice对象调用取得屏幕信息。
3、根据SurfaceComposerClient对象创建SurfafeControl对象
//创建SurfaceControl的本地代理 sp<SurfaceControl> surfaceControl = client->createSurface(String8("testsurface"), display.w, display.h, PIXEL_FORMAT_RGBA_8888, 0); |
看看createSurface源码
sp<SurfaceControl> SurfaceComposerClient::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp<SurfaceControl> sur; if (mStatus == NO_ERROR) { sp<IBinder> handle; sp<IGraphicBufferProducer> gbp; status_t err = mClient->createSurface(name, w, h, format, flags, &handle, &gbp); //通知服务端申请surface ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { sur = new SurfaceControl(this, handle, gbp); //如果申请成功就创建 } } return sur; } |
mClient是什么东西:sp<ISurfaceComposerClient> mClient; IsurfaceComposerClient是Binder的一个接口类。
先申请surface申请成功就创建一个surfaceControl的本地代理。
4、设置surface的图层Z轴
SurfaceComposerClient::openGlobalTransaction(); surfaceControl->setLayer(120000); //设置z轴 surfaceControl->setSize(display.w, display.h); surfaceControl->setPosition(0, 0); //起始位置 SurfaceComposerClient::closeGlobalTransaction(); //默认false |
SurfaceComposerClient::openGlobalTransaction() 源码展开后:
void SurfaceComposerClient::openGlobalTransaction() { Composer::openGlobalTransaction(); } |
static void openGlobalTransaction() { Composer::getInstance().openGlobalTransactionImpl(); } |
void Composer::openGlobalTransactionImpl() { { // scope for the lock Mutex::Autolock _l(mLock); mTransactionNestCount += 1; //最终是给这个变量加1 } } |
看看surfaceControl->setLayer(120000)设置z轴展开:
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_state_t* Composer::getLayerStateLocked( const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) { ComposerState s; s.client = client->mClient; s.state.surface = id; //将设置的Z轴坐标存在ComposerState对象里 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对象存放到链表中 } ComposerState* const out = mComposerStates.editArray(); return &(out[index].state); } |
以上就是设置Z轴方法,调用Composer对象getLayerStateLocked进行加锁,创建一个ComposerState对象,将传递进来的值存进行检查,检查是否存在,如果不存在就直接储到mComposerStates链表中。
SurfaceComposerClient::closeGlobalTransaction()展开:
void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) { Composer::closeGlobalTransaction(synchronous); } |
static void closeGlobalTransaction(bool synchronous) { Composer::getInstance().closeGlobalTransactionImpl(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; } mForceSynchronous = false; mAnimation = false; } sm->setTransactionState(transaction, displayTransaction, flags); } |
5、获取surface
// 获取Surface本地代理 sp<Surface> surface = surfaceControl->getSurface();//获取surface |
sp<Surface> SurfaceControl::getSurface() const { Mutex::Autolock _l(mLock); if (mSurfaceData == 0) { // This surface is always consumed by SurfaceFlinger, so the // producerControlledByApp value doesn't matter; using false. mSurfaceData = new Surface(mGraphicBufferProducer, false); } return mSurfaceData; } |
直接new一个suface对象返回
6、surface->lock() 和surface->unlockAndPost();
Lock从屏幕缓冲队列中申请屏幕,再使用unlockAndpost将申请的屏幕加入到缓冲队列中交给surfaceflinger进行组合并显示在屏幕上。其实这才是绘图显示最重要的阶段,绘图显示快慢和这里优化有直接关系。
Surface在C++层的创建源码解析的更多相关文章
- Cocos2d-X3.0 刨根问底(八)----- 场景(Scene)、层(Layer)相关源码分析
本章节我们重点分析Cocos2d-x3.0与 场景.层相关的源码.这部分源码集中在 libcocos2d –> layers_scenes_transitions_nodes目录下面 我先发个截 ...
- Mybatis源码解析,一步一步从浅入深(一):创建准备工程
Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...
- Mybaits 源码解析 (四)----- SqlSession的创建过程(看懂框架源码再也不用死记硬背面试题)
SqlSession是mybatis的核心接口之一,是myabtis接口层的主要组成部分,对外提供了mybatis常用的api.myabtis提供了两个SqlSesion接口的实现,常用的实现类是De ...
- Spring IoC源码解析——Bean的创建和初始化
Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...
- Fresco源码解析 - 创建一个ImagePipeline(一)
在Fresco源码解析 - 初始化过程分析章节中, 我们分析了Fresco的初始化过程,两个initialize方法中都用到了 ImagePipelineFactory类. ImagePipeline ...
- QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数
QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...
- QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)
前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...
- dubbo源码解析-zookeeper创建节点
前言 在之前dubbo源码解析-本地暴露中的前言部分提到了两道高频的面试题,其中一道dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,那发布者和订阅者还能通信吗?在上周的dubbo源码 ...
- [Java多线程]-线程池的基本使用和部分源码解析(创建,执行原理)
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 多线 ...
随机推荐
- iOS-推送,证书申请,本地推送
介绍一点点背景资料 众所周知,使用推送通知是一个很棒的.给应用添加实时消息通知的方式.这样做的结局是,开发者和用户之间,彼此永远保持着一种令人愉悦的亲密关系. 然而不幸的是,iOS的推送通知并非那么容 ...
- nodejs处理url工具
url模块提供3个方法:parse,format,resolve 1.parse 要先引入url模块 >url.parse('http://www.cnblogs.com/cate/108703 ...
- 解析大型.NET ERP系统数据访问 对象关系映射框架LLBL Gen Pro
LLBL Gen Pro是一个为.NET开发人员设计的的对象关系映射(ORM)框架,与NHibernate,Entity Framework等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...
- NodeJs+http+fs+request+cheerio 采集,保存数据,并在网页上展示(构建web服务器)
目的: 数据采集 写入本地文件备份 构建web服务器 将文件读取到网页中进行展示 目录结构: package.json文件中的内容与上一篇一样:NodeJs+Request+Cheerio 采集数据 ...
- JavaScript高级程序设计--对象,数组(栈方法,队列方法,重排序方法,迭代方法)
1.使用对象字面量定义对象 var person={}; 使用这种方式创建对象时,实际上不会调用Object构造函数. 开发人员更喜欢对象字面量的语法. 2.有时候需要传递大量可选参数的情形时,一 ...
- $(document).ready() 与window.onload的区别
1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 ...
- Python模拟登陆新浪微博
上篇介绍了新浪微博的登陆过程,这节使用Python编写一个模拟登陆的程序.讲解与程序如下: 1.主函数(WeiboMain.py): import urllib2 import cookielib i ...
- jvm系列(六):jvm调优-从eclipse开始
jvm调优-从eclipse开始 概述 什么是jvm调优呢?jvm调优就是根据gc日志分析jvm内存分配.回收的情况来调整各区域内存比例或者gc回收的策略:更深一层就是根据dump出来的内存结构和线程 ...
- 读书笔记--SQL必知必会06--用通配符进行过滤
6.1 LIKE操作符 通配符(wildcard),用来匹配某些值的的特殊字符. 在搜索子句中必须通过LIKE操作符使用通配符. 通配符搜索只能用于文本字段(字符串),非文本数据类型字段不能使用通配符 ...
- nodejs中使用http请求返回值为html时乱码问题
今天用nodejs进行http请求时返回的数据是一个html文件,然后我还是按照以前解析json数据的方法.果不其然报错了:SyntaxError: Unexpected token in JSON ...