/*
 * 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)
#if !USE(ANGLE)
    , m_minFilter(GraphicsContextGL::NEAREST_MIPMAP_LINEAR)
    , m_magFilter(GraphicsContextGL::LINEAR)
    , m_wrapS(GraphicsContextGL::REPEAT)
    , m_wrapT(GraphicsContextGL::REPEAT)
    , m_isNPOT(false)
    , m_isComplete(false)
    , m_needToUseBlackTexture(false)
    , m_isCompressed(false)
    , m_isFloatType(false)
    , m_isHalfFloatType(false)
    , m_isForWebGL1(ctx.isWebGL1())
#endif
{
    setObject(ctx.graphicsContextGL()->createTexture());
}

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

void WebGLTexture::setTarget(GCGLenum target, GCGLint maxLevel)
{
    if (!object())
        return;
    // Target is finalized the first time bindTexture() is called.
    if (m_target)
        return;
#if USE(ANGLE)
    UNUSED_PARAM(maxLevel);
    m_target = target;
#else
    switch (target) {
    case GraphicsContextGL::TEXTURE_2D:
        m_target = target;
        m_info.resize(1);
        m_info[0].resize(maxLevel);
        break;
    case GraphicsContextGL::TEXTURE_CUBE_MAP:
        m_target = target;
        m_info.resize(6);
        for (int ii = 0; ii < 6; ++ii)
            m_info[ii].resize(maxLevel);
        break;
    }
#endif // USE(ANGLE)
}

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

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

// Everything below this point is unused with the ANGLE backend.

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

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

void WebGLTexture::setLevelInfo(GCGLenum target, GCGLint level, GCGLenum internalFormat, GCGLsizei width, GCGLsizei height, GCGLenum 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];
            GCGLsizei width = info0.width;
            GCGLsizei height = info0.height;
            GCGLint levelCount = computeLevelCount(width, height);
            for (GCGLint 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;
}

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

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

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

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

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

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

bool WebGLTexture::isNPOT(GCGLsizei width, GCGLsizei 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 == GraphicsContextGL::NEAREST && (m_minFilter == GraphicsContextGL::NEAREST || m_minFilter == GraphicsContextGL::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::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;
}

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

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

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

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

static bool internalFormatIsHalfFloatType(GCGLenum internalFormat)
{
    switch (internalFormat) {
    case GraphicsContextGL::R16F:
    case GraphicsContextGL::RG16F:
    case GraphicsContextGL::R11F_G11F_B10F:
    case GraphicsContextGL::RGB9_E5:
    case GraphicsContextGL::RGB16F:
    case GraphicsContextGL::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];
    GCGLint 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;
            }
            GCGLsizei width = info0.width;
            GCGLsizei height = info0.height;
            for (GCGLint 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 == GraphicsContextGL::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 == GraphicsContextGL::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 == GraphicsContextGL::HALF_FLOAT_OES;
        } else {
            for (size_t ii = 0; ii < m_info.size(); ++ii) {
                if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContextGL::HALF_FLOAT_OES)
                    || (!m_isForWebGL1 && internalFormatIsHalfFloatType(m_info[ii][0].internalFormat))) {
                    m_isHalfFloatType = true;
                    break;
                }
            }
        }
    }

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

const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GCGLenum target, GCGLint 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<GCGLint>(m_info[targetIndex].size()))
        return 0;
    return &(m_info[targetIndex][level]);
}
#endif // !USE(ANGLE)

}

#endif // ENABLE(WEBGL)
