97干视频,99国产精品懂色,亚洲精品99久久久久中文字幕,伊人五月丁香综合AⅤ,国产精品成人免费999

  您的位置:華清遠見教育科技集團 >> 新聞動態(tài) >> Android資料 >> Android Layer紋理重載的實現(xiàn)  
 
Android Layer紋理重載的實現(xiàn)
分享到:

“Layer”模式是常見的一種Layer,在創(chuàng)建Surface時,會為每個Surface分配兩個緩沖:前端緩沖(Front Buffer)和后端緩沖(Back Buffer)。不論前端緩沖還是后端緩沖,其本質(zhì)上均為GraphicBuffer對象。根據(jù)渲染方式的不同,GraphicBuffer的用法可以分為多種,在“Layer”模式的Layer中,系統(tǒng)會根據(jù)緩沖的使用情況設置渲染方式是軟件渲染、硬件渲染、硬件組合等。

前端緩沖和后端緩沖是根據(jù)緩沖所處的位置來區(qū)別的,當緩沖在后端時,系統(tǒng)在該緩沖上進行渲染,當完成渲染后,該緩沖轉(zhuǎn)變?yōu)榍岸司彌_和其他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));    //獲取渲染區(qū)域
    mPostedDirtyRegion=dirty.intersect( newFrontBuffer->getBounds() );    //獲取重疊區(qū)域
    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;
        //重新計算可視區(qū)域
        recomputeVisibleRegions=true;
        }
        mFreezeLock.clear();
        }
        if (lcblk->getQueuedCount()) {    //計算前端緩沖的數(shù)量
            // signal an event if we have more buffers waiting
        mFlinger->signalEvent();
        }
        if (!mPostedDirtyRegion.isEmpty()) {     //如果有重疊區(qū)域,為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();
        }
    }

當后端緩沖切換為前端緩沖時,系統(tǒng)需要判斷該緩沖要顯示的區(qū)域是否和其他Surface的Layer有重疊,如果發(fā)生重疊,就計算出重疊的區(qū)域,然后對重疊的區(qū)域進行Layer紋理重載。Layer重載紋理的過程如下:

代碼:Layer重載紋理的過程

void Layer::reloadTexture(const Region& dirty)
    {
    Mutex::Autolock _l(mLock);
    spbuffer(getFrontBufferLocked());
    if (buffer==NULL) {
        return;
    }
    const int index=mFrontBufferIndex;
    //如果需要,創(chuàng)建新的紋理名
    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();
            }
        }
    }

 更多相關(guān)文章

·Android Surface Flinger 服務器概述
·Android 屬性動畫開發(fā)源碼
·Android系統(tǒng)層次結(jié)構(gòu)及分析
·Android平板電腦的設計
·Android本地服務的啟動