From: http://www.linuxgraphics.cn/android/gui_update_flow.html 元件圖表 相關組件如所示:
在private void draw(boolean fullRedrawNeeded)中,會調用lockCanvas,從而擷取一個Canvas對象,然後調用遞迴調用子視窗(View)的draw函數去繪製自己,最後調用unlockCanvasAndPost讓Surface把自己更新到螢幕上。 canvas = surface.lockCanvas(dirty); mView.draw(canvas); surface.unlockCanvasAndPost(canvas);
它主要對一些native函數的封裝。 private native Canvas lockCanvasNative(Rect dirty); public native void unlockCanvasAndPost(Canvas canvas);
這是native函數的實現。 Surface_lockCanvas它先鎖住Surface,從而擷取Surface相關的資訊,如果格式、寬度、高度和像素緩衝區。然後建立一個bitmap,這個bitmap和View共用一個像素緩衝區,這樣View就能直接把自己繪製到Surface上了。 status_t err = surface->lock(&info, &dirtyRegion); bitmap.setPixels(info.bits); nativeCanvas->setBitmapDevice(bitmap);Surface_unlockCanvasAndPost它斷開SkCanvas與Surface之間的關係,然後調用Surface的unlockAndPost。 nativeCanvas->setBitmapDevice(SkBitmap()); status_t err = surface->unlockAndPost();
- surfaceflinger_client/Surface.cpp
Surface::lock調用dequeueBuffer擷取一個可用的Buffer,dequeueBuffer會調用SharedBufferClient::dequeue等到backbuffer可用,然後鎖住這個Buffer並填充相關資訊。 status_t err = dequeueBuffer(&backBuffer); err = lockBuffer(backBuffer.get());Surface::unlockAndPost先unlock Buffer,然後調queueBuffer顯示Buffer。 status_t err = mLockedBuffer->unlock(); err = queueBuffer(mLockedBuffer.get());Surface::queueBuffer是比較有意思的,它設定更新的地區,然後通知服務端(SurfaceFlinger)。 mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); err = mSharedBufferClient->queue(bufIdx); client->signalServer();通過binder發送請求給服務: virtual void signal() const { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY); }
BnSurfaceComposer::onTransact case SIGNAL: { CHECK_INTERFACE(ISurfaceComposer, data, reply); signal(); } break;這是SurfaceFlinger中處理SIGNAL的代碼,它調用SurfaceFlinger::signal,再調用 SurfaceFlinger::signalEvent,最後調用MessageQueue::invalidate喚醒是 SurfaceFlinger的主迴圈。 在主迴圈中waitForEvent返回,再handleRepaint去合成個Layer/Surface。 bool SurfaceFlinger::threadLoop() { waitForEvent(); handleRepaint(); postFramebuffer(); }SurfaceFlinger::handleRepaint會調用composeSurfaces把需要繪製各個Surface合并起來,繪製到FrameBuffer的BackBuffer上。 for (size_t i=0 ; i<count ; ++i) { const sp<LayerBase>& layer = layers[i]; const Region& visibleRegion(layer->visibleRegionScreen); if (!visibleRegion.isEmpty()) { /* broncho cy add */ #ifdef USEOVERLAY mToppest[1] = mToppest[0]; mToppest[0] = layer->getIdentity(); #endif /* broncho end */ const Region clip(dirty.intersect(visibleRegion)); if (!clip.isEmpty()) { layer->draw(clip); } } }SurfaceFlinger::postFramebuffer最後把FrameBuffer的BackBuffer顯示到螢幕上: hw.flip(mInvalidRegion); -->eglSwapBuffers(dpy, surface); |