/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"

#if ENABLE(WEBGL)

#include "WebGLTexture.h"

#include "WebGLContextGroup.h"
#include "WebGLFramebuffer.h"
#include "WebGLRenderingContextBase.h"

namespace WebCore {

Ref<WebGLTexture> WebGLTexture::create(WebGLRenderingContextBase& ctx)
{
    return adoptRef(*new WebGLTexture(ctx));
}

WebGLTexture::WebGLTexture(WebGLRenderingContextBase& ctx)
    : WebGLSharedObject(ctx)
    , m_target(0)
    , m_minFilter(GraphicsContext3D::NEAREST_MIPMAP_LINEAR)
    , m_magFilter(GraphicsContext3D::LINEAR)
    , m_wrapS(GraphicsContext3D::REPEAT)
    , m_wrapT(GraphicsContext3D::REPEAT)
    , m_isNPOT(false)
    , m_isComplete(false)
    , m_needToUseBlackTexture(false)
    , m_isCompressed(false)
    , m_isFloatType(false)
    , m_isHalfFloatType(false)
    , m_isForWebGL1(ctx.isWebGL1())
{
    setObject(ctx.graphicsContext3D()->createTexture());
}

WebGLTexture::~WebGLTexture()
{
    deleteObject(0);
}

void WebGLTexture::setTarget(GC3Denum target, GC3Dint maxLevel)
{
    if (!object())
        return;
    // Target is finalized the first time bindTexture() is called.
    if (m_target)
        return;
    switch (target) {
    case GraphicsContext3D::TEXTURE_2D:
        m_target = target;
        m_info.resize(1);
        m_info[0].resize(maxLevel);
        break;
    case GraphicsContext3D::TEXTURE_CUBE_MAP:
        m_target = target;
        m_info.resize(6);
        for (int ii = 0; ii < 6; ++ii)
            m_info[ii].resize(maxLevel);
        break;
    }
}

void WebGLTexture::setParameteri(GC3Denum pname, GC3Dint param)
{
    if (!object() || !m_target)
        return;
    switch (pname) {
    case GraphicsContext3D::TEXTURE_MIN_FILTER:
        switch (param) {
        case GraphicsContext3D::NEAREST:
        case GraphicsContext3D::LINEAR:
        case GraphicsContext3D::NEAREST_MIPMAP_NEAREST:
        case GraphicsContext3D::LINEAR_MIPMAP_NEAREST:
        case GraphicsContext3D::NEAREST_MIPMAP_LINEAR:
        case GraphicsContext3D::LINEAR_MIPMAP_LINEAR:
            m_minFilter = param;
            break;
        }
        break;
    case GraphicsContext3D::TEXTURE_MAG_FILTER:
        switch (param) {
        case GraphicsContext3D::NEAREST:
        case GraphicsContext3D::LINEAR:
            m_magFilter = param;
            break;
        }
        break;
    case GraphicsContext3D::TEXTURE_WRAP_S:
        switch (param) {
        case GraphicsContext3D::CLAMP_TO_EDGE:
        case GraphicsContext3D::MIRRORED_REPEAT:
        case GraphicsContext3D::REPEAT:
            m_wrapS = param;
            break;
        }
        break;
    case GraphicsContext3D::TEXTURE_WRAP_T:
        switch (param) {
        case GraphicsContext3D::CLAMP_TO_EDGE:
        case GraphicsContext3D::MIRRORED_REPEAT:
        case GraphicsContext3D::REPEAT:
            m_wrapT = param;
            break;
        }
        break;
    default:
        return;
    }
    update();
}

void WebGLTexture::setParameterf(GC3Denum pname, GC3Dfloat param)
{
    if (!object() || !m_target)
        return;
    GC3Dint iparam = static_cast<GC3Dint>(param);
    setParameteri(pname, iparam);
}

void WebGLTexture::setLevelInfo(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type)
{
    if (!object() || !m_target)
        return;
    // We assume level, internalFormat, width, height, and type have all been
    // validated already.
    int index = mapTargetToIndex(target);
    if (index < 0)
        return;
    m_info[index][level].setInfo(internalFormat, width, height, type);
    update();
}

void WebGLTexture::generateMipmapLevelInfo()
{
    if (!object() || !m_target)
        return;
    if (!canGenerateMipmaps())
        return;
    if (!m_isComplete) {
        for (size_t ii = 0; ii < m_info.size(); ++ii) {
            const LevelInfo& info0 = m_info[ii][0];
            GC3Dsizei width = info0.width;
            GC3Dsizei height = info0.height;
            GC3Dint levelCount = computeLevelCount(width, height);
            for (GC3Dint level = 1; level < levelCount; ++level) {
                width = std::max(1, width >> 1);
                height = std::max(1, height >> 1);
                LevelInfo& info = m_info[ii][level];
                info.setInfo(info0.internalFormat, width, height, info0.type);
            }
        }
        m_isComplete = true;
    }
    m_needToUseBlackTexture = false;
}

GC3Denum WebGLTexture::getInternalFormat(GC3Denum target, GC3Dint level) const
{
    const LevelInfo* info = getLevelInfo(target, level);
    if (!info)
        return 0;
    return info->internalFormat;
}

GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const
{
    ASSERT(m_isForWebGL1);
    const LevelInfo* info = getLevelInfo(target, level);
    if (!info)
        return 0;
    return info->type;
}

GC3Dsizei WebGLTexture::getWidth(GC3Denum target, GC3Dint level) const
{
    const LevelInfo* info = getLevelInfo(target, level);
    if (!info)
        return 0;
    return info->width;
}

GC3Dsizei WebGLTexture::getHeight(GC3Denum target, GC3Dint level) const
{
    const LevelInfo* info = getLevelInfo(target, level);
    if (!info)
        return 0;
    return info->height;
}

bool WebGLTexture::isValid(GC3Denum target, GC3Dint level) const
{
    const LevelInfo* info = getLevelInfo(target, level);
    if (!info)
        return 0;
    return info->valid;
}

void WebGLTexture::markInvalid(GC3Denum target, GC3Dint level)
{
    int index = mapTargetToIndex(target);
    if (index < 0)
        return;
    m_info[index][level].valid = false;
    update();
}

bool WebGLTexture::isNPOT(GC3Dsizei width, GC3Dsizei height)
{
    ASSERT(width >= 0 && height >= 0);
    if (!width || !height)
        return false;
    if ((width & (width - 1)) || (height & (height - 1)))
        return true;
    return false;
}

bool WebGLTexture::isNPOT() const
{
    if (!object())
        return false;
    return m_isNPOT;
}

bool WebGLTexture::needToUseBlackTexture(TextureExtensionFlag extensions) const
{
    if (!object())
        return false;
    if (m_needToUseBlackTexture)
        return true;
    if (m_magFilter == GraphicsContext3D::NEAREST && (m_minFilter == GraphicsContext3D::NEAREST || m_minFilter == GraphicsContext3D::NEAREST_MIPMAP_NEAREST))
        return false;
    if (m_isForWebGL1 && m_isHalfFloatType && !(extensions & TextureExtensionHalfFloatLinearEnabled))
        return true;
    if (m_isFloatType && !(extensions & TextureExtensionFloatLinearEnabled))
        return true;
    return false;
}

bool WebGLTexture::isCompressed() const
{
    if (!object())
        return false;
    return m_isCompressed;
}

void WebGLTexture::setCompressed()
{
    ASSERT(object());
    m_isCompressed = true;
}

void WebGLTexture::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object)
{
    context3d->deleteTexture(object);
}

int WebGLTexture::mapTargetToIndex(GC3Denum target) const
{
    if (m_target == GraphicsContext3D::TEXTURE_2D) {
        if (target == GraphicsContext3D::TEXTURE_2D)
            return 0;
    } else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
        switch (target) {
        case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
            return 0;
        case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
            return 1;
        case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
            return 2;
        case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
            return 3;
        case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
            return 4;
        case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
            return 5;
        }
    }
    return -1;
}

bool WebGLTexture::canGenerateMipmaps()
{
    if (isNPOT())
        return false;
    const LevelInfo& first = m_info[0][0];
    for (size_t ii = 0; ii < m_info.size(); ++ii) {
        const LevelInfo& info = m_info[ii][0];
        if (!info.valid
            || info.width != first.width || info.height != first.height
            || info.internalFormat != first.internalFormat || (m_isForWebGL1 && info.type != first.type))
            return false;
    }
    return true;
}

GC3Dint WebGLTexture::computeLevelCount(GC3Dsizei width, GC3Dsizei height)
{
    // return 1 + log2Floor(std::max(width, height));
    GC3Dsizei n = std::max(width, height);
    if (n <= 0)
        return 0;
    GC3Dint log = 0;
    GC3Dsizei value = n;
    for (int ii = 4; ii >= 0; --ii) {
        int shift = (1 << ii);
        GC3Dsizei x = (value >> shift);
        if (x) {
            value = x;
            log += shift;
        }
    }
    ASSERT(value == 1);
    return log + 1;
}

static bool internalFormatIsFloatType(GC3Denum internalFormat)
{
    switch (internalFormat) {
    case GraphicsContext3D::R32F:
    case GraphicsContext3D::RG32F:
    case GraphicsContext3D::RGB32F:
    case GraphicsContext3D::RGBA32F:
    case GraphicsContext3D::DEPTH_COMPONENT32F:
    case GraphicsContext3D::DEPTH32F_STENCIL8:
        return true;
    default:
        return false;
    }
}

static bool internalFormatIsHalfFloatType(GC3Denum internalFormat)
{
    switch (internalFormat) {
    case GraphicsContext3D::R16F:
    case GraphicsContext3D::RG16F:
    case GraphicsContext3D::R11F_G11F_B10F:
    case GraphicsContext3D::RGB9_E5:
    case GraphicsContext3D::RGB16F:
    case GraphicsContext3D::RGBA16F:
        return true;
    default:
        return false;
    }
}

void WebGLTexture::update()
{
    m_isNPOT = false;
    for (size_t ii = 0; ii < m_info.size(); ++ii) {
        if (isNPOT(m_info[ii][0].width, m_info[ii][0].height)) {
            m_isNPOT = true;
            break;
        }
    }
    m_isComplete = true;
    const LevelInfo& first = m_info[0][0];
    GC3Dint levelCount = computeLevelCount(first.width, first.height);
    if (levelCount < 1)
        m_isComplete = false;
    else {
        for (size_t ii = 0; ii < m_info.size() && m_isComplete; ++ii) {
            const LevelInfo& info0 = m_info[ii][0];
            if (!info0.valid
                || info0.width != first.width || info0.height != first.height
                || info0.internalFormat != first.internalFormat || (m_isForWebGL1 && info0.type != first.type)) {
                m_isComplete = false;
                break;
            }
            GC3Dsizei width = info0.width;
            GC3Dsizei height = info0.height;
            for (GC3Dint level = 1; level < levelCount; ++level) {
                width = std::max(1, width >> 1);
                height = std::max(1, height >> 1);
                const LevelInfo& info = m_info[ii][level];
                if (!info.valid
                    || info.width != width || info.height != height
                    || info.internalFormat != info0.internalFormat || (m_isForWebGL1 && info.type != info0.type)) {
                    m_isComplete = false;
                    break;
                }

            }
        }
    }

    m_isFloatType = false;
    if (m_isForWebGL1) {
        if (m_isComplete) {
            if (m_isForWebGL1)
                m_isFloatType = m_info[0][0].type == GraphicsContext3D::FLOAT;
            else
                m_isFloatType = internalFormatIsFloatType(m_info[0][0].internalFormat);
        } else {
            for (size_t ii = 0; ii < m_info.size(); ++ii) {
                if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContext3D::FLOAT)
                    || (!m_isForWebGL1 && internalFormatIsFloatType(m_info[ii][0].internalFormat))) {
                    m_isFloatType = true;
                    break;
                }
            }
        }
    }

    m_isHalfFloatType = false;
    if (m_isForWebGL1) {
        if (m_isComplete) {
            if (m_isForWebGL1)
                m_isHalfFloatType = internalFormatIsHalfFloatType(m_info[0][0].internalFormat);
            else
                m_isHalfFloatType = m_info[0][0].type == GraphicsContext3D::HALF_FLOAT_OES;
        } else {
            for (size_t ii = 0; ii < m_info.size(); ++ii) {
                if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContext3D::HALF_FLOAT_OES)
                    || (!m_isForWebGL1 && internalFormatIsHalfFloatType(m_info[ii][0].internalFormat))) {
                    m_isHalfFloatType = true;
                    break;
                }
            }
        }
    }

    m_needToUseBlackTexture = false;
    // NPOT
    if (m_isNPOT && ((m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::LINEAR)
                     || m_wrapS != GraphicsContext3D::CLAMP_TO_EDGE || m_wrapT != GraphicsContext3D::CLAMP_TO_EDGE))
        m_needToUseBlackTexture = true;
    // Completeness
    if (!m_isComplete && m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::LINEAR)
        m_needToUseBlackTexture = true;
}

const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GC3Denum target, GC3Dint level) const
{
    if (!object() || !m_target)
        return 0;
    int targetIndex = mapTargetToIndex(target);
    if (targetIndex < 0 || targetIndex >= static_cast<int>(m_info.size()))
        return 0;
    if (level < 0 || level >= static_cast<GC3Dint>(m_info[targetIndex].size()))
        return 0;
    return &(m_info[targetIndex][level]);
}

}

#endif // ENABLE(WEBGL)
