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++层的创建源码解析的更多相关文章

  1. Cocos2d-X3.0 刨根问底(八)----- 场景(Scene)、层(Layer)相关源码分析

    本章节我们重点分析Cocos2d-x3.0与 场景.层相关的源码.这部分源码集中在 libcocos2d –> layers_scenes_transitions_nodes目录下面 我先发个截 ...

  2. Mybatis源码解析,一步一步从浅入深(一):创建准备工程

    Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...

  3. Mybaits 源码解析 (四)----- SqlSession的创建过程(看懂框架源码再也不用死记硬背面试题)

    SqlSession是mybatis的核心接口之一,是myabtis接口层的主要组成部分,对外提供了mybatis常用的api.myabtis提供了两个SqlSesion接口的实现,常用的实现类是De ...

  4. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  5. Fresco源码解析 - 创建一个ImagePipeline(一)

    在Fresco源码解析 - 初始化过程分析章节中, 我们分析了Fresco的初始化过程,两个initialize方法中都用到了 ImagePipelineFactory类. ImagePipeline ...

  6. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...

  7. QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)

    前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...

  8. dubbo源码解析-zookeeper创建节点

    前言 在之前dubbo源码解析-本地暴露中的前言部分提到了两道高频的面试题,其中一道dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,那发布者和订阅者还能通信吗?在上周的dubbo源码 ...

  9. [Java多线程]-线程池的基本使用和部分源码解析(创建,执行原理)

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 多线 ...

随机推荐

  1. C# 深拷贝的具体代码的封装与调用

    先封装下实现方法: public class DeepClone { public static object CopyObject(Object obj) { if (obj == null) { ...

  2. HTML5_04之SVG绘图

    1.关于Canvas绘制图像: 问题:需要绘制多张图片时,必须等待所有图片加载完成才能开始绘制:而每张图片都是异步请求,彼此没有先后顺序,哪一张先加载完成完全无法预测: 方案: var progres ...

  3. Windows 10 部署Enterprise Solution 5.5

    Windows 10正式版发布以后,新操作系统带来了许多的变化.现在新购买的电脑安装的系统应该是Windows 10.与当初用户不习惯Windows 7,购买新电脑后第一个想做的事情就是重装成XP,估 ...

  4. 断电不断网——Linux的screen

    title: 断电不断网--Linux的screen author:青南 date: 2015-01-01 20:20:23 categories: [Linux] tags: [linux,scre ...

  5. 细说Promise

    一.前言 JavaScript是单线程的,固,一次只能执行一个任务,当有一个任务耗时很长时,后面的任务就必须等待.那么,有什么办法,可以解决这类问题呢?(抛开WebWorker不谈),那就是让代码异步 ...

  6. jQuery-template.js学习

    花了点时间,看了下jQuery-template.js,不多废话,先上结构 jQuery.each({..},function(){}) jQuery.fn.extend({..}) jQuery.e ...

  7. 微信小程序定时器组件(输入时间字符串即可倒计时)

    昨天写了代码,今天发现要重用,干脆就抽出来做个组件得了,顺便还改善了一下代码通用性. 昨天的代码在这里 github下载地址 用法: 引入: var timer = require('../../pl ...

  8. 你真的会玩SQL吗?你所不知道的 数据聚合

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  9. 通过HTML5的Drag and Drop生成拓扑图片Base64信息

    HTML5 原生的 Drag and Drop是很不错的功能,网上使用例子较多如 http://html5demos.com/drag ,但这些例子大部分没实际用途,本文将搞个有点使用价值的例子,通过 ...

  10. Hadoop学习之旅一:Hello Hadoop

    开篇概述 随着计算机网络基础设施的完善,社交网络和电商的发展以及物连网的推进,产生了越来越多的大数据,使得人工智能最近几年也有了长足的发展(可供机器学习的样本数据量足够大了),大数据的存储和处理也越来 ...