1、skia库 Skia库是一个外部库,代码位于external/skia/下面,生成的库名称是libskia.so。 Skia库负责2维图形的绘制,绘制的结果最终一般以位图的形式存放在存的一块缓冲区中。我们可以从它里面几个比较重要的类来了解它到底完成什么功能。 使用SkCanvas,可以将绘制(drawing)结果保存到一个设备如位图(bitmap)中,这些绘制操作包含一系列几何图形的绘制,如绘制点、线、矩形、多边形、椭圆和圆弧等几何图形。Canvas.cpp调用了skia库的API,有的调用仅仅是对SkCanvas的简单包裹。绘制的状态(State)封装在Paint类中,如绘制的线条粗细
2、线条颜色、区域如何填充、线条形状等。SkBitmap是光栅位图,它包含高度和宽度两个整数以与格式(配置config规定),也可以通过getAddr()获取存储实际像素(pixel)块的地址。一副图形可以通过它的像素位图来保存,也可以通过保存它的绘制过程通过SkPicture保存起来,然后写到文件里,最后通过绘制过程恢复图形。另外,skia也包括将YUV格式转变为Jpg的编码,见YuvToJpegEncoder.cpp。 Java部分通过JNI调用Skia关系如下,包括但不限于下图中的四个类。 库libsurfaceflinger_client.so 库libsurfaceflinger
3、client.so到应用程序中,也到server侧(主要因为layer state管理和存控制块等类),因此,其大多数类运行在应用程序所在进程空间中,它通过Binder与与进程sufaceflinger进行交互。它的代码位于frameworks/base/libs/surfaceflinger_client下面, SurfaceComposerClient/SurfaceControl 如JNI层章节所述,在创建SurfaceSession(Java)时,会创建SurfaceComposerClient对象,并将SurfaceComposerClient对象指针保存到SurfaceSes
4、sion(Java)的mClient中。我们来看下创建SurfaceComposerClient对象时还发生了什么?SurfaceComposerClient继承自RefBase,所以在第一次初始化时,会执行其重载的onFirstRef。在onFirstRef中,会获取Composer Service,也就是SurfaceFlinger在client侧的binder—-ISurfaceComposer,接着使用它建立client connection连接(实际上是分配一个用于两侧通讯的共享存块),获取ISurfaceComposerClient,最后创建layer_state_t,保存窗口状态
5、用于两侧的窗口状态通讯。 SurfaceComposerClient可以加入到列表中由Composer来维护。 SurfaceControl对象指针保存在Surface(Java)中的mSurfaceControl。 SurfaceControl借助于SurfaceComposerClient,实现对UI控件的一些操作: · show/hide: 显示隐藏操作 · setSize/setPosition: 设置大小和位置 · SetLayer:设置图层 · freeze/unfreeze:冻结与去冻结操作,即是否更新屏幕 · SetAlpha:设置Alpha通道,即设
6、置透明等级 · SetMatrix:设置平移矩阵 · setFlags:设置其它标志 这些SurfaceControl类的功能实现仅仅是对SurfaceComposerClient的简单封装。可以通过SurfaceComposerClient的函数获取Display的个数、高、宽、旋转方向以与其它信息。它是通过ComposerService中的控制块信息来实现的。 ScreenshotClient包含屏幕截屏宽(mWidth)和高(mHeight)以与像素格式(PixelFormat),截图数据保存在IMemoryHeap中(mHeap)。它是调用ISurfaceComposer
7、的captureScreen函数来实现的。
Surface
Surface类继承自EGLNativeBase模板类,因此它实际上一个ANativeWindow,只不过该模板给它添加了引用计数功能,并可安全地进行类型转换。
class Surface
: public EGLNativeBase
8、会使用SurfaceClient和Surface去完成相应功能,SurfaceControl的getSurface函数会创建Surface,从而也会导致SurfaceClient的创建,进而相应的ISurfaceClientComposer等会被创建。 ISurfaceComposer ISurfaceComposer是SurfaceFlinger在client侧的一个binder,提供的接口用于对整个屏幕的全局性的管理,如方向旋转、屏幕快照、屏幕事件、屏幕更新的冻结与去冻结等。它提供的接口对应的枚举类型有: enum { // Note: BOOT_FINISHED must rem
9、ain this value, it is called from // Java by ActivityManagerService. BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, CREATE_CONNECTION, CREATE_CLIENT_CONNECTION, GET_CBLK, OPEN_GLOBAL_TRANSACTION, CLOSE_GLOBAL_TRANSACTION, SET_ORIENTATION, FREEZE_DISPLAY, UNFREEZE_DISPLAY, SIGNAL, CAPTU
10、RE_SCREEN, TURN_ELECTRON_BEAM_OFF, TURN_ELECTRON_BEAM_ON }; 它是通过Binder进行IPC通讯的接口,BpSurfaceComposer是client一侧, BnSurfaceComposer是service一侧。它们都继承自各自的模板类BpInterface和BnInterface,这两个模板类完成双重继承的功能,一个继承IPC通讯的API接口,一个继承Binder功能。RefBase用于索引计数,类IInterface和ISurface定义了IPC通讯的接口API,IBinder/BBinder使双方具备Binder通讯功
11、能。 其中CREATE_CONNECTION和REATE_CLIENT_CONNECTION打开关闭一个Transaction,在打开和关闭的过程中,可以设置状态,实现窗口管理。状态变化更改是在一个事务(transaction)中进行的。 其类继承关系如下: 根据Binder继承关系规则,client侧的接口调用通过最终是由Bn侧的子类完成。我们就可以知道它的它动态的调用关系如下,左侧的调用者一般可以通过指向ISurfaceComposer的智能指针将操作将调用到SurfaceFlinger类的成员函数。 ComposerService对IsurfaceComposer进行了包裹,使用
12、它的getComposerService函数可以获取IsurfaceComposer。另外,ComposerService还包含了surface_flinger_cblk_t控制块信息,该存块位于Ashem存上,由SurfaceFlinger申请,并依据display硬件信息填充字段值。client端程序通过读取它,即可得到各display的信息。 struct display_cblk_t {//dispaly的各项信息 uint16_t w; uint16_t h; uint8_t format; uint8_t orientation; uint8_t reserved[2
13、]; float fps; float density; float xdpi; float ydpi; uint32_t pad[2]; }; struct surface_flinger_cblk_t // 4KB max {//控制信息块 uint8_t connected; uint8_t reserved[3]; uint32_t pad[7]; display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];//最多4个display }; 在SufraceFlinger的readyToRun会申请
14、存,并依据DisplayHardWare中得到display信息: // create the shared control-block mServerHeap = new MemoryHeapBase(4096, MemoryHeapBase::READ_ONLY, “SurfaceFlinger read-only heap”);//分配存,没有指定设备名称或描述符fd,默认使用AShem上的存 LOGE_IF(mServerHeap==0, “can’t create shared memory dealer”); mServerCblk = //得到存基址 static_c
15、ast
16、e and go. None of this is supported yet). const GraphicPlane& plane(graphicPlane(dpy)); const DisplayHardware& hw = plane.displayHardware(); const uint32_t w = hw.getWidth(); const uint32_t h = hw.getHeight(); const uint32_t f = hw.getFormat(); hw.makeCurrent(); // initialize the shared contr
17、ol block
mServerCblk->connected |= 1<
18、tionDefault; dcblk->xdpi = hw.getDpiX(); dcblk->ydpi = hw.getDpiY(); dcblk->fps = hw.getRefreshRate(); dcblk->density = hw.getDensity(); IsurfaceComposerClient ISurfaceComposerClient用于通过Binder与SurfaceFlinger交互,创建和销毁ISurface,它也可以获取控制块。在SurfaceFlinger侧会有两种类型的surface:Client(用于创建销毁ISurace)和UserCli
19、ent(用于获取控制块进行通讯)。它提供的接口对应的枚举类型如下: enum { GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, GET_TOKEN, CREATE_SURFACE, DESTROY_SURFACE, SET_STATE }; 动态调用关系图,调用者通过对IsurfaceComposerClient的引用,最后由SufaceFlinger进程中的Client或UserClient来完成: ISurface Isurface提供了一个与SufaceFlinger侧进行IPC交互的接口,它主要功能是操作缓冲区。我们可以从I
20、Surface这个纯虚类中看出起定义的接口操作: enum { REGISTER_BUFFERS = IBinder::FIRST_CALL_TRANSACTION, UNREGISTER_BUFFERS, POST_BUFFER, // one-way transaction CREATE_OVERLAY, REQUEST_BUFFER, SET_BUFFER_COUNT, }; 这些枚举就是所支持的接口操作,相应地对应着纯虚成员函数。我们可以望文生义理解其含义。 如下图,BpSurface是client一侧, BnSurface是service一侧。它们都继承自各自的模
21、板类BpInterface和BnInterface,这两个模板类完成双重继承的功能,一个继承IPC通讯的API接口,一个继承Binder功能。RefBase用于索引计数,类IInterface和ISurface定义了IPC通讯的接口API,IBinder/BBinder使双方具备Binder通讯功能。
类继承关系图
动态调用关系如下图所示:
sp
22、k_t定义: struct display_cblk_t//显示控制块,Android中默认支持最多4个diaplay { uint16_t w; //display的宽 uint16_t h; //display的高 uint8_t format; //格式 uint8_t orientation; //旋转方向 uint8_t reserved[2]; //保留字节 float fps; //刷新率 float density; //密度 float xdpi;//x方向上的解析度,每英寸的点阵数(dots/inch) float ydpi;//y方向上的解析度 u
23、int32_t pad[2];//填充字节 }; struct surface_flinger_cblk_t // 4KB max { uint8_t connected;//是否连接 uint8_t reserved[3];//保留字节 uint32_t pad[7];//填充字节 display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];//支持最多4个的display }; Java层在创建一个SurfaceSession实例时,建立到server侧的连接,这个连接的动作实际就是分配存、创建surface_f
24、linger_cblk_t对象并初始化获得初始值、以与可以跨进程访问的过程。具体过程是:在client一侧,创建Surface Session时,会创建一个SurfaceComposerClient对象,接着会调用SurfaceComposerClient::onFirstRef:
void SurfaceComposerClient::onFirstRef()//第一次创建对象时被调用
{
sp 25、t> conn = sm->createConnection();//创建一个连接,surface flinger侧会创建一个Client对象
if (conn != 0) {
mClient = conn;
Composer::addClient(this);
mPrebuiltLayerState = new layer_state_t;
mStatus = NO_ERROR;
}
}
}
在上面的代码中,先在ComposerService的构造函数中获取surface flinger控制块。
ComposerService(也就是ISurfaceComposer的Wr 26、apper)构造函数获取surface flinger控制块的过程如下:
ComposerService::ComposerService()
: Singleton 27、blk = static_cast 28、erver侧的真正实现者)构造函数创建一个Client对象进行类型转换后返回。而实际的存分配是在server侧创建SurfaceFlinger后准备运行其工作线程时完成的,见SurfaceFlinger::readyToRun函数:
status_t SurfaceFlinger::readyToRun()
{
LOGI( “SurfaceFlinger’s main thread ready to run. ”
“Initializing graphics H/W…”);
// we only support one display currently
int dpy = 0;
29、
{
// initialize the main display
GraphicPlane& plane(graphicPlane(dpy));
DisplayHardware* const hw = new DisplayHardware(this, dpy);
plane.setDisplayHardware(hw);
}
// create the shared control-block
//创建共享控制块,因未指定在何处分配存,默认的是ashmem上
mServerHeap = new MemoryHeapBase(4096,
MemoryHeapBase::RE 30、AD_ONLY, “SurfaceFlinger read-only heap”);
LOGE_IF(mServerHeap==0, “can’t create shared memory dealer”);
mServerCblk = static_cast 31、k_t;
// initialize primary screen
// (other display should be initialized in the same manner, but
// asynchronously, as they could come and go. None of this is supported yet).
const GraphicPlane& plane(graphicPlane(dpy));
const DisplayHardware& hw = plane.displayHardware();
const uint32_t w = 32、hw.getWidth();
const uint32_t h = hw.getHeight();
const uint32_t f = hw.getFormat();
hw.makeCurrent();
// initialize the shared control block
mServerCblk->connected |= 1< 33、 = plane.getWidth();
dcblk->h = plane.getHeight();
dcblk->format = f;
dcblk->orientation = ISurfaceComposer::eOrientationDefault;
dcblk->xdpi = hw.getDpiX();
dcblk->ydpi = hw.getDpiY();
dcblk->fps = hw.getRefreshRate();
dcblk->density = hw.getDensity();
……//省略部分代码
}
它为该控制块在ashmem上分配存并对其初始化 34、赋值。
SharedClient控制块
在SurfaceControl的getSurface() 时,会创建一个Surface,接着调用SurfaceClient的构造函数,由于SurfaceClient是singleton,即系统中只有一个实例,因此,在其第一次创建时调用了构造函数,而在其构造函数中调用了createClientConnection,这个就是建立连接的过程,就是分配存控制块的过程。在client侧,其代码如下:
SurfaceClient(): Singleton 35、poser> //获取Composer service
sf(ComposerService::getComposerService());
mComposerService = sf;
mClient = sf->createClientConnection();//创建client连接
if (mClient != NULL) {//创建成功的话
mControlMemory = mClient->getControlBlock();//获取存块
if (mControlMemory != NULL) {
mControl = static_cast 36、 *>(
mControlMemory->getBase());//得到基地址,并转换为SharedClient指针,然后赋值给mControl
if (mControl) {
mStatus = NO_ERROR;
}
}
}
}
在server侧,它调用UserClient的构造函数:
UserClient::UserClient(const sp 37、页大小
const int cblksize = //控制块大小,即进行页对齐后的SharedClient大小
((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0,//在ashmem上分配存
“SurfaceFlinger Client control-block”);
ctrlblk = static_cast 38、ruct the shared structure in-place.
new(ctrlblk) SharedClient;//调用构造函数初始化存块对象
}
}
也就是说,建立一个clientConnection的过程,也就是在server侧:在堆上分配一块页对齐的存块,它被用来存储SharedClient对象;之后,client侧同样也拥有该块存,同样也被解释为SharedClient对象指针。TODO:它们是跨进程的,所以通过IMemoryHeap这个binder接口来操作。
那么SharedClient是何方神圣呢?在头文件SharedBufferStack.h中有代码注释: 39、
These classes manage a stack of buffers in shared memory.
SharedClient: represents a client with several stacks
SharedBufferStack: represents a stack of buffers
SharedBufferClient: manipulates the SharedBufferStack from the client side
SharedBufferServer: manipulates the SharedBufferStack fro 40、m the server side
Buffers can be dequeued until there are none available, they can be locked
unless they are in use by the server, which is only the case for the last
dequeue-able buffer. When these various conditions are not met, the caller
waits until the condition is met.
”
我们先来看一下比较重要的一个类S 41、haredBufferStack
class SharedBufferStack
{
……//省略部分代码
struct SmallRect {//定义了一个矩形:左上角和右下角的坐标
uint16_t l, t, r, b;
};
//定义了一个平面区域,包含了若干(不超过5个)矩形
struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
static const unsigned int NUM_RECT_MAX = 5;
uint32_t count;
SmallRect rects[NUM_RECT_MAX];
};
s 42、truct BufferData {//64Bytes
FlatRegion dirtyRegion;//5个矩形区域
SmallRect crop;//1个剪切矩形区
uint8_t transform;
uint8_t reserved[3];
};
……//省略部分代码
//双方同步
// these attributes are part of the conditions/updates
volatile int32_t head; // server’s current front buffer
volatile int32_t available; // nu 43、mber of dequeue-able buffers
volatile int32_t queued; // number of buffers waiting for post
volatile int32_t reserved1;
volatile status_t status; // surface’s status code
// not part of the conditions
volatile int32_t reallocMask;
volatile int8_t index[NUM_BUFFER_MAX];
int32_t identity; // su 44、rface’s identity (const)
int32_t token; // surface’s token (for debugging)
Statistics stats;
int8_t headBuf; // last retired buffer
uint8_t reservedBytes[3];
int32_t reserved;
BufferData buffers[NUM_BUFFER_MAX]; // 16个数组元素
};
可见SharedBufferStack里面定义了几个结构体,用于保存矩形区域。如果我们把BufferData所保存的区域称为一块区域 45、的话,那么SharedBufferStack里可以包含多达16块区域。在Android系统里,一个Surface对应一个SharedBufferStack。而SharedClient则包含了31个SharedBufferStack:
// 32 KB max
class SharedClient
{
……//省略部分代码
// FIXME: this should be replaced by a lock-less primitive
Mutex lock;
Condition cv;
SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];//31个数组元素
};
因此,上图展示了SharedClient中包含的31个Stack元素
每当client侧创建一个surface时,都要通过SharedBufferClient的dequeue从SharedBufferStack取出一个不用的slot。
17 / 17






