/*
 * 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 <utils/Log.h>

#include "Caches.h"
#include "Extensions.h"
#include "PixelBuffer.h"
#include "Properties.h"

namespace android {
namespace uirenderer {

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

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

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

    uint8_t* getMappedPointer() const;

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

private:
    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)];
}

CpuPixelBuffer::~CpuPixelBuffer() {
    delete[] mBuffer;
}

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

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

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

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);
    void unmap();

    uint8_t* getMappedPointer() const;

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

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

GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height):
        PixelBuffer(format, width, height), mMappedPointer(0), mCaches(Caches::getInstance()) {
    glGenBuffers(1, &mBuffer);
    mCaches.bindPixelBuffer(mBuffer);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), NULL, GL_DYNAMIC_DRAW);
    mCaches.unbindPixelBuffer();
}

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

uint8_t* GpuPixelBuffer::map(AccessMode mode) {
    if (mAccessMode == kAccessMode_None) {
        mCaches.bindPixelBuffer(mBuffer);
        mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
        mAccessMode = mode;
    }

    return mMappedPointer;
}

void GpuPixelBuffer::unmap() {
    if (mAccessMode != kAccessMode_None) {
        if (mMappedPointer) {
            mCaches.bindPixelBuffer(mBuffer);
            glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
        }
        mAccessMode = kAccessMode_None;
        mMappedPointer = NULL;
    }
}

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.bindPixelBuffer(mBuffer);
    unmap();
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
            GL_UNSIGNED_BYTE, (void*) offset);
}

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

PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
    bool gpuBuffer = type == kBufferType_Auto && Extensions::getInstance().getMajorGlVersion() >= 3;
    if (gpuBuffer) {
        char property[PROPERTY_VALUE_MAX];
        if (property_get(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, property, "false") > 0) {
            if (!strcmp(property, "true")) {
                return new GpuPixelBuffer(format, width, height);
            }
        }
    }
    return new CpuPixelBuffer(format, width, height);
}

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