下面幾張圖片分別表示了不同Layer產(chǎn)生的視覺效果:
- Layer對(duì)應(yīng)普通的窗口
- LayerDim 會(huì)使他后面的窗口產(chǎn)生一個(gè)變暗的透明效果
- LayerBlur在LayerDim的基礎(chǔ)上,背景會(huì)產(chǎn)生模糊的效果
創(chuàng)建Layer
默認(rèn)地,創(chuàng)建普通的窗口Surface,在SurfaceFlinger中會(huì)創(chuàng)建Layer類,如果想創(chuàng)建LayerDim或LayerBlur,應(yīng)用程序需要在綁定View之前設(shè)置一下窗口的標(biāo)志位:
創(chuàng)建LayerDim效果:
- @Override
- protected void onCreate(Bundle icicle) {
-
- super.onCreate(icicle);
-
-
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
- WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- ......
- setContentView(......);
- }
創(chuàng)建LayerBlur效果:
- @Override
- protected void onCreate(Bundle icicle) {
-
- super.onCreate(icicle);
-
-
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
- WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
- ......
- setContentView(......);
- }
相應(yīng)地,在SufaceFlinger中,會(huì)根據(jù)Java層傳入的標(biāo)志,創(chuàng)建不同的Layer:
- sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
- const String8& name, ISurfaceFlingerClient::surface_data_t* params,
- DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags)
- {
- sp<LayerBaseClient> layer;
- sp<LayerBaseClient::Surface> surfaceHandle;
- ......
- switch (flags & eFXSurfaceMask) {
- case eFXSurfaceNormal:
- if (UNLIKELY(flags & ePushBuffers)) {
- layer = createPushBuffersSurfaceLocked(client, d, id,
- w, h, flags);
- } else {
- layer = createNormalSurfaceLocked(client, d, id,
- w, h, flags, format);
- }
- break;
- case eFXSurfaceBlur:
- layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
- break;
- case eFXSurfaceDim:
- layer = createDimSurfaceLocked(client, d, id, w, h, flags);
- break;
- }
-
- if (layer != 0) {
- layer->setName(name);
- setTransactionFlags(eTransactionNeeded);
- surfaceHandle = layer->getSurface();
- ........
- }
-
- return surfaceHandle;
- }
Layer類的靜態(tài)結(jié)構(gòu)
下面的圖展示了Layer類之間的繼承關(guān)系:
- 所有的Layer都繼承了LayerBaseClient,SurfaceFlinger統(tǒng)一通過LayerBaseClient類訪問其他的派生Layer類
- LayerBaseClient的內(nèi)嵌類Surface繼承了ISurface接口,ISurface用于和SurfaceFlinger的客戶端交互
- Layer和LayerBuffer都有各自的內(nèi)嵌類:SurfaceLayer、SurfaceLayerBuffer,繼承了LayerBaseClient的內(nèi)嵌類Surface
- LayerBuffer還有另外的內(nèi)嵌類:Source,并且派生出另外兩個(gè)內(nèi)嵌類:BufferSource、OverlaySource
ISurface接口
ISurface接口其實(shí)非常簡單,只有幾個(gè)函數(shù):
- requestBuffer() // Layer類使用,用于申請(qǐng)frontbuffer、backbuffer,初始化或size變化時(shí)調(diào)用
- registerBuffers() // LayerBuffer類使用,用于注冊(cè)IMemoryHeap接口
- unregisterBuffers() // LayerBuffer類使用,用于注銷IMemoryHeap接口
- postBuffer() // post用于刷新的圖像數(shù)據(jù)
- createOverlay() // 用于創(chuàng)建Overlay表面
LayerBaseClient的派生類中,會(huì)有一個(gè)內(nèi)嵌類,繼承LayerBaseClient::Surface,然后根據(jù)需要會(huì)實(shí)現(xiàn)該接口的相應(yīng)函數(shù)。
Layer類
Layer類是使用最多的一個(gè),普通的應(yīng)用程序窗口都會(huì)對(duì)應(yīng)一個(gè)Layer類,Layer類的內(nèi)嵌類SurfaceLayer繼承了ISurface接口,創(chuàng)建Layer類時(shí),將會(huì)返回一個(gè)ISurface接口給創(chuàng)建者。并且,Layer類在創(chuàng)建時(shí)會(huì)建立兩個(gè)GraphicBuffer對(duì)象,這兩個(gè)Buffer在不同的時(shí)刻分別被作為frontbuffer和backbuffer,frontbuffer用于本窗口的畫圖操作,backbuffer用于所有窗口的混合操作。但是兩個(gè)GraphicBuffer對(duì)象在創(chuàng)建時(shí)并沒有真正地分配內(nèi)存,而是在第一次lockBuffer時(shí)才正式通過ISurface接口的requestBuffer方法申請(qǐng)內(nèi)存,當(dāng)窗口的大小發(fā)生變化時(shí),也要重新分配適合窗口大小的內(nèi)存。Layer類的主要成員函數(shù)如下:
- createSurface() 返回ISurface接口
- setBuffers() 創(chuàng)建兩個(gè)GraphicBuffer對(duì)象,創(chuàng)建ISurface接口的實(shí)現(xiàn)類SurfaceLayer
- onDraw() 把frontbuffer中的圖像數(shù)據(jù)通過OpenGL混合到OpenGL的主表面中
- doTransaction() 檢測并處理窗口大小變化
- lockPageFlip() 獲取frontbuffer,并且生成frontbuffer的OpenGL貼圖
- finishPageFlip() unlock frontbuffer,此后該buffer會(huì)queue到空閑列表中,下次可以作為backbuffer使用
LayerDim和LayerBlur
LayerDim和LayerBlur,他們的顯示內(nèi)容是固定不變的(透明的黑色),所以不需要分配兩個(gè)GraphicBuffer對(duì)象,因此它們也沒有繼承自LayerBaseClient::Surface的內(nèi)嵌類,而是直接使用LayerBaseClient::Surface類作為它們的ISurface接口。以LayerDim為例跟蹤一下它的Draw過程:
- 創(chuàng)建LayerDim時(shí),在LayerDim.initDimmer()中生成純黑的OpenGL貼圖
- void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
- {
- sTexId = -1;
- sImage = EGL_NO_IMAGE_KHR;
- ......
- if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
-
- sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
- GraphicBuffer::USAGE_SW_WRITE_OFTEN |
- GraphicBuffer::USAGE_HW_TEXTURE);
-
- android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
-
- glGenTextures(1, &sTexId);
- glBindTexture(GL_TEXTURE_2D, sTexId);
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);
- ......
-
- GGLSurface t;
- buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
- memset(t.data, 0, t.stride * t.height * 2);
- buffer->unlock();
- sUseTexture = true;
- }
- }
- 在OnDraw()中把第一步生成的貼圖混合到OpenGL的主表面中
- void LayerDim::onDraw(const Region& clip) const
- {
- const State& s(drawingState());
- Region::const_iterator it = clip.begin();
- Region::const_iterator const end = clip.end();
- if (s.alpha>0 && (it != end)) {
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- ......
-
- glColor4x(0, 0, 0, alpha);
-
- #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
- if (sUseTexture) {
- glBindTexture(GL_TEXTURE_2D, sTexId);
- glEnable(GL_TEXTURE_2D);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- const GLshort texCoords[4][2] = {
- { 0, 0 },
- { 0, 1 },
- { 1, 1 },
- { 1, 0 }
- };
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_SHORT, 0, texCoords);
- } else
- #endif
- {
- glDisable(GL_TEXTURE_2D);
- }
-
- GLshort w = sWidth;
- GLshort h = sHeight;
- const GLshort vertices[4][2] = {
- { 0, 0 },
- { 0, h },
- { w, h },
- { w, 0 }
- };
- glVertexPointer(2, GL_SHORT, 0, vertices);
-
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- }
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- }
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。