Android的Graphic系统分析之skia_第1页
Android的Graphic系统分析之skia_第2页
Android的Graphic系统分析之skia_第3页
Android的Graphic系统分析之skia_第4页
Android的Graphic系统分析之skia_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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_client.so链

3、接到应用程序中,也链接到server侧(主要因为layer state管理和内存控制块等类),因此,其大多数类运行在应用程序所在进程空间中,它通过Binder与与进程sufaceflinger进行交互。它的代码位于frameworks/base/libs/surfaceflinger_client下面,SurfaceComposerClient/SurfaceControl如JNI层章节所述,在创建SurfaceSession(Java)时,会创建SurfaceComposerClient对象,并将SurfaceComposerClient对象指针保存到SurfaceSession(Java)

4、的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)。它是调用ISurfaceCompose

7、r的captureScreen函数来实现的。SurfaceSurface类继承自EGLNativeBase模板类,因此它实际上一个ANativeWindow,只不过该模板给它添加了引用计数功能,并可安全地进行类型转换。class Surface: public EGLNativeBase<ANativeWindow, Surface, RefBase>上层应用程序各有自己的surface,因此多个surface会同时存在,这些surface在本侧就是SurfaceComposerClient所代表,它们可以添加到Composer类维护的列表中。SurfaceControl会使用Su

8、rfaceClient和Surface去完成相应功能,SurfaceControl的getSurface函数会创建Surface,从而也会导致SurfaceClient的创建,进而相应的ISurfaceClientComposer等会被创建。ISurfaceComposerISurfaceComposer是SurfaceFlinger在client侧的一个binder,提供的接口用于对整个屏幕的全局性的管理,如方向旋转、屏幕快照、屏幕事件、屏幕更新的冻结与去冻结等。它提供的接口对应的枚举类型有:enum / Note: BOOT_FINISHED must remain this value,

9、 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,CAPTURE_SCREEN,TURN_ELECTRON_BEAM_OFF,TURN_ELE

10、CTRON_BEAM_ON;它是通过Binder进行IPC通讯的接口,BpSurfaceComposer是client一侧, BnSurfaceComposer是service一侧。它们都继承自各自的模板类BpInterface和BnInterface,这两个模板类完成双重继承的功能,一个继承IPC通讯的API接口,一个继承Binder功能。RefBase用于索引计数,类IInterface和ISurface定义了IPC通讯的接口API,IBinder/BBinder使双方具备Binder通讯功能。其中CREATE_CONNECTION和REATE_CLIENT_CONNECTION打开关闭一

11、个Transaction,在打开和关闭的过程中,可以设置状态,实现窗口管理。状态变化更改是在一个事务(transaction)中进行的。其类继承关系如下:根据Binder继承关系规则,client侧的接口调用通过最终是由Bn侧的子类完成。我们就可以知道它的它动态的调用关系如下,左侧的调用者一般可以通过指向ISurfaceComposer的智能指针将操作将调用到SurfaceFlinger类的成员函数。ComposerService对IsurfaceComposer进行了包裹,使用它的getComposerService函数可以获取IsurfaceComposer。另外,ComposerServ

12、ice还包含了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 reserved2;float fps;float density;float xdpi;float ydpi;uint32_t pad2;struct surfa

13、ce_flinger_cblk_t / 4KB max/控制信息块uint8_t connected;uint8_t reserved3;uint32_t pad7;display_cblk_t displaysSharedBufferStack:NUM_DISPLAY_MAX;/最多4个display;在SufraceFlinger的readyToRun会申请内存,并依据DisplayHardWare中得到display信息:/ create the shared control-blockmServerHeap = new MemoryHeapBase(4096,MemoryHeapBas

14、e:READ_ONLY, “SurfaceFlinger read-only heap”);/分配内存,没有指定设备名称或描述符fd,默认使用AShem上的内存LOGE_IF(mServerHeap=0, “cant create shared memory dealer”);mServerCblk = /得到内存基址static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase();LOGE_IF(mServerCblk=0, “cant get to shared control blocks address”);new

15、(mServerCblk) surface_flinger_cblk_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.displayHard

16、ware();const uint32_t w = hw.getWidth();const uint32_t h = hw.getHeight();const uint32_t f = hw.getFormat();hw.makeCurrent();/ initialize the shared control blockmServerCblk->connected |= 1<<dpy;display_cblk_t* dcblk = mServerCblk->displays + dpy;memset(dcblk, 0, sizeof(display_cblk_t);/

17、给结构体赋值,同一块内存上,client侧可以立即得到dcblk->w = 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.getDensit

18、y();IsurfaceComposerClientISurfaceComposerClient用于通过Binder与SurfaceFlinger交互,创建和销毁ISurface,它也可以获取控制块。在SurfaceFlinger侧会有两种类型的surface:Client(用于创建销毁ISurace)和UserClient(用于获取控制块进行通讯)。它提供的接口对应的枚举类型如下:enum GET_CBLK = IBinder:FIRST_CALL_TRANSACTION,GET_TOKEN,CREATE_SURFACE,DESTROY_SURFACE,SET_STATE;动态调用关系图,调

19、用者通过对IsurfaceComposerClient的引用,最后由SufaceFlinger进程中的Client或UserClient来完成:ISurfaceIsurface提供了一个与SufaceFlinger侧进行IPC交互的接口,它主要功能是操作缓冲区。我们可以从ISurface这个纯虚类中看出起定义的接口操作:enum REGISTER_BUFFERS = IBinder:FIRST_CALL_TRANSACTION,UNREGISTER_BUFFERS,POST_BUFFER, / one-way transactionCREATE_OVERLAY,REQUEST_BUFFER,S

20、ET_BUFFER_COUNT,;这些枚举就是所支持的接口操作,相应地对应着纯虚成员函数。我们可以望文生义理解其含义。如下图,BpSurface是client一侧, BnSurface是service一侧。它们都继承自各自的模板类BpInterface和BnInterface,这两个模板类完成双重继承的功能,一个继承IPC通讯的API接口,一个继承Binder功能。RefBase用于索引计数,类IInterface和ISurface定义了IPC通讯的接口API,IBinder/BBinder使双方具备Binder通讯功能。类继承关系图动态调用关系如下图所示:sp<Isurface>

21、Surface flinger制块在文件SharedBufferStack.h中定义了一个结构体,它是为了通过共享内存的方式快速获取系统所有display物理信息,这个控制块由结构体surface_flinger_cblk_t定义:struct display_cblk_t/显示控制块,Android中默认支持最多4个diaplayuint16_t w; /display的宽uint16_t h; /display的高uint8_t format; /格式uint8_t orientation; /旋转方向uint8_t reserved2; /保留字节float fps; /刷新率float

22、 density; /密度float xdpi;/x方向上的解析度,每英寸的点阵数(dots/inch)float ydpi;/y方向上的解析度uint32_t pad2;/填充字节;struct surface_flinger_cblk_t / 4KB maxuint8_t connected;/是否连接uint8_t reserved3;/保留字节uint32_t pad7;/填充字节display_cblk_t displaysSharedBufferStack:NUM_DISPLAY_MAX;/支持最多4个的display;Java层在创建一个SurfaceSession实例时,建立到

23、server侧的连接,这个连接的动作实际就是分配内存、创建surface_flinger_cblk_t对象并初始化获得初始值、以及可以跨进程访问的过程。具体过程是:在client一侧,创建Surface Session时,会创建一个SurfaceComposerClient对象,接着会调用SurfaceComposerClient:onFirstRef:void SurfaceComposerClient:onFirstRef()/第一次创建对象时被调用sp<ISurfaceComposer> sm(getComposerService();/导致获取全局控制块if (sm !=

24、0) sp<ISurfaceComposerClient> 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(也就是ISurfaceC

25、omposer的Wrapper)构造函数获取surface flinger控制块的过程如下:ComposerService:ComposerService(): Singleton<ComposerService>() const String16 name(“SurfaceFlinger”);while (getService(name, &mComposerService) != NO_ERROR) usleep(250000);mServerCblkMemory = mComposerService->getCblk();/获取IMemoryHeapmServe

26、rCblk = static_cast<surface_flinger_cblk_t volatile *>(mServerCblkMemory->getBase();/在IMemoryHeap中的基址指针转换为surface_flinger_cblk_t指针另外,SurfaceComposerClient的onFirstRef会创建一个connection,它的目的是创建代理对象,用于Binder IPC通讯,ISurfaceComposerClient接口强指针指向该代理对象。在server侧,它只是调用Client(也就是ISurfaceComposerClient接口

27、在server侧的真正实现者)构造函数创建一个Client对象进行类型转换后返回。而实际的内存分配是在server侧创建SurfaceFlinger后准备运行其工作线程时完成的,见SurfaceFlinger:readyToRun函数:status_t SurfaceFlinger:readyToRun()LOGI( “SurfaceFlingers main thread ready to run. ”“Initializing graphics H/W”);/ we only support one display currentlyint dpy = 0;/ initialize the

28、 main displayGraphicPlane& plane(graphicPlane(dpy);DisplayHardware* const hw = new DisplayHardware(this, dpy);plane.setDisplayHardware(hw);/ create the shared control-block/创建共享控制块,因未指定在何处分配内存,默认的是ashmem上mServerHeap = new MemoryHeapBase(4096,MemoryHeapBase:READ_ONLY, “SurfaceFlinger read-only he

29、ap”);LOGE_IF(mServerHeap=0, “cant create shared memory dealer”);mServerCblk = static_cast<surface_flinger_cblk_t*> (mServerHeap->getBase();/获取基址LOGE_IF(mServerCblk=0, “cant get to shared control blocks address”);new(mServerCblk) surface_flinger_cblk_t;/ initialize primary screen/ (other dis

30、play 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 = hw.getWidth();const uint32_t h = hw.getHeight();con

31、st uint32_t f = hw.getFormat();hw.makeCurrent();/ initialize the shared control blockmServerCblk->connected |= 1<<dpy;/下面是为共享控制块赋值display_cblk_t* dcblk = mServerCblk->displays + dpy;memset(dcblk, 0, sizeof(display_cblk_t);dcblk->w = plane.getWidth();dcblk->h = plane.getHeight();dcb

32、lk->format = f;dcblk->orientation = ISurfaceComposer:eOrientationDefault;dcblk->xdpi = hw.getDpiX();dcblk->ydpi = hw.getDpiY();dcblk->fps = hw.getRefreshRate();dcblk->density = hw.getDensity();/省略部分代码它为该控制块在ashmem上分配内存并对其初始化赋值。SharedClient控制块在SurfaceControl的getSurface() 时,会创建一个Surf

33、ace,接着调用SurfaceClient的构造函数,由于SurfaceClient是singleton,即系统中只有一个实例,因此,在其第一次创建时调用了构造函数,而在其构造函数中调用了createClientConnection,这个就是建立连接的过程,就是分配内存控制块的过程。在client侧,其代码如下:SurfaceClient(): Singleton<SurfaceClient>(), mStatus(NO_INIT)sp<ISurfaceComposer> /获取Composer servicesf(ComposerService:getComposer

34、Service();mComposerService = sf;mClient = sf->createClientConnection();/创建client连接if (mClient != NULL) /创建成功的话mControlMemory = mClient->getControlBlock();/获取内存块if (mControlMemory != NULL) mControl = static_cast<SharedClient *>(mControlMemory->getBase();/得到基地址,并转换为SharedClient指针,然后赋值给m

35、Controlif (mControl) mStatus = NO_ERROR;在server侧,它调用UserClient的构造函数:UserClient:UserClient(const sp<SurfaceFlinger>& flinger): ctrlblk(0), mBitmap(0), mFlinger(flinger)const int pgsize = getpagesize();/获取内存页大小const int cblksize = /控制块大小,即进行页对齐后的SharedClient大小(sizeof(SharedClient)+(pgsize-1)

36、&(pgsize-1);mCblkHeap = new MemoryHeapBase(cblksize, 0,/在ashmem上分配内存“SurfaceFlinger Client control-block”);ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase();/指针类型转换if (ctrlblk) / construct the shared structure in-place.new(ctrlblk) SharedClient;/调用构造函数初始化内存块对象也就是说,建立一个clientCon

37、nection的过程,也就是在server侧:在堆上分配一块页对齐的内存块,它被用来存储SharedClient对象;之后,client侧同样也拥有该块内存,同样也被解释为SharedClient对象指针。TODO:它们是跨进程的,所以通过IMemoryHeap这个binder接口来操作。那么SharedClient是何方神圣呢?在头文件SharedBufferStack.h中有代码注释:“These classes manage a stack of buffers in shared memory.SharedClient: represents a client with several

38、 stacksSharedBufferStack: represents a stack of buffersSharedBufferClient: manipulates the SharedBufferStack from the client sideSharedBufferServer: manipulates the SharedBufferStack from the server sideBuffers can be dequeued until there are none available, they can be lockedunless they are in use

39、by the server, which is only the case for the lastdequeue-able buffer. When these various conditions are not met, the callerwaits until the condition is met.”我们先来看一下比较重要的一个类SharedBufferStackclass SharedBufferStack/省略部分代码struct SmallRect /定义了一个矩形:左上角和右下角的坐标uint16_t l, t, r, b;/定义了一个平面区域,包含了若干(不超过5个)矩形struct FlatRegion / 52 bytes = 4 * (1 + 2*N)static const unsig

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论