Android graphic path

UI的画图流程中,先不管怎么填充要画的数据的,只是来看一下需要画到屏幕上的数据是通过怎样的流程最终传递到屏幕上的。这个流程都是UI获取并创建Surface并利用Cavans,Bitmap等画好之后,传递给SurfaceFlinger去Composite并传递给HWComposer去画到屏幕上的。根据Chris Simmonds关于graphic path的说明来具体看一。下http://elinux.org/images/2/2b/Android_graphics_path–chis_simmonds.pdf)。

Android graphic path_第1张图片

Inception of a pixel

  1. Everything begins when an activity draws to a surface
  2. 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
  3. In all cases the drawing is rendered to a Surface which contains a GraphicBuffer

SurfaceFlinger binder interfaces

Android graphic path_第2张图片

ISurfaceComposer

Android graphic path_第3张图片

ISurfaceComposerClient

Android graphic path_第4张图片

IDisplayEventConnection

Android graphic path_第5张图片

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

sp<ISurfaceComposer> 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<ISurfaceComposerClient> composerClient = composer->createConnection();

The above two methods can be combined in single step:

sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;

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

sp<SurfaceControl> surfaceControl = composerClient->createSurface();

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

sp<Surface> 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<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
        const Rect bounds(backBuffer->width, backBuffer->height);

        Region newDirtyRegion;
        if (inOutDirtyBounds) {
            newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
            newDirtyRegion.andSelf(bounds);
        } else {
            newDirtyRegion.set(bounds);
        }

        // figure out if we can copy the frontbuffer back
        const sp<GraphicBuffer>& 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<NUM_BUFFER_SLOTS ; i++) {
                mSlots[i].dirtyRegion.clear();
            }
        }

        { // scope for the lock
            Mutex::Autolock lock(mMutex);
            int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
            if (backBufferSlot >= 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)。如下图:

Android graphic path_第6张图片

  • 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:    
        wp<ConsumerListener>mConsumerListener;
}

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

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

Android graphic path_第7张图片
也是有一對BpGraphicBufferConsumer/BnGraphicBufferConsumer支持他們之間的信息傳輸
下面是BufferQueue中的核心函數分析:

Android graphic path_第8张图片

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

status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* 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;h<sBuffer.height;h++){
                memcpy((char*)sBuffer.bits+(sBuffer.stride*bytesPerPixel(sBuffer.format)*h), DecData+(sBuffer.width*bytesPerPixel(sBuffer.format)*h),sBuffer.width*bytesPerPixel(sBuffer.format)) ;
            }
        }
    }
    mFlingerSurface->unlockAndPost();//post过去!!
}

2D rendering path

Android graphic path_第9张图片

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

Android graphic path_第10张图片

Composition

Android graphic path_第11张图片

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

Android graphic path_第12张图片

BufferQueue state diagram

BufferQueue

Android graphic path_第13张图片

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<mDisplays.size() ; dpy++) {
        const sp<DisplayDevice>& 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的几种显示状态:
Android graphic path_第14张图片

  • 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>& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* 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

Android graphic path_第15张图片

Displays

IGraphicBufferAlloc and friends

Android graphic path_第16张图片

Buffer usage and pixel format

Android graphic path_第17张图片

Gralloc

Android graphic path_第18张图片

OpenGL ES

Android graphic path_第19张图片

EGL

Android graphic path_第20张图片

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<GraphicBuffer> buf;
123 sp<Fence> 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<Fence>& acquireFence, const sp<GraphicBuffer>& 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=<optimized out>, request=17921) at bionic/libc/bionic/ioctl.c:41
#2 0x400eed38 in fb_post (dev=<optimized out>, buffer=0x4122ff80) at hardware/qcom/display/libgralloc/framebuffer.cpp:129
#3 0x4004ec5a in android::FramebufferNativeWindow::queueBuffer (window=0x4122f578, buffer=<optimized out>) 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 <updater_thread>, arg=0x41230f10, tls=0x41041f00) at bionic/libc/bionic/pthread.c:218
#6 0x4027860c in pthread_create (thread_out=0x41230f58, attr=0x402a0154 <gDefaultPthreadAttr>, start_routine=0x40423c55 <updater_thread>, 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<NativeBuffer*>(buffer)->handle;
281
282 sp<Fence> 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<NativeBuffer*>(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

Android graphic path_第21张图片

Android graphic path_第22张图片

Android graphic path_第23张图片

Android graphic path_第24张图片

Android graphic path_第25张图片

Android graphic path_第26张图片

Android graphic path_第27张图片

你可能感兴趣的:(android,Surface)