/*
 * Copyright (C) 2013 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 "OpenGLRenderer"

#include "PixelBuffer.h"

#include "Debug.h"
#include "Extensions.h"
#include "Properties.h"
#include "renderstate/RenderState.h"

#include <utils/Log.h>

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// CPU pixel buffer
///////////////////////////////////////////////////////////////////////////////

class CpuPixelBuffer: public PixelBuffer {
public:
    CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);

    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
    void unmap() override;

    uint8_t* getMappedPointer() const override;

    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;

private:
    std::unique_ptr<uint8_t[]> mBuffer;
};

CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
        : PixelBuffer(format, width, height)
        , mBuffer(new uint8_t[width * height * formatSize(format)]) {
}

uint8_t* CpuPixelBuffer::map(AccessMode mode) {
    if (mAccessMode == kAccessMode_None) {
        mAccessMode = mode;
    }
    return mBuffer.get();
}

void CpuPixelBuffer::unmap() {
    mAccessMode = kAccessMode_None;
}

uint8_t* CpuPixelBuffer::getMappedPointer() const {
    return mAccessMode == kAccessMode_None ? nullptr : mBuffer.get();
}

void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
            mFormat, GL_UNSIGNED_BYTE, &mBuffer[offset]);
}

///////////////////////////////////////////////////////////////////////////////
// GPU pixel buffer
///////////////////////////////////////////////////////////////////////////////

class GpuPixelBuffer: public PixelBuffer {
public:
    GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
    ~GpuPixelBuffer();

    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
    void unmap() override;

    uint8_t* getMappedPointer() const override;

    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;

private:
    GLuint mBuffer;
    uint8_t* mMappedPointer;
    Caches& mCaches;
};

GpuPixelBuffer::GpuPixelBuffer(GLenum format,
        uint32_t width, uint32_t height)
        : PixelBuffer(format, width, height)
        , mMappedPointer(nullptr)
        , mCaches(Caches::getInstance()){
    glGenBuffers(1, &mBuffer);

    mCaches.pixelBufferState().bind(mBuffer);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
    mCaches.pixelBufferState().unbind();
}

GpuPixelBuffer::~GpuPixelBuffer() {
    glDeleteBuffers(1, &mBuffer);
}

uint8_t* GpuPixelBuffer::map(AccessMode mode) {
    if (mAccessMode == kAccessMode_None) {
        mCaches.pixelBufferState().bind(mBuffer);
        mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
#if DEBUG_OPENGL
        if (!mMappedPointer) {
            GLenum status = GL_NO_ERROR;
            while ((status = glGetError()) != GL_NO_ERROR) {
                ALOGE("Could not map GPU pixel buffer: 0x%x", status);
            }
        }
#endif
        mAccessMode = mode;
    }

    return mMappedPointer;
}

void GpuPixelBuffer::unmap() {
    if (mAccessMode != kAccessMode_None) {
        if (mMappedPointer) {
            mCaches.pixelBufferState().bind(mBuffer);
            GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
            if (status == GL_FALSE) {
                ALOGE("Corrupted GPU pixel buffer");
            }
        }
        mAccessMode = kAccessMode_None;
        mMappedPointer = nullptr;
    }
}

uint8_t* GpuPixelBuffer::getMappedPointer() const {
    return mMappedPointer;
}

void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
    // If the buffer is not mapped, unmap() will not bind it
    mCaches.pixelBufferState().bind(mBuffer);
    unmap();
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
            GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
}

///////////////////////////////////////////////////////////////////////////////
// Factory
///////////////////////////////////////////////////////////////////////////////

PixelBuffer* PixelBuffer::create(GLenum format,
        uint32_t width, uint32_t height, BufferType type) {
    if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
        return new GpuPixelBuffer(format, width, height);
    }
    return new CpuPixelBuffer(format, width, height);
}

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