編輯:關於Android編程
UI的畫圖流程中,先不管怎麼填充要畫的數據的,只是來看一下需要畫到屏幕上的數據是通過怎樣的流程最終傳遞到屏幕上的。這個流程都是UI獲取並創建Surface並利用Cavans,Bitmap等畫好之後,傳遞給SurfaceFlinger去Composite並傳遞給HWComposer去畫到屏幕上的。根據Chris Simmonds關於graphic path的說明來具體看一。
一個activity等Client畫一個UI的流程如下:
ISurfaceComposer is the interface to talk to SurfaceFlinger, there’re two ways to get ISurfaceComposer interface in Client:
spcomposer; composer = ComposerService::getComposerService();
or
getService("SurfaceFlinger", &composer);
ISurfaceComposerClient is the interface to create Surface. To get ISurfaceComposerClient interface, use the ISurfaceComposer instance returned above:
spcomposerClient = composer->createConnection();
The above two methods can be combined in single step:
spcomposerClient = new SurfaceComposerClient;
To operate on Surface, you have to get SurfaceControl first, simply call createSurface on the SurfaceComposerClient instance:
spsurfaceControl = composerClient->createSurface();
And call getSurface on SurfaceControl instance, you can finally get Surface:
spsurface = 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) { spbackBuffer(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過去!! }
? 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
frameworks/native/include/ui/GraphicBuffer.h
Represents a buffer, wraps ANativeWindowBuffer Attributes including width, height, format, usage inherited from ANativeWindowBuffer這裏先用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中。
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:
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驅動去顯示了。。
Layer在createSurface()創建Surface的時候被一起創建並保存。在使用SurfaceComposerClient::createSurface()創建surface的時候,需要傳名字,顯示的寬度/高通,而且需要顯示的format,最後還有一個參數是flags,這個是顯示窗口顯示狀態的(dim,blur等等)。以下是Layer的幾種顯示狀態:
創建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
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 spbuf; 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
??嵌入式設備的一個普遍特點是內存容量相對有限。當運行的程序超過一定數量時,或者涉及復雜的計算時,很可能出現內存不足,進而導致系統卡頓的現象。Android 系統也不例外
android原生的dialog太生硬了,之前看到了這個效果非常不錯但是沒有用過,今天給別人推薦使用,他遇到了問題,導入後錯誤非常多,也沒有庫工程。於是自己認真看了一下,
安裝Android Support Repository最低版本 minSdkVersion 18添加Uiautomator在build.gradle添加對Uiautom
一、簡介 地圖控件自v2.3.5版本起,支持多實例,即開發者可以在一個頁面中建立多個地圖對象,並且針對這些對象分別操作且不會產生相互干擾。 文件名:D