/*
 ** 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;
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
    copybits_fd = -1;
#endif // LIBAGL_USE_GRALLOC_COPYBITS
}

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
