Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android graphic path

Android graphic path

編輯:關於Android編程

UI的畫圖流程中,先不管怎麼填充要畫的數據的,只是來看一下需要畫到屏幕上的數據是通過怎樣的流程最終傳遞到屏幕上的。這個流程都是UI獲取並創建Surface並利用Cavans,Bitmap等畫好之後,傳遞給SurfaceFlinger去Composite並傳遞給HWComposer去畫到屏幕上的。根據Chris Simmonds關於graphic path的說明來具體看一。

這裡寫圖片描述

Inception of a pixel

Everything begins when an activity draws to a surface 2D applications can use
1) drawing functions in Canvas to write to a Bitmap:android.graphics.Canvas.drawRect(), drawText(), etc
2) descendants of the View class to draw objects such as buttons and lists
3) a custom View class to implement your own appearance and behaviour In all cases the drawing is rendered to a Surface which contains a GraphicBuffer

SurfaceFlinger binder interfaces

這裡寫圖片描述

ISurfaceComposer

這裡寫圖片描述

ISurfaceComposerClient

這裡寫圖片描述

IDisplayEventConnection

這裡寫圖片描述

一個activity等Client畫一個UI的流程如下:
ISurfaceComposer is the interface to talk to SurfaceFlinger, there’re two ways to get ISurfaceComposer interface in Client:

sp composer;
composer = ComposerService::getComposerService();

or

getService("SurfaceFlinger", &composer);

ISurfaceComposerClient is the interface to create Surface. To get ISurfaceComposerClient interface, use the ISurfaceComposer instance returned above:

sp composerClient = composer->createConnection();

The above two methods can be combined in single step:

sp composerClient = new SurfaceComposerClient;

To operate on Surface, you have to get SurfaceControl first, simply call createSurface on the SurfaceComposerClient instance:

sp surfaceControl = composerClient->createSurface();

And call getSurface on SurfaceControl instance, you can finally get Surface:

sp surface = surfaceControl->getSurface();

獲取Buffer並填充:

status_t Surface::lock(
        ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
    if (mLockedBuffer != 0) {
        ALOGE("Surface::lock failed, already locked");
        return INVALID_OPERATION;
    }

    if (!mConnectedToCpu) {
        int err = Surface::connect(NATIVE_WINDOW_API_CPU);
        if (err) {
            return err;
        }
        // we're intending to do software rendering from this point
        setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
    }

    ANativeWindowBuffer* out;
    int fenceFd = -1;
    status_t err = dequeueBuffer(&out, &fenceFd);
    ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
    if (err == NO_ERROR) {
        sp backBuffer(GraphicBuffer::getSelf(out));
        const Rect bounds(backBuffer->width, backBuffer->height);

        Region newDirtyRegion;
        if (inOutDirtyBounds) {
            newDirtyRegion.set(static_cast(*inOutDirtyBounds));
            newDirtyRegion.andSelf(bounds);
        } else {
            newDirtyRegion.set(bounds);
        }

        // figure out if we can copy the frontbuffer back
        const sp& frontBuffer(mPostedBuffer);
        const bool canCopyBack = (frontBuffer != 0 &&
                backBuffer->width  == frontBuffer->width &&
                backBuffer->height == frontBuffer->height &&
                backBuffer->format == frontBuffer->format);

        if (canCopyBack) {
            // copy the area that is invalid and not repainted this round
            const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
            if (!copyback.isEmpty())
                copyBlt(backBuffer, frontBuffer, copyback);
        } else {
            // if we can't copy-back anything, modify the user's dirty
            // region to make sure they redraw the whole buffer
            newDirtyRegion.set(bounds);
            mDirtyRegion.clear();
            Mutex::Autolock lock(mMutex);
            for (size_t i=0 ; i= 0) {
                Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
                mDirtyRegion.subtract(dirtyRegion);
                dirtyRegion = newDirtyRegion;
            }
        }

        mDirtyRegion.orSelf(newDirtyRegion);
        if (inOutDirtyBounds) {
            *inOutDirtyBounds = newDirtyRegion.getBounds();
        }

        void* vaddr;
        status_t res = backBuffer->lockAsync(
                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                newDirtyRegion.bounds(), &vaddr, fenceFd);

        ALOGW_IF(res, "failed locking buffer (handle = %p)",
                backBuffer->handle);

        if (res != 0) {
            err = INVALID_OPERATION;
        } else {
            mLockedBuffer = backBuffer;
            outBuffer->width  = backBuffer->width;
            outBuffer->height = backBuffer->height;
            outBuffer->stride = backBuffer->stride;
            outBuffer->format = backBuffer->format;
            outBuffer->bits   = vaddr;
        }
    }
    return err;
}

Surface::lock()函數中outBuffer就是backBuffer,是通過GraphicBufferProducer從BufferQueue中獲取的空閒buffer。
獲取了這個空閒的backBuffer之後就可以往backBuffer中填充數據,並通過queueBuffer發給SurfaceFlinger了(backBuffer是畫畫用的,frontBuffer是composite用的)。
所以Surface和SurfaceFlinger之間也是一個C/S架構,其橋梁就是BufferQueue。Surface從BufferQueue中獲取空閒Buffer填充數據並發給BufferQueue。SurfaceFlinger也是從BufferQueue中獲取buffer並畫上去。buffer是共享緩沖區,所以會涉及互斥鎖,buffer狀態也有很多種,一般buffer會大致經過FREE->DEQUEUED->QUEUED->ACQUIRED->FREE這幾種流程(狀態機參考下面的BufferQueue state diagram)。如下圖:

這裡寫圖片描述

BufferQueue
可以認爲BufferQueue是一個服務中心,其它兩個owner必須要通過它來管理buffer。比如說當producer想要獲取一個buffer時,它不能越過BufferQueue直接與consumer進行聯系,反之亦然。

Producer
生産者就是“填充”buffer空間的人,通常情況下當然就是應用程序。因爲應用程序不斷地刷新UI,從而將産生的顯示數據源源不斷地寫到buffer中。當Producer需要使用一塊buffer時,它首先會向中介BufferQueue發起dequeue申請,然後才能對指定的緩沖區進行操作。這種情況下buffer就屬於producer一個人的了,它可以對buffer進行任何必要的操作,而其它owner此刻絕不能擅自插手。
當生産者認爲一塊buffer已經寫入完成後,它進一步調用BufferQueue的queue。從字面上看這個函數是“入列”的意思,形象地表達了buffer此時的操作——把buffer歸還到BufferQueue的隊列中。一旦queue成功後,owner也就隨之改變爲BufferQueue了

Consumer
消費者是與生産者相對應的,它的操作同樣受到BufferQueue的管控。當一塊buffer已經就緒後,Consumer就可以開始工作了。這裏需要特別留意的是,從各個對象所扮演的角色來看,BufferQueue是中介機構,屬於服務提供方;Producer屬於buffer內容的産出方,它對緩沖區的操作是一個“主動”的過程;反之,Consumer對buffer的處理則是“被動”的、“等待式”的——它必須要等到一塊buffer填充完成後才能做工作。在這樣的模型下,我們怎麽保證Consumer可以及時的處理buffer呢?換句話說,當一塊buffer數據ready後,應該怎麽告知Consumer來操作呢?
仔細觀察的話,可以看到BufferQueue裏還同時提供了一個特別的類,名稱爲ProxyConsumerListener,其中的函數接口包括:

class ProxyConsumerListener : public BnConsumerListener {
    public:
        //省略構造函數
        virtual void onFrameAvailable();
        /*當一塊buffer可以被消費時,這個函數會被調用,特別注意此時沒有共享鎖的保護*/

        virtual voidonBuffersReleased();
        /*BufferQueue通知consumer它已經釋放其slot中的一個或多個 GraphicBuffer引用*/

    private:    
        wpmConsumerListener;
}

這樣子就很清楚了,當有一幀數據准備就緒後,BufferQueue就會調用onFrameAvailable()來通知Consumer進行消費。

BufferQueue和SurfaceFlinger之間的通信模式如下:

這裡寫圖片描述
也是有一對BpGraphicBufferConsumer/BnGraphicBufferConsumer支持他們之間的信息傳輸
下面是BufferQueue中的核心函數分析:

這裡寫圖片描述

BufferQueue是IGraphicBufferProducer和IGraphicBufferConsumer的具體實現,用戶在請求和SurfaceFlinger連接的過程中會請求SF創建一個Layer,IGraphicBufferProducer就是在這個過程中獲取一個BufferQueue對象,又轉化成IGraphicBufferProducer類對象,是爲了進一步和BufferQueue進行交互,下面是關鍵代碼:

status_t SurfaceFlinger::createNormalLayer(const sp& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp* handle, sp* gbp, sp* outLayer)
{
    // initialize the surfaces
    switch (format) {
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
        format = PIXEL_FORMAT_RGBX_8888;
        break;
    }

    *outLayer = new Layer(this, client, name, w, h, flags);
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        *handle = (*outLayer)->getHandle();
        *gbp = (*outLayer)->getProducer();
    }

    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
    return err;
}

前面獲取Buffer並填充完之後,通過unlockAndroidPost()就可以把畫好的buffer發給surfaceflinger去顯示出來了。

int Surface::unlockAndPost();
{
    if (mLockedBuffer == 0) {
        ALOGE("Surface::unlockAndPost failed, no locked buffer");
        return INVALID_OPERATION;
    }

    int fd = -1;
    status_t err = mLockedBuffer->unlockAsync(&fd);
    ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);

    err = queueBuffer(mLockedBuffer.get(), fd);
    ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
    mLockedBuffer->handle, strerror(-err));

    mPostedBuffer = mLockedBuffer;
    mLockedBuffer = 0;
    return err;
}

If some operations need atomic transaction, just wrap them inside:

SurfaceComposerClient::openGlobalTransaction();
...
SurfaceComposerClient::closeGlobalTransaction();

在BootanimationLoader.cpp文件中,可以看到如下代碼,就是按上面的過程畫buffer然後發過去的。
這裡DecData即為decode完的圖片數據。

if ((DecData != NULL || DecData_mini != NULL)&& !mThread->checkExit()) {
    mFlingerSurface->lock(&sBuffer, NULL);//獲取backbuffer
    ssize_t bpr = sBuffer.stride * bytesPerPixel(sBuffer.format);
    if(ClearCover_closed &&  DecData_mini != NULL) {
        if(BootAnimData_STATUS & BootAnimData_QMG_MAIN_MINI || BootAnimData_STATUS & 
            BootAnimData_QMG_LOOP_MINI) {
            memset(sBuffer.bits, 0, 
            sBuffer.stride*sBuffer.height*bytesPerPixel(sBuffer.format));
            for(int32_t h=0; h < header_info_mini.height; h++) {
                if(coverModelName == COVER_MODEL_NAME_TB) { //edge screen mini bootanimation
                    memcpy((char*)sBuffer.bits+(sBuffer.stride*bytesPerPixel(sBuffer.format)*h)+bytesPerPixel(sBuffer.format)*(sBuffer.width-header_info_mini.width), DecData_mini+(header_info_mini.width*bytesPerPixel(sBuffer.format)*h),header_info_mini.width*bytesPerPixel(sBuffer.format));
                }
                else {
                    memcpy((char*)sBuffer.bits+(sBuffer.stride*bytesPerPixel(sBuffer.format)*h),     DecData_mini+(sBuffer.width*bytesPerPixel(sBuffer.format)*h),sBuffer.width*bytesPerPixel(sBuffer.format));
                }
            }
        }
    }else {
        if( DecData != NULL) {
            for(int32_t h=0;hunlockAndPost();//post過去!!
}

2D rendering path

這裡寫圖片描述

Skia and hwui

For 2D drawing there are two rendering paths hwui: (libwhui.so) hardware accelerated using OpenGL ES 2.0 skia: (libskia.so) software render engine hwui is the default Hardware rendering can be disabled per view,window, activity, application or for the whole device Maybe for comparability reasons: hwui produces results different to skia in some (rare) cases

3D rendering path

? An activity can instead create a GLSurfaceView and use OpenGL ES bindings for Java (the
android.opengl.* classes)
? Using either the vendor GPU driver (which must support OpenGL ES 2.0 and optinally 3.0)
? Or as a fall-back, using PixelFlinger, a software GPU that implements OpenGL ES 1.0 only
? Once again, the drawing is rendered to a Surface

這裡寫圖片描述

Composition

這裡寫圖片描述

SurfaceFlinger

A high-priority native (C++) daemon, started by init with UID=system Services connections from activities via Binder interface ISurfaceComposer Receives activity status from Activity Manager Receives window status (visibility, Z-order) from Window Manager Composits multiple Surfaces into a single image Passes image to one or more displays Manages buffer allocation, synchronisation

BufferQueue

這裡寫圖片描述

BufferQueue state diagram

這裡寫圖片描述

BufferQueue

這裡寫圖片描述

GraphicBuffer

frameworks/native/include/ui/GraphicBuffer.h

Represents a buffer, wraps ANativeWindowBuffer Attributes including width, height, format, usage inherited from ANativeWindowBuffer

SurfaceFlinger處理buffer

這裏先用2張圖來介紹下SurfaceFlinger的整個消息處理機制和工作流程:

這裡寫圖片描述

這裡寫圖片描述

這裏繼續下去對handleMessageRefresh分析,這是SuefaceFlinger的核心處理函數(每個vsync都會調用handleMessageRefresh)。

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();
    preComposition();
    rebuildLayerStacks();
    setUpHWComposer();
    doDebugFlashRegions();
    doComposition();
    postComposition();
}

調用順序:

handleMessageRefresh
     |—> preComposition
     |—> rebuildLayerStacks
     |—> setUpHWComposer
          |—> HWComposer::createWorkList <== hwc structures are allocated
          |—> Layer::setGeometry()
          |—  set per frame data
          |—  HWComposer::prepare
               |—> hwc prepare
     |—> doComposition
          |---- skip composition on external display if condition meets
          |—> doDisplayComposition
          |    |—> doComposeSurfaces
          |     |—> DisplayDevice::swapBuffers
          |          |—> eglSwapBuffers
          |          |—> FramebufferSurface::advanceFrame
          |—> DisplayDevice::flip(…)     <== just update statistics count
          |--> Call DisplayDevice::compositionComplete(), notify each display
               |--> DisplaySurface::compositionComplete()
                    |--> FramebufferSurface::compositionComplete()
                         |--> HWComposer::fbCompositionComplete()
                              |--> NoOP if HWC >= 1.1
                              |--> used only in framebuffer device case.
          |—> postFrameBuffer
               |—> HWComposer::commit
                    |—> hwc set
                    |—> update retireFenceFd of hwc_display_contents_1
               |—> DisplayDevice::onSwapBuffersCompleted
                    |—> FramebufferSurface::onFrameComitted
               |—> Layer::onLayerDisplayed
               |—   update some statistics
     |—> postComposition 

doComposeSurfaces

handleMessageRefresh -> doComposition -> doDisplayComposition -> doComposeSurfaces
    1.Preparation work:
        1) If GLES and hwc compositing, clear frame buffer target first
        2) If GLES only, drawWarmHole first
    2.Render layers to framebuffer
        1) For all layers if using hwc
            (1)do nothing if HWC_OVERLAY layer, display hardware will blend the layer
            (2)render with opengl if HWC_FRAMEBUFFER layer, call layer->draw()
            (3)set the layer’s acquireFence
        2) For all layers if no hwc
            (1)just render with OpenGL, call layer->draw()
            (2)Now all the GLES layers are drawn on frame buffer target, waiting to 
            swapBuffers

在DisplayDevice::swapBuffers()->eglSwapBuffers()函數,最終會調用到FramebufferSurface::onFrameAvailable()。
FramebufferSurface::onFrameAvailable()會調用到HwComposer::fbPost()把buffer發給顯示設備。
下面會講這個過程。先來看一下FramebufferSurface和DisplayDevice。
JB版本開始,Android支持外部顯示(HDMI和Wifi等)。每個顯示設備由DisplayDevice代表,而且關聯著FramebufferSurface。SurfaceFlinger會保存所有的DisplayDevice在mDisplays成員變量中。SurfaceFlinger::readyToRun() 函數中會創建所有的DisplayDevice和FramebufferSurface。
HWComposer一般會像如下定義幾個顯示類型:

HWC_DISPLAY_PRIMARY e.g. built-in LCD screen
HWC_DISPLAY_EXTERNAL e.g. HDMI, WiDi
HWC_DISPLAY_VIRTUAL not a real display

對於每一個display type,都會以DisplayDevice對象保存在SurfaceFlinger中。

How FrameBufferSurface and eglSwapBuffers interact(??)

Back to BufferQueue, usually client application create Surface, it’s provider end of a BufferQueue, SurfaceFlinger acts as consumer of the Surface provided by client. However, SurfaceFlinger also acts as provider as regard to FrameBufferSurface, which is consumed by display.

In SurfaceFlinger::init, the mDisplaySurface in DisplayDevice comes from the same BufferQueue as EGLSurface, look at the code

bq = new BufferQueue(new GraphicBufferAlloc());
fbs = new FramebufferSurface(…, bq);
hw = new DisplayDevice(…, fbs, bq, …);
mDisplays.add(…,hw);

So now EGL can swap to the FrameBufferSurface, because the EGLSurface is the provider end of the same BufferQueue which hosts FrameBufferSurface. The layer represented by the frame buffer target is tracked by DisplayDevice::framebufferTarget, ANativeWindow and ANativeWindowBuffer is the interface used by EGL to access the buffer allocated in SurfaceFlinger. Basically flow is:

swap to DisplayDevice::mSurface, DisplayDevice::mNativeWindow influenced too -> BufferQueue::queueBuffer -> FramebufferSurface::onFrameAvailable -> HWComposer::fbPost -> HWComposer::setFramebufferTarget -> get framebuffer target fram handle parameter -> disp.framebufferTarget.handle = disp.fbTargetHandle;

To get clear understanding of the process and the role, reference to this picture:

這裡寫圖片描述

Summary

1.Surface dequeueBuffer eventually works on BuffferQueue in SF, Surface is provider, SurfaceFlingerConsumer is consumer
2.GraphicBuffer in allocated for Surface to draw.
3.Surface queueBuffer eventually works on BufferQueue in SF, Layer::onFrameAvailable called.
4.SurfaceFlingerConsumer::updateTexImage bind EGLImage as texture
5.Layer::onDraw draws to the BufferQueue of FramebufferSurface, here egl is provider, FramebufferSurface is consumer
6.FramebufferSurface::onFrameAvailable -> HWComposer::fbPost -> HWComposer::setFramebufferTarget
7.All layers prepared, sent to HWC

###########################################################################
preComposition();預先准備“合成物“就是客戶端那邊傳來的UI信息的buffer;
rebuildLayerStacks();在每一個screen上重建可見區域;
setUpHWComposer();初始化一個硬件容器;
doDebugFlashRegions();這個函數一般進去就返回來了;
doComposition();實質的合成過程,並且合成完的BUFFER由opengl es處理,處理之後由postFramebuffer()送到display上顯示;

這裏重點研究doComposition()

void SurfaceFlinger::doComposition() {
    ATRACE_CALL();
    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]);
        if (hw->isDisplayOn()) {
            // transform the dirty region into this screen's coordinate space
            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

            // repaint the framebuffer (if needed)
            doDisplayComposition(hw, dirtyRegion);

            hw->dirtyRegion.clear();
            hw->flip(hw->swapRegion);
            hw->swapRegion.clear();
        }
        // inform the h/w that we're done compositing
        hw->compositionComplete();
    }
    postFramebuffer();
}

doDisplayComposition(hw, dirtyRegion);負責渲染的核心函數。
它的調用過程是:

doDisplayComposition-> doComposeSurfaces->draw->onDraw->drawWithOpenGL

一直走到OPENGL層Composite。
之後就是調用hw->flip()函數交換backBuffer和frontBuffer(?)。

之後postFramebuffer()就會調用hwc.commit(),把需要顯示的發給底層fb驅動去顯示了。。

Composition

這裡寫圖片描述

Layer

這裡寫圖片描述

Layer在createSurface()創建Surface的時候被一起創建並保存。在使用SurfaceComposerClient::createSurface()創建surface的時候,需要傳名字,顯示的寬度/高通,而且需要顯示的format,最後還有一個參數是flags,這個是顯示窗口顯示狀態的(dim,blur等等)。以下是Layer的幾種顯示狀態:
這裡寫圖片描述

Layer對應普通的窗口 LayerDim 會使他後面的窗口產生一個變暗的透明效果 LayerBlur在LayerDim的基礎上,背景會產生模糊的效果

創建Layer
默認地,創建普通的窗口Surface,在SurfaceFlinger中會創建Layer類,如果想創建LayerDim或LayerBlur,應用程序需要在綁定View之前設置一下窗口的標志位。
創建LayerDim效果:

@Override  
protected void onCreate(Bundle icicle) {  
    // Be sure to call the super class.  
    super.onCreate(icicle);  

    // Have the system blur any windows behind this one.  
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,  
            WindowManager.LayoutParams.FLAG_DIM_BEHIND);  
    ......  
    setContentView(......);  
}  

創建LayerBlur效果:

@Override  
protected void onCreate(Bundle icicle) {  
    // Be sure to call the super class.  
    super.onCreate(icicle);  

    // Have the system blur any windows behind this one.  
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,  
            WindowManager.LayoutParams.FLAG_BLUR_BEHIND);  
    ......  
    setContentView(......);  
}  

這樣設置的,最後在status_t SurfaceFlinger::createLayer()函數中,會根據相應的flag的值創建不同的layer

status_t SurfaceFlinger::createLayer(
        const String8& name,
        const sp& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp* handle, sp* gbp)
{
    ...
    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createNormalLayer(client,
                    name, w, h, flags, format,
                    handle, gbp, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceDim:
            result = createDimLayer(client,
                    name, w, h, flags,
                    handle, gbp, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }
    ...
}

所以,比如mSession->createSurface(String8(“samsungAniDim”), dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565, 0x00020000),是對應eFXSurfaceDim!!

http://blog.csdn.net/DroidPhone/article/details/6002237

改了一點代碼,可以讓SurfaceFlinger顯示當前的layer個數,顯示flag等:

01-11 03:13:15.580  2123  2123 D SurfaceFlinger:   numHwLayers=3, flags=00000000
01-11 03:13:15.580  2123  2123 D SurfaceFlinger:     type   |  handle  | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name 
01-11 03:13:15.580  2123  2123 D SurfaceFlinger: -----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------
01-11 03:13:15.580  2123  2123 D SurfaceFlinger:        HWC | b5c44520 | 0000 | 0000 | 00 | 0100 | RGBA_8888   |    0.0,   33.0,  800.0, 1280.0 |    0,   33,  800, 1280 | com.samsung.android.FactoryTestLauncher/com.samsung.android.FactoryTestLauncher.ui.Main
01-11 03:13:15.580  2123  2123 D SurfaceFlinger:        HWC | b5c44200 | 0000 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0,  800.0,   33.0 |    0,    0,  800,   33 | StatusBar
01-11 03:13:15.580  2123  2123 D SurfaceFlinger:  FB TARGET | b606d340 | 0000 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0,  800.0, 1280.0 |    0,    0,  800, 1280 | HWC_FRAMEBUFFER_TARGET

HWComposer

這裡寫圖片描述

prepare() and set()

這裡寫圖片描述

vsync

這裡寫圖片描述

Displays

這裡寫圖片描述

IGraphicBufferAlloc and friends

這裡寫圖片描述

Buffer usage and pixel format

這裡寫圖片描述

Gralloc

這裡寫圖片描述

OpenGL ES

這裡寫圖片描述

EGL

這裡寫圖片描述

OpenGL vendor implementation

這裡寫圖片描述

SurfaceFlinger::doComposition()
-->doDisplayComposition()
//DisplayDevicce::PARTIAL_UPDATES NOTE
-->-->doComposeSurface()
-->-->-->HWComposer::hasGlesComposition()
//by check disp.hasFbComp
-->-->-->-->LayerBase::draw()
-->-->-->-->-->Layer::onDraw()
-->-->-->-->-->-->drawWithOpenGL()
-->-->-->HWComposer::hasHwcComposition()
//by check disp.hasOvComp

-->-->DisplayDevice->swapBuffers(getHwComposer()) // ** in doDisplayComposition
-->-->-->eglSwapBuffers()@libEGL.so // ** Swap buffers in EGLSurface, holding BufferQueue(USAGE_HW_FB) with consumer FrameBufferSurface. 
-->-->-->-->eglSwapBuffers()@libEGL_adreno.so
-->-->-->-->-->qeglDrvAPI_eglSwapBuffers()@libEGL_adreno.so
-->-->-->-->-->-->SwapBuffers()@eglsubAndroid.so
-->-->-->-->-->-->-->Surface::hook_queueBuffer()
-->-->-->-->-->-->-->-->Surface::queueBuffer()
-->-->-->-->-->-->-->-->-->BufferQueue::queueBuffer()
-->-->-->-->-->-->-->-->-->-->BufferQueue::ProxyConsumerListener::onFrameAvailable()
-->-->-->-->-->-->-->-->-->-->-->FramebufferSurface::onFrameAvailable()
-->-->-->-->-->-->-->-->-->-->-->-->HWComposer::fbPost()
-->-->-->-->-->-->-->-->-->-->-->-->-->framebuffer_device_t::(*post)() = fb_post()
-->-->-->-->-->-->-->-->-->-->-->-->-->-->ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) // ** the framebuffer is swapped.

in DisplayDevice::readyToRun, Surface instance will be registered as egl's window surface. Surface includes FramebufferSurface's BufferQueue(USAGE_HW_FB|USAGE_HW_COMPOSER) and inherits from ANativeWindow. in Surface, ANativeWindow's hook function should be called by egl!!! Thus Surface's and its BufferQueue's queuebuffer()s will be called. Then BufferQueue's and its comsumer FramebufferSurface's onframeavailable will be called.

-->DisplayDevice::flip()
-->-->eglSetSwapRectangleANDROID() ************** I think should be 'set' the region..

-->-->-->-->DisplayDevice::onSwapBuffersCompleted() // ** callbacked by eglSwpaBuufers
-->-->-->-->-->Signal the Fence

-->postFramebuffer()
-->-->HWComposer::commit()
-->-->-->mHwc->set() that is hwc_set
-->-->-->-->MDPComp::draw()
-->-->-->-->-->MDPCompSplit::draw()
-->-->-->-->-->-->Overlay::queueBuffer
-->-->-->-->-->-->-->GenericPipe::queueBuffer()
-->-->-->-->-->-->-->-->MdpData::queueBuffer()
-->-->-->-->-->-->-->-->-->MdpData::play()
-->-->-->-->-->-->-->-->-->-->mdp_wrapper::play()
-->-->-->-->-->-->-->-->-->-->-->ioctl(MSMFB_OVERLAY_PLAY) // **start the layerMixer to composite, overlay the HWC_OVERLAY layer to framebuffer.
-->-->-->-->Overlay::displayCommit()
-->-->-->-->->Overlay::displayCommit()
-->-->-->-->->-->mdp_wrapper::displayCommit()
-->-->-->-->->-->-->ioctl(MSMFB_DISPLAY_COMMIT) // ** start DMA, transfer layerMixer output to DSI controller

FramebufferSurface no longer speaks directly to the FB HAL. Now
everything goes through HWComposer (which may or may not be
connected to a hardware composer).

120// Overrides ConsumerBase: onFrameAvailable(), does not call base class impl.
121void FramebufferSurface: onFrameAvailable() {
122 sp buf;
123 sp acquireFence;
124 status_t err = nextBuffer(buf, acquireFence);
125 if (err != NO_ERROR) {
126 ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
127 strerror(-err), err);
128 return;
129 }
130 err = mHwc.fbPost(mDisplayType, acquireFence, buf);
131 if (err != NO_ERROR) {
132 ALOGE("error posting framebuffer: %d", err);
133 }
134}

757int HWComposer::fbPost(int32_t id,
758 const sp& acquireFence, const sp& buffer) {
759 if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
760 return setFramebufferTarget(id, acquireFence, buffer);
761 } else {
762 acquireFence->waitForever("HWComposer::fbPost");
763 return mFbDev->post(mFbDev, buffer->handle); // ** fb_post
764 }
765}

195void DisplayDevice::flip(const Region& dirty) const
196{
197 checkGLErrors();
198
199 EGLDisplay dpy = mDisplay;
200 EGLSurface surface = mSurface;
201
202#ifdef EGL_ANDROID_swap_rectangle
203 if (mFlags & SWAP_RECTANGLE) {
204 const Region newDirty(dirty.intersect(bounds()));
205 const Rect b(newDirty.getBounds());
206 eglSetSwapRectangleANDROID(dpy, surface,
// *****
207 b.left, b.top, b.width(), b.height());
208 }
209#endif
210
211 mPageFlipCount++;
212}

Another ANativeWindow with same role of Class Surface(for USAGE_HW_FB) is FrameBufferNativeWindow used by QCom's "GL updater" thread.

GL updater will call this.
GL updater, call FrameBufferNativeWindow::queueBuffer ANativeWindow::dequeueBuffer in eglsubAndroid.so
Thread 3 (LWP 511):
#0 __ioctl () at bionic/libc/arch-arm/syscalls/__ioctl.S:10
#1 0x4028e070 in ioctl (fd=, request=17921) at bionic/libc/bionic/ioctl.c:41
#2 0x400eed38 in fb_post (dev=, buffer=0x4122ff80) at hardware/qcom/display/libgralloc/framebuffer.cpp:129
#3 0x4004ec5a in android::FramebufferNativeWindow::queueBuffer (window=0x4122f578, buffer=) at frameworks/native/libs/ui/FramebufferNativeWindow.cpp:304
#4 0x40423da4 in updater_thread (ptr=0x41230f10) at vendor/qcom/proprietary/gles/adreno200/egl14/src/linux/android/eglUpdaterAndroid.c:451
#5 0x40278eb4 in __thread_entry (func=0x40423c55 , arg=0x41230f10, tls=0x41041f00) at bionic/libc/bionic/pthread.c:218
#6 0x4027860c in pthread_create (thread_out=0x41230f58, attr=0x402a0154 , start_routine=0x40423c55 , arg=0x41230f10) at bionic/libc/bionic/pthread.c:357
#7 0x00000000 in ?? ()

FramebufferNativeWindow::queueBuffer
274int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
275 ANativeWindowBuffer* buffer, int fenceFd)
276{
277 FramebufferNativeWindow* self = getSelf(window);
278 Mutex::Autolock _l(self->mutex);
279 framebuffer_device_t* fb = self->fbDev;
280 buffer_handle_t handle = static_cast(buffer)->handle;
281
282 sp fence(new Fence(fenceFd));
283 fence->wait(Fence::TIMEOUT_NEVER);
284
285 const int index = self->mCurrentBufferIndex;
286 int res = fb->post(fb, handle); // ** fb_post
287 self->front = static_cast(buffer);
288 self->mNumFreeBuffers++;
289 self->mCondition.broadcast();
290 return res;
291}

SurfaceTextureClient(USAGE_TEXTURE) is used by normal application layers with GPU used buffers.
#05 pc 00014a6b /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+34)
#06 pc 0001e337 /system/lib/libgui.so 
#07 pc 000217fb /system/lib/libgui.so (android::SurfaceTextureClient::dequeueBuffer(ANativeWindowBuffer**)+86)
#08 pc 000207a7 /system/lib/libgui.so (android::SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow*, ANativeWindowBuffer**)+10)
#09 pc 00002705 /system/lib/egl/eglsubAndroid.so (oeglSwapBuffers something maybe)
#10 pc 000037dd /system/lib/egl/eglsubAndroid.so (eglSwapBuffers something maybe)
#11 pc 00010f90 /system/lib/egl/libEGL_adreno200.so (qeglDrvAPI_eglSwapBuffers+452)
#12 pc 000061bc /system/lib/egl/libEGL_adreno200.so (eglSwapBuffers+16)
#13 pc 0000c6a9 /system/lib/libEGL.so (eglSwapBuffers+164)

http://ivivaldi.blog.me/120093023673

http://elinux.org/images/2/2b/Android_graphics_path–chis_simmonds.pdf

https://charleszblog.wordpress.com/category/android-2/graphics-android/surfaceflinger/

https://www.nskint.co.jp/01_solution/02_kumikomi/ForeignActivities/mamenight_Android.pdf

http://wnwolf.com/android/2014/06/22/surfaceflinger-and-client/ good

http://www.bkjia.com/Androidjc/862070.html

http://www.tamabc.com/article/104698.html

http://www.programgo.com/article/67324442081/

http://2net.co.uk/training.html

http://blog.csdn.net/windskier/article/details/7041610

apendix

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved