/*
 * Copyright (C) 2015 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 "OffscreenBufferPool.h"

#include "Caches.h"
#include "Properties.h"
#include "renderstate/RenderState.h"
#include "utils/FatVector.h"
#include "utils/TraceUtils.h"

#include <utils/Log.h>

#include <GLES2/gl2.h>

namespace android {
namespace uirenderer {

////////////////////////////////////////////////////////////////////////////////
// OffscreenBuffer
////////////////////////////////////////////////////////////////////////////////

OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches,
        uint32_t viewportWidth, uint32_t viewportHeight)
        : GpuMemoryTracker(GpuObjectType::OffscreenBuffer)
        , renderState(renderState)
        , viewportWidth(viewportWidth)
        , viewportHeight(viewportHeight)
        , texture(caches) {
    uint32_t width = computeIdealDimension(viewportWidth);
    uint32_t height = computeIdealDimension(viewportHeight);
    ATRACE_FORMAT("Allocate %ux%u HW Layer", width, height);
    caches.textureState().activateTexture(0);
    texture.resize(width, height, GL_RGBA);
    texture.blend = true;
    texture.setWrap(GL_CLAMP_TO_EDGE);
    // not setting filter on texture, since it's set when drawing, based on transform
}

Rect OffscreenBuffer::getTextureCoordinates() {
    const float texX = 1.0f / static_cast<float>(texture.width());
    const float texY = 1.0f / static_cast<float>(texture.height());
    return Rect(0, viewportHeight * texY, viewportWidth * texX, 0);
}

void OffscreenBuffer::dirty(Rect dirtyArea) {
    dirtyArea.doIntersect(0, 0, viewportWidth, viewportHeight);
    if (!dirtyArea.isEmpty()) {
        region.orSelf(android::Rect(dirtyArea.left, dirtyArea.top,
                dirtyArea.right, dirtyArea.bottom));
    }
}

void OffscreenBuffer::updateMeshFromRegion() {
    // avoid T-junctions as they cause artifacts in between the resultant
    // geometry when complex transforms occur.
    // TODO: generate the safeRegion only if necessary based on drawing transform
    Region safeRegion = Region::createTJunctionFreeRegion(region);

    size_t count;
    const android::Rect* rects = safeRegion.getArray(&count);

    const float texX = 1.0f / float(texture.width());
    const float texY = 1.0f / float(texture.height());

    FatVector<TextureVertex, 64> meshVector(count * 4); // uses heap if more than 64 vertices needed
    TextureVertex* mesh = &meshVector[0];
    for (size_t i = 0; i < count; i++) {
        const android::Rect* r = &rects[i];

        const float u1 = r->left * texX;
        const float v1 = (viewportHeight - r->top) * texY;
        const float u2 = r->right * texX;
        const float v2 = (viewportHeight - r->bottom) * texY;

        TextureVertex::set(mesh++, r->left, r->top, u1, v1);
        TextureVertex::set(mesh++, r->right, r->top, u2, v1);
        TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
        TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
    }
    elementCount = count * 6;
    renderState.meshState().genOrUpdateMeshBuffer(&vbo,
            sizeof(TextureVertex) * count * 4,
            &meshVector[0],
            GL_DYNAMIC_DRAW); // TODO: GL_STATIC_DRAW if savelayer
}

uint32_t OffscreenBuffer::computeIdealDimension(uint32_t dimension) {
    return uint32_t(ceilf(dimension / float(LAYER_SIZE)) * LAYER_SIZE);
}

OffscreenBuffer::~OffscreenBuffer() {
    ATRACE_FORMAT("Destroy %ux%u HW Layer", texture.width(), texture.height());
    texture.deleteTexture();
    renderState.meshState().deleteMeshBuffer(vbo);
    elementCount = 0;
    vbo = 0;
}

///////////////////////////////////////////////////////////////////////////////
// OffscreenBufferPool
///////////////////////////////////////////////////////////////////////////////

OffscreenBufferPool::OffscreenBufferPool()
    : mMaxSize(Properties::layerPoolSize) {
}

OffscreenBufferPool::~OffscreenBufferPool() {
    clear(); // TODO: unique_ptr?
}

int OffscreenBufferPool::Entry::compare(const Entry& lhs, const Entry& rhs) {
    int deltaInt = int(lhs.width) - int(rhs.width);
    if (deltaInt != 0) return deltaInt;

    return int(lhs.height) - int(rhs.height);
}

void OffscreenBufferPool::clear() {
    for (auto& entry : mPool) {
        delete entry.layer;
    }
    mPool.clear();
    mSize = 0;
}

OffscreenBuffer* OffscreenBufferPool::get(RenderState& renderState,
        const uint32_t width, const uint32_t height) {
    OffscreenBuffer* layer = nullptr;

    Entry entry(width, height);
    auto iter = mPool.find(entry);

    if (iter != mPool.end()) {
        entry = *iter;
        mPool.erase(iter);

        layer = entry.layer;
        layer->viewportWidth = width;
        layer->viewportHeight = height;
        mSize -= layer->getSizeInBytes();
    } else {
        layer = new OffscreenBuffer(renderState, Caches::getInstance(), width, height);
    }

    return layer;
}

OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer,
        const uint32_t width, const uint32_t height) {
    RenderState& renderState = layer->renderState;
    if (layer->texture.width() == OffscreenBuffer::computeIdealDimension(width)
            && layer->texture.height() == OffscreenBuffer::computeIdealDimension(height)) {
        // resize in place
        layer->viewportWidth = width;
        layer->viewportHeight = height;

        // entire area will be repainted (and may be smaller) so clear usage region
        layer->region.clear();
        return layer;
    }
    putOrDelete(layer);
    return get(renderState, width, height);
}

void OffscreenBufferPool::dump() {
    for (auto entry : mPool) {
        ALOGD("  Layer size %dx%d", entry.width, entry.height);
    }
}

void OffscreenBufferPool::putOrDelete(OffscreenBuffer* layer) {
    const uint32_t size = layer->getSizeInBytes();
    // Don't even try to cache a layer that's bigger than the cache
    if (size < mMaxSize) {
        // TODO: Use an LRU
        while (mSize + size > mMaxSize) {
            OffscreenBuffer* victim = mPool.begin()->layer;
            mSize -= victim->getSizeInBytes();
            delete victim;
            mPool.erase(mPool.begin());
        }

        // clear region, since it's no longer valid
        layer->region.clear();

        Entry entry(layer);

        mPool.insert(entry);
        mSize += size;
    } else {
        delete layer;
    }
}

}; // namespace uirenderer
}; // namespace android
