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

#ifndef ANDROID_HWUI_TEXTURE_H
#define ANDROID_HWUI_TEXTURE_H

#include "GpuMemoryTracker.h"
#include "hwui/Bitmap.h"

#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <SkBitmap.h>

namespace android {

class GraphicBuffer;

namespace uirenderer {

class Caches;
class UvMapper;
class Layer;

/**
 * Represents an OpenGL texture.
 */
class Texture : public GpuMemoryTracker {
public:
    static SkBitmap uploadToN32(const SkBitmap& bitmap,
            bool hasLinearBlending, sk_sp<SkColorSpace> sRGB);
    static bool hasUnsupportedColorType(const SkImageInfo& info,
            bool hasLinearBlending, SkColorSpace* sRGB);
    static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
            bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType);

    explicit Texture(Caches& caches)
        : GpuMemoryTracker(GpuObjectType::Texture)
        , mCaches(caches)
    { }

    virtual ~Texture() { }

    inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
        setWrapST(wrap, wrap, bindTexture, force);
    }

    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
            bool force = false);

    inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
        setFilterMinMag(filter, filter, bindTexture, force);
    }

    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
            bool force = false);

    /**
     * Convenience method to call glDeleteTextures() on this texture's id.
     */
    void deleteTexture();

    /**
     * Sets the width, height, and format of the texture along with allocating
     * the texture ID. Does nothing if the width, height, and format are already
     * the requested values.
     *
     * The image data is undefined after calling this.
     */
    void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
        upload(internalFormat, width, height, format, GL_UNSIGNED_BYTE, nullptr);
    }

    /**
     * Updates this Texture with the contents of the provided Bitmap,
     * also setting the appropriate width, height, and format. It is not necessary
     * to call resize() prior to this.
     *
     * Note this does not set the generation from the Bitmap.
     */
    void upload(Bitmap& source);

    /**
     * Basically glTexImage2D/glTexSubImage2D.
     */
    void upload(GLint internalFormat, uint32_t width, uint32_t height,
            GLenum format, GLenum type, const void* pixels);

    /**
     * Wraps an existing texture.
     */
    void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat,
            GLint format, GLenum target);

    GLuint id() const {
        return mId;
    }

    uint32_t width() const {
        return mWidth;
    }

    uint32_t height() const {
        return mHeight;
    }

    GLint format() const {
        return mFormat;
    }

    GLint internalFormat() const {
        return mInternalFormat;
    }

    GLenum target() const {
        return mTarget;
    }

    /**
     * Returns true if this texture uses a linear encoding format.
     */
    bool isLinear() const;

    /**
     * Generation of the backing bitmap,
     */
    uint32_t generation = 0;
    /**
     * Indicates whether the texture requires blending.
     */
    bool blend = false;
    /**
     * Indicates whether this texture should be cleaned up after use.
     */
    bool cleanup = false;
    /**
     * Optional, size of the original bitmap.
     */
    uint32_t bitmapSize = 0;
    /**
     * Indicates whether this texture will use trilinear filtering.
     */
    bool mipMap = false;

    /**
     * Optional, pointer to a texture coordinates mapper.
     */
    const UvMapper* uvMapper = nullptr;

    /**
     * Whether or not the Texture is marked in use and thus not evictable for
     * the current frame. This is reset at the start of a new frame.
     */
    void* isInUse = nullptr;
private:
    // TODO: Temporarily grant private access to GlLayer, remove once
    // GlLayer can be de-tangled from being a dual-purpose render target
    // and external texture wrapper
    friend class GlLayer;

    // Returns true if the size changed, false if it was the same
    bool updateSize(uint32_t width, uint32_t height, GLint internalFormat,
            GLint format, GLenum target);
    void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
    void resetCachedParams();

    GLuint mId = 0;
    uint32_t mWidth = 0;
    uint32_t mHeight = 0;
    GLint mFormat = 0;
    GLint mInternalFormat = 0;
    GLenum mTarget = GL_NONE;
    EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR;

    /* See GLES spec section 3.8.14
     * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
     * NEAREST_MIPMAP_LINEAR and the value for TEXTURE_MAG_FILTER is LINEAR.
     * s, t, and r wrap modes are all set to REPEAT."
     */
    GLenum mWrapS = GL_REPEAT;
    GLenum mWrapT = GL_REPEAT;
    GLenum mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
    GLenum mMagFilter = GL_LINEAR;

    Caches& mCaches;
}; // struct Texture

class AutoTexture {
public:
    explicit AutoTexture(Texture* texture)
            : texture(texture) {}
    ~AutoTexture() {
        if (texture && texture->cleanup) {
            texture->deleteTexture();
            delete texture;
        }
    }

    Texture* const texture;
}; // class AutoTexture

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

#endif // ANDROID_HWUI_TEXTURE_H
