/*
 * Copyright (C) 2010 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 <stdlib.h>
#include <stdint.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/Log.h>

#include <ui/GraphicBuffer.h>

#include <GLES/gl.h>
#include <GLES/glext.h>

#include <hardware/hardware.h>

#include "clz.h"
#include "DisplayHardware/DisplayHardware.h"
#include "GLExtensions.h"
#include "TextureManager.h"

namespace android {

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

TextureManager::TextureManager()
    : mGLExtensions(GLExtensions::getInstance())
{
}

GLenum TextureManager::getTextureTarget(const Image* image) {
#if defined(GL_OES_EGL_image_external)
    switch (image->target) {
        case Texture::TEXTURE_EXTERNAL:
            return GL_TEXTURE_EXTERNAL_OES;
    }
#endif
    return GL_TEXTURE_2D;
}

status_t TextureManager::initTexture(Texture* texture)
{
    if (texture->name != -1UL)
        return INVALID_OPERATION;

    GLuint textureName = -1;
    glGenTextures(1, &textureName);
    texture->name = textureName;
    texture->width = 0;
    texture->height = 0;

    const GLenum target = GL_TEXTURE_2D;
    glBindTexture(target, textureName);
    glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    return NO_ERROR;
}

status_t TextureManager::initTexture(Image* pImage, int32_t format)
{
    if (pImage->name != -1UL)
        return INVALID_OPERATION;

    GLuint textureName = -1;
    glGenTextures(1, &textureName);
    pImage->name = textureName;
    pImage->width = 0;
    pImage->height = 0;

    GLenum target = GL_TEXTURE_2D;
#if defined(GL_OES_EGL_image_external)
    if (GLExtensions::getInstance().haveTextureExternal()) {
        if (format && isYuvFormat(format)) {
            target = GL_TEXTURE_EXTERNAL_OES;
            pImage->target = Texture::TEXTURE_EXTERNAL;
        }
    }
#endif

    glBindTexture(target, textureName);
    glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    return NO_ERROR;
}

bool TextureManager::isSupportedYuvFormat(int format)
{
    switch (format) {
    case HAL_PIXEL_FORMAT_YV12:
        return true;
    }
    return false;
}

bool TextureManager::isYuvFormat(int format)
{
    switch (format) {
    // supported YUV formats
    case HAL_PIXEL_FORMAT_YV12:
    // Legacy/deprecated YUV formats
    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    case HAL_PIXEL_FORMAT_YCbCr_422_I:
        return true;
    }

    // Any OEM format needs to be considered
    if (format>=0x100 && format<=0x1FF)
        return true;

    return false;
}

status_t TextureManager::initEglImage(Image* pImage,
        EGLDisplay dpy, const sp<GraphicBuffer>& buffer)
{
    status_t err = NO_ERROR;
    if (!pImage->dirty) return err;

    // free the previous image
    if (pImage->image != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(dpy, pImage->image);
        pImage->image = EGL_NO_IMAGE_KHR;
    }

    // construct an EGL_NATIVE_BUFFER_ANDROID
    android_native_buffer_t* clientBuf = buffer->getNativeBuffer();

    // create the new EGLImageKHR
    const EGLint attrs[] = {
            EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
            EGL_NONE,                   EGL_NONE
    };
    pImage->image = eglCreateImageKHR(
            dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
            (EGLClientBuffer)clientBuf, attrs);

    if (pImage->image != EGL_NO_IMAGE_KHR) {
        if (pImage->name == -1UL) {
            initTexture(pImage, buffer->format);
        }
        const GLenum target = getTextureTarget(pImage);
        glBindTexture(target, pImage->name);
        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)pImage->image);
        GLint error = glGetError();
        if (error != GL_NO_ERROR) {
            LOGE("glEGLImageTargetTexture2DOES(%p) failed err=0x%04x",
                    pImage->image, error);
            err = INVALID_OPERATION;
        } else {
            // Everything went okay!
            pImage->dirty  = false;
            pImage->width  = clientBuf->width;
            pImage->height = clientBuf->height;
        }
    } else {
        LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
        err = INVALID_OPERATION;
    }
    return err;
}

status_t TextureManager::loadTexture(Texture* texture,
        const Region& dirty, const GGLSurface& t)
{
    if (texture->name == -1UL) {
        status_t err = initTexture(texture);
        LOGE_IF(err, "loadTexture failed in initTexture (%s)", strerror(err));
        return err;
    }

    if (texture->target != Texture::TEXTURE_2D)
        return INVALID_OPERATION;

    glBindTexture(GL_TEXTURE_2D, texture->name);

    /*
     * In OpenGL ES we can't specify a stride with glTexImage2D (however,
     * GL_UNPACK_ALIGNMENT is a limited form of stride).
     * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
     * need to do something reasonable (here creating a bigger texture).
     *
     * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
     *
     * This situation doesn't happen often, but some h/w have a limitation
     * for their framebuffer (eg: must be multiple of 8 pixels), and
     * we need to take that into account when using these buffers as
     * textures.
     *
     * This should never be a problem with POT textures
     */

    int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
    unpack = 1 << ((unpack > 3) ? 3 : unpack);
    glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);

    /*
     * round to POT if needed
     */
    if (!mGLExtensions.haveNpot()) {
        texture->NPOTAdjust = true;
    }

    if (texture->NPOTAdjust) {
        // find the smallest power-of-two that will accommodate our surface
        texture->potWidth  = 1 << (31 - clz(t.width));
        texture->potHeight = 1 << (31 - clz(t.height));
        if (texture->potWidth  < t.width)  texture->potWidth  <<= 1;
        if (texture->potHeight < t.height) texture->potHeight <<= 1;
        texture->wScale = float(t.width)  / texture->potWidth;
        texture->hScale = float(t.height) / texture->potHeight;
    } else {
        texture->potWidth  = t.width;
        texture->potHeight = t.height;
    }

    Rect bounds(dirty.bounds());
    GLvoid* data = 0;
    if (texture->width != t.width || texture->height != t.height) {
        texture->width  = t.width;
        texture->height = t.height;

        // texture size changed, we need to create a new one
        bounds.set(Rect(t.width, t.height));
        if (t.width  == texture->potWidth &&
            t.height == texture->potHeight) {
            // we can do it one pass
            data = t.data;
        }

        if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_RGB, texture->potWidth, texture->potHeight, 0,
                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
                   t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
                    GL_RGBA, GL_UNSIGNED_BYTE, data);
        } else if (isSupportedYuvFormat(t.format)) {
            // just show the Y plane of YUV buffers
            glTexImage2D(GL_TEXTURE_2D, 0,
                    GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
                    GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
        } else {
            // oops, we don't handle this format!
            LOGE("texture=%d, using format %d, which is not "
                 "supported by the GL", texture->name, t.format);
        }
    }
    if (!data) {
        if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
                    t.data + bounds.top*t.stride*2);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
                    t.data + bounds.top*t.stride*2);
        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
                   t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_RGBA, GL_UNSIGNED_BYTE,
                    t.data + bounds.top*t.stride*4);
        } else if (isSupportedYuvFormat(t.format)) {
            // just show the Y plane of YUV buffers
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                    0, bounds.top, t.width, bounds.height(),
                    GL_LUMINANCE, GL_UNSIGNED_BYTE,
                    t.data + bounds.top*t.stride);
        }
    }
    return NO_ERROR;
}

void TextureManager::activateTexture(const Texture& texture, bool filter)
{
    const GLenum target = getTextureTarget(&texture);
    if (target == GL_TEXTURE_2D) {
        glBindTexture(GL_TEXTURE_2D, texture.name);
        glEnable(GL_TEXTURE_2D);
#if defined(GL_OES_EGL_image_external)
        if (GLExtensions::getInstance().haveTextureExternal()) {
            glDisable(GL_TEXTURE_EXTERNAL_OES);
        }
    } else {
        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture.name);
        glEnable(GL_TEXTURE_EXTERNAL_OES);
        glDisable(GL_TEXTURE_2D);
#endif
    }

    if (filter) {
        glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    } else {
        glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    }
}

void TextureManager::deactivateTextures()
{
    glDisable(GL_TEXTURE_2D);
#if defined(GL_OES_EGL_image_external)
    if (GLExtensions::getInstance().haveTextureExternal()) {
        glDisable(GL_TEXTURE_EXTERNAL_OES);
    }
#endif
}

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

}; // namespace android
