19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** Copyright 2007, The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **
4106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** Licensed under the Apache License, Version 2.0 (the "License");
5106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** you may not use this file except in compliance with the License.
6106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **
8106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich **     http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **
10106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** Unless required by applicable law or agreed to in writing, software
11106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** distributed under the License is distributed on an "AS IS" BASIS,
12106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich ** See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
178451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes#include "jni.h"
188451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes#include "JNIHelp.h"
19f4faeac3525fe1ce3707ab785a1651aec367589dJohn Reck#include "GraphicsJNI.h"
208451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <math.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dlfcn.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/gl.h>
29a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich#include <ETC1/etc1.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkBitmap.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "OpenGLUtil"
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h"
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "poly.h"
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z + pM[0 + 4 * 3] * w;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDest[1] = pM[1 + 4 * 0] * x + pM[1 + 4 * 1] * y + pM[1 + 4 * 2] * z + pM[1 + 4 * 3] * w;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDest[2] = pM[2 + 4 * 0] * x + pM[2 + 4 * 1] * y + pM[2 + 4 * 2] * z + pM[2 + 4 * 3] * w;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDest[3] = pM[3 + 4 * 0] * x + pM[3 + 4 * 1] * y + pM[3 + 4 * 2] * z + pM[3 + 4 * 3] * w;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass MallocHelper {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MallocHelper() {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mData = 0;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
57106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~MallocHelper() {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mData != 0) {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            free(mData);
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
63106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* alloc(size_t size) {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mData = malloc(size);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mData;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
68106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* mData;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprint_poly(const char* label, Poly* pPoly) {
776215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    ALOGI("%s: %d verts", label, pPoly->n);
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < pPoly->n; i++) {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Poly_vert* pV = & pPoly->vert[i];
806215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        ALOGI("[%d] %g, %g, %g %g", i, pV->sx, pV->sy, pV->sz, pV->sw);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint visibilityTest(float* pWS, float* pPositions, int positionsLength,
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unsigned short* pIndices, int indexCount) {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MallocHelper mallocHelper;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result = POLY_CLIP_OUT;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pTransformed = 0;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int transformedIndexCount = 0;
92106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( indexCount < 3 ) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return POLY_CLIP_OUT;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
96106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Find out how many vertices we need to transform
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We transform every vertex between the min and max indices, inclusive.
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This is OK for the data sets we expect to use with this function, but
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for other loads it might be better to use a more sophisticated vertex
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // cache of some sort.
102106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int minIndex = 65536;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int maxIndex = -1;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < indexCount; i++) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int index = pIndices[i];
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( index < minIndex ) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            minIndex = index;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( index > maxIndex ) {
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            maxIndex = index;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
114106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( maxIndex * 3 > positionsLength) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
118106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    transformedIndexCount = maxIndex - minIndex + 1;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pTransformed = (float*) mallocHelper.alloc(transformedIndexCount * 4 * sizeof(float));
121106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pTransformed == 0 ) {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -2;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
125106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Transform the vertices
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const float* pSrc = pPositions + 3 * minIndex;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float* pDst = pTransformed;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < transformedIndexCount; i++, pSrc += 3, pDst += 4) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mx4transform(pSrc[0], pSrc[1], pSrc[2], 1.0f, pWS,  pDst);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
134106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Clip the triangles
136106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Poly poly;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pDest = & poly.vert[0].sx;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < indexCount; i += 3) {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        poly.n = 3;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(pDest    , pTransformed + 4 * (pIndices[i    ] - minIndex), 4 * sizeof(float));
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(pDest + 4, pTransformed + 4 * (pIndices[i + 1] - minIndex), 4 * sizeof(float));
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(pDest + 8, pTransformed + 4 * (pIndices[i + 2] - minIndex), 4 * sizeof(float));
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = poly_clip_to_frustum(&poly);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( result != POLY_CLIP_OUT) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1535b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass ByteArrayGetter {
1545b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1555b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jbyteArray array, jboolean* is_copy) {
1565b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetByteArrayElements(array, is_copy);
1575b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1585b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1595b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass BooleanArrayGetter {
1605b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1615b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jbooleanArray array, jboolean* is_copy) {
1625b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetBooleanArrayElements(array, is_copy);
1635b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1645b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1655b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass CharArrayGetter {
1665b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1675b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jcharArray array, jboolean* is_copy) {
1685b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetCharArrayElements(array, is_copy);
1695b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1705b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1715b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass ShortArrayGetter {
1725b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1735b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jshortArray array, jboolean* is_copy) {
1745b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetShortArrayElements(array, is_copy);
1755b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1765b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1775b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass IntArrayGetter {
1785b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1795b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jintArray array, jboolean* is_copy) {
1805b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetIntArrayElements(array, is_copy);
1815b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1825b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1835b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass LongArrayGetter {
1845b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1855b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jlongArray array, jboolean* is_copy) {
1865b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetLongArrayElements(array, is_copy);
1875b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1885b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1895b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass FloatArrayGetter {
1905b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1915b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jfloatArray array, jboolean* is_copy) {
1925b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetFloatArrayElements(array, is_copy);
1935b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
1945b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
1955b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass DoubleArrayGetter {
1965b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
1975b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void* Get(JNIEnv* _env, jdoubleArray array, jboolean* is_copy) {
1985b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        return _env->GetDoubleArrayElements(array, is_copy);
1995b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2005b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2015b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi
2025b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass ByteArrayReleaser {
2035b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2045b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jbyteArray array, jbyte* data, jint mode) {
2055b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseByteArrayElements(array, data, mode);
2065b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2075b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2085b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass BooleanArrayReleaser {
2095b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2105b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jbooleanArray array, jboolean* data, jint mode) {
2115b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseBooleanArrayElements(array, data, mode);
2125b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2135b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2145b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass CharArrayReleaser {
2155b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2165b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jcharArray array, jchar* data, jint mode) {
2175b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseCharArrayElements(array, data, mode);
2185b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2195b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2205b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass ShortArrayReleaser {
2215b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2225b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jshortArray array, jshort* data, jint mode) {
2235b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseShortArrayElements(array, data, mode);
2245b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2255b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2265b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass IntArrayReleaser {
2275b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2285b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jintArray array, jint* data, jint mode) {
2295b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseIntArrayElements(array, data, mode);
2305b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2315b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2325b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass LongArrayReleaser {
2335b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2345b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jlongArray array, jlong* data, jint mode) {
2355b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseLongArrayElements(array, data, mode);
2365b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2375b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2385b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass FloatArrayReleaser {
2395b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2405b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jfloatArray array, jfloat* data, jint mode) {
2415b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseFloatArrayElements(array, data, mode);
2425b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2435b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2445b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchiclass DoubleArrayReleaser {
2455b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchipublic:
2465b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    static void Release(JNIEnv* _env, jdoubleArray array, jdouble* data, jint mode) {
2475b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        _env->ReleaseDoubleArrayElements(array, data, mode);
2485b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi    }
2495b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi};
2505b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi
2515b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchitemplate<class JArray, class T, class ArrayGetter, class ArrayReleaser>
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass ArrayHelper {
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayHelper(JNIEnv* env, JArray ref, jint offset, jint minSize) {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnv = env;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRef = ref;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOffset = offset;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMinSize = minSize;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBase = 0;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mReleaseParam = JNI_ABORT;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~ArrayHelper() {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBase) {
2655b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi            ArrayReleaser::Release(mEnv, mRef, mBase, mReleaseParam);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
268106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We seperate the bounds check from the initialization because we want to
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // be able to bounds-check multiple arrays, and we can't throw an exception
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // after we've called GetPrimitiveArrayCritical.
272106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Return true if the bounds check succeeded
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Else instruct the runtime to throw an exception
275106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool check() {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( ! mRef) {
2788451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(mEnv, "array == null");
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( mOffset < 0) {
2828451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(mEnv, "offset < 0");
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLength = mEnv->GetArrayLength(mRef) - mOffset;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLength < mMinSize ) {
2878451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(mEnv, "length - offset < n");
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
292106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Bind the array.
294106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void bind() {
2965b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchi        mBase = (T*) ArrayGetter::Get(mEnv, mRef, (jboolean *) 0);
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mData = mBase + mOffset;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void commitChanges() {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mReleaseParam = 0;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
303106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    T* mData;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLength;
306106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    T* mBase;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    JNIEnv* mEnv;
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    JArray mRef;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jint mOffset;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jint mMinSize;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mReleaseParam;
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3165b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchitypedef ArrayHelper<jfloatArray, float, FloatArrayGetter, FloatArrayReleaser> FloatArrayHelper;
3175b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchitypedef ArrayHelper<jcharArray, unsigned short, CharArrayGetter, CharArrayReleaser> UnsignedShortArrayHelper;
3185b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchitypedef ArrayHelper<jintArray, int, IntArrayGetter, IntArrayReleaser> IntArrayHelper;
3195b406cb7b548443b589f0acb235c8a7465ffb82bHiroshi Yamauchitypedef ArrayHelper<jbyteArray, unsigned char, ByteArrayGetter, ByteArrayReleaser> ByteArrayHelper;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectinline float distance2(float x, float y, float z) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return x * x + y * y + z * z;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectinline float distance(float x, float y, float z) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return sqrtf(distance2(x, y, z));
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
328106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid util_computeBoundingSphere(JNIEnv *env, jclass clazz,
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray positions_ref, jint positionsOffset, jint positionsCount,
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray sphere_ref, jint sphereOffset) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper sphere(env, sphere_ref, sphereOffset, 4);
335106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = positions.check() && sphere.check();
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (! checkOK) {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
340106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    positions.bind();
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sphere.bind();
343106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( positionsCount < 1 ) {
3458451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env, "positionsCount < 1");
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
348106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const float* pSrc = positions.mData;
350106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // find bounding box
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float x0 = *pSrc++;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float x1 = x0;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float y0 = *pSrc++;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float y1 = y0;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float z0 = *pSrc++;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float z1 = z0;
358106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 1; i < positionsCount; i++) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = *pSrc++;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (x < x0) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                x0 = x;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (x > x1) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                x1 = x;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = *pSrc++;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (y < y0) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                y0 = y;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (y > y1) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                y1 = y;
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = *pSrc++;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (z < z0) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                z0 = z;
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (z > z1) {
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                z1 = z;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
388106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Because we know our input meshes fit pretty well into bounding boxes,
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // just take the diagonal of the box as defining our sphere.
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pSphere = sphere.mData;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float dx = x1 - x0;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float dy = y1 - y0;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float dz = z1 - z0;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = x0 + dx * 0.5f;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = y0 + dy * 0.5f;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = z0 + dz * 0.5f;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = distance(dx, dy, dz) * 0.5f;
399106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sphere.commitChanges();
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void normalizePlane(float* p) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float rdist = 1.0f / distance(p[0], p[1], p[2]);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < 4; i++) {
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p[i] *= rdist;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline float dot3(float x0, float y0, float z0, float x1, float y1, float z1) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return x0 * x1 + y0 * y1 + z0 * z1;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline float signedDistance(const float* pPlane, float x, float y, float z) {
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return dot3(pPlane[0], pPlane[1], pPlane[2], x, y, z) + pPlane[3];
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Return true if the sphere intersects or is inside the frustum
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool sphereHitsFrustum(const float* pFrustum, const float* pSphere) {
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float x = pSphere[0];
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float y = pSphere[1];
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float z = pSphere[2];
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float negRadius = -pSphere[3];
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < 6; i++, pFrustum += 4) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (signedDistance(pFrustum, x, y, z) <= negRadius) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void computeFrustum(const float* m, float* f) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m3 = m[3];
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m7 = m[7];
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m11 = m[11];
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m15 = m[15];
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // right
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  - m[0];
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  - m[4];
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 - m[8];
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 - m[12];
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
446106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich    // left
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  + m[0];
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  + m[4];
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 + m[8];
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 + m[12];
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // top
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  - m[1];
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  - m[5];
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 - m[9];
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 - m[13];
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // bottom
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  + m[1];
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  + m[5];
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 + m[9];
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 + m[13];
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // far
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  - m[2];
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  - m[6];
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 - m[10];
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 - m[14];
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // near
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  + m[2];
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  + m[6];
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 + m[10];
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 + m[14];
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
48736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatjint util_frustumCullSpheres(JNIEnv *env, jclass clazz,
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray mvp_ref, jint mvpOffset,
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray spheres_ref, jint spheresOffset, jint spheresCount,
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jintArray results_ref, jint resultsOffset, jint resultsCapacity) {
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float frustum[6*4];
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int outputCount;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int* pResults;
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pSphere;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper mvp(env, mvp_ref, mvpOffset, 16);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper spheres(env, spheres_ref, spheresOffset, spheresCount * 4);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IntArrayHelper results(env, results_ref, resultsOffset, resultsCapacity);
498106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool initializedOK = mvp.check() && spheres.check() && results.check();
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (! initializedOK) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
503106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mvp.bind();
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    spheres.bind();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    results.bind();
507106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    computeFrustum(mvp.mData, frustum);
509106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Cull the spheres
511106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pSphere = spheres.mData;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pResults = results.mData;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    outputCount = 0;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < spheresCount; i++, pSphere += 4) {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sphereHitsFrustum(frustum, pSphere)) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outputCount < resultsCapacity) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *pResults++ = i;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outputCount++;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    results.commitChanges();
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return outputCount;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public native int visibilityTest(float[] ws, int wsOffset,
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float[] positions, int positionsOffset,
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] indices, int indicesOffset, int indexCount);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
53436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatjint util_visibilityTest(JNIEnv *env, jclass clazz,
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray ws_ref, jint wsOffset,
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray positions_ref, jint positionsOffset,
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jcharArray indices_ref, jint indicesOffset, jint indexCount) {
538106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper ws(env, ws_ref, wsOffset, 16);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    UnsignedShortArrayHelper indices(env, indices_ref, indicesOffset, 0);
542106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = ws.check() && positions.check() && indices.check();
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (! checkOK) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Return value will be ignored, because an exception has been thrown.
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
548106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (indices.mLength < indexCount) {
5508451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env, "length < offset + indexCount");
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
553106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ws.bind();
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    positions.bind();
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    indices.bind();
557106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return visibilityTest(ws.mData,
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            positions.mData, positions.mLength,
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            indices.mData, indexCount);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define I(_i, _j) ((_j)+ 4*(_i))
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid multiplyMM(float* r, const float* lhs, const float* rhs)
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
56946d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        const float rhs_i0 = rhs[ I(i,0) ];
57046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        float ri0 = lhs[ I(0,0) ] * rhs_i0;
57146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        float ri1 = lhs[ I(0,1) ] * rhs_i0;
57246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        float ri2 = lhs[ I(0,2) ] * rhs_i0;
57346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        float ri3 = lhs[ I(0,3) ] * rhs_i0;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=1 ; j<4 ; j++) {
57546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert            const float rhs_ij = rhs[ I(i,j) ];
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri0 += lhs[ I(j,0) ] * rhs_ij;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri1 += lhs[ I(j,1) ] * rhs_ij;
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri2 += lhs[ I(j,2) ] * rhs_ij;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri3 += lhs[ I(j,3) ] * rhs_ij;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,0) ] = ri0;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,1) ] = ri1;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,2) ] = ri2;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,3) ] = ri3;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid util_multiplyMM(JNIEnv *env, jclass clazz,
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray result_ref, jint resultOffset,
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray lhs_ref, jint lhsOffset,
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray rhs_ref, jint rhsOffset) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper resultMat(env, result_ref, resultOffset, 16);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16);
597106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = resultMat.check() && lhs.check() && rhs.check();
599106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( !checkOK ) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
603106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultMat.bind();
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lhs.bind();
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    rhs.bind();
607106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    multiplyMM(resultMat.mData, lhs.mData, rhs.mData);
609106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultMat.commitChanges();
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid multiplyMV(float* r, const float* lhs, const float* rhs)
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid util_multiplyMV(JNIEnv *env, jclass clazz,
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray result_ref, jint resultOffset,
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray lhs_ref, jint lhsOffset,
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray rhs_ref, jint rhsOffset) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper resultV(env, result_ref, resultOffset, 4);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4);
628106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = resultV.check() && lhs.check() && rhs.check();
630106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( !checkOK ) {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
634106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultV.bind();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lhs.bind();
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    rhs.bind();
638106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    multiplyMV(resultV.mData, lhs.mData, rhs.mData);
640106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultV.commitChanges();
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6461103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reedstatic int checkFormat(SkColorType colorType, int format, int type)
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6481103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    switch(colorType) {
6491103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kIndex_8_SkColorType:
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (format == GL_PALETTE8_RGBA8_OES)
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
6521103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kN32_SkColorType:
6531103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kAlpha_8_SkColorType:
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type == GL_UNSIGNED_BYTE)
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
6561103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kARGB_4444_SkColorType:
6571103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kRGB_565_SkColorType:
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (type) {
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_SHORT_4_4_4_4:
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_SHORT_5_6_5:
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_SHORT_5_5_5_1:
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return 0;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_BYTE:
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (format == GL_LUMINANCE_ALPHA)
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return 0;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6741103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reedstatic int getInternalFormat(SkColorType colorType)
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6761103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    switch(colorType) {
6771103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kAlpha_8_SkColorType:
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_ALPHA;
6791103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kARGB_4444_SkColorType:
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_RGBA;
6811103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kN32_SkColorType:
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_RGBA;
6831103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kIndex_8_SkColorType:
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_PALETTE8_RGBA8_OES;
6851103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kRGB_565_SkColorType:
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_RGB;
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6921103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reedstatic int getType(SkColorType colorType)
693708c17b4168404042852e480f25a91a02cf14247Jack Palevich{
6941103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    switch(colorType) {
6951103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kAlpha_8_SkColorType:
696708c17b4168404042852e480f25a91a02cf14247Jack Palevich            return GL_UNSIGNED_BYTE;
6971103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kARGB_4444_SkColorType:
698708c17b4168404042852e480f25a91a02cf14247Jack Palevich            return GL_UNSIGNED_SHORT_4_4_4_4;
6991103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kN32_SkColorType:
700708c17b4168404042852e480f25a91a02cf14247Jack Palevich            return GL_UNSIGNED_BYTE;
7011103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kIndex_8_SkColorType:
702708c17b4168404042852e480f25a91a02cf14247Jack Palevich            return -1; // No type for compressed data.
7031103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        case kRGB_565_SkColorType:
704708c17b4168404042852e480f25a91a02cf14247Jack Palevich            return GL_UNSIGNED_SHORT_5_6_5;
705708c17b4168404042852e480f25a91a02cf14247Jack Palevich        default:
706708c17b4168404042852e480f25a91a02cf14247Jack Palevich            return -1;
707708c17b4168404042852e480f25a91a02cf14247Jack Palevich    }
708708c17b4168404042852e480f25a91a02cf14247Jack Palevich}
709708c17b4168404042852e480f25a91a02cf14247Jack Palevich
710708c17b4168404042852e480f25a91a02cf14247Jack Palevichstatic jint util_getInternalFormat(JNIEnv *env, jclass clazz,
711708c17b4168404042852e480f25a91a02cf14247Jack Palevich        jobject jbitmap)
712708c17b4168404042852e480f25a91a02cf14247Jack Palevich{
713ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    SkBitmap nativeBitmap;
714ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap);
715ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    return getInternalFormat(nativeBitmap.colorType());
716708c17b4168404042852e480f25a91a02cf14247Jack Palevich}
717708c17b4168404042852e480f25a91a02cf14247Jack Palevich
718708c17b4168404042852e480f25a91a02cf14247Jack Palevichstatic jint util_getType(JNIEnv *env, jclass clazz,
719708c17b4168404042852e480f25a91a02cf14247Jack Palevich        jobject jbitmap)
720708c17b4168404042852e480f25a91a02cf14247Jack Palevich{
721ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    SkBitmap nativeBitmap;
722ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap);
723ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    return getType(nativeBitmap.colorType());
724708c17b4168404042852e480f25a91a02cf14247Jack Palevich}
725708c17b4168404042852e480f25a91a02cf14247Jack Palevich
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint util_texImage2D(JNIEnv *env, jclass clazz,
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint target, jint level, jint internalformat,
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jobject jbitmap, jint type, jint border)
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
730ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    SkBitmap bitmap;
731ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
7321103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = bitmap.colorType();
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (internalformat < 0) {
7341103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        internalformat = getInternalFormat(colorType);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
736708c17b4168404042852e480f25a91a02cf14247Jack Palevich    if (type < 0) {
7371103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        type = getType(colorType);
738708c17b4168404042852e480f25a91a02cf14247Jack Palevich    }
7391103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    int err = checkFormat(colorType, internalformat, type);
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err)
741106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich        return err;
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.lockPixels();
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int w = bitmap.width();
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int h = bitmap.height();
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* p = bitmap.getPixels();
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (internalformat == GL_PALETTE8_RGBA8_OES) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sizeof(SkPMColor) != sizeof(uint32_t)) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            err = -1;
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto error;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t size = bitmap.getSize();
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t palette_size = 256*sizeof(SkPMColor);
753106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich        const size_t imageSize = size + palette_size;
754106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich        void* const data = malloc(imageSize);
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (data) {
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            void* const pixels = (char*)data + palette_size;
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SkColorTable* ctable = bitmap.getColorTable();
75871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed            memcpy(data, ctable->readColors(), ctable->count() * sizeof(SkPMColor));
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            memcpy(pixels, p, size);
760106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich            glCompressedTexImage2D(target, level, internalformat, w, h, border, imageSize, data);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            free(data);
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            err = -1;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexImage2D(target, level, internalformat, w, h, border, internalformat, type, p);
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecterror:
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.unlockPixels();
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return err;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint util_texSubImage2D(JNIEnv *env, jclass clazz,
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint target, jint level, jint xoffset, jint yoffset,
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jobject jbitmap, jint format, jint type)
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
777ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    SkBitmap bitmap;
778ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
7791103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = bitmap.colorType();
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (format < 0) {
7811103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        format = getInternalFormat(colorType);
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (format == GL_PALETTE8_RGBA8_OES)
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1; // glCompressedTexSubImage2D() not supported
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7851103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    int err = checkFormat(colorType, format, type);
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err)
787106006cbdedc79ce8746ca5449610c69a2f69655Jack Palevich        return err;
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.lockPixels();
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int w = bitmap.width();
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int h = bitmap.height();
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* p = bitmap.getPixels();
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexSubImage2D(target, level, xoffset, yoffset, w, h, format, type, p);
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.unlockPixels();
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
798a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * ETC1 methods.
799a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
800a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
801a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jclass nioAccessClass;
802a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jclass bufferClass;
803a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jmethodID getBasePointerID;
804a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jmethodID getBaseArrayID;
805a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jmethodID getBaseArrayOffsetID;
806a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jfieldID positionID;
807a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jfieldID limitID;
808a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jfieldID elementSizeShiftID;
809a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
810a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/* Cache method IDs each time the class is loaded. */
811a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
812a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void
813ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas GampenativeClassInitBuffer(JNIEnv *env)
814a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich{
815ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass nioAccessClassLocal = FindClassOrDie(env, "java/nio/NIOAccess");
816ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    nioAccessClass = MakeGlobalRefOrDie(env, nioAccessClassLocal);
817ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    getBasePointerID = GetStaticMethodIDOrDie(env, nioAccessClass,
818a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            "getBasePointer", "(Ljava/nio/Buffer;)J");
819ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    getBaseArrayID = GetStaticMethodIDOrDie(env, nioAccessClass,
820a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
821ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    getBaseArrayOffsetID = GetStaticMethodIDOrDie(env, nioAccessClass,
822a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
823ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
824ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass bufferClassLocal = FindClassOrDie(env, "java/nio/Buffer");
825ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    bufferClass = MakeGlobalRefOrDie(env, bufferClassLocal);
826ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    positionID = GetFieldIDOrDie(env, bufferClass, "position", "I");
827ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    limitID = GetFieldIDOrDie(env, bufferClass, "limit", "I");
828ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    elementSizeShiftID = GetFieldIDOrDie(env, bufferClass, "_elementSizeShift", "I");
829a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
830a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
831a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void *
832a6276fdd4253c3a7150ab675678c750473ab6c45Jack PalevichgetPointer(JNIEnv *_env, jobject buffer, jint *remaining)
833a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich{
834a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jint position;
835a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jint limit;
836a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jint elementSizeShift;
837a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jlong pointer;
838a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
839a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    position = _env->GetIntField(buffer, positionID);
840a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    limit = _env->GetIntField(buffer, limitID);
841a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
842a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    *remaining = (limit - position) << elementSizeShift;
843a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    pointer = _env->CallStaticLongMethod(nioAccessClass,
844a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            getBasePointerID, buffer);
845a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (pointer != 0L) {
84636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        return reinterpret_cast<void *>(pointer);
847a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
848a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    return NULL;
849a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
850a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
851a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichclass BufferHelper {
852a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichpublic:
853a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper(JNIEnv *env, jobject buffer) {
854a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        mEnv = env;
855a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        mBuffer = buffer;
856a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        mData = NULL;
857a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        mRemaining = 0;
858a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
859a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
860a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    bool checkPointer(const char* errorMessage) {
861a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (mBuffer) {
862a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            mData = getPointer(mEnv, mBuffer, &mRemaining);
863a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            if (mData == NULL) {
8648451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes                doThrowIAE(mEnv, errorMessage);
865a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            }
866a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            return mData != NULL;
867a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
8688451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(mEnv, errorMessage);
869a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            return false;
870a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
871a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
872a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
873a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    inline void* getData() {
874a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        return mData;
875a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
876a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
877a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    inline jint remaining() {
878a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        return mRemaining;
879a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
880a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
881a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichprivate:
882a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    JNIEnv* mEnv;
883a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jobject mBuffer;
884a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    void* mData;
885a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jint mRemaining;
886a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich};
887a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
888a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
889a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Encode a block of pixels.
890a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *
891a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param in a pointer to a ETC1_DECODED_BLOCK_SIZE array of bytes that represent a
892a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
893a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * value of pixel (x, y).
894a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *
895a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether
896a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing.
897a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *
898a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param out an ETC1 compressed version of the data.
899a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *
900a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
901a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void etc1_encodeBlock(JNIEnv *env, jclass clazz,
902a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject in, jint validPixelMask, jobject out) {
903a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (validPixelMask < 0 || validPixelMask > 15) {
9048451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env, "validPixelMask");
905a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        return;
906a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
907a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper inB(env, in);
908a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper outB(env, out);
909a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (inB.checkPointer("in") && outB.checkPointer("out")) {
910a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (inB.remaining() < ETC1_DECODED_BLOCK_SIZE) {
9118451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "in's remaining data < DECODED_BLOCK_SIZE");
912a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else if (outB.remaining() < ETC1_ENCODED_BLOCK_SIZE) {
9138451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "out's remaining data < ENCODED_BLOCK_SIZE");
914a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
915a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            etc1_encode_block((etc1_byte*) inB.getData(), validPixelMask,
916a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich                    (etc1_byte*) outB.getData());
917a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
918a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
919a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
920a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
921a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
922a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Decode a block of pixels.
923a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *
924a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param in an ETC1 compressed version of the data.
925a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *
926a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param out a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
927a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
928a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * value of pixel (x, y).
929a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
930a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void etc1_decodeBlock(JNIEnv *env, jclass clazz,
931a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject in, jobject out){
932a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper inB(env, in);
933a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper outB(env, out);
934a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (inB.checkPointer("in") && outB.checkPointer("out")) {
935a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (inB.remaining() < ETC1_ENCODED_BLOCK_SIZE) {
9368451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "in's remaining data < ENCODED_BLOCK_SIZE");
937a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else if (outB.remaining() < ETC1_DECODED_BLOCK_SIZE) {
9388451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "out's remaining data < DECODED_BLOCK_SIZE");
939a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
940a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            etc1_decode_block((etc1_byte*) inB.getData(),
941a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich                    (etc1_byte*) outB.getData());
942a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
943a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
944a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
945a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
946a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
947a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Return the size of the encoded image data (does not include size of PKM header).
948a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
949a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jint etc1_getEncodedDataSize(JNIEnv *env, jclass clazz,
950a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint width, jint height) {
951a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    return etc1_get_encoded_data_size(width, height);
952a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
953a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
954a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
955a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Encode an entire image.
956a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param in pointer to the image data. Formatted such that
957a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *           pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset;
958a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param out pointer to encoded data. Must be large enough to store entire encoded image.
959a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
960a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void etc1_encodeImage(JNIEnv *env, jclass clazz,
961a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject in, jint width, jint height,
962a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint pixelSize, jint stride, jobject out) {
963a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (pixelSize < 2 || pixelSize > 3) {
9648451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env, "pixelSize must be 2 or 3");
965a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        return;
966a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
967a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper inB(env, in);
968a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper outB(env, out);
969a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (inB.checkPointer("in") && outB.checkPointer("out")) {
970a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint imageSize = stride * height;
971a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint encodedImageSize = etc1_get_encoded_data_size(width, height);
972a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (inB.remaining() < imageSize) {
9738451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "in's remaining data < image size");
974a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else if (outB.remaining() < encodedImageSize) {
9758451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "out's remaining data < encoded image size");
976a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
9770f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe            etc1_encode_image((etc1_byte*) inB.getData(), width, height, pixelSize, stride,
9780f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe                              (etc1_byte*) outB.getData());
979a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
980a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
981a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
982a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
983a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
984a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Decode an entire image.
985a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param in the encoded data.
986a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param out pointer to the image data. Will be written such that
987a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *            pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
988a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich *            large enough to store entire image.
989a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
990a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void etc1_decodeImage(JNIEnv *env, jclass clazz,
991a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject  in, jobject out,
992a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint width, jint height,
993a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint pixelSize, jint stride) {
994a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (pixelSize < 2 || pixelSize > 3) {
9958451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env, "pixelSize must be 2 or 3");
996a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        return;
997a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
998a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper inB(env, in);
999a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper outB(env, out);
1000a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (inB.checkPointer("in") && outB.checkPointer("out")) {
1001a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint imageSize = stride * height;
1002a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jint encodedImageSize = etc1_get_encoded_data_size(width, height);
1003a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (inB.remaining() < encodedImageSize) {
10048451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "in's remaining data < encoded image size");
1005a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else if (outB.remaining() < imageSize) {
10068451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "out's remaining data < image size");
1007a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
10080f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe            etc1_decode_image((etc1_byte*) inB.getData(), (etc1_byte*) outB.getData(),
10090f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe                              width, height, pixelSize, stride);
1010a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
1011a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
1012a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
1013a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
1014a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
1015a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Format a PKM header
1016a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
1017a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic void etc1_formatHeader(JNIEnv *env, jclass clazz,
1018a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject header, jint width, jint height) {
1019a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper headerB(env, header);
1020a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (headerB.checkPointer("header") ){
1021a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
10228451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
1023a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
1024a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            etc1_pkm_format_header((etc1_byte*) headerB.getData(), width, height);
1025a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
1026a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
1027a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
1028a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
1029a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
1030a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Check if a PKM header is correctly formatted.
1031a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
1032a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jboolean etc1_isValid(JNIEnv *env, jclass clazz,
1033a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject header) {
1034a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jboolean result = false;
1035a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper headerB(env, header);
1036a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (headerB.checkPointer("header") ){
1037a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
10388451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
1039a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
1040a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            result = etc1_pkm_is_valid((etc1_byte*) headerB.getData());
1041a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
1042a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
104336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    return result ? JNI_TRUE : JNI_FALSE;
1044a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
1045a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
1046a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
1047a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Read the image width from a PKM header
1048a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
1049a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichstatic jint etc1_getWidth(JNIEnv *env, jclass clazz,
1050a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject header) {
1051a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jint result = 0;
1052a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper headerB(env, header);
1053a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (headerB.checkPointer("header") ){
1054a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
10558451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
1056a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        } else {
1057a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich            result = etc1_pkm_get_width((etc1_byte*) headerB.getData());
1058a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        }
1059a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    }
1060a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    return result;
1061a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich}
1062a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich
1063a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/**
1064a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Read the image height from a PKM header
1065a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */
106636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatstatic jint etc1_getHeight(JNIEnv *env, jclass clazz,
1067a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich        jobject header) {
1068a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    jint result = 0;
1069a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    BufferHelper headerB(env, header);
1070a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich    if (headerB.checkPointer("header") ){
1071