接上篇文章,我们来看一下init()都做了什么事。以下是源码:
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
status_t err;
Mutex::Autolock _l(mStateLock);
// initialize EGL for the default display
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
mHwc = new HWComposer(this,
*static_cast(this));
// First try to get an ES2 config
err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,
&mEGLConfig);
if (err != NO_ERROR) {
// If ES2 fails, try ES1
err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),
EGL_OPENGL_ES_BIT, &mEGLConfig);
}
if (err != NO_ERROR) {
// still didn't work, probably because we're on the emulator...
// try a simplified query
ALOGW("no suitable EGLConfig found, trying a simpler query");
err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);
}
if (err != NO_ERROR) {
// this EGL is too lame for android
LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
}
// print some debugging info
EGLint r,g,b,a;
eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE, &r);
eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);
eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE, &b);
eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);
ALOGI("EGL informations:");
ALOGI("vendor : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));
ALOGI("version : %s", eglQueryString(mEGLDisplay, EGL_VERSION));
ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");
ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);
// get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);
// retrieve the EGL context that was selected/created
mEGLContext = mRenderEngine->getEGLContext();
// figure out which format we got
eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);
LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext");
// initialize our non-virtual displays
for (size_t i=0 ; iisConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
// All non-virtual displays are currently considered secure.
bool isSecure = true;
createBuiltinDisplayLocked(type);
wp token = mBuiltinDisplays[i];
sp bq = new BufferQueue(new GraphicBufferAlloc());
sp fbs = new FramebufferSurface(*mHwc, i, bq);
sp hw = new DisplayDevice(this,
type, allocateHwcDisplayId(type), isSecure, token,
fbs, bq,
mEGLConfig,
mHardwareOrientation);
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always
// assume a connected display is unblanked.
ALOGD("marking display %d as acquired/unblanked", i);
hw->acquireScreen();
}
mDisplays.add(token, hw);
}
}
// make the GLContext current so that we can create textures when creating Layers
// (which may happens before we render something)
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
// start the EventThread
sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true);
mEventThread = new EventThread(vsyncSrc);
sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, false);
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
// set a fake vsync period if there is no HWComposer
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod(16666667);
}
// initialize our drawing state
mDrawingState = mCurrentState;
// set initial conditions (e.g. unblank default device)
initializeDisplays();
char value[PROPERTY_VALUE_MAX];
memset(value,0,PROPERTY_VALUE_MAX);
property_get("sys.enable.wfd.optimize", value, "0");
mWfdOptimize = atoi(value);
// start boot animation
startBootAnim();
}
如上代码量太大了我稍微总结了下,它做了以下几件事:
1.初始化EGL,这是干嘛用?首先介绍下EGL,EGL是OpenGL ES和底层Native平台视窗系统之间的接口,也就是说初始化了openGL的API。
2.初始化H/W composer,也就是HardWare的一些事,具体不去研究
3.获得一个显示器的渲染引擎,RendEngine,这是OPENGL发挥作用的平台
4.初始化显示器的一些东西,代码太多,没看懂做了哪些事。
5.启动了线程,EventThread,这个线程在以后的研究中会涉及到。
6.初始化了一些状态条件等。
好了先告一段落,初始化做了一些事情,肯定是为以后做铺垫,暂且继续研究下去。
前一篇文章,研究到了addService(),接下去的一行是:flinger->run();
我们来看下run的实体函数,他定义在SF类中:
void SurfaceFlinger::run() {
do {
waitForEvent();
} while (true);
}
最核心的代码就是waitForEvent();继续跟踪:
void SurfaceFlinger::waitForEvent() {
mEventQueue.waitMessage();
}
再继续:
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1);
switch (ret) {
case ALOOPER_POLL_WAKE:
case ALOOPER_POLL_CALLBACK:
continue;
case ALOOPER_POLL_ERROR:
ALOGE("ALOOPER_POLL_ERROR");
case ALOOPER_POLL_TIMEOUT:
// timeout (should not happen)
continue;
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
continue;
}
} while (true);
}
到这里,晕了没,看出眉头来了没,这是个庞大的事件机制,稍后给出一张图诠释一下这个事件机制,这张图是网上的大牛画的佩服的五体投地,一看马上拨开云雾见青天。我们还是看下代码把,关键代码在第四行pollOnece(),其实我不敢在写下去,因为里面文章太多,我查阅了网上的一些资料网址如下,大家可参考下:http://blog.csdn.net/broadview2006/article/details/8552148 ,然后我简单说下这里扯到了Looper,这可不是一个好鸟,庞大的事件机制军团中的一员,他配合着Message Handle Thread MessageQueue 完成了太多的事情,以后再去讨论。在这里简单说就是它搞了一个睡眠等待事件,然后等着被唤醒。结合到SF中就是说,这里开了一个线程等待surface的刷新,而做出相关的操作。至于是怎么唤醒的可以参考那个连接博文,这里不再赘述。
既然被睡眠了,那研究该如何进行下去,于是我开始研究是谁把它唤醒的。开始复杂了,要费脑袋了。
这里我先给一张图:
这张图是网上一位大牛博文中的,忘记链接地址了,如有侵权,还请告知我。好了开始正文:
我刚刚说的那个睡眠事件其实就是蓝色框框流程图的走向,图中标的是线程2。这里说一下其他线程分别是什么时候创建的
主线程:在SF中的onFirstRef()创建的,这里有个问题,是谁调用onFirstRef()?android里面 当一个对象第一次被一个强指针应用时,那么这个对象的成员函数onFirstRef就会被调用,如上所说它一早就被调用了,我们看看它的实体:
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
}
继续跟踪:
void MessageQueue::init(const sp& flinger)
{
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
这里new了Looper和Handle,关于这两个什么东西,推荐一片博文:http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html 里面讲的很详细。好了这个是主线程1的创建。
线程2:前面说过,当调用SF::run();时就开始了。
线程3:在SF::init();中创建。也就是初始化中创建:创建关键代码如下:
mEventThread = new EventThread(vsyncSrc);
sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, false);
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
这里我们分两个路线来讲:
1.EventThread继承了Thread线程类,还有它的基类中有RefBase所以当其定义的时候会调用onFirstRef,这个函数里面就一句 run();这里EventThread中的 threadLoop成员函数会被调用,这里看一下函数实体:
bool EventThread::threadLoop() {
DisplayEventReceiver::Event event;
Vector< sp > signalConnections;
signalConnections = waitForEvent(&event);
// dispatch events to listeners...
const size_t count = signalConnections.size();
for (size_t i=0 ; i& conn(signalConnections[i]);
// now see if we still need to report this event
status_t err = conn->postEvent(event);
if (err == -EAGAIN || err == -EWOULDBLOCK) {
// The destination doesn't accept events anymore, it's probably
// full. For now, we just drop the events on the floor.
// FIXME: Note that some events cannot be dropped and would have
// to be re-sent later.
// Right-now we don't have the ability to do this.
ALOGW("EventThread: dropping event (%08x) for connection %p",
event.header.type, conn.get());
} else if (err < 0) {
// handle any other error on the pipe as fatal. the only
// reasonable thing to do is to clean-up this connection.
// The most common error we'll get here is -EPIPE.
removeDisplayEventConnection(signalConnections[i]);
}
}
return true;
}
这里的waitForEvent就是在等待消息了,官方给出这个函数的作用是:
This will return when (1) a vsync event has been received, and (2) there was at least one connection interested in receiving it when we started waiting.大概意思就是等待vsync事件,如果有就返回正常值。那么是谁给他发的这个信号了,那必然是客户端请求渲染一个surface的时候了。这里以后会有研究。
如果收到一个vsync的消息,就会往下执行到status_t err = conn->postEvent(event);这里是将事件信息写入到BitTube,也就是已建立连接的套接字队的一个套接字中,注册的接收端通过另一个套接字接收数据。这里注册的接收端就下面要阐述的第二点。到这里为止EventThread线程发送了一个套接字信息。
2. 到底是谁来接收套接字呢?当中的setEventThread就是扯到了套接字,跟之前说的pollOnce有关联,这里打住。我们看看这个函数的实体:
void MessageQueue::setEventThread(const sp& eventThread)
{
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();// 这里创建了一个到EventThread的连接
mEventTube = mEvents->getDataChannel();//得到发送VSync事件通知的BitTube
mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
在这里addFd当中的第一个参数就是获得套接字队中的信息,一旦有东西就会回调cb_eventReceiver这个函数,我们跟踪那个回调函数:
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast(data);
return queue->eventReceiver(fd, events);
}
第二行是得到事件的queue,以便于下面返回事件接收者。继续跟踪:
int MessageQueue::eventReceiver(int fd, int events) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; idispatchInvalidate();
#else
mHandler->dispatchRefresh();
#endif
break;
}
}
}
return 1;
}
这个函数大概的意思就是,主循环一直在等待事件的接收,并判断事件的类型是不是DISPLAY_EVENT_VSYNC,如果是就开始执行下一步了,因为文件头有定义#define INVALIDATE_ON_VSYNC 1 所以走的是mHandler->dispatchInvalidate();这个函数。好了到这里,已经出现太多跟VSync有关的字眼,好像也起了很大的作用,这里暂不做研究,之后就会真相大白。不过还是推荐一篇博文大家参考下http://blog.csdn.net/broadview2006/article/details/8541727 继续跟踪dispatchInvalidate()这个函数。
void MessageQueue::Handler::dispatchInvalidate() {
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}
}
看到了一个关键的函数,sendMessage();发出去的消息是 INVALIDATE.看过事件机制的就知道,这里发出的消息是由handleMessage()来接收处理的。到底是哪边的handleMessage()来处理了,还记得之前的主线程2在睡眠等待消息?对就是在它里面。看上面那张图可以知道应该是在pollInner中处理消息的,由于这个消息机制过于复杂这里就略过了,不过推荐大家一篇博文很详细的阐述了 pollOnce和pollInner之间的关系 :http://book.2cto.com/201208/1946.html ,你会发现在函数pollInner中有个处理函数handleMessage();这里继续跟踪:
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case TRANSACTION:
android_atomic_and(~eventMaskTransaction, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
用switch来判断接收的消息到底是什么,刚刚发送的是INVALDATE,所以执行第一条,跟踪onMessageReceived();
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
if(mDelayFlag) {
usleep(20000);
mDelayFlag = 0;
}
switch (what) {
case MessageQueue::TRANSACTION:
handleMessageTransaction();
break;
case MessageQueue::INVALIDATE:
handleMessageTransaction();
handleMessageInvalidate();
signalRefresh();
break;
case MessageQueue::REFRESH:
handleMessageRefresh();
break;
}
}
这里走的是第二个分支,第一个函数handleTransaction();这里处理了各种事务,如窗口状态属性变化,继续跟踪handleMessageInvalidate,他调用了一个handlePageFlip()函数,该函数的作用是便利各图层,计算得到需要更新的区域。在走下一个函数会发现其实最终都是走到第三个分支。那么就跟踪handleMessageRefresh():
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition();
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doComposition();
postComposition();
/* Dynamic check debug.sf.fps ,if 1 then print fps*/
if(frm_count++%300==0) {
frm_count = 1;
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.fps", value, "0");
mDebugFPS = atoi(value);
}
到这里为止还是属于SF这一层,在接下去就是Layer层对surface的绘制问题了