/*
 * 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);

    // We don't have color space information, we assume the data is gamma encoded
    mIsLinear = false;

    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;

    // RGBA16F is always linear extended sRGB
    if (internalFormat == GL_RGBA16F) {
        mIsLinear = true;
    }

    mConnector.reset();

    // Alpha masks don't have color profiles
    // If an RGBA16F bitmap needs conversion, we know the target will be sRGB
    if (!mIsLinear && 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
