“Layer”模式是常见的一种Layer,在创建Surface时,会为每个Surface分配两个缓冲:前端缓冲(Front Buffer)和后端缓冲(Back Buffer)。不论前端缓冲还是后端缓冲,其本质上均为GraphicBuffer对象。根据渲染方式的不同,GraphicBuffer的用法可以分为多种,在“Layer”模式的Layer中,系统会根据缓冲的使用情况设置渲染方式是软件渲染、硬件渲染、硬件组合等。
        前端缓冲和后端缓冲是根据缓冲所处的位置来区别的,当缓冲在后端时,系统在该缓冲上进行渲染,当完成渲染后,该缓冲转变为前端缓冲和其他Surface中的Layer重载纹理并显示在屏幕上。
        后端缓冲切换为前段缓冲并向屏幕上渲染的过程如下:
        代码:后端缓冲切换为前端缓冲并渲染的过程
        void Layer::lockPageFlip(bool& recomputeVisibleRegions)
    {
        ssize_t buf=lcblk->retireAndLock(); //利用共享缓冲服务对缓冲加锁
        if (buf < NO_ERROR) {
                return;
            }
        mFrontBufferIndex=buf;    //缓冲由后端缓冲切换为前端缓冲
        sp< GraphicBuffer> newFrontBuffer(getBuffer(buf));
        const Region dirty(lcblk->getDirtyRegion(buf));    //获取渲染区域
        mPostedDirtyRegion=dirty.intersect( newFrontBuffer->getBounds() );    //获取重叠区域
        const Layer::State& front(drawingState());
        if (newFrontBuffer->getWidth()==front.requested_w &&
            newFrontBuffer->getHeight()==front.requested_h)
        {
                if ((front.w !=front.requested_w) ||
                        (front.h !=front.requested_h))
                {
                    Layer::State& editDraw(mDrawingState);
                    editDraw.w=editDraw.requested_w;
                    editDraw.h=editDraw.requested_h;
                    Layer::State& editTemp(currentState());
                    editTemp.w=editDraw.w;
                    editTemp.h=editDraw.h;
			        //重新计算可视区域
                    recomputeVisibleRegions=true;
                }
                mFreezeLock.clear();
            }
            if (lcblk->getQueuedCount()) {    //计算前端缓冲的数量
                    // signal an event if we have more buffers waiting
                mFlinger->signalEvent();
            }
            if (!mPostedDirtyRegion.isEmpty()) {	    //如果有重叠区域,为Layer重载纹理
                    reloadTexture( mPostedDirtyRegion );
            }
    }
    void Layer::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
    {
        Region dirtyRegion(mPostedDirtyRegion);
        if (!dirtyRegion.isEmpty()) {
            mPostedDirtyRegion.clear();
            const Layer::State& s(drawingState());
            const Transform tr(planeTransform * s.transform);
            dirtyRegion=tr.transform(dirtyRegion);
            dirtyRegion.andSelf(visibleRegionScreen);
            outDirtyRegion.orSelf(dirtyRegion);
            }
        if (visibleRegionScreen.isEmpty()) {
                mFreezeLock.clear();
            }
    }
        当后端缓冲切换为前端缓冲时,系统需要判断该缓冲要显示的区域是否和其他Surface的Layer有重叠,如果发生重叠,就计算出重叠的区域,然后对重叠的区域进行Layer纹理重载。Layer重载纹理的过程如下:
        代码:Layer重载纹理的过程
        void Layer::reloadTexture(const Region& dirty)
    {
        Mutex::Autolock _l(mLock);
        spbuffer(getFrontBufferLocked());
        if (buffer==NULL) {
                return;
        }
        const int index=mFrontBufferIndex;
	    //如果需要,创建新的纹理名
        if (UNLIKELY(mTextures[index].name==-1U)) {
                mTextures[index].name=createTexture();
                mTextures[index].width=0;
                mTextures[index].height=0;
        }
    #ifdef EGL_ANDROID_image_native_buffer
        if (mFlags & DisplayHardware::DIRECT_TEXTURE) {    //直接渲染
            if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {//判断是否硬件组合
                if (mTextures[index].dirty) {
                        initializeEglImage(buffer, &mTextures[index]);    //组合为EglImage
                    }
            } else {    //通过mHybridBuffer去渲染
                if (mHybridBuffer==0 || (mHybridBuffer->width !=buffer->width ||
                           mHybridBuffer->height !=buffer->height)) {
                        mHybridBuffer.clear();
                        mHybridBuffer=new GraphicBuffer(
                                buffer->width, buffer->height, buffer->format,
                                GraphicBuffer::USAGE_SW_WRITE_OFTEN |
                                GraphicBuffer::USAGE_HW_TEXTURE);
                        initializeEglImage(mHybridBuffer, &mTextures[0]);
                    }
                GGLSurface t;
                status_t res=buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
                LOGE_IF(res, "error %d (%s) locking buffer %p",
                            res, strerror(res), buffer.get());
                if (res==NO_ERROR) {
                    Texture* const texture(&mTextures[0]);
                    glBindTexture(GL_TEXTURE_2D, texture->name);
                    sp< GraphicBuffer> buf(mHybridBuffer);
                    void* vaddr;
                    res=buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
                    if (res==NO_ERROR) {
                        int bpp=0;
                        switch (t.format) {
                        case GGL_PIXEL_FORMAT_RGB_565:
                        case GGL_PIXEL_FORMAT_RGBA_4444:
                                bpp=2;
                                break;
                        case GGL_PIXEL_FORMAT_RGBA_8888:
                        case GGL_PIXEL_FORMAT_RGBX_8888:
                                bpp=4;
                                break;
                        case GGL_PIXEL_FORMAT_YCbCr_422_SP:
                        case GGL_PIXEL_FORMAT_YCbCr_420_SP:
                                bpp=1;
                                break;
                        default:
                            LOGE("layer %p, texture=%d, using format %d, which is not ""supported by the GL", this, texture->name, t.format);
                        }
                        if (bpp) {
                            const Rect bounds(dirty.getBounds());
                            size_t src_stride=t.stride;
                            size_t dst_stride=buf->stride;
                            if (src_stride==dst_stride &&
                                bounds.width()==t.width &&
                                bounds.height()==t.height)
                                {
                                        memcpy(vaddr, t.data, t.height * t.stride * bpp);
                                } else {
                                GLubyte const * src=t.data+(bounds.left+bounds.top * src_stride) * bpp;
                                GLubyte * dst=(GLubyte *)vaddr+(bounds.left+bounds.top * dst_stride) * bpp;
                                const size_t length=bounds.width() * bpp;
                                size_t h=bounds.height();
                                src_stride *=bpp;
                                dst_stride *=bpp;
                                    while (h--) {
                                     memcpy(dst, src, length);
                                        dst +=dst_stride;
                                        src +=src_stride;
                                            }
                                    }
                            }
                            buf->unlock();
                    }
                    buffer->unlock();
                        }
                }
        } else
    #endif
        {
            for (size_t i=0 ; i< NUM_BUFFERS ; i++) {
                    mTextures[i].image=EGL_NO_IMAGE_KHR;
                }
            GGLSurface t;
            status_t res=buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
            LOGE_IF(res, "error %d (%s) locking buffer %p",res, strerror(res), buffer.get());
            if (res==NO_ERROR) {
                    loadTexture(&mTextures[0], dirty, t);	//加载纹理
                    buffer->unlock();
                    }
            }
    }