/*
 * 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/PixelFormat.h>
#include <ui/Surface.h>

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


#define DEBUG_RESIZE    0


namespace android {

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

const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
const char* const Layer::typeID = "Layer";

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

Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
    :   LayerBaseClient(flinger, display, c, i),
        mSecure(false),
        mFrontBufferIndex(1),
        mNeedsBlending(true),
        mResizeTransactionDone(false)
{
    // no OpenGL operation is possible here, since we might not be
    // in the OpenGL thread.
}

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

void Layer::destroy()
{
    for (int i=0 ; i<NUM_BUFFERS ; i++) {
        if (mTextures[i].name != -1U) {
            glDeleteTextures(1, &mTextures[i].name);
            mTextures[i].name = -1U;
        }
        if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
            eglDestroyImageKHR(dpy, mTextures[i].image);
            mTextures[i].image = EGL_NO_IMAGE_KHR;
        }
    }
}

void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
{
    LayerBase::initStates(w,h,flags);

    if (flags & ISurfaceComposer::eDestroyBackbuffer)
        lcblk->flags |= eNoCopyBack;
}

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

status_t Layer::ditch()
{
    // the layer is not on screen anymore. free as much resources as possible
    mSurface.clear();
    destroy();
    return NO_ERROR;
}

status_t Layer::setBuffers( Client* client,
                            uint32_t w, uint32_t h,
                            PixelFormat format, uint32_t flags)
{
    PixelFormatInfo info;
    status_t err = getPixelFormatInfo(format, &info);
    if (err) return err;

    uint32_t bufferFlags = 0;
    if (flags & ISurfaceComposer::eGPU)
        bufferFlags |= Buffer::GPU;

    if (flags & ISurfaceComposer::eSecure)
        bufferFlags |= Buffer::SECURE;

    /* FIXME we need this code for msm7201A
    if (bufferFlags & Buffer::GPU) {
        // FIXME: this is msm7201A specific, as its GPU only supports
        // BGRA_8888.
        if (format == PIXEL_FORMAT_RGBA_8888) {
            format = PIXEL_FORMAT_BGRA_8888;
        }
    }
    */

    mSecure = (bufferFlags & Buffer::SECURE) ? true : false;
    mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
    for (int i=0 ; i<2 ; i++) {
        err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags);
        if (err != NO_ERROR) {
            return err;
        }
    }
    mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
    return NO_ERROR;
}

void Layer::reloadTexture(const Region& dirty)
{
    const sp<Buffer>& buffer(frontBuffer().getBuffer());
    if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
        int index = mFrontBufferIndex;
        if (LIKELY(!mTextures[index].dirty)) {
            glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
        } else {
            // we need to recreate the texture
            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
            
            // create the new texture name if needed
            if (UNLIKELY(mTextures[index].name == -1U)) {
                mTextures[index].name = createTexture();
            } else {
                glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
            }

            // free the previous image
            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
                eglDestroyImageKHR(dpy, mTextures[index].image);
                mTextures[index].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 
            };
            mTextures[index].image = eglCreateImageKHR(
                    dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                    (EGLClientBuffer)clientBuf, attrs);

            LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR,
                    "eglCreateImageKHR() failed. err=0x%4x",
                    eglGetError());
            
            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
                glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, 
                        (GLeglImageOES)mTextures[index].image);
                GLint error = glGetError();
                if (UNLIKELY(error != GL_NO_ERROR)) {
                    // this failed, for instance, because we don't support
                    // NPOT.
                    // FIXME: do something!
                    mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
                } else {
                    // Everything went okay!
                    mTextures[index].dirty = false;
                }
            }                
        }
    } else {
        GGLSurface t;
        status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY);
        LOGE_IF(res, "error %d (%s) locking buffer %p",
                res, strerror(res), buffer.get());
        if (res == NO_ERROR) {
            if (UNLIKELY(mTextures[0].name == -1U)) {
                mTextures[0].name = createTexture();
            }
            loadTexture(dirty, mTextures[0].name, t, 
                    mTextures[0].width, mTextures[0].height);
            buffer->unlock();
        }
    }
}


void Layer::onDraw(const Region& clip) const
{
    const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? 
            mFrontBufferIndex : 0;
    GLuint textureName = mTextures[index].name;

    if (UNLIKELY(textureName == -1LU)) {
        LOGW("Layer %p doesn't have a texture", this);
        // the texture has not been created yet, this Layer has
        // in fact never been drawn into. this happens frequently with
        // SurfaceView.
        clearWithOpenGL(clip);
        return;
    }

    GGLSurface t;
    sp<const Buffer> buffer(frontBuffer().getBuffer());
    drawWithOpenGL(clip, textureName, buffer);
}

sp<SurfaceBuffer> Layer::peekBuffer()
{
    /*
     * This is called from the client's Surface::lock(), after it locked
     * the surface successfully. We're therefore guaranteed that the
     * back-buffer is not in use by ourselves.
     * Of course, we need to validate all this, which is not trivial.
     *
     * FIXME: A resize could happen at any time here. What to do about this?
     *  - resize() form post()
     *  - resize() from doTransaction()
     *  
     *  We'll probably need an internal lock for this.
     *     
     * 
     * TODO: We need to make sure that post() doesn't swap
     *       the buffers under us.
     */

    // it's okay to read swapState for the purpose of figuring out the 
    // backbuffer index, which cannot change (since the app has locked it).
    const uint32_t state = lcblk->swapState;
    const int32_t backBufferIndex = layer_cblk_t::backBuffer(state);
    
    // get rid of the EGL image, since we shouldn't need it anymore
    // (note that we're in a different thread than where it is being used)
    if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) {
        EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
        eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image);
        mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR;
    }
    
    LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
    sp<SurfaceBuffer> buffer = layerBitmap.allocate();
    
    LOGD_IF(DEBUG_RESIZE,
            "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
            this, backBufferIndex,
            layerBitmap.getWidth(),
            layerBitmap.getHeight(),
            layerBitmap.getBuffer()->getWidth(),
            layerBitmap.getBuffer()->getHeight());

    if (UNLIKELY(buffer == 0)) {
        // XXX: what to do, what to do?
    } else {
        // texture is now dirty...
        mTextures[backBufferIndex].dirty = true;
        // ... so it the visible region (because we consider the surface's
        // buffer size for visibility calculations)
        forceVisibilityTransaction();
        mFlinger->setTransactionFlags(eTraversalNeeded);
    }
    return buffer;
}

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

    // the test front.{w|h} != temp.{w|h} is not enough because it is possible
    // that the size changed back to its previous value before the buffer
    // was resized (in the eLocked case below), in which case, we still
    // need to execute the code below so the clients have a chance to be
    // release. resize() deals with the fact that the size can be the same.

    /*
     *  Various states we could be in...

         resize = state & eResizeRequested;
         if (backbufferChanged) {
             if (resize == 0) {
                 // ERROR, the resized buffer doesn't have its resize flag set
             } else if (resize == mask) {
                 // ERROR one of the buffer has already been resized
             } else if (resize == mask ^ eResizeRequested) {
                 // ERROR, the resized buffer doesn't have its resize flag set
             } else if (resize == eResizeRequested) {
                 // OK, Normal case, proceed with resize
             }
         } else {
             if (resize == 0) {
                 // OK, nothing special, do nothing
             } else if (resize == mask) {
                 // restarted transaction, do nothing
             } else if (resize == mask ^ eResizeRequested) {
                 // restarted transaction, do nothing
             } else if (resize == eResizeRequested) {
                 // OK, size reset to previous value, proceed with resize
             }
         }
     */

    // Index of the back buffer
    const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
    const uint32_t state = lcblk->swapState;
    const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
    const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
    uint32_t resizeFlags = state & eResizeRequested;

    if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
        LOGE(   "backbuffer size changed, but both resize flags are not set! "
                "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
                "index=%d, (%dx%d), (%dx%d)",
                this,  state,
                int(temp.w), int(temp.h),
                int(drawingState().w), int(drawingState().h),
                int(clientBackBufferIndex),
                int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
                int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
        // if we get there we're pretty screwed. the only reasonable
        // thing to do is to pretend we should do the resize since
        // backbufferChanged is set (this also will give a chance to
        // client to get unblocked)
        resizeFlags = eResizeRequested;
    }

    if (resizeFlags == eResizeRequested)  {
        // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
        // here, would be wrong and misleading because by this point
        // mFrontBufferIndex has not been updated yet.

        LOGD_IF(DEBUG_RESIZE,
                    "resize (layer=%p), state=%08x, "
                    "requested (%dx%d), "
                    "drawing (%d,%d), "
                    "index=%d, (%dx%d), (%dx%d)",
                    this,  state,
                    int(temp.w), int(temp.h),
                    int(drawingState().w), int(drawingState().h),
                    int(clientBackBufferIndex),
                    int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
                    int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));

        if (state & eLocked) {
            // if the buffer is locked, we can't resize anything because
            // - the backbuffer is currently in use by the user
            // - the front buffer is being shown
            // We just act as if the transaction didn't happen and we
            // reschedule it later...
            flags |= eRestartTransaction;
        } else {
            // This buffer needs to be resized
            status_t err =
                resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
            if (err == NO_ERROR) {
                const uint32_t mask = clientBackBufferIndex ?
                        eResizeBuffer1 : eResizeBuffer0;
                android_atomic_and(~mask, &(lcblk->swapState));
                // since a buffer became available, we can let the client go...
                mFlinger->scheduleBroadcast(client);
                mResizeTransactionDone = true;

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

status_t Layer::resize(
        int32_t clientBackBufferIndex,
        uint32_t width, uint32_t height,
        const char* what)
{
    /*
     * handle resize (backbuffer and frontbuffer reallocation)
     * this is called from post() or from doTransaction()
     */

    const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);

    // if the new (transaction) size is != from the the backbuffer
    // then we need to reallocate the backbuffer
    bool backbufferChanged = (clientBackBuffer.getWidth()  != width) ||
                             (clientBackBuffer.getHeight() != height);

    LOGD_IF(!backbufferChanged,
            "(%s) eResizeRequested (layer=%p), but size not changed: "
            "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
            "state=%08lx, index=%d, (%dx%d), (%dx%d)",
            what, this,
            int(width), int(height),
            int(drawingState().w), int(drawingState().h),
            int(currentState().w), int(currentState().h),
            long(lcblk->swapState),
            int(clientBackBufferIndex),
            int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
            int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));

    // this can happen when changing the size back and forth quickly
    status_t err = NO_ERROR;
    if (backbufferChanged) {

        LOGD_IF(DEBUG_RESIZE,
                "resize (layer=%p), requested (%dx%d), "
                "index=%d, (%dx%d), (%dx%d)",
                this, int(width), int(height), int(clientBackBufferIndex),
                int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
                int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));

        err = mBuffers[clientBackBufferIndex].setSize(width, height);
        if (UNLIKELY(err != NO_ERROR)) {
            // This really should never happen
            LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
                    clientBackBufferIndex, width, height, err, strerror(err));
            // couldn't reallocate the surface
            android_atomic_write(eInvalidSurface, &lcblk->swapState);
        }
    }
    return err;
}

void Layer::setSizeChanged(uint32_t w, uint32_t h)
{
    LOGD_IF(DEBUG_RESIZE,
            "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
            w, h, mCurrentState.w, mCurrentState.h);
    android_atomic_or(eResizeRequested, &(lcblk->swapState));
}

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

void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
    uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
    // preemptively block the client, because he might set
    // eFlipRequested at any time and want to use this buffer
    // for the next frame. This will be unset below if it
    // turns out we didn't need it.

    uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
    if (!(state & mask))
        return;

    if (UNLIKELY(state & eInvalidSurface)) {
        // if eInvalidSurface is set, this means the surface
        // became invalid during a transaction (NO_MEMORY for instance)
        mFlinger->scheduleBroadcast(client);
        return;
    }

    if (UNLIKELY(state & eFlipRequested)) {
        uint32_t oldState;
        mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
        if (oldState & eNextFlipPending) {
            // Process another round (we know at least a buffer
            // is ready for that client).
            mFlinger->signalEvent();
        }
    }
}

Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
{
    // atomically swap buffers and (re)set eFlipRequested
    int32_t oldValue, newValue;
    layer_cblk_t * const lcblk = this->lcblk;
    do {
        oldValue = lcblk->swapState;
            // get the current value

        LOG_ASSERT(oldValue&eFlipRequested,
            "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
            long(oldValue));

        newValue = (oldValue ^ eIndex);
            // swap buffers

        newValue &= ~(eFlipRequested | eNextFlipPending);
            // clear eFlipRequested and eNextFlipPending

        if (oldValue & eNextFlipPending)
            newValue |= eFlipRequested;
            // if eNextFlipPending is set (second buffer already has something
            // in it) we need to reset eFlipRequested because the client
            // might never do it

    } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
    *previousSate = oldValue;
    
    const int32_t index = (newValue & eIndex) ^ 1;
    mFrontBufferIndex = index;

    /* NOTE: it's safe to set this flag here because this is only touched
     * from LayerBitmap::allocate(), which by construction cannot happen
     * while we're in post().
     */
    lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty;

    // ... post the new front-buffer
    Region dirty(lcblk->region + index);
    dirty.andSelf(frontBuffer().getBounds());

    //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
    //    oldValue, newValue, mFrontBufferIndex);
    //dirty.dump("dirty");

    if (UNLIKELY(oldValue & eResizeRequested)) {

        LOGD_IF(DEBUG_RESIZE,
                     "post (layer=%p), state=%08x, "
                     "index=%d, (%dx%d), (%dx%d)",
                     this,  newValue,
                     int(1-index),
                     int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
                     int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));

        // here, we just posted the surface and we have resolved
        // the front/back buffer indices. The client is blocked, so
        // it cannot start using the new backbuffer.

        // If the backbuffer was resized in THIS round, we actually cannot
        // resize the frontbuffer because it has *just* been drawn (and we
        // would have nothing to draw). In this case we just skip the resize
        // it'll happen after the next page flip or during the next
        // transaction.

        const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
        if (mResizeTransactionDone && (newValue & mask)) {
            // Resize the layer's second buffer only if the transaction
            // happened. It may not have happened yet if eResizeRequested
            // was set immediately after the "transactionRequested" test,
            // in which case the drawing state's size would be wrong.
            mFreezeLock.clear();
            const Layer::State& s(drawingState());
            if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
                do {
                    oldValue = lcblk->swapState;
                    if ((oldValue & eResizeRequested) == eResizeRequested) {
                        // ugh, another resize was requested since we processed
                        // the first buffer, don't free the client, and let
                        // the next transaction handle everything.
                        break;
                    }
                    newValue = oldValue & ~mask;
                } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
            }
            mResizeTransactionDone = false;
            recomputeVisibleRegions = true;
            this->contentDirty = true;
        }
    }

    reloadTexture(dirty);

    return dirty;
}

Point Layer::getPhysicalSize() const
{
    sp<const Buffer> front(frontBuffer().getBuffer());
    return Point(front->getWidth(), front->getHeight());
}

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);

        // client could be blocked, so signal them so they get a
        // chance to reevaluate their condition.
        mFlinger->scheduleBroadcast(client);
    }
}

void Layer::finishPageFlip()
{
    if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
        LOGE_IF(!(lcblk->swapState & eBusy),
                "layer %p wasn't locked!", this);
        android_atomic_and(~eBusy, &(lcblk->swapState));
    }
    mFlinger->scheduleBroadcast(client);
}

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

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

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

sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
{
    sp<SurfaceBuffer> buffer = 0;
    sp<Layer> owner(getOwner());
    if (owner != 0) {
        buffer = owner->peekBuffer();
    }
    return buffer;
}

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


}; // namespace android
