/*
 ** Copyright 2006, 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 <stdio.h>
#include <stdlib.h>
#include "context.h"
#include "TextureObjectManager.h"

namespace android {
// ----------------------------------------------------------------------------

EGLTextureObject::EGLTextureObject()
    : mCount(0), mSize(0)
{
    init();
}

EGLTextureObject::~EGLTextureObject()
{
    if (!direct) {
        if (mSize && surface.data)
            free(surface.data);
        if (mMipmaps)
            freeMipmaps();
    }
}

void EGLTextureObject::init()
{
    memset(&surface, 0, sizeof(surface));
    surface.version = sizeof(surface);
    mMipmaps = 0;
    mNumExtraLod = 0;
    mIsComplete = false;
    wraps = GL_REPEAT;
    wrapt = GL_REPEAT;
    min_filter = GL_LINEAR;
    mag_filter = GL_LINEAR;
    internalformat = 0;
    memset(crop_rect, 0, sizeof(crop_rect));
    generate_mipmap = GL_FALSE;
    direct = GL_FALSE;
}

void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
{
    wraps = old->wraps;
    wrapt = old->wrapt;
    min_filter = old->min_filter;
    mag_filter = old->mag_filter;
    memcpy(crop_rect, old->crop_rect, sizeof(crop_rect));
    generate_mipmap = old->generate_mipmap;
    direct = old->direct;
}

status_t EGLTextureObject::allocateMipmaps()
{
    // here, by construction, mMipmaps=0 && mNumExtraLod=0

    if (!surface.data)
        return NO_INIT;

    int w = surface.width;
    int h = surface.height;
    const int numLods = 31 - gglClz(max(w,h));
    if (numLods <= 0)
        return NO_ERROR;

    mMipmaps = (GGLSurface*)malloc(numLods * sizeof(GGLSurface));
    if (!mMipmaps)
        return NO_MEMORY;

    memset(mMipmaps, 0, numLods * sizeof(GGLSurface));
    mNumExtraLod = numLods;
    return NO_ERROR;
}

void EGLTextureObject::freeMipmaps()
{
    if (mMipmaps) {
        for (int i=0 ; i<mNumExtraLod ; i++) {
            if (mMipmaps[i].data) {
                free(mMipmaps[i].data);
            }
        }
        free(mMipmaps);
        mMipmaps = 0;
        mNumExtraLod = 0;
    }
}

const GGLSurface& EGLTextureObject::mip(int lod) const
{
    if (lod<=0 || !mMipmaps)
        return surface;
    lod = min(lod-1, mNumExtraLod-1);
    return mMipmaps[lod];
}

GGLSurface& EGLTextureObject::editMip(int lod)
{
    return const_cast<GGLSurface&>(mip(lod));
}

status_t EGLTextureObject::setSurface(GGLSurface const* s)
{
    // XXX: glFlush() on 's'
    if (mSize && surface.data) {
        free(surface.data);
    }
    surface = *s;
    internalformat = 0;

    // we should keep the crop_rect, but it's delicate because
    // the new size of the surface could make it invalid.
    // so for now, we just loose it.
    memset(crop_rect, 0, sizeof(crop_rect));

    // it would be nice if we could keep the generate_mipmap flag,
    // we would have to generate them right now though.
    generate_mipmap = GL_FALSE;

    direct = GL_TRUE;
    mSize = 0;  // we don't own this surface
    if (mMipmaps)
        freeMipmaps();
    mIsComplete = true;
    return NO_ERROR;
}

status_t EGLTextureObject::reallocate(
        GLint level, int w, int h, int s,
        int format, int compressedFormat, int bpr)
{
    const size_t size = h * bpr;
    if (level == 0) 
    {
        if (size!=mSize || !surface.data) {
            if (mSize && surface.data) {
                free(surface.data);
            }
            surface.data = (GGLubyte*)malloc(size);
            if (!surface.data) {
                mSize = 0;
                mIsComplete = false;
                return NO_MEMORY;
            }
            mSize = size;
        }
        surface.version = sizeof(GGLSurface);
        surface.width  = w;
        surface.height = h;
        surface.stride = s;
        surface.format = format;
        surface.compressedFormat = compressedFormat;
        if (mMipmaps)
            freeMipmaps();
        mIsComplete = true;
    }
    else
    {
        if (!mMipmaps) {
            if (allocateMipmaps() != NO_ERROR)
                return NO_MEMORY;
        }

        LOGW_IF(level-1 >= mNumExtraLod, 
                "specifying mipmap level %d, but # of level is %d",
                level, mNumExtraLod+1);        

        GGLSurface& mipmap = editMip(level);
        if (mipmap.data)
            free(mipmap.data);

        mipmap.data = (GGLubyte*)malloc(size);
        if (!mipmap.data) {
            memset(&mipmap, 0, sizeof(GGLSurface));
            mIsComplete = false;
            return NO_MEMORY;
        }

        mipmap.version = sizeof(GGLSurface);
        mipmap.width  = w;
        mipmap.height = h;
        mipmap.stride = s;
        mipmap.format = format;
        mipmap.compressedFormat = compressedFormat;

        // check if the texture is complete
        mIsComplete = true;
        const GGLSurface* prev = &surface;
        for (int i=0 ; i<mNumExtraLod ; i++) {
            const GGLSurface* curr = mMipmaps + i;
            if (curr->format != surface.format) {
                mIsComplete = false;
                break;
            }

            uint32_t w = (prev->width  >> 1) ? : 1;
            uint32_t h = (prev->height >> 1) ? : 1;
            if (w != curr->width || h != curr->height) {
                mIsComplete = false;
                break;
            }
            prev = curr;
        }
    }
    return NO_ERROR;
}

// ----------------------------------------------------------------------------

EGLSurfaceManager::EGLSurfaceManager()
    : TokenManager(), mCount(0)
{
}

EGLSurfaceManager::~EGLSurfaceManager()
{
    // everything gets freed automatically here...
}

sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name)
{
    sp<EGLTextureObject> result;

    Mutex::Autolock _l(mLock);
    if (mTextures.indexOfKey(name) >= 0)
        return result; // already exists!

    result = new EGLTextureObject();

    status_t err = mTextures.add(name, result);
    if (err < 0)
        result.clear();

    return result;
}

sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name)
{
    Mutex::Autolock _l(mLock);
    const ssize_t index = mTextures.indexOfKey(name);
    if (index >= 0) {
        sp<EGLTextureObject> result(mTextures.valueAt(index));
        mTextures.removeItemsAt(index);
        return result;
    }
    return 0;
}

sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name)
{
    sp<EGLTextureObject> tex;
    Mutex::Autolock _l(mLock);
    const ssize_t index = mTextures.indexOfKey(name);
    if (index >= 0) {
        const sp<EGLTextureObject>& old = mTextures.valueAt(index);
        const uint32_t refs = old->getStrongCount();
        if (ggl_likely(refs == 1)) {
            // we're the only owner
            tex = old;
        } else {
            // keep the texture's parameters
            tex = new EGLTextureObject();
            tex->copyParameters(old);
            mTextures.removeItemsAt(index);
            mTextures.add(name, tex);
        }
    }
    return tex;
}

void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens)
{
    // free all textures
    Mutex::Autolock _l(mLock);
    for (GLsizei i=0 ; i<n ; i++) {
        const GLuint t(*tokens++);
        if (t) {
            mTextures.removeItem(t);
        }
    }
}

sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name)
{
    Mutex::Autolock _l(mLock);
    const ssize_t index = mTextures.indexOfKey(name);
    if (index >= 0)
        return mTextures.valueAt(index);
    return 0;
}

// ----------------------------------------------------------------------------
}; // namespace android
