/*
 * 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.
 */

#include "Caches.h"
#include "Texture.h"
#include "utils/GLUtils.h"
#include "utils/MathUtils.h"
#include "utils/TraceUtils.h"

#include <utils/Log.h>

#include <math/mat4.h>

#include <SkCanvas.h>

namespace android {
namespace uirenderer {

// Number of bytes used by a texture in the given format
static int bytesPerPixel(GLint glFormat) {
    switch (glFormat) {
    // The wrapped-texture case, usually means a SurfaceTexture
    case 0:
        return 0;
    case GL_LUMINANCE:
    case GL_ALPHA:
        return 1;
    case GL_SRGB8:
    case GL_RGB:
        return 3;
    case GL_SRGB8_ALPHA8:
    case GL_RGBA:
        return 4;
    case GL_RGBA16F:
        return 8;
    default:
        LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat);
    }
}

void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) {
    if (force || wrapS != mWrapS || wrapT != mWrapT) {
        mWrapS = wrapS;
        mWrapT = wrapT;

        if (bindTexture) {
            mCaches.textureState().bindTexture(mTarget, mId);
        }

        glTexParameteri(mTarget, GL_TEXTURE_WRAP_S, wrapS);
        glTexParameteri(mTarget, GL_TEXTURE_WRAP_T, wrapT);
    }
}

void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool force) {
    if (force || min != mMinFilter || mag != mMagFilter) {
        mMinFilter = min;
        mMagFilter = mag;

        if (bindTexture) {
            mCaches.textureState().bindTexture(mTarget, mId);
        }

        if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;

        glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, min);
        glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, mag);
    }
}

void Texture::deleteTexture() {
    mCaches.textureState().deleteTexture(mId);
    mId = 0;
    mTarget = GL_NONE;
    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
        EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
        mEglImageHandle = EGL_NO_IMAGE_KHR;
    }
}

bool Texture::updateLayout(uint32_t width, uint32_t height, GLint internalFormat,
        GLint format, GLenum target) {
    if (mWidth == width
            && mHeight == height
            && mFormat == format
            && mInternalFormat == internalFormat
            && mTarget == target) {
        return false;
    }
    mWidth = width;
    mHeight = height;
    mFormat = format;
    mInternalFormat = internalFormat;
    mTarget = target;
    notifySizeChanged(mWidth * mHeight * bytesPerPixel(internalFormat));
    return true;
}

void Texture::resetCachedParams() {
    mWrapS = GL_REPEAT;
    mWrapT = GL_REPEAT;
    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
    mMagFilter = GL_LINEAR;
}

void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height,
        GLenum format, GLenum type, const void* pixels) {
    GL_CHECKPOINT(MODERATE);
    bool needsAlloc = updateLayout(width, height, internalFormat, format, GL_TEXTURE_2D);
    if (!mId) {
        glGenTextures(1, &mId);
        needsAlloc = true;
        resetCachedParams();
    }
    mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId);
    if (needsAlloc) {
        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0,
                format, type, pixels);
    } else if (pixels) {
        glTexSubImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0,
                format, type, pixels);
    }
    GL_CHECKPOINT(MODERATE);
}

void Texture::uploadHardwareBitmapToTexture(GraphicBuffer* buffer) {
    EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
        mEglImageHandle = EGL_NO_IMAGE_KHR;
    }
    mEglImageHandle = eglCreateImageKHR(eglDisplayHandle, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
            buffer->getNativeBuffer(), 0);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, mEglImageHandle);
}

static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
        GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height, const GLvoid * data) {

    const bool useStride = stride != width
            && Caches::getInstance().extensions().hasUnpackRowLength();
    if ((stride == width) || useStride) {
        if (useStride) {
            glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
        }

        if (resize) {
            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, data);
        } else {
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
        }

        if (useStride) {
            glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        }
    } else {
        //  With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
        //  if the stride doesn't match the width

        GLvoid * temp = (GLvoid *) malloc(width * height * bpp);
        if (!temp) return;

        uint8_t * pDst = (uint8_t *)temp;
        uint8_t * pSrc = (uint8_t *)data;
        for (GLsizei i = 0; i < height; i++) {
            memcpy(pDst, pSrc, width * bpp);
            pDst += width * bpp;
            pSrc += stride * bpp;
        }

        if (resize) {
            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, temp);
        } else {
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
        }

        free(temp);
    }
}

void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
        bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType) {
    switch (colorType) {
    case kAlpha_8_SkColorType:
        *outFormat = GL_ALPHA;
        *outInternalFormat = GL_ALPHA;
        *outType = GL_UNSIGNED_BYTE;
        break;
    case kRGB_565_SkColorType:
        if (needSRGB) {
            // We would ideally use a GL_RGB/GL_SRGB8 texture but the
            // intermediate Skia bitmap needs to be ARGB_8888
            *outFormat = GL_RGBA;
            *outInternalFormat = caches.rgbaInternalFormat();
            *outType = GL_UNSIGNED_BYTE;
        } else {
            *outFormat = GL_RGB;
            *outInternalFormat = GL_RGB;
            *outType = GL_UNSIGNED_SHORT_5_6_5;
        }
        break;
    // ARGB_4444 and Index_8 are both upconverted to RGBA_8888
    case kARGB_4444_SkColorType:
    case kIndex_8_SkColorType:
    case kN32_SkColorType:
        *outFormat = GL_RGBA;
        *outInternalFormat = caches.rgbaInternalFormat(needSRGB);
        *outType = GL_UNSIGNED_BYTE;
        break;
    case kGray_8_SkColorType:
        *outFormat = GL_LUMINANCE;
        *outInternalFormat = GL_LUMINANCE;
        *outType = GL_UNSIGNED_BYTE;
        break;
    case kRGBA_F16_SkColorType:
        if (caches.extensions().getMajorGlVersion() >= 3) {
            // This format is always linear
            *outFormat = GL_RGBA;
            *outInternalFormat = GL_RGBA16F;
            *outType = GL_HALF_FLOAT;
        } else {
            *outFormat = GL_RGBA;
            *outInternalFormat = caches.rgbaInternalFormat(true);
            *outType = GL_UNSIGNED_BYTE;
        }
        break;
    default:
        LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
        break;
    }
}

SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
        sk_sp<SkColorSpace> sRGB) {
    SkBitmap rgbaBitmap;
    rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
            bitmap.info().alphaType(), hasLinearBlending ? sRGB : nullptr));
    rgbaBitmap.eraseColor(0);

    if (bitmap.colorType() == kRGBA_F16_SkColorType) {
        // Drawing RGBA_F16 onto ARGB_8888 is not supported
        bitmap.readPixels(rgbaBitmap.info()
                .makeColorSpace(SkColorSpace::MakeSRGB()),
                rgbaBitmap.getPixels(), rgbaBitmap.rowBytes(), 0, 0);
    } else {
        SkCanvas canvas(rgbaBitmap);
        canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
    }

    return rgbaBitmap;
}

bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending) {
    return info.colorType() == kARGB_4444_SkColorType
        || info.colorType() == kIndex_8_SkColorType
        || (info.colorType() == kRGB_565_SkColorType
                && hasLinearBlending
                && info.colorSpace()->isSRGB())
        || (info.colorType() == kRGBA_F16_SkColorType
                && Caches::getInstance().extensions().getMajorGlVersion() < 3);
}

void Texture::upload(Bitmap& bitmap) {
    if (!bitmap.readyToDraw()) {
        ALOGE("Cannot generate texture from bitmap");
        return;
    }

    ATRACE_FORMAT("Upload %ux%u Texture", bitmap.width(), bitmap.height());

    // We could also enable mipmapping if both bitmap dimensions are powers
    // of 2 but we'd have to deal with size changes. Let's keep this simple
    const bool canMipMap = mCaches.extensions().hasNPot();

    // If the texture had mipmap enabled but not anymore,
    // force a glTexImage2D to discard the mipmap levels
    bool needsAlloc = canMipMap && mipMap && !bitmap.hasHardwareMipMap();
    bool setDefaultParams = false;

    if (!mId) {
        glGenTextures(1, &mId);
        needsAlloc = true;
        setDefaultParams = true;
    }

    bool hasLinearBlending = mCaches.extensions().hasLinearBlending();
    bool needSRGB = transferFunctionCloseToSRGB(bitmap.info().colorSpace());

    GLint internalFormat, format, type;
    colorTypeToGlFormatAndType(mCaches, bitmap.colorType(),
            needSRGB && hasLinearBlending, &internalFormat, &format, &type);

    // Some devices don't support GL_RGBA16F, so we need to compare the color type
    // and internal GL format to decide what to do with 16 bit bitmaps
    bool rgba16fNeedsConversion = bitmap.colorType() == kRGBA_F16_SkColorType
            && internalFormat != GL_RGBA16F;

    mConnector.reset();

    // RGBA16F is always extended sRGB, alpha masks don't have color profiles
    // If an RGBA16F bitmap needs conversion, we know the target will be sRGB
    if (internalFormat != GL_RGBA16F && internalFormat != GL_ALPHA && !rgba16fNeedsConversion) {
        SkColorSpace* colorSpace = bitmap.info().colorSpace();
        // If the bitmap is sRGB we don't need conversion
        if (colorSpace != nullptr && !colorSpace->isSRGB()) {
            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
            if (!colorSpace->toXYZD50(&xyzMatrix)) {
                ALOGW("Incompatible color space!");
            } else {
                SkColorSpaceTransferFn fn;
                if (!colorSpace->isNumericalTransferFn(&fn)) {
                    ALOGW("Incompatible color space, no numerical transfer function!");
                } else {
                    float data[16];
                    xyzMatrix.asColMajorf(data);

                    ColorSpace::TransferParameters p =
                            {fn.fG, fn.fA, fn.fB, fn.fC, fn.fD, fn.fE, fn.fF};
                    ColorSpace src("Unnamed", mat4f((const float*) &data[0]).upperLeft(), p);
                    mConnector.reset(new ColorSpaceConnector(src, ColorSpace::sRGB()));

                    // A non-sRGB color space might have a transfer function close enough to sRGB
                    // that we can save shader instructions by using an sRGB sampler
                    // This is only possible if we have hardware support for sRGB textures
                    if (needSRGB && internalFormat == GL_RGBA
                            && mCaches.extensions().hasSRGB() && !bitmap.isHardware()) {
                        internalFormat = GL_SRGB8_ALPHA8;
                    }
                }
            }
        }
    }

    GLenum target = bitmap.isHardware() ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
    needsAlloc |= updateLayout(bitmap.width(), bitmap.height(), internalFormat, format, target);

    blend = !bitmap.isOpaque();
    mCaches.textureState().bindTexture(mTarget, mId);

    // TODO: Handle sRGB gray bitmaps
    if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasLinearBlending))) {
        SkBitmap skBitmap;
        bitmap.getSkBitmap(&skBitmap);
        sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
        SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
        uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
                rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(),
                rgbaBitmap.height(), rgbaBitmap.getPixels());
    } else if (bitmap.isHardware()) {
        uploadHardwareBitmapToTexture(bitmap.graphicBuffer());
    } else {
        uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
                bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.pixels());
    }

    if (canMipMap) {
        mipMap = bitmap.hasHardwareMipMap();
        if (mipMap) {
            glGenerateMipmap(GL_TEXTURE_2D);
        }
    }

    if (setDefaultParams) {
        setFilter(GL_NEAREST);
        setWrap(GL_CLAMP_TO_EDGE);
    }
}

void Texture::wrap(GLuint id, uint32_t width, uint32_t height,
        GLint internalFormat, GLint format, GLenum target) {
    mId = id;
    mWidth = width;
    mHeight = height;
    mFormat = format;
    mInternalFormat = internalFormat;
    mTarget = target;
    mConnector.reset();
    // We're wrapping an existing texture, so don't double count this memory
    notifySizeChanged(0);
}

TransferFunctionType Texture::getTransferFunctionType() const {
    if (mConnector.get() != nullptr && mInternalFormat != GL_SRGB8_ALPHA8) {
        const ColorSpace::TransferParameters& p = mConnector->getSource().getTransferParameters();
        if (MathUtils::isZero(p.e) && MathUtils::isZero(p.f)) {
            if (MathUtils::areEqual(p.a, 1.0f) && MathUtils::isZero(p.b)
                    && MathUtils::isZero(p.c) && MathUtils::isZero(p.d)) {
                if (MathUtils::areEqual(p.g, 1.0f)) {
                    return TransferFunctionType::None;
                }
                return TransferFunctionType::Gamma;
            }
            return TransferFunctionType::Limited;
        }
        return TransferFunctionType::Full;
    }
    return TransferFunctionType::None;
}

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