/*
 * Copyright 2011, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define LOG_TAG "TransferQueue"
#define LOG_NDEBUG 1

#include "config.h"
#include "TransferQueue.h"

#if USE(ACCELERATED_COMPOSITING)

#include "AndroidLog.h"
#include "BaseRenderer.h"
#include "DrawQuadData.h"
#include "GLUtils.h"
#include "Tile.h"
#include "TileTexture.h"
#include "TilesManager.h"
#include <android/native_window.h>
#include <gui/SurfaceTexture.h>
#include <gui/SurfaceTextureClient.h>

// For simple webView usage, MINIMAL_SIZE is recommended for memory saving.
// In browser case, EFFICIENT_SIZE is preferred.
#define MINIMAL_SIZE 1
#define EFFICIENT_SIZE 6

// Set this to 1 if we would like to take the new GpuUpload approach which
// relied on the glCopyTexSubImage2D instead of a glDraw call
#define GPU_UPLOAD_WITHOUT_DRAW 1

namespace WebCore {

TransferQueue::TransferQueue(bool useMinimalMem)
    : m_eglSurface(EGL_NO_SURFACE)
    , m_transferQueueIndex(0)
    , m_fboID(0)
    , m_sharedSurfaceTextureId(0)
    , m_hasGLContext(true)
    , m_currentDisplay(EGL_NO_DISPLAY)
    , m_currentUploadType(DEFAULT_UPLOAD_TYPE)
{
    memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit));
    m_transferQueueSize = useMinimalMem ? MINIMAL_SIZE : EFFICIENT_SIZE;
    m_emptyItemCount = m_transferQueueSize;
    m_transferQueue = new TileTransferData[m_transferQueueSize];
}

TransferQueue::~TransferQueue()
{
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    cleanupGLResources();
    delete[] m_transferQueue;
}

// Set the queue to be totally empty, abandon the Surface Texture. This should
// be called only when we hit a wrong EGL Context in an error situation.
void TransferQueue::resetQueue()
{
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    emptyAndAbandonQueue();
    m_sharedSurfaceTextureId = 0;
}

// This should be called within the m_transferQueueItemLocks.
// Now only called by emptyQueue() and destructor.
void TransferQueue::cleanupGLResources()
{
    if (m_fboID) {
        glDeleteFramebuffers(1, &m_fboID);
        m_fboID = 0;
    }
    if (m_sharedSurfaceTextureId) {
        glDeleteTextures(1, &m_sharedSurfaceTextureId);
        m_sharedSurfaceTextureId = 0;
    }
}

void TransferQueue::initGLResources(int width, int height)
{
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    if (!m_sharedSurfaceTextureId) {
        glGenTextures(1, &m_sharedSurfaceTextureId);
        sp<BufferQueue> bufferQueue(new BufferQueue(true));
        m_sharedSurfaceTexture =
#if GPU_UPLOAD_WITHOUT_DRAW
            new android::SurfaceTexture(m_sharedSurfaceTextureId, true,
                                        GL_TEXTURE_2D, true, bufferQueue);
#else
            new android::SurfaceTexture(m_sharedSurfaceTextureId, true,
                                        GL_TEXTURE_EXTERNAL_OES, true,
                                        bufferQueue);
#endif
        m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture);
        m_sharedSurfaceTexture->setSynchronousMode(true);

        int extraBuffersNeeded = 0;
        m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
                     &extraBuffersNeeded);
        bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded);

        int result = native_window_set_buffers_geometry(m_ANW.get(),
                width, height, HAL_PIXEL_FORMAT_RGBA_8888);
        GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result);
        result = native_window_set_usage(m_ANW.get(),
                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
        GLUtils::checkSurfaceTextureError("native_window_set_usage", result);
    }

    if (!m_fboID)
        glGenFramebuffers(1, &m_fboID);
}

// When bliting, if the item from the transfer queue is mismatching b/t the
// Tile and the content, then the item is considered as obsolete, and
// the content is discarded.
bool TransferQueue::checkObsolete(const TileTransferData* data)
{
    Tile* baseTilePtr = data->savedTilePtr;
    if (!baseTilePtr) {
        ALOGV("Invalid savedTilePtr , such that the tile is obsolete");
        return true;
    }

    TileTexture* baseTileTexture = baseTilePtr->backTexture();
    if (!baseTileTexture || baseTileTexture != data->savedTileTexturePtr) {
        ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete",
              baseTileTexture, data->savedTileTexturePtr);
        return true;
    }

    return false;
}

void TransferQueue::blitTileFromQueue(GLuint fboID, TileTexture* destTex,
                                      GLuint srcTexId, GLenum srcTexTarget,
                                      int index)
{
#if GPU_UPLOAD_WITHOUT_DRAW
    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
    glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId);

    int textureWidth = destTex->getSize().width();
    int textureHeight = destTex->getSize().height();

    glFramebufferTexture2D(GL_FRAMEBUFFER,
                           GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D,
                           srcTexId,
                           0);

    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
                        textureWidth, textureHeight);
    if (GLUtils::checkGlError("At the end of blitTileFromQueue()")) {
#ifndef DEBUG
        if (GLUtils::allowGLLog())
#endif
        ALOGE("blitTileFromQueue ERROR: fboId %d, destTexId %d, srcTexId %d,"
              " textureWidth %d, textureHeight %d", fboID, destTex->m_ownTextureId,
              srcTexId, textureWidth, textureHeight);
    }
#else
    // Then set up the FBO and copy the SurfTex content in.
    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
    glFramebufferTexture2D(GL_FRAMEBUFFER,
                           GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D,
                           destTex->m_ownTextureId,
                           0);
    setGLStateForCopy(destTex->getSize().width(),
                      destTex->getSize().height());
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        ALOGV("Error: glCheckFramebufferStatus failed");
        return;
    }

    // Use empty rect to set up the special matrix to draw.
    SkRect rect  = SkRect::MakeEmpty();

    TextureQuadData data(srcTexId, GL_NEAREST, srcTexTarget, Blit, 0, 0, 1.0, false);
    TilesManager::instance()->shader()->drawQuad(&data);
#endif
}

// This function must be called inside the m_transferQueueItemLocks, for the
// wait and getHasGLContext().
// Only called by updateQueueWithBitmap() for now.
bool TransferQueue::readyForUpdate()
{
    if (!getHasGLContext())
        return false;
    // Don't use a while loop since when the WebView tear down, the emptyCount
    // will still be 0, and we bailed out b/c of GL context lost.
    if (!m_emptyItemCount)
        m_transferQueueItemCond.wait(m_transferQueueItemLocks);

    if (!getHasGLContext())
        return false;

    return true;
}

// Both getHasGLContext and setHasGLContext should be called within the lock.
bool TransferQueue::getHasGLContext()
{
    return m_hasGLContext;
}

void TransferQueue::setHasGLContext(bool hasContext)
{
    m_hasGLContext = hasContext;
}

// Call within a m_transferQueueItemLocks, now called by resetQueue() and
// cleanupGLResoucesAndQueue()
void TransferQueue::emptyAndAbandonQueue()
{
    for (int i = 0 ; i < m_transferQueueSize; i++)
        clearItemInTranferQueue(i);
    m_emptyItemCount = m_transferQueueSize;
    clearPureColorQueue();

    if (m_sharedSurfaceTexture.get()) {
        m_sharedSurfaceTexture->abandon();
        m_sharedSurfaceTexture.clear();
    }
    // This can prevent the tex gen thread to produce, until next incoming draw.
    setHasGLContext(false);
}

void TransferQueue::cleanupGLResourcesAndQueue()
{
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    emptyAndAbandonQueue();
    cleanupGLResources();
}

// Set all the content in the queue to pendingDiscard, after this, there will
// be nothing added to the queue, and this can be called in any thread.
// However, in order to discard the content in the Surface Texture using
// updateTexImage, cleanupPendingDiscard need to be called on the UI thread.
// Must be called within a m_transferQueueItemLocks.
void TransferQueue::setPendingDiscard()
{
    for (int i = 0 ; i < m_transferQueueSize; i++)
        if (m_transferQueue[i].status == pendingBlit)
            m_transferQueue[i].status = pendingDiscard;

    clearPureColorQueue();

    bool GLContextExisted = getHasGLContext();
    // Unblock the Tex Gen thread first before Tile Page deletion.
    // Otherwise, there will be a deadlock while removing operations.
    setHasGLContext(false);

    // Only signal once when GL context lost.
    if (GLContextExisted)
        m_transferQueueItemCond.signal();
}

void TransferQueue::clearPureColorQueue()
{
    for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
        SkSafeUnref(m_pureColorTileQueue[i].savedTilePainter);
        m_pureColorTileQueue[i].savedTilePainter = 0;
    }
    m_pureColorTileQueue.clear();
}

void TransferQueue::updatePureColorTiles()
{
    for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
        TileTransferData* data = &m_pureColorTileQueue[i];
        if (data->status == pendingBlit) {
            TileTexture* destTexture = 0;
            bool obsoleteTile = checkObsolete(data);
            if (!obsoleteTile) {
                destTexture = data->savedTilePtr->backTexture();
                destTexture->setPureColor(data->pureColor);
                destTexture->transferComplete();
            }
        } else if (data->status == emptyItem || data->status == pendingDiscard) {
            // The queue should be clear instead of setting to different status.
            ALOGV("Warning: Don't expect an emptyItem here.");
        }
    }
    clearPureColorQueue();
}

// Call on UI thread to copy from the shared Surface Texture to the Tile's texture.
void TransferQueue::updateDirtyTiles()
{
    android::Mutex::Autolock lock(m_transferQueueItemLocks);

    cleanupPendingDiscard();
    if (!getHasGLContext())
        setHasGLContext(true);

    // Check the pure color tile first, since it is simpler.
    updatePureColorTiles();

    // Start from the oldest item, we call the updateTexImage to retrive
    // the texture and blit that into each Tile's texture.
    const int nextItemIndex = getNextTransferQueueIndex();
    int index = nextItemIndex;
    bool usedFboForUpload = false;
    for (int k = 0; k < m_transferQueueSize ; k++) {
        if (m_transferQueue[index].status == pendingBlit) {
            bool obsoleteTile = checkObsolete(&m_transferQueue[index]);
            // Save the needed info, update the Surf Tex, clean up the item in
            // the queue. Then either move on to next item or copy the content.
            TileTexture* destTexture = 0;
            if (!obsoleteTile)
                destTexture = m_transferQueue[index].savedTilePtr->backTexture();

            if (m_transferQueue[index].uploadType == GpuUpload) {
                status_t result = m_sharedSurfaceTexture->updateTexImage();
                if (result != OK)
                    ALOGE("unexpected error: updateTexImage return %d", result);
            }

            if (obsoleteTile) {
                ALOGV("Warning: the texture is obsolete for this baseTile");
                clearItemInTranferQueue(index);
                index = (index + 1) % m_transferQueueSize;
                continue;
            }

            // guarantee that we have a texture to blit into
            destTexture->requireGLTexture();
            GLUtils::checkGlError("before blitTileFromQueue");
            if (m_transferQueue[index].uploadType == CpuUpload) {
                // Here we just need to upload the bitmap content to the GL Texture
                GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId,
                                                 *m_transferQueue[index].bitmap);
            } else {
                if (!usedFboForUpload) {
                    saveGLState();
                    usedFboForUpload = true;
                }
                blitTileFromQueue(m_fboID, destTexture, m_sharedSurfaceTextureId,
                                  m_sharedSurfaceTexture->getCurrentTextureTarget(),
                                  index);
            }

            destTexture->setPure(false);
            destTexture->transferComplete();
            clearItemInTranferQueue(index);
            ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d",
                  m_transferQueue[index].savedTilePtr,
                  destTexture,
                  destTexture->m_ownTextureId);
        }
        index = (index + 1) % m_transferQueueSize;
    }

    // Clean up FBO setup. Doing this for both CPU/GPU upload can make the
    // dynamic switch possible. Moving this out from the loop can save some
    // milli-seconds.
    if (usedFboForUpload) {
        restoreGLState();
        GLUtils::checkGlError("updateDirtyTiles");
    }

    m_emptyItemCount = m_transferQueueSize;
    m_transferQueueItemCond.signal();
}

void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
                                          SkBitmap& bitmap)
{
    TRACE_METHOD();
    if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) {
        // failed placing bitmap in queue, discard tile's texture so it will be
        // re-enqueued (and repainted)
        Tile* tile = renderInfo->baseTile;
        if (tile)
            tile->backTextureTransferFail();
    }
}

bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
                                             SkBitmap& bitmap)
{
    // This lock need to cover the full update since it is possible that queue
    // will be cleaned up in the middle of this update without the lock.
    // The Surface Texture will not block us since the readyForUpdate will check
    // availability of the slots in the queue first.
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    bool ready = readyForUpdate();
    TextureUploadType currentUploadType = m_currentUploadType;
    if (!ready) {
        ALOGV("Quit bitmap update: not ready! for tile x y %d %d",
              renderInfo->x, renderInfo->y);
        return false;
    }
    if (currentUploadType == GpuUpload) {
        // a) Dequeue the Surface Texture and write into the buffer
        if (!m_ANW.get()) {
            ALOGV("ERROR: ANW is null");
            return false;
        }

        if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap))
            return false;
    }

    // b) After update the Surface Texture, now udpate the transfer queue info.
    addItemInTransferQueue(renderInfo, currentUploadType, bitmap);

    ALOGV("Bitmap updated x, y %d %d, baseTile %p",
          renderInfo->x, renderInfo->y, renderInfo->baseTile);
    return true;
}

void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo)
{
    // The pure color tiles' queue will be read from UI thread and written in
    // Tex Gen thread, thus we need to have a lock here.
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    TileTransferData data;
    addItemCommon(renderInfo, GpuUpload, &data);
    data.pureColor = renderInfo->pureColor;
    m_pureColorTileQueue.append(data);
}

void TransferQueue::clearItemInTranferQueue(int index)
{
    m_transferQueue[index].savedTilePtr = 0;
    SkSafeUnref(m_transferQueue[index].savedTilePainter);
    m_transferQueue[index].savedTilePainter = 0;
    m_transferQueue[index].status = emptyItem;
}

// Translates the info from TileRenderInfo and others to TileTransferData.
// This is used by pure color tiles and normal tiles.
void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo,
                                  TextureUploadType type,
                                  TileTransferData* data)
{
    data->savedTileTexturePtr = renderInfo->baseTile->backTexture();
    data->savedTilePainter = renderInfo->tilePainter;
    SkSafeRef(data->savedTilePainter);
    data->savedTilePtr = renderInfo->baseTile;
    data->status = pendingBlit;
    data->uploadType = type;

    IntRect inval(0, 0, 0, 0);
}

// Note that there should be lock/unlock around this function call.
// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap.
void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
                                           TextureUploadType type,
                                           SkBitmap& bitmap)
{
    m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize;

    int index = m_transferQueueIndex;
    if (m_transferQueue[index].savedTilePtr
        || m_transferQueue[index].status != emptyItem) {
        ALOGV("ERROR update a tile which is dirty already @ index %d", index);
    }

    TileTransferData* data = &m_transferQueue[index];
    addItemCommon(renderInfo, type, data);
    if (type == CpuUpload) {
        // Lazily create the bitmap
        if (!m_transferQueue[index].bitmap) {
            m_transferQueue[index].bitmap = new SkBitmap();
            int w = bitmap.width();
            int h = bitmap.height();
            m_transferQueue[index].bitmap->setConfig(bitmap.config(), w, h);
            m_transferQueue[index].bitmap->allocPixels();
        }
        SkBitmap temp = (*m_transferQueue[index].bitmap);
        (*m_transferQueue[index].bitmap) = bitmap;
        bitmap = temp;
    }

    m_emptyItemCount--;
}

void TransferQueue::setTextureUploadType(TextureUploadType type)
{
    android::Mutex::Autolock lock(m_transferQueueItemLocks);
    if (m_currentUploadType == type)
        return;

    setPendingDiscard();

    m_currentUploadType = type;
    ALOGD("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload");
}

// Note: this need to be called within the lock and on the UI thread.
// Only called by updateDirtyTiles() and emptyQueue() for now
void TransferQueue::cleanupPendingDiscard()
{
    int index = getNextTransferQueueIndex();

    for (int i = 0 ; i < m_transferQueueSize; i++) {
        if (m_transferQueue[index].status == pendingDiscard) {
            // No matter what the current upload type is, as long as there has
            // been a Surf Tex enqueue operation, this updateTexImage need to
            // be called to keep things in sync.
            if (m_transferQueue[index].uploadType == GpuUpload) {
                status_t result = m_sharedSurfaceTexture->updateTexImage();
                if (result != OK)
                    ALOGE("unexpected error: updateTexImage return %d", result);
            }

            // since tiles in the queue may be from another webview, remove
            // their textures so that they will be repainted / retransferred
            Tile* tile = m_transferQueue[index].savedTilePtr;
            TileTexture* texture = m_transferQueue[index].savedTileTexturePtr;
            if (tile && texture && texture->owner() == tile) {
                // since tile destruction removes textures on the UI thread, the
                // texture->owner ptr guarantees the tile is valid
                tile->discardBackTexture();
                ALOGV("transfer queue discarded tile %p, removed texture", tile);
            }
            clearItemInTranferQueue(index);
        }
        index = (index + 1) % m_transferQueueSize;
    }
}

void TransferQueue::saveGLState()
{
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, m_GLStateBeforeBlit.bufferId);
    glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport);
    glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor);
    glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth);
#ifdef DEBUG
    glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor);
#endif
}

void TransferQueue::setGLStateForCopy(int width, int height)
{
    // Need to match the texture size.
    glViewport(0, 0, width, height);
    glDisable(GL_SCISSOR_TEST);
    glDisable(GL_DEPTH_TEST);
    // Clear the content is only for debug purpose.
#ifdef DEBUG
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
#endif
}

void TransferQueue::restoreGLState()
{
    glBindFramebuffer(GL_FRAMEBUFFER, m_GLStateBeforeBlit.bufferId[0]);
    glViewport(m_GLStateBeforeBlit.viewport[0],
               m_GLStateBeforeBlit.viewport[1],
               m_GLStateBeforeBlit.viewport[2],
               m_GLStateBeforeBlit.viewport[3]);

    if (m_GLStateBeforeBlit.scissor[0])
        glEnable(GL_SCISSOR_TEST);

    if (m_GLStateBeforeBlit.depth[0])
        glEnable(GL_DEPTH_TEST);
#ifdef DEBUG
    glClearColor(m_GLStateBeforeBlit.clearColor[0],
                 m_GLStateBeforeBlit.clearColor[1],
                 m_GLStateBeforeBlit.clearColor[2],
                 m_GLStateBeforeBlit.clearColor[3]);
#endif
}

int TransferQueue::getNextTransferQueueIndex()
{
    return (m_transferQueueIndex + 1) % m_transferQueueSize;
}

} // namespace WebCore

#endif // USE(ACCELERATED_COMPOSITING
