Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55c97878 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android Git Automerger
Browse files

am e0630ae3: am 6a70cb8a: Merge "Refactor some code in surfaceflinger in...

am e0630ae3: am 6a70cb8a: Merge "Refactor some code in surfaceflinger in preparation of upcoming changes" into kraken
parents 74c932d9 e0630ae3
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@ LOCAL_SRC_FILES:= \
    LayerDim.cpp \
    LayerDim.cpp \
    MessageQueue.cpp \
    MessageQueue.cpp \
    SurfaceFlinger.cpp \
    SurfaceFlinger.cpp \
    TextureManager.cpp \
    Tokenizer.cpp \
    Tokenizer.cpp \
    Transform.cpp
    Transform.cpp


+156 −81
Original line number Original line Diff line number Diff line
@@ -48,41 +48,49 @@ template <typename T> inline T min(T a, T b) {
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


Layer::Layer(SurfaceFlinger* flinger, DisplayID display, 
Layer::Layer(SurfaceFlinger* flinger, DisplayID display, 
        const sp<Client>& c, int32_t i)
        const sp<Client>& client, int32_t i)
    :   LayerBaseClient(flinger, display, c, i),
    :   LayerBaseClient(flinger, display, client, i),
        lcblk(NULL),
        mSecure(false),
        mSecure(false),
        mNeedsBlending(true),
        mNeedsBlending(true),
        mNeedsDithering(false)
        mNeedsDithering(false),
        mTextureManager(mFlags),
        mBufferManager(mTextureManager)
{
{
    // no OpenGL operation is possible here, since we might not be
    // no OpenGL operation is possible here, since we might not be
    // in the OpenGL thread.
    // in the OpenGL thread.
    mFrontBufferIndex = lcblk->getFrontBuffer();
    lcblk = new SharedBufferServer(
            client->ctrlblk, i, mBufferManager.getBufferCount(),
            getIdentity());

   mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
}
}


Layer::~Layer()
Layer::~Layer()
{
{
    destroy();
    destroy();
    // the actual buffers will be destroyed here
    // the actual buffers will be destroyed here
    delete lcblk;
}
}


void Layer::destroy()
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
{
{
    for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
    // wake up the condition
        if (mTextures[i].name != -1U) {
    lcblk->setStatus(NO_INIT);
            glDeleteTextures(1, &mTextures[i].name);
            mTextures[i].name = -1U;
}
}
        if (mTextures[i].image != EGL_NO_IMAGE_KHR) {

void Layer::destroy()
{
    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
            eglDestroyImageKHR(dpy, mTextures[i].image);
    mBufferManager.destroy(dpy);
            mTextures[i].image = EGL_NO_IMAGE_KHR;

        }
    mSurface.clear();

    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
        mBuffers[i].clear();
    mWidth = mHeight = 0;
    mWidth = mHeight = 0;
}
}
    mSurface.clear();
}


sp<LayerBaseClient::Surface> Layer::createSurface() const
sp<LayerBaseClient::Surface> Layer::createSurface() const
{
{
@@ -131,17 +139,13 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
    int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
    int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
    mNeedsDithering = layerRedsize > displayRedSize;
    mNeedsDithering = layerRedsize > displayRedSize;


    for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
        mBuffers[i] = new GraphicBuffer();
    }
    mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
    mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
    return NO_ERROR;
    return NO_ERROR;
}
}


void Layer::reloadTexture(const Region& dirty)
void Layer::reloadTexture(const Region& dirty)
{
{
    Mutex::Autolock _l(mLock);
    sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
    sp<GraphicBuffer> buffer(getFrontBufferLocked());
    if (buffer == NULL) {
    if (buffer == NULL) {
        // this situation can happen if we ran out of memory for instance.
        // this situation can happen if we ran out of memory for instance.
        // not much we can do. continue to use whatever texture was bound
        // not much we can do. continue to use whatever texture was bound
@@ -149,37 +153,24 @@ void Layer::reloadTexture(const Region& dirty)
        return;
        return;
    }
    }


    const int index = mFrontBufferIndex;

    // create the new texture name if needed
    if (UNLIKELY(mTextures[index].name == -1U)) {
        mTextures[index].name = createTexture();
        mTextures[index].width = 0;
        mTextures[index].height = 0;
    }

#ifdef EGL_ANDROID_image_native_buffer
#ifdef EGL_ANDROID_image_native_buffer
    if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
    if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
        if (mTextures[index].dirty) {
        EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
            if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) {
        if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
            // not sure what we can do here...
            // not sure what we can do here...
            mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
            mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
            goto slowpath;
            goto slowpath;
        }
        }
        }
    } else
    } else
#endif
#endif
    {
    {
slowpath:
slowpath:
        for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
            mTextures[i].image = EGL_NO_IMAGE_KHR;
        }
        GGLSurface t;
        GGLSurface t;
        status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
        status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
        LOGE_IF(res, "error %d (%s) locking buffer %p",
        LOGE_IF(res, "error %d (%s) locking buffer %p",
                res, strerror(res), buffer.get());
                res, strerror(res), buffer.get());
        if (res == NO_ERROR) {
        if (res == NO_ERROR) {
            loadTexture(&mTextures[0], dirty, t);
            mBufferManager.loadTexture(dirty, t);
            buffer->unlock();
            buffer->unlock();
        }
        }
    }
    }
@@ -187,11 +178,8 @@ slowpath:


void Layer::onDraw(const Region& clip) const
void Layer::onDraw(const Region& clip) const
{
{
    int index = mFrontBufferIndex;
    Texture tex(mBufferManager.getActiveTexture());
    if (mTextures[index].image == EGL_NO_IMAGE_KHR)
    if (tex.name == -1LU) {
        index = 0;
    GLuint textureName = mTextures[index].name;
    if (UNLIKELY(textureName == -1LU)) {
        // the texture has not been created yet, this Layer has
        // the texture has not been created yet, this Layer has
        // in fact never been drawn into. This happens frequently with
        // in fact never been drawn into. This happens frequently with
        // SurfaceView because the WindowManager can't know when the client
        // SurfaceView because the WindowManager can't know when the client
@@ -217,7 +205,7 @@ void Layer::onDraw(const Region& clip) const
        }
        }
        return;
        return;
    }
    }
    drawWithOpenGL(clip, mTextures[index]);
    drawWithOpenGL(clip, tex);
}
}


sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
@@ -254,15 +242,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
        Mutex::Autolock _l(mLock);
        Mutex::Autolock _l(mLock);
        w = mWidth;
        w = mWidth;
        h = mHeight;
        h = mHeight;
        buffer = mBuffers[index];
        buffer = mBufferManager.detachBuffer(index);
        
        // destroy() could have been called before we get here, we log it
        // because it's uncommon, and the code below should handle it
        LOGW_IF(buffer==0, 
                "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
                index, w, h);
        
        mBuffers[index].clear();
    }
    }


    const uint32_t effectiveUsage = getEffectiveUsage(usage);
    const uint32_t effectiveUsage = getEffectiveUsage(usage);
@@ -290,10 +270,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
    if (err == NO_ERROR && buffer->handle != 0) {
    if (err == NO_ERROR && buffer->handle != 0) {
        Mutex::Autolock _l(mLock);
        Mutex::Autolock _l(mLock);
        if (mWidth && mHeight) {
        if (mWidth && mHeight) {
            // and we have new buffer
            mBufferManager.attachBuffer(index, buffer);
            mBuffers[index] = buffer;
            // texture is now dirty...
            mTextures[index].dirty = true;
        } else {
        } else {
            // oops we got killed while we were allocating the buffer
            // oops we got killed while we were allocating the buffer
            buffer.clear();
            buffer.clear();
@@ -338,13 +315,10 @@ uint32_t Layer::doTransaction(uint32_t flags)
        (front.requested_h != temp.requested_h)) {
        (front.requested_h != temp.requested_h)) {
        // the size changed, we need to ask our client to request a new buffer
        // the size changed, we need to ask our client to request a new buffer
        LOGD_IF(DEBUG_RESIZE,
        LOGD_IF(DEBUG_RESIZE,
                    "resize (layer=%p), requested (%dx%d), "
                    "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
                    "drawing (%d,%d), (%dx%d), (%dx%d)",
                    this, 
                    this, 
                    int(temp.requested_w), int(temp.requested_h),
                    int(temp.requested_w), int(temp.requested_h),
                    int(front.requested_w), int(front.requested_h),
                    int(front.requested_w), int(front.requested_h));
                    int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
                    int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));


        // we're being resized and there is a freeze display request,
        // we're being resized and there is a freeze display request,
        // acquire a freeze lock, so that the screen stays put
        // acquire a freeze lock, so that the screen stays put
@@ -396,22 +370,25 @@ void Layer::setDrawingSize(uint32_t w, uint32_t h) {
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
{
    ssize_t buf = lcblk->retireAndLock();
    ssize_t buf = lcblk->retireAndLock();
    if (buf < NO_ERROR) {
    if (buf == NOT_ENOUGH_DATA) {
        //LOGW("nothing to retire (%s)", strerror(-buf));
        // NOTE: This is not an error, it simply means there is nothing to
        // NOTE: here the buffer is locked because we will used 
        // retire. The buffer is locked because we will use it
        // for composition later in the loop
        // for composition later in the loop
        return;
        return;
    }
    }


    // ouch, this really should never happen
    if (buf < NO_ERROR) {
    if (uint32_t(buf)>=NUM_BUFFERS) {
        LOGE("retireAndLock() buffer index (%d) out of range", buf);
        LOGE("retireAndLock() buffer index (%d) out of range", buf);
        mPostedDirtyRegion.clear();
        mPostedDirtyRegion.clear();
        return;
        return;
    }
    }


    // we retired a buffer, which becomes the new front buffer
    // we retired a buffer, which becomes the new front buffer
    mFrontBufferIndex = buf;
    if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
        LOGE("retireAndLock() buffer index (%d) out of range", buf);
        mPostedDirtyRegion.clear();
        return;
    }


    // get the dirty region
    // get the dirty region
    sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
    sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
@@ -503,10 +480,9 @@ void Layer::unlockPageFlip(


void Layer::finishPageFlip()
void Layer::finishPageFlip()
{
{
    status_t err = lcblk->unlock( mFrontBufferIndex );
    int buf = mBufferManager.getActiveBufferIndex();
    LOGE_IF(err!=NO_ERROR, 
    status_t err = lcblk->unlock( buf );
            "layer %p, buffer=%d wasn't locked!",
    LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
            this, mFrontBufferIndex);
}
}




@@ -543,6 +519,109 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


Layer::BufferManager::BufferManager(TextureManager& tm)
    : mTextureManager(tm), mActiveBuffer(0), mFailover(false)
{
}

size_t Layer::BufferManager::getBufferCount() const {
    return NUM_BUFFERS;
}

// only for debugging
sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
    return mBufferData[index].buffer;
}

status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
    // TODO: need to validate 'index'
    mActiveBuffer = index;
    return NO_ERROR;
}

size_t Layer::BufferManager::getActiveBufferIndex() const {
    return mActiveBuffer;
}

Texture Layer::BufferManager::getActiveTexture() const {
    return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture;
}

sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
    Mutex::Autolock _l(mLock);
    return mBufferData[mActiveBuffer].buffer;
}

sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
{
    sp<GraphicBuffer> buffer;
    Mutex::Autolock _l(mLock);
    buffer = mBufferData[index].buffer;
    mBufferData[index].buffer = 0;
    return buffer;
}

status_t Layer::BufferManager::attachBuffer(size_t index,
        const sp<GraphicBuffer>& buffer)
{
    Mutex::Autolock _l(mLock);
    mBufferData[index].buffer = buffer;
    mBufferData[index].texture.dirty = true;
    return NO_ERROR;
}

status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy)
{
    if (tex->name != -1U) {
        glDeleteTextures(1, &tex->name);
        tex->name = -1U;
    }
    if (tex->image != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(dpy, tex->image);
        tex->image = EGL_NO_IMAGE_KHR;
    }
    return NO_ERROR;
}

status_t Layer::BufferManager::destroy(EGLDisplay dpy)
{
    Mutex::Autolock _l(mLock);
    for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
        destroyTexture(&mBufferData[i].texture, dpy);
        mBufferData[i].buffer = 0;
    }
    destroyTexture(&mFailoverTexture, dpy);
    return NO_ERROR;
}

status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
        const sp<GraphicBuffer>& buffer)
{
    size_t index = mActiveBuffer;
    Texture& texture(mBufferData[index].texture);
    status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
    // if EGLImage fails, we switch to regular texture mode, and we
    // free all resources associated with using EGLImages.
    if (err == NO_ERROR) {
        mFailover = false;
        destroyTexture(&mFailoverTexture, dpy);
    } else {
        mFailover = true;
        for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
            destroyTexture(&mBufferData[i].texture, dpy);
        }
    }
    return err;
}

status_t Layer::BufferManager::loadTexture(
        const Region& dirty, const GGLSurface& t)
{
    return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
}

// ---------------------------------------------------------------------------

Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
        SurfaceID id, const sp<Layer>& owner)
        SurfaceID id, const sp<Layer>& owner)
    : Surface(flinger, id, owner->getIdentity(), owner)
    : Surface(flinger, id, owner->getIdentity(), owner)
@@ -558,12 +637,8 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
    sp<GraphicBuffer> buffer;
    sp<GraphicBuffer> buffer;
    sp<Layer> owner(getOwner());
    sp<Layer> owner(getOwner());
    if (owner != 0) {
    if (owner != 0) {
        LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
                "getBuffer() index (%d) out of range", index);
        if (uint32_t(index) < NUM_BUFFERS) {
        buffer = owner->requestBuffer(index, usage);
        buffer = owner->requestBuffer(index, usage);
    }
    }
    }
    return buffer;
    return buffer;
}
}


+66 −18
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@


#include "LayerBase.h"
#include "LayerBase.h"
#include "Transform.h"
#include "Transform.h"
#include "TextureManager.h"


namespace android {
namespace android {


@@ -41,11 +42,13 @@ class FreezeLock;


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


const size_t NUM_BUFFERS = 2;

class Layer : public LayerBaseClient
class Layer : public LayerBaseClient
{
{
public:
public:
    // lcblk is (almost) only accessed from the main SF thread, in the places
    // where it's not, a reference to Client must be held
    SharedBufferServer*     lcblk;

                 Layer(SurfaceFlinger* flinger, DisplayID display,
                 Layer(SurfaceFlinger* flinger, DisplayID display,
                         const sp<Client>& client, int32_t i);
                         const sp<Client>& client, int32_t i);


@@ -66,15 +69,14 @@ public:
    virtual bool isSecure() const           { return mSecure; }
    virtual bool isSecure() const           { return mSecure; }
    virtual sp<Surface> createSurface() const;
    virtual sp<Surface> createSurface() const;
    virtual status_t ditch();
    virtual status_t ditch();
    virtual void onRemoved();
    
    
    // only for debugging
    // only for debugging
    inline sp<GraphicBuffer> getBuffer(int i) const { return mBuffers[i]; }
    inline sp<GraphicBuffer> getBuffer(int i) const { return mBufferManager.getBuffer(i); }
    // only for debugging
    // only for debugging
    inline const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
    inline const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
    // only for debugging
    // only for debugging
    inline PixelFormat pixelFormat() const { return mFormat; }
    inline PixelFormat pixelFormat() const { return mFormat; }
    // only for debugging
    inline int getFrontBufferIndex() const { return mFrontBufferIndex; }


    virtual const char* getTypeId() const { return "Layer"; }
    virtual const char* getTypeId() const { return "Layer"; }


@@ -82,10 +84,6 @@ protected:
    virtual void dump(String8& result, char* scratch, size_t size) const;
    virtual void dump(String8& result, char* scratch, size_t size) const;


private:
private:
    inline sp<GraphicBuffer> getFrontBufferLocked() {
        return mBuffers[mFrontBufferIndex];
    }
 
    void reloadTexture(const Region& dirty);
    void reloadTexture(const Region& dirty);


    uint32_t getEffectiveUsage(uint32_t usage) const;
    uint32_t getEffectiveUsage(uint32_t usage) const;
@@ -116,13 +114,63 @@ private:
            sp<FreezeLock>  mFreezeLock;
            sp<FreezeLock>  mFreezeLock;
            PixelFormat     mFormat;
            PixelFormat     mFormat;


            // protected by mLock
            class BufferManager {
            sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
                static const size_t NUM_BUFFERS = 2;
            Texture         mTextures[NUM_BUFFERS];
                struct BufferData {
            uint32_t        mWidth;
                    sp<GraphicBuffer>   buffer;
            uint32_t        mHeight;
                    Texture             texture;
                };
                mutable Mutex mLock;
                BufferData          mBufferData[NUM_BUFFERS];
                Texture             mFailoverTexture;
                TextureManager&     mTextureManager;
                ssize_t             mActiveBuffer;
                bool                mFailover;
                static status_t destroyTexture(Texture* tex, EGLDisplay dpy);

            public:
                BufferManager(TextureManager& tm);

                size_t getBufferCount() const;

                // detach/attach buffer from/to given index
                sp<GraphicBuffer> detachBuffer(size_t index);
                status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);

                // ----------------------------------------------
                // must be called from GL thread

                // set/get active buffer index
                status_t setActiveBufferIndex(size_t index);
                size_t getActiveBufferIndex() const;

                // return the active buffer
                sp<GraphicBuffer> getActiveBuffer() const;

                // return the active texture (or fail-over)
                Texture getActiveTexture() const;

                // frees resources associated with all buffers
                status_t destroy(EGLDisplay dpy);

                // load bitmap data into the active buffer
                status_t loadTexture(const Region& dirty, const GGLSurface& t);

                // make active buffer an EGLImage if needed
                status_t initEglImage(EGLDisplay dpy,
                        const sp<GraphicBuffer>& buffer);

                // ----------------------------------------------
                // only for debugging
                sp<GraphicBuffer> getBuffer(size_t index) const;
            };

            TextureManager mTextureManager;
            BufferManager mBufferManager;


            mutable Mutex mLock;
            mutable Mutex mLock;
            uint32_t    mWidth;
            uint32_t    mHeight;
};
};


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
+2 −206
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#include "LayerBase.h"
#include "LayerBase.h"
#include "SurfaceFlinger.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
#include "DisplayHardware/DisplayHardware.h"
#include "TextureManager.h"




namespace android {
namespace android {
@@ -340,18 +341,6 @@ void LayerBase::draw(const Region& inClip) const
    */
    */
}
}


GLuint LayerBase::createTexture() const
{
    GLuint textureName = -1;
    glGenTextures(1, &textureName);
    glBindTexture(GL_TEXTURE_2D, textureName);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    return textureName;
}

void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
                                GLclampx green, GLclampx blue,
                                GLclampx green, GLclampx blue,
                                GLclampx alpha) const
                                GLclampx alpha) const
@@ -492,187 +481,6 @@ void LayerBase::validateTexture(GLint textureName) const
    }
    }
}
}


bool LayerBase::isSupportedYuvFormat(int format) const
{
    switch (format) {
        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
        case HAL_PIXEL_FORMAT_YCbCr_422_P:
        case HAL_PIXEL_FORMAT_YCbCr_420_P:
        case HAL_PIXEL_FORMAT_YCbCr_422_I:
        case HAL_PIXEL_FORMAT_YCbCr_420_I:
        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
            return true;
    }
    return false;
}

void LayerBase::loadTexture(Texture* texture, 
        const Region& dirty, const GGLSurface& t) const
{
    if (texture->name == -1U) {
        // uh?
        return;
    }

    glBindTexture(GL_TEXTURE_2D, texture->name);

    /*
     * In OpenGL ES we can't specify a stride with glTexImage2D (however,
     * GL_UNPACK_ALIGNMENT is a limited form of stride).
     * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
     * need to do something reasonable (here creating a bigger texture).
     * 
     * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
     * 
     * This situation doesn't happen often, but some h/w have a limitation
     * for their framebuffer (eg: must be multiple of 8 pixels), and
     * we need to take that into account when using these buffers as
     * textures.
     *
     * This should never be a problem with POT textures
     */
    
    int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
    unpack = 1 << ((unpack > 3) ? 3 : unpack);
    glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
    
    /*
     * round to POT if needed 
     */
    if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
        texture->NPOTAdjust = true;
    }
    
    if (texture->NPOTAdjust) {
        // find the smallest power-of-two that will accommodate our surface
        texture->potWidth  = 1 << (31 - clz(t.width));
        texture->potHeight = 1 << (31 - clz(t.height));
        if (texture->potWidth  < t.width)  texture->potWidth  <<= 1;
        if (texture->potHeight < t.height) texture->potHeight <<= 1;
        texture->wScale = float(t.width)  / texture->potWidth;
        texture->hScale = float(t.height) / texture->potHeight;
    } else {
        texture->potWidth  = t.width;
        texture->potHeight = t.height;
    }

    Rect bounds(dirty.bounds());
    GLvoid* data = 0;
    if (texture->width != t.width || texture->height != t.height) {
        texture->width  = t.width;
        texture->height = t.height;

        // texture size changed, we need to create a new one
        bounds.set(Rect(t.width, t.height));
        if (t.width  == texture->potWidth &&
            t.height == texture->potHeight) {
            // we can do it one pass
            data = t.data;
        }

        if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_RGB, texture->potWidth, texture->potHeight, 0,
                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
                   t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
                    GL_RGBA, GL_UNSIGNED_BYTE, data);
        } else if (isSupportedYuvFormat(t.format)) {
            // just show the Y plane of YUV buffers
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
                    GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
        } else {
            // oops, we don't handle this format!
            LOGE("layer %p, texture=%d, using format %d, which is not "
                 "supported by the GL", this, texture->name, t.format);
        }
    }
    if (!data) {
        if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
                    t.data + bounds.top*t.stride*2);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
                    t.data + bounds.top*t.stride*2);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
                   t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_RGBA, GL_UNSIGNED_BYTE,
                    t.data + bounds.top*t.stride*4);
        } else if (isSupportedYuvFormat(t.format)) {
            // just show the Y plane of YUV buffers
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_LUMINANCE, GL_UNSIGNED_BYTE,
                    t.data + bounds.top*t.stride);
        }
    }
}

status_t LayerBase::initializeEglImage(
        const sp<GraphicBuffer>& buffer, Texture* texture)
{
    status_t err = NO_ERROR;

    // we need to recreate the texture
    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());

    // free the previous image
    if (texture->image != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(dpy, texture->image);
        texture->image = EGL_NO_IMAGE_KHR;
    }

    // construct an EGL_NATIVE_BUFFER_ANDROID
    android_native_buffer_t* clientBuf = buffer->getNativeBuffer();

    // create the new EGLImageKHR
    const EGLint attrs[] = {
            EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
            EGL_NONE,                   EGL_NONE
    };
    texture->image = eglCreateImageKHR(
            dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
            (EGLClientBuffer)clientBuf, attrs);

    if (texture->image != EGL_NO_IMAGE_KHR) {
        glBindTexture(GL_TEXTURE_2D, texture->name);
        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
                (GLeglImageOES)texture->image);
        GLint error = glGetError();
        if (UNLIKELY(error != GL_NO_ERROR)) {
            LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
                 "failed err=0x%04x",
                 this, texture->image, error);
            err = INVALID_OPERATION;
        } else {
            // Everything went okay!
            texture->NPOTAdjust = false;
            texture->dirty  = false;
            texture->width  = clientBuf->width;
            texture->height = clientBuf->height;
        }
    } else {
        LOGE("layer=%p, eglCreateImageKHR() failed. err=0x%4x",
                this, eglGetError());
        err = INVALID_OPERATION;
    }
    return err;
}

void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
{
    const Layer::State& s(drawingState());
    const Layer::State& s(drawingState());
@@ -696,12 +504,9 @@ int32_t LayerBaseClient::sIdentity = 0;


LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
        const sp<Client>& client, int32_t i)
        const sp<Client>& client, int32_t i)
    : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),
    : LayerBase(flinger, display), client(client), mIndex(i),
      mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
      mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
{
    lcblk = new SharedBufferServer(
            client->ctrlblk, i, NUM_BUFFERS,
            mIdentity);
}
}


void LayerBaseClient::onFirstRef()
void LayerBaseClient::onFirstRef()
@@ -718,7 +523,6 @@ LayerBaseClient::~LayerBaseClient()
    if (client != 0) {
    if (client != 0) {
        client->free(mIndex);
        client->free(mIndex);
    }
    }
    delete lcblk;
}
}


ssize_t LayerBaseClient::serverIndex() const
ssize_t LayerBaseClient::serverIndex() const
@@ -748,14 +552,6 @@ sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
            const_cast<LayerBaseClient *>(this));
            const_cast<LayerBaseClient *>(this));
}
}


// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void LayerBaseClient::onRemoved()
{
    // wake up the condition
    lcblk->setStatus(NO_INIT);
}

void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
{
{
    LayerBase::dump(result, buffer, SIZE);
    LayerBase::dump(result, buffer, SIZE);
+1 −30

File changed.

Preview size limit exceeded, changes collapsed.

Loading