/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>

#include <cutils/properties.h>
#include <cutils/native_handle.h>

#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/StopWatch.h>

#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>

#include <surfaceflinger/Surface.h>

#include "clz.h"
#include "GLExtensions.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"


#define DEBUG_RESIZE    0


namespace android {

template <typename T> inline T min(T a, T b) {
    return a<b ? a : b;
}

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

Layer::Layer(SurfaceFlinger* flinger,
        DisplayID display, const sp<Client>& client)
    :   LayerBaseClient(flinger, display, client),
        mGLExtensions(GLExtensions::getInstance()),
        mNeedsBlending(true),
        mNeedsDithering(false),
        mSecure(false),
        mTextureManager(),
        mBufferManager(mTextureManager),
        mWidth(0), mHeight(0), mFixedSize(false)
{
}

Layer::~Layer()
{
    // FIXME: must be called from the main UI thread
    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
    mBufferManager.destroy(dpy);

    // we can use getUserClientUnsafe here because we know we're
    // single-threaded at that point.
    sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe());
    if (ourClient != 0) {
        ourClient->detachLayer(this);
    }
}

status_t Layer::setToken(const sp<UserClient>& userClient,
        SharedClient* sharedClient, int32_t token)
{
    sp<SharedBufferServer> lcblk = new SharedBufferServer(
            sharedClient, token, mBufferManager.getDefaultBufferCount(),
            getIdentity());

    status_t err = mUserClientRef.setToken(userClient, lcblk, token);

    LOGE_IF(err != NO_ERROR,
            "ClientRef::setToken(%p, %p, %u) failed",
            userClient.get(), lcblk.get(), token);

    if (err == NO_ERROR) {
        // we need to free the buffers associated with this surface
    }

    return err;
}

int32_t Layer::getToken() const
{
    return mUserClientRef.getToken();
}

sp<UserClient> Layer::getClient() const
{
    return mUserClientRef.getClient();
}

// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
{
    ClientRef::Access sharedClient(mUserClientRef);
    SharedBufferServer* lcblk(sharedClient.get());
    if (lcblk) {
        // wake up the condition
        lcblk->setStatus(NO_INIT);
    }
}

sp<LayerBaseClient::Surface> Layer::createSurface() const
{
    return mSurface;
}

status_t Layer::ditch()
{
    // NOTE: Called from the main UI thread

    // the layer is not on screen anymore. free as much resources as possible
    mFreezeLock.clear();

    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
    mBufferManager.destroy(dpy);
    mSurface.clear();

    Mutex::Autolock _l(mLock);
    mWidth = mHeight = 0;
    return NO_ERROR;
}

status_t Layer::setBuffers( uint32_t w, uint32_t h,
                            PixelFormat format, uint32_t flags)
{
    // this surfaces pixel format
    PixelFormatInfo info;
    status_t err = getPixelFormatInfo(format, &info);
    if (err) return err;

    // the display's pixel format
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    uint32_t const maxSurfaceDims = min(
            hw.getMaxTextureSize(), hw.getMaxViewportDims());

    // never allow a surface larger than what our underlying GL implementation
    // can handle.
    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
        return BAD_VALUE;
    }

    PixelFormatInfo displayInfo;
    getPixelFormatInfo(hw.getFormat(), &displayInfo);
    const uint32_t hwFlags = hw.getFlags();
    
    mFormat = format;
    mReqFormat = format;
    mWidth  = w;
    mHeight = h;
    mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
    mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;

    // we use the red index
    int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
    int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
    mNeedsDithering = layerRedsize > displayRedSize;

    mSurface = new SurfaceLayer(mFlinger, this);
    return NO_ERROR;
}

void Layer::reloadTexture(const Region& dirty)
{
    sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
    if (buffer == NULL) {
        // this situation can happen if we ran out of memory for instance.
        // not much we can do. continue to use whatever texture was bound
        // to this context.
        return;
    }

    if (mGLExtensions.haveDirectTexture()) {
        EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
        if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
            // not sure what we can do here...
            goto slowpath;
        }
    } else {
slowpath:
        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) {
            mBufferManager.loadTexture(dirty, t);
            buffer->unlock();
        }
    }
}

void Layer::onDraw(const Region& clip) const
{
    Texture tex(mBufferManager.getActiveTexture());
    if (tex.name == -1LU) {
        // the texture has not been created yet, this Layer has
        // in fact never been drawn into. This happens frequently with
        // SurfaceView because the WindowManager can't know when the client
        // has drawn the first time.

        // If there is nothing under us, we paint the screen in black, otherwise
        // we just skip this update.

        // figure out if there is something below us
        Region under;
        const SurfaceFlinger::LayerVector& drawingLayers(mFlinger->mDrawingState.layersSortedByZ);
        const size_t count = drawingLayers.size();
        for (size_t i=0 ; i<count ; ++i) {
            const sp<LayerBase>& layer(drawingLayers[i]);
            if (layer.get() == static_cast<LayerBase const*>(this))
                break;
            under.orSelf(layer->visibleRegionScreen);
        }
        // if not everything below us is covered, we plug the holes!
        Region holes(clip.subtract(under));
        if (!holes.isEmpty()) {
            clearWithOpenGL(holes, 0, 0, 0, 1);
        }
        return;
    }
    drawWithOpenGL(clip, tex);
}

bool Layer::needsFiltering() const
{
    if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
        // NOTE: there is a race here, because mFixedSize is updated in a
        // binder transaction. however, it doesn't really matter since it is
        // evaluated each time we draw. To be perfectly correct, this flag
        // would have to be associated with a buffer.
        if (mFixedSize)
            return true;
    }
    return LayerBase::needsFiltering();
}


status_t Layer::setBufferCount(int bufferCount)
{
    ClientRef::Access sharedClient(mUserClientRef);
    SharedBufferServer* lcblk(sharedClient.get());
    if (!lcblk) {
        // oops, the client is already gone
        return DEAD_OBJECT;
    }

    // NOTE: lcblk->resize() is protected by an internal lock
    status_t err = lcblk->resize(bufferCount);
    if (err == NO_ERROR)
        mBufferManager.resize(bufferCount);

    return err;
}

sp<GraphicBuffer> Layer::requestBuffer(int index,
        uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
        uint32_t usage)
{
    sp<GraphicBuffer> buffer;

    if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
        return buffer;

    if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
        return buffer;

    // this ensures our client doesn't go away while we're accessing
    // the shared area.
    ClientRef::Access sharedClient(mUserClientRef);
    SharedBufferServer* lcblk(sharedClient.get());
    if (!lcblk) {
        // oops, the client is already gone
        return buffer;
    }

    /*
     * This is called from the client's Surface::dequeue(). This can happen
     * at any time, especially while we're in the middle of using the
     * buffer 'index' as our front buffer.
     *
     * Make sure the buffer we're resizing is not the front buffer and has been
     * dequeued. Once this condition is asserted, we are guaranteed that this
     * buffer cannot become the front buffer under our feet, since we're called
     * from Surface::dequeue()
     */
    status_t err = lcblk->assertReallocate(index);
    LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
    if (err != NO_ERROR) {
        // the surface may have died
        return buffer;
    }

    uint32_t w, h, f;
    { // scope for the lock
        Mutex::Autolock _l(mLock);
        const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
        const bool formatChanged    = mReqFormat != reqFormat;
        mReqWidth  = reqWidth;
        mReqHeight = reqHeight;
        mReqFormat = reqFormat;
        mFixedSize = reqWidth && reqHeight;
        w = reqWidth  ? reqWidth  : mWidth;
        h = reqHeight ? reqHeight : mHeight;
        f = reqFormat ? reqFormat : mFormat;
        buffer = mBufferManager.detachBuffer(index);
        if (fixedSizeChanged || formatChanged) {
            lcblk->reallocateAllExcept(index);
        }
    }

    const uint32_t effectiveUsage = getEffectiveUsage(usage);
    if (buffer!=0 && buffer->getStrongCount() == 1) {
        err = buffer->reallocate(w, h, f, effectiveUsage);
    } else {
        // here we have to reallocate a new buffer because we could have a
        // client in our process with a reference to it (eg: status bar),
        // and we can't release the handle under its feet.
        buffer.clear();
        buffer = new GraphicBuffer(w, h, f, effectiveUsage);
        err = buffer->initCheck();
    }

    if (err || buffer->handle == 0) {
        LOGE_IF(err || buffer->handle == 0,
                "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
                this, index, w, h, strerror(-err));
    } else {
        LOGD_IF(DEBUG_RESIZE,
                "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
                this, index, w, h, buffer->handle);
    }

    if (err == NO_ERROR && buffer->handle != 0) {
        Mutex::Autolock _l(mLock);
        mBufferManager.attachBuffer(index, buffer);
    }
    return buffer;
}

uint32_t Layer::getEffectiveUsage(uint32_t usage) const
{
    /*
     *  buffers used for software rendering, but h/w composition
     *  are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
     *
     *  buffers used for h/w rendering and h/w composition
     *  are allocated with  HW_RENDER | HW_TEXTURE
     *
     *  buffers used with h/w rendering and either NPOT or no egl_image_ext
     *  are allocated with SW_READ_RARELY | HW_RENDER
     *
     */

    if (mSecure) {
        // secure buffer, don't store it into the GPU
        usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
                GraphicBuffer::USAGE_SW_WRITE_OFTEN;
    } else {
        // it's allowed to modify the usage flags here, but generally
        // the requested flags should be honored.
        // request EGLImage for all buffers
        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    }
    return usage;
}

uint32_t Layer::doTransaction(uint32_t flags)
{
    const Layer::State& front(drawingState());
    const Layer::State& temp(currentState());

    const bool sizeChanged = (front.requested_w != temp.requested_w) ||
            (front.requested_h != temp.requested_h);

    if (sizeChanged) {
        // the size changed, we need to ask our client to request a new buffer
        LOGD_IF(DEBUG_RESIZE,
                "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
                this,
                int(temp.requested_w), int(temp.requested_h),
                int(front.requested_w), int(front.requested_h));

        if (!isFixedSize()) {
            // we're being resized and there is a freeze display request,
            // acquire a freeze lock, so that the screen stays put
            // until we've redrawn at the new size; this is to avoid
            // glitches upon orientation changes.
            if (mFlinger->hasFreezeRequest()) {
                // if the surface is hidden, don't try to acquire the
                // freeze lock, since hidden surfaces may never redraw
                if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
                    mFreezeLock = mFlinger->getFreezeLock();
                }
            }

            // this will make sure LayerBase::doTransaction doesn't update
            // the drawing state's size
            Layer::State& editDraw(mDrawingState);
            editDraw.requested_w = temp.requested_w;
            editDraw.requested_h = temp.requested_h;

            // record the new size, form this point on, when the client request
            // a buffer, it'll get the new size.
            setBufferSize(temp.requested_w, temp.requested_h);

            ClientRef::Access sharedClient(mUserClientRef);
            SharedBufferServer* lcblk(sharedClient.get());
            if (lcblk) {
                // all buffers need reallocation
                lcblk->reallocateAll();
            }
        } else {
            // record the new size
            setBufferSize(temp.requested_w, temp.requested_h);
        }
    }

    if (temp.sequence != front.sequence) {
        if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
            // this surface is now hidden, so it shouldn't hold a freeze lock
            // (it may never redraw, which is fine if it is hidden)
            mFreezeLock.clear();
        }
    }
        
    return LayerBase::doTransaction(flags);
}

void Layer::setBufferSize(uint32_t w, uint32_t h) {
    Mutex::Autolock _l(mLock);
    mWidth = w;
    mHeight = h;
}

bool Layer::isFixedSize() const {
    Mutex::Autolock _l(mLock);
    return mFixedSize;
}

// ----------------------------------------------------------------------------
// pageflip handling...
// ----------------------------------------------------------------------------

void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
    ClientRef::Access sharedClient(mUserClientRef);
    SharedBufferServer* lcblk(sharedClient.get());
    if (!lcblk) {
        // client died
        recomputeVisibleRegions = true;
        return;
    }

    ssize_t buf = lcblk->retireAndLock();
    if (buf == NOT_ENOUGH_DATA) {
        // NOTE: This is not an error, it simply means there is nothing to
        // retire. The buffer is locked because we will use it
        // for composition later in the loop
        return;
    }

    if (buf < NO_ERROR) {
        LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
        mPostedDirtyRegion.clear();
        return;
    }

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

    // get the dirty region
    sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
    if (newFrontBuffer != NULL) {
        // compute the posted region
        const Region dirty(lcblk->getDirtyRegion(buf));
        mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );

        // update the layer size and release freeze-lock
        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))
            {
                // Here we pretend the transaction happened by updating the
                // current and drawing states. Drawing state is only accessed
                // in this thread, no need to have it locked
                Layer::State& editDraw(mDrawingState);
                editDraw.w = editDraw.requested_w;
                editDraw.h = editDraw.requested_h;

                // We also need to update the current state so that we don't
                // end-up doing too much work during the next transaction.
                // NOTE: We actually don't need hold the transaction lock here
                // because State::w and State::h are only accessed from
                // this thread
                Layer::State& editTemp(currentState());
                editTemp.w = editDraw.w;
                editTemp.h = editDraw.h;

                // recompute visible region
                recomputeVisibleRegions = true;
            }

            // we now have the correct size, unfreeze the screen
            mFreezeLock.clear();
        }
    } else {
        // this should not happen unless we ran out of memory while
        // allocating the buffer. we're hoping that things will get back
        // to normal the next time the app tries to draw into this buffer.
        // meanwhile, pretend the screen didn't update.
        mPostedDirtyRegion.clear();
    }

    if (lcblk->getQueuedCount()) {
        // signal an event if we have more buffers waiting
        mFlinger->signalEvent();
    }

    /* a buffer was posted, so we need to call reloadTexture(), which
     * will update our internal data structures (eg: EGLImageKHR or
     * texture names). we need to do this even if mPostedDirtyRegion is
     * empty -- it's orthogonal to the fact that a new buffer was posted,
     * for instance, a degenerate case could be that the user did an empty
     * update but repainted the buffer with appropriate content (after a
     * resize for instance).
     */
    reloadTexture( mPostedDirtyRegion );
}

void Layer::unlockPageFlip(
        const Transform& planeTransform, Region& outDirtyRegion)
{
    Region dirtyRegion(mPostedDirtyRegion);
    if (!dirtyRegion.isEmpty()) {
        mPostedDirtyRegion.clear();
        // The dirty region is given in the layer's coordinate space
        // transform the dirty region by the surface's transformation
        // and the global transformation.
        const Layer::State& s(drawingState());
        const Transform tr(planeTransform * s.transform);
        dirtyRegion = tr.transform(dirtyRegion);

        // At this point, the dirty region is in screen space.
        // Make sure it's constrained by the visible region (which
        // is in screen space as well).
        dirtyRegion.andSelf(visibleRegionScreen);
        outDirtyRegion.orSelf(dirtyRegion);
    }
    if (visibleRegionScreen.isEmpty()) {
        // an invisible layer should not hold a freeze-lock
        // (because it may never be updated and therefore never release it)
        mFreezeLock.clear();
    }
}

void Layer::finishPageFlip()
{
    ClientRef::Access sharedClient(mUserClientRef);
    SharedBufferServer* lcblk(sharedClient.get());
    if (lcblk) {
        int buf = mBufferManager.getActiveBufferIndex();
        if (buf >= 0) {
            status_t err = lcblk->unlock( buf );
            LOGE_IF(err!=NO_ERROR,
                    "layer %p, buffer=%d wasn't locked!",
                    this, buf);
        }
    }
}


void Layer::dump(String8& result, char* buffer, size_t SIZE) const
{
    LayerBaseClient::dump(result, buffer, SIZE);

    ClientRef::Access sharedClient(mUserClientRef);
    SharedBufferServer* lcblk(sharedClient.get());
    uint32_t totalTime = 0;
    if (lcblk) {
        SharedBufferStack::Statistics stats = lcblk->getStats();
        totalTime= stats.totalTime;
        result.append( lcblk->dump("      ") );
    }

    sp<const GraphicBuffer> buf0(getBuffer(0));
    sp<const GraphicBuffer> buf1(getBuffer(1));
    uint32_t w0=0, h0=0, s0=0;
    uint32_t w1=0, h1=0, s1=0;
    if (buf0 != 0) {
        w0 = buf0->getWidth();
        h0 = buf0->getHeight();
        s0 = buf0->getStride();
    }
    if (buf1 != 0) {
        w1 = buf1->getWidth();
        h1 = buf1->getHeight();
        s1 = buf1->getStride();
    }
    snprintf(buffer, SIZE,
            "      "
            "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
            " freezeLock=%p, dq-q-time=%u us\n",
            mFormat, w0, h0, s0, w1, h1, s1,
            getFreezeLock().get(), totalTime);

    result.append(buffer);
}

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

Layer::ClientRef::ClientRef()
    : mControlBlock(0), mToken(-1) {
}

Layer::ClientRef::~ClientRef() {
}

int32_t Layer::ClientRef::getToken() const {
    Mutex::Autolock _l(mLock);
    return mToken;
}

sp<UserClient> Layer::ClientRef::getClient() const {
    Mutex::Autolock _l(mLock);
    return mUserClient.promote();
}

status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
        const sp<SharedBufferServer>& sharedClient, int32_t token) {
    Mutex::Autolock _l(mLock);

    { // scope for strong mUserClient reference
        sp<UserClient> userClient(mUserClient.promote());
        if (mUserClient != 0 && mControlBlock != 0) {
            mControlBlock->setStatus(NO_INIT);
        }
    }

    mUserClient = uc;
    mToken = token;
    mControlBlock = sharedClient;
    return NO_ERROR;
}

sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
    return mUserClient.promote();
}

// this class gives us access to SharedBufferServer safely
// it makes sure the UserClient (and its associated shared memory)
// won't go away while we're accessing it.
Layer::ClientRef::Access::Access(const ClientRef& ref)
    : mControlBlock(0)
{
    Mutex::Autolock _l(ref.mLock);
    mUserClientStrongRef = ref.mUserClient.promote();
    if (mUserClientStrongRef != 0)
        mControlBlock = ref.mControlBlock;
}

Layer::ClientRef::Access::~Access()
{
}

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

Layer::BufferManager::BufferManager(TextureManager& tm)
    : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
      mActiveBuffer(-1), mFailover(false)
{
}

Layer::BufferManager::~BufferManager()
{
}

status_t Layer::BufferManager::resize(size_t size)
{
    Mutex::Autolock _l(mLock);
    mNumBuffers = size;
    return NO_ERROR;
}

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

status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
    mActiveBuffer = index;
    return NO_ERROR;
}

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

Texture Layer::BufferManager::getActiveTexture() const {
    Texture res;
    if (mFailover || mActiveBuffer<0) {
        res = mFailoverTexture;
    } else {
        static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
    }
    return res;
}

sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
    sp<GraphicBuffer> result;
    const ssize_t activeBuffer = mActiveBuffer;
    if (activeBuffer >= 0) {
        BufferData const * const buffers = mBufferData;
        Mutex::Autolock _l(mLock);
        result = buffers[activeBuffer].buffer;
    }
    return result;
}

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

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

status_t Layer::BufferManager::destroy(EGLDisplay dpy)
{
    BufferData* const buffers = mBufferData;
    size_t num;
    { // scope for the lock
        Mutex::Autolock _l(mLock);
        num = mNumBuffers;
        for (size_t i=0 ; i<num ; i++) {
            buffers[i].buffer = 0;
        }
    }
    for (size_t i=0 ; i<num ; i++) {
        destroyTexture(&buffers[i].texture, dpy);
    }
    destroyTexture(&mFailoverTexture, dpy);
    return NO_ERROR;
}

status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
        const sp<GraphicBuffer>& buffer)
{
    status_t err = NO_INIT;
    ssize_t index = mActiveBuffer;
    if (index >= 0) {
        if (!mFailover) {
            Image& texture(mBufferData[index].texture);
            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;
                const size_t num = mNumBuffers;
                for (size_t i=0 ; i<num ; i++) {
                    destroyTexture(&mBufferData[i].texture, dpy);
                }
            }
        } else {
            // we failed once, don't try again
            err = BAD_VALUE;
        }
    }
    return err;
}

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

status_t Layer::BufferManager::destroyTexture(Image* 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;
}

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

Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
        const sp<Layer>& owner)
    : Surface(flinger, owner->getIdentity(), owner)
{
}

Layer::SurfaceLayer::~SurfaceLayer()
{
}

sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
        uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
{
    sp<GraphicBuffer> buffer;
    sp<Layer> owner(getOwner());
    if (owner != 0) {
        /*
         * requestBuffer() cannot be called from the main thread
         * as it could cause a dead-lock, since it may have to wait
         * on conditions updated my the main thread.
         */
        buffer = owner->requestBuffer(index, w, h, format, usage);
    }
    return buffer;
}

status_t Layer::SurfaceLayer::setBufferCount(int bufferCount)
{
    status_t err = DEAD_OBJECT;
    sp<Layer> owner(getOwner());
    if (owner != 0) {
        /*
         * setBufferCount() cannot be called from the main thread
         * as it could cause a dead-lock, since it may have to wait
         * on conditions updated my the main thread.
         */
        err = owner->setBufferCount(bufferCount);
    }
    return err;
}

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


}; // namespace android
