您的位置:华清远见教育科技集团 >> Android资料 >> Android Layer纹理重载的实现  
 
Android Layer纹理重载的实现
分享到:

“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();
            }
        }
    }

 更多相关文章

·Android Surface Flinger 服务器概述
·Android 属性动画开发源码
·Android系统层次结构及分析
·Android平板电脑的设计
·Android本地服务的启动