文章目录
- 显示整体体系
- 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内核设计思想》