文章目录
- 显示整体体系
- FramebufferNativeWindow
- FramebufferNativeWindow构造函数
- dequeueBuffer
- Surface
- 总结
- 参考
显示整体体系
native window为OpenGL与本地窗口系统之间搭建了桥梁。
这个窗口系统中,有两类本地窗口,nativewindow1是能直接显示在屏幕的,使用的是帧缓冲区;nativewindow2是从内存缓冲区分配的空间,通常需要通过其他方式(例如将其内容绘制到帧缓冲区)才能在屏幕上显示。
当系统中存在多个需要显示UI的应用程序时,一方面这种改进设计保证了它们都能获得一个“本地窗口”;另一方面这些“本地窗口”也都可以被有序地显示到终端屏幕上,因为SurfaceFlinger会收集所有程序的显示需求,对它们进行统一的图像混合操作,然后输出到自己的NativeWindow-1上。
应用程序也可以使用Skia等第三方图形库,只要它们和SurfaceFlinger之间的“协议”不变即可。
FramebufferNativeWindow
EGL需要本地窗口为OpenGL创造环境:
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
NativeWindowTypewindow, const EGLint *attrib_list);
无论哪种本地窗口都需要和NativeWindowType保持一致,数据类型的定义:
/*frameworks/native/opengl/include/egl/Eglplatform.h*/
typedef EGLNativeWindowType NativeWindowType;//注意这两种数据类型其实是一样的
…
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)/* Win32 和 WinCE系统下的定义 */
…
typedef HWND EGLNativeWindowType;
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian系统 */
…
typedef void *EGLNativeWindowType;
#elif defined(__ANDROID__) || defined(ANDROID)/* Android系统 */
struct ANativeWindow;
…
typedef struct ANativeWindow* EGLNativeWindowType;
…
#elif defined(__unix__)/* UNIX系统 */
…
typedef Window EGLNativeWindowType;
#else
#error "Platform not recognized"
#endif
ANativeWindow定义:
/*system/core/include/system/Window.h*/
struct ANativeWindow
{…const uint32_t flags; //与Surface或updater有关的属性const int minSwapInterval;//所支持的最小交换间隔时间const int maxSwapInterval;//所支持的最大交换间隔时间const float xdpi; //水平方向的密度,以dpi为单位const float ydpi;//垂直方向的密度,以dpi为单位intptr_t oem[4];//为OEM定制驱动所保留的空间int (*setSwapInterval)(struct ANativeWindow* window, int interval);int (*dequeueBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer** buffer, int* fenceFd);int (*queueBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer, int fenceFd);int (*cancelBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer, int fenceFd);int (*query)(const struct ANativeWindow* window,int what, int* value);int (*perform)(struct ANativeWindow* window,int operation, ... );void* reserved_proc[2];
};
FramebufferNativeWindow构造函数
/*frameworks/native/libs/ui/FramebufferNativeWindow.cpp*/
FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{hw_module_t const* module;if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {…//加载模块int stride;int err;int i;err = framebuffer_open(module, &fbDev);err = gralloc_open(module, &grDev);//分别打开fb和gralloc…if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS &&fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){//根据fb设备属性获得buffer数mNumBuffers = fbDev->numFramebuffers;} else {mNumBuffers = MIN_NUM_FRAME_BUFFERS;//否则就采用最少的buffer数值,即2}mNumFreeBuffers = mNumBuffers;//可用的buffer个数,初始时是所有buffer可用mBufferHead = mNumBuffers-1;…for (i = 0; i < mNumBuffers; i++) //给每个buffer初始化{buffers[i] = new NativeBuffer(fbDev->width, fbDev->height, fbDev->format,GRALLOC_USAGE _HW_FB);}//NativeBuffer是什么?for (i = 0; i < mNumBuffers; i++) //给每个buffer分配空间{err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format,GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);…}/*为本地窗口赋属性值*/const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;const_cast<int&>(ANativeWindow::minSwapInterval) =fbDev->minSwapInterval;const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval;} else {ALOGE("Couldn't get gralloc module");}/*以下代码段开始履行窗口“协议”*/ANativeWindow::setSwapInterval = setSwapInterval;ANativeWindow::dequeueBuffer = dequeueBuffer;ANativeWindow::queueBuffer = queueBuffer;ANativeWindow::query = query;ANativeWindow::perform = perform;/*下面这几个接口已经被废弃了,不过为了保持兼容性,暂时还是保留的*/ANativeWindow::dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED;ANativeWindow::lockBuffer_DEPRECATED = lockBuffer_DEPRECATED;ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED;
}
重点关注的是FramebufferNativeWindow是如何分配buffer的。
成员变量mNumBuffers代表了FramebufferNativeWindow所管理的buffer总数。它取决于两个方面:首先从fb设备中取值,即numFramebuffers;否则就默认定义为MIN_NUM_FRAME_BUFFERS:
#define MIN_NUM_FRAME_BUFFERS 2
#define MAX_NUM_FRAME_BUFFERS 3
这代表双缓冲或者三缓冲机制。
FramebufferNativeWindow构造函数中的第一个for循环里先给各buffer创建相应的实例(new NativeBuffer),其中的属性值都来源于fbDev,如宽、高、格式等。紧随其后的就是调用Gralloc设备的alloc()方法:
err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format,
GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
所有申请到的缓冲区都需要由FramebufferNativeWindow中的全局变量buffers[MAX_NUM_FRAME_BUFFERS]来记录,每个数据元素是一个NativeBuffer:
class NativeBuffer : public ANativeObjectBase<ANativeWindowBuffer, NativeBuffer,LightRefBase<NativeBuffer>>
{…
NativeBuffer 继承自ANativeWindowBuffer:
typedef struct ANativeWindowBuffer
{…int width; //宽int height;//高…buffer_handle_t handle;/*代表内存块的句柄,比如ashmem机制。*/…
} ANativeWindowBuffer_t;
一个本地窗口包含了很多属性值,如各种标志(flags)、横纵坐标的密度值等。这些数值都可以从fb设备中查询到,我们需要将它们赋予刚生成的FramebufferNativeWindow实例的属性。
FramebufferNativeWindow会将其对应的成员函数逐个填充到ANativeWindow的函数指针中:
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
这样的话OpenGL ES就通过ANativeWindow与本地窗口建立了联系。
dequeueBuffer
OpenGL ES就是通过这个方法来分配用于渲染的缓冲区的:
int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd)
{FramebufferNativeWindow* self = getSelf(window); /*Step1*/Mutex::Autolock _l(self->mutex);/*Step2*/…/*Step3. 计算mBufferHead */int index = self->mBufferHead++;if (self->mBufferHead >= self->mNumBuffers)self->mBufferHead = 0;//循环/*Step4. 如果当前没有可用缓冲区*/while (!self->mNumFreeBuffers) {self->mCondition.wait(self->mutex);}/*Step5. 如果有人释放了缓冲区*/self->mNumFreeBuffers--;self->mCurrentBufferIndex = index;*buffer = self->buffers[index].get();*fenceFd = -1;return 0;
}
Surface
应用程序端的本地窗口是Surface,和FramebufferNativeWindow一样,它必须继承AnativeWindow
class Surface: public ANativeObjectBase<ANativeWindow, Surface, RefBase>
/*frameworks/native/libs/gui/Surface.cpp*/
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer): mGraphicBufferPro duc er(bufferProducer)
{/*给ANativeWindow中的函数指针赋值*/ANativeWindow::setSwapInterval = hook_setSwapInterval;ANativeWindow::dequeueBuffer = hook_dequeueBuffer;…/*为各内部变量赋值,因为此时用户还没有发起申请,所以大部分变量的初始值是0*/mReqWidth = 0;mReqHeight = 0;…mDefaultWidth = 0;mDefaultHeight = 0;mUserWidth = 0;mUserHeight = 0;…
}
surface承担应用进程UI显示的责任。
Surface将通过mGraphicBufferProducer来获取buffer,而且这些缓冲区会被记录在mSlots数组中。
int Surface::dequeueBuffer(android_native_buffer_t** buffer,int *fenceFd) {…Mutex::Autolock lock(mMutex);int buf = -1;/*Step1. 宽高计算*/int reqW = mReqWidth ? mReqWidth : mUserWidth;int reqH = mReqHeight ? mReqHeight : mUserHeight;/*Step2. dequeueBuffer得到一个缓冲区*/sp<Fence> fence;status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,reqW, reqH, mReqFormat, mReqUsage);/*生产者发挥作用了*/ …
sp<GraphicBuffer>&gbuf(mSlots[buf].buffer);/*注意buf是一个int值,代表的是mSlots数组序号*/…if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);//申请空间…}…*buffer = gbuf.get();
}
摘自原书:
大致流程是:ViewRootImpl持有一个Java层的Surface对象(即mSurface),初始时是空的。后续ViewRootImpl将向WindowManagerService发起relayout请求,此时mSurface才被赋予真正有效的值。WindowManagerService会先让WindowStateAnimator生成一个SurfaceControl,然后通过Surface.copyFrom()函数将其复制到mSurface中。这个复制函数会通过native接口nativeCreateFrom SurfaceControl来生成本地Surface(C++)对象,具体是在android_view_Surface.cpp文件中。JNI函数nativeCreateFromSurfaceControl将从SurfaceControl中提取出Surface(C++),最终记录到Surface(Java)的成员变量中。这样,后期我们就可以从此变量中还原出底层的Surface对象了。
Surface由SurfaceControl管理,而后者又由SurfaceComposerClient创建。
/*frameworks/native/libs/gui/SurfaceComposerClient.cpp*/
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…if (err == NO_ERROR) {sur = new SurfaceControl(this, handle, gbp);//SurfaceControl是“本地”的对象}}return sur;
}
mClient是一个ISurfaceComposerClient的sp指针,通过它创建一个surface。
SurfaceControl对象并不是由ISurfaceComposerClient的createSurface直接生成的,这个函数的参数中包括了gbp,即前面所说的“buffer生产者”。
真正与SurfaceFlinger间有联系的应该就是gbp。
来看下ISurfaceComposerClient的服务端:
void SurfaceComposerClient::onFirstRef() {sp<ISurfaceComposer> sm(ComposerService::getComposerService());if (sm != 0) {sp<ISurfaceComposerClient> conn = sm->createConnection();if (conn != 0) {mClient = conn;mStatus = NO_ERROR;}}
}
这里面与三个匿名Binder相关联,它们是由surfaceflinger提供的。surface flinger是注册在server manager上面的。
总结
FramebufferNativeWindow是为surfaceflinger服务的,由Gralloc提供。
surface虽然为应用程序服务的,但是本质上还是由surface flinger服务统一管理的。
参考
《深入理解Android内核设计思想》