/*
 * 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.
 */

#define LOG_TAG "Surface"

#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/IPCThreadState.h>
#include <utils/IMemory.h>
#include <utils/Log.h>

#include <ui/DisplayInfo.h>
#include <ui/BufferMapper.h>
#include <ui/EGLNativeWindowSurface.h>
#include <ui/ISurface.h>
#include <ui/Surface.h>
#include <ui/SurfaceComposerClient.h>
#include <ui/Rect.h>

#include <EGL/android_natives.h>

#include <private/ui/SharedState.h>
#include <private/ui/LayerState.h>

#include <pixelflinger/pixelflinger.h>

namespace android {

// ============================================================================
//  SurfaceBuffer
// ============================================================================

template<class SurfaceBuffer> Mutex Singleton<SurfaceBuffer>::sLock; 
template<> SurfaceBuffer* Singleton<SurfaceBuffer>::sInstance(0); 

SurfaceBuffer::SurfaceBuffer() 
    : BASE(), handle(0), mOwner(false)
{
    width  = 
    height = 
    stride = 
    format = 
    usage  = 0;
    android_native_buffer_t::getHandle = getHandle;
}

SurfaceBuffer::SurfaceBuffer(const Parcel& data) 
    : BASE(), handle(0), mOwner(true)
{
    // we own the handle in this case
    width  = data.readInt32();
    height = data.readInt32();
    stride = data.readInt32();
    format = data.readInt32();
    usage  = data.readInt32();
    handle = data.readNativeHandle();
    android_native_buffer_t::getHandle = getHandle;
}

SurfaceBuffer::~SurfaceBuffer()
{
    if (handle && mOwner) {
        native_handle_close(handle);
        native_handle_delete(const_cast<native_handle*>(handle));
    }
}

int SurfaceBuffer::getHandle(android_native_buffer_t const * base, 
        buffer_handle_t* handle)
{
    *handle = getSelf(base)->handle;
    return 0;
}

status_t SurfaceBuffer::writeToParcel(Parcel* reply, 
        android_native_buffer_t const* buffer)
{
    buffer_handle_t handle;
    status_t err = buffer->getHandle(buffer, &handle);
    if (err < 0) {
        return err;
    }
    reply->writeInt32(buffer->width);
    reply->writeInt32(buffer->height);
    reply->writeInt32(buffer->stride);
    reply->writeInt32(buffer->format);
    reply->writeInt32(buffer->usage);
    reply->writeNativeHandle(handle);
    return NO_ERROR;
}

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

static void copyBlt(const android_native_buffer_t* dst,
        const android_native_buffer_t* src, const Region& reg)
{
    Region::iterator iterator(reg);
    if (iterator) {
        // NOTE: dst and src must be the same format
        Rect r;
        const size_t bpp = bytesPerPixel(src->format);
        const size_t dbpr = dst->stride * bpp;
        const size_t sbpr = src->stride * bpp;
        while (iterator.iterate(&r)) {
            ssize_t h = r.bottom - r.top;
            if (h) {
                size_t size = (r.right - r.left) * bpp;
                uint8_t* s = (GGLubyte*)src->bits + 
                        (r.left + src->stride * r.top) * bpp;
                uint8_t* d = (GGLubyte*)dst->bits +
                        (r.left + dst->stride * r.top) * bpp;
                if (dbpr==sbpr && size==sbpr) {
                    size *= h;
                    h = 1;
                }
                do {
                    memcpy(d, s, size);
                    d += dbpr;
                    s += sbpr;
                } while (--h > 0);
            }
        }
    }
}

// ============================================================================
//  Surface
// ============================================================================

Surface::Surface(const sp<SurfaceComposerClient>& client, 
        const sp<ISurface>& surface,
        const ISurfaceFlingerClient::surface_data_t& data,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        bool owner)
    : mClient(client), mSurface(surface),
      mToken(data.token), mIdentity(data.identity),
      mFormat(format), mFlags(flags), mOwner(owner)
{
    android_native_window_t::connect          = connect;
    android_native_window_t::disconnect       = disconnect;
    android_native_window_t::setSwapInterval  = setSwapInterval;
    android_native_window_t::setSwapRectangle = setSwapRectangle;
    android_native_window_t::dequeueBuffer    = dequeueBuffer;
    android_native_window_t::lockBuffer       = lockBuffer;
    android_native_window_t::queueBuffer      = queueBuffer;

    mSwapRectangle.makeInvalid();

    DisplayInfo dinfo;
    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
    const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
    const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
    // FIXME: set real values here
    const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
    const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
}

Surface::Surface(Surface const* rhs)
    : mOwner(false)
{
    // FIXME: we really should get rid of this ctor. the memcpy below
    //should be safe for now, but android_native_window_t is not supposed
    // to be clonable.
    memcpy( static_cast<android_native_window_t*>(this),
            static_cast<android_native_window_t const *>(rhs),
            sizeof(android_native_window_t));

    mToken      = rhs->mToken;
    mIdentity   = rhs->mIdentity;
    mClient     = rhs->mClient;
    mSurface    = rhs->mSurface;
    mBuffers[0] = rhs->mBuffers[0];
    mBuffers[1] = rhs->mBuffers[1];
    mFormat     = rhs->mFormat;
    mFlags      = rhs->mFlags;
    mSwapRectangle.makeInvalid();
}

Surface::~Surface()
{
    if (mOwner && mToken>=0 && mClient!=0) {
        mClient->destroySurface(mToken);
        if (mBuffers[0] != 0) {
            BufferMapper::get().unmap(mBuffers[0]->getHandle(), this);
        }
        if (mBuffers[1] != 0) {
            BufferMapper::get().unmap(mBuffers[1]->getHandle(), this);
        }
    }
    mClient.clear();
    mSurface.clear();
    IPCThreadState::self()->flushCommands();
}

sp<Surface> Surface::dup() const
{
    // FIXME: we should get rid of Surface::dup()
    Surface const * r = this;
    if (this && mOwner) {
        // the only reason we need to do this is because of Java's garbage
        // collector: because we're creating a copy of the Surface
        // instead of a reference, we can guarantee that when our last
        // reference goes away, the real surface will be deleted.
        // Without this hack (the code is correct too), we'd have to
        // wait for a GC for the surface to go away.
        r = new Surface(this);        
    }
    return const_cast<Surface*>(r);
}

status_t Surface::validate(per_client_cblk_t const* cblk) const
{
    if (cblk == 0) {
        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
        return NO_INIT;
    }
    status_t err = cblk->validate(mToken);
    if (err != NO_ERROR) {
        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
                mToken, mIdentity, err, strerror(-err));
        return err;
    }
    if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
        LOGE("using an invalid surface id=%d, identity=%u should be %d",
                mToken, mIdentity, cblk->layers[mToken].identity);
        return NO_INIT;
    }
    return NO_ERROR;
}

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

int Surface::setSwapRectangle(android_native_window_t* window,
        int l, int t, int w, int h)
{
    Surface* self = getSelf(window);
    self->setSwapRectangle(Rect(l, t, l+w, t+h));
    return 0;
}

void Surface::connect(android_native_window_t* window)
{
}

void Surface::disconnect(android_native_window_t* window)
{
}

int Surface::setSwapInterval(android_native_window_t* window, int interval)
{
    return 0;
}

int Surface::dequeueBuffer(android_native_window_t* window, 
        android_native_buffer_t** buffer)
{
    Surface* self = getSelf(window);
    return self->dequeueBuffer(buffer);
}

int Surface::lockBuffer(android_native_window_t* window, 
        android_native_buffer_t* buffer)
{
    Surface* self = getSelf(window);
    return self->lockBuffer(buffer);
}

int Surface::queueBuffer(android_native_window_t* window, 
        android_native_buffer_t* buffer)
{
    Surface* self = getSelf(window);
    return self->queueBuffer(buffer);
}

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

int Surface::dequeueBuffer(android_native_buffer_t** buffer)
{
    // FIXME: dequeueBuffer() needs proper implementation

    Mutex::Autolock _l(mSurfaceLock);

    per_client_cblk_t* const cblk = mClient->mControl;
    status_t err = validate(cblk);
    if (err != NO_ERROR)
        return err;

    SurfaceID index(mToken); 
    
    int32_t backIdx = cblk->lock_layer(size_t(index),
            per_client_cblk_t::BLOCKING);

    if (backIdx < 0)
        return status_t(backIdx); 

    mBackbufferIndex = backIdx;
    layer_cblk_t* const lcblk = &(cblk->layers[index]);

    volatile const surface_info_t* const back = lcblk->surface + backIdx;
    if (back->flags & surface_info_t::eNeedNewBuffer) {
        getBufferLocked(backIdx);
    }

    const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
    *buffer = backBuffer.get();

    return NO_ERROR;
}

int Surface::lockBuffer(android_native_buffer_t* buffer)
{
    // FIXME: lockBuffer() needs proper implementation
    return 0;
}

int Surface::queueBuffer(android_native_buffer_t* buffer)
{   
    Mutex::Autolock _l(mSurfaceLock);

    per_client_cblk_t* const cblk = mClient->mControl;
    status_t err = validate(cblk);
    if (err != NO_ERROR)
        return err;

    // transmit the dirty region
    const Region dirty(swapRectangle());
    SurfaceID index(mToken); 
    layer_cblk_t* const lcblk = &(cblk->layers[index]);
    _send_dirty_region(lcblk, dirty);

    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
    if (!(newstate & eNextFlipPending))
        mClient->signalServer();

    return NO_ERROR;
}

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

status_t Surface::lock(SurfaceInfo* info, bool blocking) {
    return Surface::lock(info, NULL, blocking);
}

status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking) 
{
    // FIXME: needs some locking here
    android_native_buffer_t* backBuffer;
    status_t err = dequeueBuffer(&backBuffer);
    if (err == NO_ERROR) {
        err = lockBuffer(backBuffer);
        if (err == NO_ERROR) {
            backBuffer->common.incRef(&backBuffer->common);
            mLockedBuffer = backBuffer;
            other->w      = backBuffer->width;
            other->h      = backBuffer->height;
            other->s      = backBuffer->stride;
            other->usage  = backBuffer->usage;
            other->format = backBuffer->format;
            other->bits   = backBuffer->bits;

            // we handle copy-back here...
            
            const Rect bounds(backBuffer->width, backBuffer->height);
            Region newDirtyRegion;

            per_client_cblk_t* const cblk = mClient->mControl;
            layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
            volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
            if (back->flags & surface_info_t::eBufferDirty) {
                // content is meaningless in this case and the whole surface
                // needs to be redrawn.
                newDirtyRegion.set(bounds);
                if (dirty) {
                    *dirty = newDirtyRegion;
                }
            } else 
            {
                if (dirty) {
                    dirty->andSelf(Region(bounds));
                    newDirtyRegion = *dirty;
                } else {
                    newDirtyRegion.set(bounds);
                }
                Region copyback;
                if (!(lcblk->flags & eNoCopyBack)) {
                    const Region previousDirtyRegion(dirtyRegion());
                    copyback = previousDirtyRegion.subtract(newDirtyRegion);
                }
                const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
                if (!copyback.isEmpty() && frontBuffer!=0) {
                    // copy front to back
                    copyBlt(backBuffer, frontBuffer.get(), copyback);
                }
            }
            setDirtyRegion(newDirtyRegion);


            Rect lockBounds(backBuffer->width, backBuffer->height);
            if (dirty) {
                lockBounds = dirty->bounds();
            }
            buffer_handle_t handle;
            backBuffer->getHandle(backBuffer, &handle);
            status_t res = BufferMapper::get().lock(handle,
                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 
                    lockBounds);
            LOGW_IF(res, "failed locking buffer %d (%p)", 
                    mBackbufferIndex, handle);
            setSwapRectangle(lockBounds);
        }
    }
    return err;
}
    
status_t Surface::unlockAndPost() 
{
    // FIXME: needs some locking here

    if (mLockedBuffer == 0)
        return BAD_VALUE;

    buffer_handle_t handle;
    mLockedBuffer->getHandle(mLockedBuffer, &handle);
    status_t res = BufferMapper::get().unlock(handle);
    LOGW_IF(res, "failed unlocking buffer %d (%p)",
            mBackbufferIndex, handle);

    const Rect dirty(dirtyRegion().bounds());
    setSwapRectangle(dirty);
    status_t err = queueBuffer(mLockedBuffer);
    mLockedBuffer->common.decRef(&mLockedBuffer->common);
    mLockedBuffer = 0;
    return err;
}

void Surface::_send_dirty_region(
        layer_cblk_t* lcblk, const Region& dirty)
{
    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
    flat_region_t* flat_region = lcblk->region + index;
    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
    if (err < NO_ERROR) {
        // region doesn't fit, use the bounds
        const Region reg(dirty.bounds());
        reg.write(flat_region, sizeof(flat_region_t));
    }
}


status_t Surface::setLayer(int32_t layer) {
    return mClient->setLayer(this, layer);
}
status_t Surface::setPosition(int32_t x, int32_t y) {
    return mClient->setPosition(this, x, y);
}
status_t Surface::setSize(uint32_t w, uint32_t h) {
    return mClient->setSize(this, w, h);
}
status_t Surface::hide() {
    return mClient->hide(this);
}
status_t Surface::show(int32_t layer) {
    return mClient->show(this, layer);
}
status_t Surface::freeze() {
    return mClient->freeze(this);
}
status_t Surface::unfreeze() {
    return mClient->unfreeze(this);
}
status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
    return mClient->setFlags(this, flags, mask);
}
status_t Surface::setTransparentRegionHint(const Region& transparent) {
    return mClient->setTransparentRegionHint(this, transparent);
}
status_t Surface::setAlpha(float alpha) {
    return mClient->setAlpha(this, alpha);
}
status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
}
status_t Surface::setFreezeTint(uint32_t tint) {
    return mClient->setFreezeTint(this, tint);
}

Region Surface::dirtyRegion() const  {
    return mDirtyRegion; 
}
void Surface::setDirtyRegion(const Region& region) const {
    mDirtyRegion = region;
}
const Rect& Surface::swapRectangle() const {
    return mSwapRectangle;
}
void Surface::setSwapRectangle(const Rect& r) {
    mSwapRectangle = r;
}

sp<Surface> Surface::readFromParcel(Parcel* parcel)
{
    sp<SurfaceComposerClient> client;
    ISurfaceFlingerClient::surface_data_t data;
    sp<IBinder> clientBinder= parcel->readStrongBinder();
    sp<ISurface> surface    = interface_cast<ISurface>(parcel->readStrongBinder());
    data.token              = parcel->readInt32();
    data.identity           = parcel->readInt32();
    PixelFormat format      = parcel->readInt32();
    uint32_t flags          = parcel->readInt32();

    if (clientBinder != NULL)
        client = SurfaceComposerClient::clientForConnection(clientBinder);

    return new Surface(client, surface, data, 0, 0, format, flags, false);
}

status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
{
    uint32_t flags=0;
    uint32_t format=0;
    SurfaceID token = -1;
    uint32_t identity = 0;
    sp<SurfaceComposerClient> client;
    sp<ISurface> sur;
    if (surface->isValid()) {
        token = surface->mToken;
        identity = surface->mIdentity;
        client = surface->mClient;
        sur = surface->mSurface;
        format = surface->mFormat;
        flags = surface->mFlags;
    }
    parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
    parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
    parcel->writeInt32(token);
    parcel->writeInt32(identity);
    parcel->writeInt32(format);
    parcel->writeInt32(flags);
    return NO_ERROR;
}

bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) 
{
    if (lhs == 0 || rhs == 0)
        return false;
    return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
}

status_t Surface::getBufferLocked(int index)
{
    status_t err = NO_MEMORY;
    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
    LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
    if (buffer != 0) {
        sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
        if (currentBuffer != 0) {
            BufferMapper::get().unmap(currentBuffer->getHandle(), this);
            currentBuffer.clear();
        }
        err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
        LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
        if (err == NO_ERROR) {
            currentBuffer = buffer;
        }
    }
    return err; 
}

}; // namespace android

