/**
 ** Copyright 2007, 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 "jni.h"
#include <nativehelper/JNIHelp.h>
#include "GraphicsJNI.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dlfcn.h>

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
#include <ETC1/etc1.h>

#include <SkBitmap.h>

#include "core_jni_helpers.h"

#undef LOG_TAG
#define LOG_TAG "OpenGLUtil"
#include <utils/Log.h>
#include "utils/misc.h"

#include "poly.h"

namespace android {

static inline
void mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) {
    pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z + pM[0 + 4 * 3] * w;
    pDest[1] = pM[1 + 4 * 0] * x + pM[1 + 4 * 1] * y + pM[1 + 4 * 2] * z + pM[1 + 4 * 3] * w;
    pDest[2] = pM[2 + 4 * 0] * x + pM[2 + 4 * 1] * y + pM[2 + 4 * 2] * z + pM[2 + 4 * 3] * w;
    pDest[3] = pM[3 + 4 * 0] * x + pM[3 + 4 * 1] * y + pM[3 + 4 * 2] * z + pM[3 + 4 * 3] * w;
}

#if 0
static
void
print_poly(const char* label, Poly* pPoly) {
    ALOGI("%s: %d verts", label, pPoly->n);
    for(int i = 0; i < pPoly->n; i++) {
        Poly_vert* pV = & pPoly->vert[i];
        ALOGI("[%d] %g, %g, %g %g", i, pV->sx, pV->sy, pV->sz, pV->sw);
    }
}
#endif

static
int visibilityTest(float* pWS, float* pPositions, int positionsLength,
        unsigned short* pIndices, int indexCount) {
    int result = POLY_CLIP_OUT;

    if ( indexCount < 3 ) {
        return POLY_CLIP_OUT;
    }

    // Find out how many vertices we need to transform
    // We transform every vertex between the min and max indices, inclusive.
    // This is OK for the data sets we expect to use with this function, but
    // for other loads it might be better to use a more sophisticated vertex
    // cache of some sort.

    int minIndex = 65536;
    int maxIndex = -1;
    for(int i = 0; i < indexCount; i++) {
        int index = pIndices[i];
        if ( index < minIndex ) {
            minIndex = index;
        }
        if ( index > maxIndex ) {
            maxIndex = index;
        }
    }

    if ( maxIndex * 3 > positionsLength) {
        return -1;
    }

    int transformedIndexCount = maxIndex - minIndex + 1;
    std::unique_ptr<float[]> holder{new float[transformedIndexCount * 4]};
    float* pTransformed = holder.get();

    if (pTransformed == 0 ) {
        return -2;
    }

    // Transform the vertices
    {
        const float* pSrc = pPositions + 3 * minIndex;
        float* pDst = pTransformed;
        for (int i = 0; i < transformedIndexCount; i++, pSrc += 3, pDst += 4) {
            mx4transform(pSrc[0], pSrc[1], pSrc[2], 1.0f, pWS,  pDst);
        }
    }

    // Clip the triangles

    Poly poly;
    float* pDest = & poly.vert[0].sx;
    for (int i = 0; i < indexCount; i += 3) {
        poly.n = 3;
        memcpy(pDest    , pTransformed + 4 * (pIndices[i    ] - minIndex), 4 * sizeof(float));
        memcpy(pDest + 4, pTransformed + 4 * (pIndices[i + 1] - minIndex), 4 * sizeof(float));
        memcpy(pDest + 8, pTransformed + 4 * (pIndices[i + 2] - minIndex), 4 * sizeof(float));
        result = poly_clip_to_frustum(&poly);
        if ( result != POLY_CLIP_OUT) {
            return result;
        }
    }

    return result;
}

class ByteArrayGetter {
public:
    static void* Get(JNIEnv* _env, jbyteArray array, jboolean* is_copy) {
        return _env->GetByteArrayElements(array, is_copy);
    }
};
class BooleanArrayGetter {
public:
    static void* Get(JNIEnv* _env, jbooleanArray array, jboolean* is_copy) {
        return _env->GetBooleanArrayElements(array, is_copy);
    }
};
class CharArrayGetter {
public:
    static void* Get(JNIEnv* _env, jcharArray array, jboolean* is_copy) {
        return _env->GetCharArrayElements(array, is_copy);
    }
};
class ShortArrayGetter {
public:
    static void* Get(JNIEnv* _env, jshortArray array, jboolean* is_copy) {
        return _env->GetShortArrayElements(array, is_copy);
    }
};
class IntArrayGetter {
public:
    static void* Get(JNIEnv* _env, jintArray array, jboolean* is_copy) {
        return _env->GetIntArrayElements(array, is_copy);
    }
};
class LongArrayGetter {
public:
    static void* Get(JNIEnv* _env, jlongArray array, jboolean* is_copy) {
        return _env->GetLongArrayElements(array, is_copy);
    }
};
class FloatArrayGetter {
public:
    static void* Get(JNIEnv* _env, jfloatArray array, jboolean* is_copy) {
        return _env->GetFloatArrayElements(array, is_copy);
    }
};
class DoubleArrayGetter {
public:
    static void* Get(JNIEnv* _env, jdoubleArray array, jboolean* is_copy) {
        return _env->GetDoubleArrayElements(array, is_copy);
    }
};

class ByteArrayReleaser {
public:
    static void Release(JNIEnv* _env, jbyteArray array, jbyte* data, jint mode) {
        _env->ReleaseByteArrayElements(array, data, mode);
    }
};
class BooleanArrayReleaser {
public:
    static void Release(JNIEnv* _env, jbooleanArray array, jboolean* data, jint mode) {
        _env->ReleaseBooleanArrayElements(array, data, mode);
    }
};
class CharArrayReleaser {
public:
    static void Release(JNIEnv* _env, jcharArray array, jchar* data, jint mode) {
        _env->ReleaseCharArrayElements(array, data, mode);
    }
};
class ShortArrayReleaser {
public:
    static void Release(JNIEnv* _env, jshortArray array, jshort* data, jint mode) {
        _env->ReleaseShortArrayElements(array, data, mode);
    }
};
class IntArrayReleaser {
public:
    static void Release(JNIEnv* _env, jintArray array, jint* data, jint mode) {
        _env->ReleaseIntArrayElements(array, data, mode);
    }
};
class LongArrayReleaser {
public:
    static void Release(JNIEnv* _env, jlongArray array, jlong* data, jint mode) {
        _env->ReleaseLongArrayElements(array, data, mode);
    }
};
class FloatArrayReleaser {
public:
    static void Release(JNIEnv* _env, jfloatArray array, jfloat* data, jint mode) {
        _env->ReleaseFloatArrayElements(array, data, mode);
    }
};
class DoubleArrayReleaser {
public:
    static void Release(JNIEnv* _env, jdoubleArray array, jdouble* data, jint mode) {
        _env->ReleaseDoubleArrayElements(array, data, mode);
    }
};

template<class JArray, class T, class ArrayGetter, class ArrayReleaser>
class ArrayHelper {
public:
    ArrayHelper(JNIEnv* env, JArray ref, jint offset, jint minSize) {
        mEnv = env;
        mRef = ref;
        mOffset = offset;
        mMinSize = minSize;
        mBase = 0;
        mReleaseParam = JNI_ABORT;
    }

    ~ArrayHelper() {
        if (mBase) {
            ArrayReleaser::Release(mEnv, mRef, mBase, mReleaseParam);
        }
    }

    // We seperate the bounds check from the initialization because we want to
    // be able to bounds-check multiple arrays, and we can't throw an exception
    // after we've called GetPrimitiveArrayCritical.

    // Return true if the bounds check succeeded
    // Else instruct the runtime to throw an exception

    bool check() {
        if ( ! mRef) {
            doThrowIAE(mEnv, "array == null");
            return false;
        }
        if ( mOffset < 0) {
            doThrowIAE(mEnv, "offset < 0");
            return false;
        }
        mLength = mEnv->GetArrayLength(mRef) - mOffset;
        if (mLength < mMinSize ) {
            doThrowIAE(mEnv, "length - offset < n");
            return false;
        }
        return true;
    }

    // Bind the array.

    void bind() {
        mBase = (T*) ArrayGetter::Get(mEnv, mRef, (jboolean *) 0);
        mData = mBase + mOffset;
    }

    void commitChanges() {
        mReleaseParam = 0;
    }

    T* mData;
    int mLength;

private:
    T* mBase;
    JNIEnv* mEnv;
    JArray mRef;
    jint mOffset;
    jint mMinSize;
    int mReleaseParam;
};

typedef ArrayHelper<jfloatArray, float, FloatArrayGetter, FloatArrayReleaser> FloatArrayHelper;
typedef ArrayHelper<jcharArray, unsigned short, CharArrayGetter, CharArrayReleaser> UnsignedShortArrayHelper;
typedef ArrayHelper<jintArray, int, IntArrayGetter, IntArrayReleaser> IntArrayHelper;
typedef ArrayHelper<jbyteArray, unsigned char, ByteArrayGetter, ByteArrayReleaser> ByteArrayHelper;

inline float distance2(float x, float y, float z) {
    return x * x + y * y + z * z;
}

inline float distance(float x, float y, float z) {
    return sqrtf(distance2(x, y, z));
}

static
void util_computeBoundingSphere(JNIEnv *env, jclass clazz,
        jfloatArray positions_ref, jint positionsOffset, jint positionsCount,
        jfloatArray sphere_ref, jint sphereOffset) {
    FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
    FloatArrayHelper sphere(env, sphere_ref, sphereOffset, 4);

    bool checkOK = positions.check() && sphere.check();
        if (! checkOK) {
        return;
    }

    positions.bind();
    sphere.bind();

    if ( positionsCount < 1 ) {
        doThrowIAE(env, "positionsCount < 1");
        return;
    }

    const float* pSrc = positions.mData;

    // find bounding box
    float x0 = *pSrc++;
    float x1 = x0;
    float y0 = *pSrc++;
    float y1 = y0;
    float z0 = *pSrc++;
    float z1 = z0;

    for(int i = 1; i < positionsCount; i++) {
        {
            float x = *pSrc++;
            if (x < x0) {
                x0 = x;
            }
            else if (x > x1) {
                x1 = x;
            }
        }
        {
            float y = *pSrc++;
            if (y < y0) {
                y0 = y;
            }
            else if (y > y1) {
                y1 = y;
            }
        }
        {
            float z = *pSrc++;
            if (z < z0) {
                z0 = z;
            }
            else if (z > z1) {
                z1 = z;
            }
        }
    }

    // Because we know our input meshes fit pretty well into bounding boxes,
    // just take the diagonal of the box as defining our sphere.
    float* pSphere = sphere.mData;
    float dx = x1 - x0;
    float dy = y1 - y0;
    float dz = z1 - z0;
    *pSphere++ = x0 + dx * 0.5f;
    *pSphere++ = y0 + dy * 0.5f;
    *pSphere++ = z0 + dz * 0.5f;
    *pSphere++ = distance(dx, dy, dz) * 0.5f;

    sphere.commitChanges();
}

static void normalizePlane(float* p) {
    float rdist = 1.0f / distance(p[0], p[1], p[2]);
    for(int i = 0; i < 4; i++) {
        p[i] *= rdist;
    }
}

static inline float dot3(float x0, float y0, float z0, float x1, float y1, float z1) {
    return x0 * x1 + y0 * y1 + z0 * z1;
}

static inline float signedDistance(const float* pPlane, float x, float y, float z) {
    return dot3(pPlane[0], pPlane[1], pPlane[2], x, y, z) + pPlane[3];
}

// Return true if the sphere intersects or is inside the frustum

static bool sphereHitsFrustum(const float* pFrustum, const float* pSphere) {
    float x = pSphere[0];
    float y = pSphere[1];
    float z = pSphere[2];
    float negRadius = -pSphere[3];
    for (int i = 0; i < 6; i++, pFrustum += 4) {
        if (signedDistance(pFrustum, x, y, z) <= negRadius) {
            return false;
        }
    }
    return true;
}

static void computeFrustum(const float* m, float* f) {
    float m3 = m[3];
    float m7 = m[7];
    float m11 = m[11];
    float m15 = m[15];
    // right
    f[0] = m3  - m[0];
    f[1] = m7  - m[4];
    f[2] = m11 - m[8];
    f[3] = m15 - m[12];
    normalizePlane(f);
    f+= 4;

    // left
    f[0] = m3  + m[0];
    f[1] = m7  + m[4];
    f[2] = m11 + m[8];
    f[3] = m15 + m[12];
    normalizePlane(f);
    f+= 4;

    // top
    f[0] = m3  - m[1];
    f[1] = m7  - m[5];
    f[2] = m11 - m[9];
    f[3] = m15 - m[13];
    normalizePlane(f);
    f+= 4;

    // bottom
    f[0] = m3  + m[1];
    f[1] = m7  + m[5];
    f[2] = m11 + m[9];
    f[3] = m15 + m[13];
    normalizePlane(f);
    f+= 4;

    // far
    f[0] = m3  - m[2];
    f[1] = m7  - m[6];
    f[2] = m11 - m[10];
    f[3] = m15 - m[14];
    normalizePlane(f);
    f+= 4;

    // near
    f[0] = m3  + m[2];
    f[1] = m7  + m[6];
    f[2] = m11 + m[10];
    f[3] = m15 + m[14];
    normalizePlane(f);
}

static
jint util_frustumCullSpheres(JNIEnv *env, jclass clazz,
        jfloatArray mvp_ref, jint mvpOffset,
        jfloatArray spheres_ref, jint spheresOffset, jint spheresCount,
        jintArray results_ref, jint resultsOffset, jint resultsCapacity) {
    float frustum[6*4];
    int outputCount;
    int* pResults;
    float* pSphere;
    FloatArrayHelper mvp(env, mvp_ref, mvpOffset, 16);
    FloatArrayHelper spheres(env, spheres_ref, spheresOffset, spheresCount * 4);
    IntArrayHelper results(env, results_ref, resultsOffset, resultsCapacity);

    bool initializedOK = mvp.check() && spheres.check() && results.check();
        if (! initializedOK) {
        return -1;
    }

    mvp.bind();
    spheres.bind();
    results.bind();

    computeFrustum(mvp.mData, frustum);

    // Cull the spheres

    pSphere = spheres.mData;
    pResults = results.mData;
    outputCount = 0;
    for(int i = 0; i < spheresCount; i++, pSphere += 4) {
        if (sphereHitsFrustum(frustum, pSphere)) {
            if (outputCount < resultsCapacity) {
                *pResults++ = i;
            }
            outputCount++;
        }
    }
    results.commitChanges();
    return outputCount;
}

/*
 public native int visibilityTest(float[] ws, int wsOffset,
 float[] positions, int positionsOffset,
 char[] indices, int indicesOffset, int indexCount);
 */

static
jint util_visibilityTest(JNIEnv *env, jclass clazz,
        jfloatArray ws_ref, jint wsOffset,
        jfloatArray positions_ref, jint positionsOffset,
        jcharArray indices_ref, jint indicesOffset, jint indexCount) {

    FloatArrayHelper ws(env, ws_ref, wsOffset, 16);
    FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
    UnsignedShortArrayHelper indices(env, indices_ref, indicesOffset, 0);

    bool checkOK = ws.check() && positions.check() && indices.check();
    if (! checkOK) {
        // Return value will be ignored, because an exception has been thrown.
        return -1;
    }

    if (indices.mLength < indexCount) {
        doThrowIAE(env, "length < offset + indexCount");
        return -1;
    }

    ws.bind();
    positions.bind();
    indices.bind();

    return visibilityTest(ws.mData,
            positions.mData, positions.mLength,
            indices.mData, indexCount);
}

#define I(_i, _j) ((_j)+ 4*(_i))

static
void multiplyMM(float* r, const float* lhs, const float* rhs)
{
    for (int i=0 ; i<4 ; i++) {
        const float rhs_i0 = rhs[ I(i,0) ];
        float ri0 = lhs[ I(0,0) ] * rhs_i0;
        float ri1 = lhs[ I(0,1) ] * rhs_i0;
        float ri2 = lhs[ I(0,2) ] * rhs_i0;
        float ri3 = lhs[ I(0,3) ] * rhs_i0;
        for (int j=1 ; j<4 ; j++) {
            const float rhs_ij = rhs[ I(i,j) ];
            ri0 += lhs[ I(j,0) ] * rhs_ij;
            ri1 += lhs[ I(j,1) ] * rhs_ij;
            ri2 += lhs[ I(j,2) ] * rhs_ij;
            ri3 += lhs[ I(j,3) ] * rhs_ij;
        }
        r[ I(i,0) ] = ri0;
        r[ I(i,1) ] = ri1;
        r[ I(i,2) ] = ri2;
        r[ I(i,3) ] = ri3;
    }
}

static
void util_multiplyMM(JNIEnv *env, jclass clazz,
    jfloatArray result_ref, jint resultOffset,
    jfloatArray lhs_ref, jint lhsOffset,
    jfloatArray rhs_ref, jint rhsOffset) {

    FloatArrayHelper resultMat(env, result_ref, resultOffset, 16);
    FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
    FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16);

    bool checkOK = resultMat.check() && lhs.check() && rhs.check();

    if ( !checkOK ) {
        return;
    }

    resultMat.bind();
    lhs.bind();
    rhs.bind();

    multiplyMM(resultMat.mData, lhs.mData, rhs.mData);

    resultMat.commitChanges();
}

static
void multiplyMV(float* r, const float* lhs, const float* rhs)
{
    mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r);
}

static
void util_multiplyMV(JNIEnv *env, jclass clazz,
    jfloatArray result_ref, jint resultOffset,
    jfloatArray lhs_ref, jint lhsOffset,
    jfloatArray rhs_ref, jint rhsOffset) {

    FloatArrayHelper resultV(env, result_ref, resultOffset, 4);
    FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
    FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4);

    bool checkOK = resultV.check() && lhs.check() && rhs.check();

    if ( !checkOK ) {
        return;
    }

    resultV.bind();
    lhs.bind();
    rhs.bind();

    multiplyMV(resultV.mData, lhs.mData, rhs.mData);

    resultV.commitChanges();
}

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

// The internal format is no longer the same as pixel format, per Table 2 in
// https://www.khronos.org/registry/OpenGL-Refpages/es3.1/html/glTexImage2D.xhtml
static int checkInternalFormat(SkColorType colorType, int internalformat,
    int type)
{
    switch(colorType) {
        case kN32_SkColorType:
            return (type == GL_UNSIGNED_BYTE &&
                    internalformat == GL_RGBA) ||
                (type == GL_UNSIGNED_BYTE &&
                 internalformat == GL_SRGB8_ALPHA8) ? 0 : -1;
        case kAlpha_8_SkColorType:
            return (type == GL_UNSIGNED_BYTE &&
                internalformat == GL_ALPHA) ? 0 : -1;
        case kARGB_4444_SkColorType:
            return (type == GL_UNSIGNED_SHORT_4_4_4_4 &&
                internalformat == GL_RGBA) ? 0 : -1;
        case kRGB_565_SkColorType:
            return (type == GL_UNSIGNED_SHORT_5_6_5 &&
                internalformat == GL_RGB) ? 0 : -1;
        case kRGBA_F16_SkColorType:
            return (type == GL_HALF_FLOAT &&
                internalformat == GL_RGBA16F) ? 0 : -1;
        default:
            break;
    }
    return -1;
}

// The internal format is no longer the same as pixel format, per Table 2 in
// https://www.khronos.org/registry/OpenGL-Refpages/es3.1/html/glTexImage2D.xhtml
static int getPixelFormatFromInternalFormat(uint32_t internalFormat) {
    switch (internalFormat) {
        // For sized internal format.
        case GL_RGBA16F:
        case GL_SRGB8_ALPHA8:
            return GL_RGBA;
        // Base internal formats and pixel formats are still the same, see Table 1 in
        // https://www.khronos.org/registry/OpenGL-Refpages/es3.1/html/glTexImage2D.xhtml
        default:
            return internalFormat;
    }
}

static int getInternalFormat(SkColorType colorType)
{
    switch(colorType) {
        case kAlpha_8_SkColorType:
            return GL_ALPHA;
        case kARGB_4444_SkColorType:
            return GL_RGBA;
        case kN32_SkColorType:
            return GL_RGBA;
        case kRGB_565_SkColorType:
            return GL_RGB;
        case kRGBA_F16_SkColorType:
            return GL_RGBA16F;
        default:
            return -1;
    }
}

static int getType(SkColorType colorType)
{
    switch(colorType) {
        case kAlpha_8_SkColorType:
            return GL_UNSIGNED_BYTE;
        case kARGB_4444_SkColorType:
            return GL_UNSIGNED_SHORT_4_4_4_4;
        case kN32_SkColorType:
            return GL_UNSIGNED_BYTE;
        case kRGB_565_SkColorType:
            return GL_UNSIGNED_SHORT_5_6_5;
        case kRGBA_F16_SkColorType:
            return GL_HALF_FLOAT;
        default:
            return -1;
    }
}

static jint util_getInternalFormat(JNIEnv *env, jclass clazz,
        jlong bitmapPtr)
{
    SkBitmap nativeBitmap;
    bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap);
    return getInternalFormat(nativeBitmap.colorType());
}

static jint util_getType(JNIEnv *env, jclass clazz,
        jlong bitmapPtr)
{
    SkBitmap nativeBitmap;
    bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap);
    return getType(nativeBitmap.colorType());
}

static jint util_texImage2D(JNIEnv *env, jclass clazz,
        jint target, jint level, jint internalformat,
        jlong bitmapPtr, jint type, jint border)
{
    SkBitmap bitmap;
    bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
    SkColorType colorType = bitmap.colorType();
    if (internalformat < 0) {
        internalformat = getInternalFormat(colorType);
    }
    if (type < 0) {
        type = getType(colorType);
    }
    int err = checkInternalFormat(colorType, internalformat, type);
    if (err)
        return err;
    const int w = bitmap.width();
    const int h = bitmap.height();
    const void* p = bitmap.getPixels();
    if (internalformat == GL_PALETTE8_RGBA8_OES) {
        err = -1;
    } else {
        glTexImage2D(target, level, internalformat, w, h, border,
                     getPixelFormatFromInternalFormat(internalformat), type, p);
    }
    return err;
}

static jint util_texSubImage2D(JNIEnv *env, jclass clazz,
        jint target, jint level, jint xoffset, jint yoffset,
        jlong bitmapPtr, jint format, jint type)
{
    SkBitmap bitmap;
    bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
    SkColorType colorType = bitmap.colorType();
    int internalFormat = getInternalFormat(colorType);
    if (format < 0) {
        format = getPixelFormatFromInternalFormat(internalFormat);
        if (format == GL_PALETTE8_RGBA8_OES)
            return -1; // glCompressedTexSubImage2D() not supported
    }
    int err = checkInternalFormat(colorType, internalFormat, type);
    if (err)
        return err;
    const int w = bitmap.width();
    const int h = bitmap.height();
    const void* p = bitmap.getPixels();
    glTexSubImage2D(target, level, xoffset, yoffset, w, h, format, type, p);
    return 0;
}

/*
 * ETC1 methods.
 */

static void *
getPointer(JNIEnv *_env, jobject buffer, jint *remaining)
{
    jint position;
    jint limit;
    jint elementSizeShift;
    jlong pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
    if (pointer != 0L) {
        pointer += position << elementSizeShift;
    }
    *remaining = (limit - position) << elementSizeShift;
    return reinterpret_cast<void*>(pointer);
}

class BufferHelper {
public:
    BufferHelper(JNIEnv *env, jobject buffer) {
        mEnv = env;
        mBuffer = buffer;
        mData = NULL;
        mRemaining = 0;
    }

    bool checkPointer(const char* errorMessage) {
        if (mBuffer) {
            mData = getPointer(mEnv, mBuffer, &mRemaining);
            if (mData == NULL) {
                doThrowIAE(mEnv, errorMessage);
            }
            return mData != NULL;
        } else {
            doThrowIAE(mEnv, errorMessage);
            return false;
        }
    }

    inline void* getData() {
        return mData;
    }

    inline jint remaining() {
        return mRemaining;
    }

private:
    JNIEnv* mEnv;
    jobject mBuffer;
    void* mData;
    jint mRemaining;
};

/**
 * Encode a block of pixels.
 *
 * @param in a pointer to a ETC1_DECODED_BLOCK_SIZE array of bytes that represent a
 * 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
 * value of pixel (x, y).
 *
 * @param validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether
 * the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing.
 *
 * @param out an ETC1 compressed version of the data.
 *
 */
static void etc1_encodeBlock(JNIEnv *env, jclass clazz,
        jobject in, jint validPixelMask, jobject out) {
    if (validPixelMask < 0 || validPixelMask > 15) {
        doThrowIAE(env, "validPixelMask");
        return;
    }
    BufferHelper inB(env, in);
    BufferHelper outB(env, out);
    if (inB.checkPointer("in") && outB.checkPointer("out")) {
        if (inB.remaining() < ETC1_DECODED_BLOCK_SIZE) {
            doThrowIAE(env, "in's remaining data < DECODED_BLOCK_SIZE");
        } else if (outB.remaining() < ETC1_ENCODED_BLOCK_SIZE) {
            doThrowIAE(env, "out's remaining data < ENCODED_BLOCK_SIZE");
        } else {
            etc1_encode_block((etc1_byte*) inB.getData(), validPixelMask,
                    (etc1_byte*) outB.getData());
        }
    }
}

/**
 * Decode a block of pixels.
 *
 * @param in an ETC1 compressed version of the data.
 *
 * @param out a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
 * 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
 * value of pixel (x, y).
 */
static void etc1_decodeBlock(JNIEnv *env, jclass clazz,
        jobject in, jobject out){
    BufferHelper inB(env, in);
    BufferHelper outB(env, out);
    if (inB.checkPointer("in") && outB.checkPointer("out")) {
        if (inB.remaining() < ETC1_ENCODED_BLOCK_SIZE) {
            doThrowIAE(env, "in's remaining data < ENCODED_BLOCK_SIZE");
        } else if (outB.remaining() < ETC1_DECODED_BLOCK_SIZE) {
            doThrowIAE(env, "out's remaining data < DECODED_BLOCK_SIZE");
        } else {
            etc1_decode_block((etc1_byte*) inB.getData(),
                    (etc1_byte*) outB.getData());
        }
    }
}

/**
 * Return the size of the encoded image data (does not include size of PKM header).
 */
static jint etc1_getEncodedDataSize(JNIEnv *env, jclass clazz,
        jint width, jint height) {
    return etc1_get_encoded_data_size(width, height);
}

/**
 * Encode an entire image.
 * @param in pointer to the image data. Formatted such that
 *           pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset;
 * @param out pointer to encoded data. Must be large enough to store entire encoded image.
 */
static void etc1_encodeImage(JNIEnv *env, jclass clazz,
        jobject in, jint width, jint height,
        jint pixelSize, jint stride, jobject out) {
    if (pixelSize < 2 || pixelSize > 3) {
        doThrowIAE(env, "pixelSize must be 2 or 3");
        return;
    }
    BufferHelper inB(env, in);
    BufferHelper outB(env, out);
    if (inB.checkPointer("in") && outB.checkPointer("out")) {
        jint imageSize = stride * height;
        jint encodedImageSize = etc1_get_encoded_data_size(width, height);
        if (inB.remaining() < imageSize) {
            doThrowIAE(env, "in's remaining data < image size");
        } else if (outB.remaining() < encodedImageSize) {
            doThrowIAE(env, "out's remaining data < encoded image size");
        } else {
            etc1_encode_image((etc1_byte*) inB.getData(), width, height, pixelSize, stride,
                              (etc1_byte*) outB.getData());
        }
    }
}

/**
 * Decode an entire image.
 * @param in the encoded data.
 * @param out pointer to the image data. Will be written such that
 *            pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
 *            large enough to store entire image.
 */
static void etc1_decodeImage(JNIEnv *env, jclass clazz,
        jobject  in, jobject out,
        jint width, jint height,
        jint pixelSize, jint stride) {
    if (pixelSize < 2 || pixelSize > 3) {
        doThrowIAE(env, "pixelSize must be 2 or 3");
        return;
    }
    BufferHelper inB(env, in);
    BufferHelper outB(env, out);
    if (inB.checkPointer("in") && outB.checkPointer("out")) {
        jint imageSize = stride * height;
        jint encodedImageSize = etc1_get_encoded_data_size(width, height);
        if (inB.remaining() < encodedImageSize) {
            doThrowIAE(env, "in's remaining data < encoded image size");
        } else if (outB.remaining() < imageSize) {
            doThrowIAE(env, "out's remaining data < image size");
        } else {
            etc1_decode_image((etc1_byte*) inB.getData(), (etc1_byte*) outB.getData(),
                              width, height, pixelSize, stride);
        }
    }
}

/**
 * Format a PKM header
 */
static void etc1_formatHeader(JNIEnv *env, jclass clazz,
        jobject header, jint width, jint height) {
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            etc1_pkm_format_header((etc1_byte*) headerB.getData(), width, height);
        }
    }
}

/**
 * Check if a PKM header is correctly formatted.
 */
static jboolean etc1_isValid(JNIEnv *env, jclass clazz,
        jobject header) {
    jboolean result = false;
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            result = etc1_pkm_is_valid((etc1_byte*) headerB.getData());
        }
    }
    return result ? JNI_TRUE : JNI_FALSE;
}

/**
 * Read the image width from a PKM header
 */
static jint etc1_getWidth(JNIEnv *env, jclass clazz,
        jobject header) {
    jint result = 0;
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            result = etc1_pkm_get_width((etc1_byte*) headerB.getData());
        }
    }
    return result;
}

/**
 * Read the image height from a PKM header
 */
static jint etc1_getHeight(JNIEnv *env, jclass clazz,
        jobject header) {
    jint result = 0;
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            result = etc1_pkm_get_height((etc1_byte*) headerB.getData());
        }
    }
    return result;
}

/*
 * JNI registration
 */

static const JNINativeMethod gMatrixMethods[] = {
    { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
    { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
};

static const JNINativeMethod gVisibilityMethods[] = {
    { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
    { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
    { "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest },
};

static const JNINativeMethod gUtilsMethods[] = {
    { "native_getInternalFormat", "(J)I", (void*) util_getInternalFormat },
    { "native_getType", "(J)I", (void*) util_getType },
    { "native_texImage2D", "(IIIJII)I", (void*)util_texImage2D },
    { "native_texSubImage2D", "(IIIIJII)I", (void*)util_texSubImage2D },
};

static const JNINativeMethod gEtc1Methods[] = {
    { "encodeBlock", "(Ljava/nio/Buffer;ILjava/nio/Buffer;)V", (void*) etc1_encodeBlock },
    { "decodeBlock", "(Ljava/nio/Buffer;Ljava/nio/Buffer;)V", (void*) etc1_decodeBlock },
    { "getEncodedDataSize", "(II)I", (void*) etc1_getEncodedDataSize },
    { "encodeImage", "(Ljava/nio/Buffer;IIIILjava/nio/Buffer;)V", (void*) etc1_encodeImage },
    { "decodeImage", "(Ljava/nio/Buffer;Ljava/nio/Buffer;IIII)V", (void*) etc1_decodeImage },
    { "formatHeader", "(Ljava/nio/Buffer;II)V", (void*) etc1_formatHeader },
    { "isValid", "(Ljava/nio/Buffer;)Z", (void*) etc1_isValid },
    { "getWidth", "(Ljava/nio/Buffer;)I", (void*) etc1_getWidth },
    { "getHeight", "(Ljava/nio/Buffer;)I", (void*) etc1_getHeight },
};

typedef struct _ClassRegistrationInfo {
    const char* classPath;
    const JNINativeMethod* methods;
    size_t methodCount;
} ClassRegistrationInfo;

static const ClassRegistrationInfo gClasses[] = {
    {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
    {"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)},
    {"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
    {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)},
};

int register_android_opengl_classes(JNIEnv* env)
{
    int result = 0;
    for (int i = 0; i < NELEM(gClasses); i++) {
        const ClassRegistrationInfo* cri = &gClasses[i];
        result = RegisterMethodsOrDie(env, cri->classPath, cri->methods, cri->methodCount);
    }
    return result;
}

} // namespace android
