util.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** Copyright 2007, The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **     http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project **
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ** 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
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <nativehelper/jni.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <math.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dlfcn.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/gl.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <core/SkBitmap.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h"
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "OpenGLUtil"
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h"
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "poly.h"
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gIAEClass;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gUOEClass;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass MallocHelper {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MallocHelper() {
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mData = 0;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~MallocHelper() {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mData != 0) {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            free(mData);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* alloc(size_t size) {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mData = malloc(size);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mData;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* mData;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprint_poly(const char* label, Poly* pPoly) {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGI("%s: %d verts", label, pPoly->n);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < pPoly->n; i++) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Poly_vert* pV = & pPoly->vert[i];
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGI("[%d] %g, %g, %g %g", i, pV->sx, pV->sy, pV->sz, pV->sw);
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint visibilityTest(float* pWS, float* pPositions, int positionsLength,
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unsigned short* pIndices, int indexCount) {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MallocHelper mallocHelper;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result = POLY_CLIP_OUT;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pTransformed = 0;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int transformedIndexCount = 0;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( indexCount < 3 ) {
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return POLY_CLIP_OUT;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Find out how many vertices we need to transform
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We transform every vertex between the min and max indices, inclusive.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This is OK for the data sets we expect to use with this function, but
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for other loads it might be better to use a more sophisticated vertex
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // cache of some sort.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int minIndex = 65536;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int maxIndex = -1;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < indexCount; i++) {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int index = pIndices[i];
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( index < minIndex ) {
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            minIndex = index;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( index > maxIndex ) {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            maxIndex = index;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( maxIndex * 3 > positionsLength) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    transformedIndexCount = maxIndex - minIndex + 1;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pTransformed = (float*) mallocHelper.alloc(transformedIndexCount * 4 * sizeof(float));
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pTransformed == 0 ) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -2;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Transform the vertices
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const float* pSrc = pPositions + 3 * minIndex;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float* pDst = pTransformed;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < transformedIndexCount; i++, pSrc += 3, pDst += 4) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mx4transform(pSrc[0], pSrc[1], pSrc[2], 1.0f, pWS,  pDst);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Clip the triangles
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Poly poly;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pDest = & poly.vert[0].sx;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < indexCount; i += 3) {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        poly.n = 3;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(pDest    , pTransformed + 4 * (pIndices[i    ] - minIndex), 4 * sizeof(float));
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(pDest + 4, pTransformed + 4 * (pIndices[i + 1] - minIndex), 4 * sizeof(float));
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(pDest + 8, pTransformed + 4 * (pIndices[i + 2] - minIndex), 4 * sizeof(float));
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = poly_clip_to_frustum(&poly);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( result != POLY_CLIP_OUT) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<class JArray, class T>
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass ArrayHelper {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayHelper(JNIEnv* env, JArray ref, jint offset, jint minSize) {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnv = env;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRef = ref;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOffset = offset;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMinSize = minSize;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBase = 0;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mReleaseParam = JNI_ABORT;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~ArrayHelper() {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBase) {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnv->ReleasePrimitiveArrayCritical(mRef, mBase, mReleaseParam);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We seperate the bounds check from the initialization because we want to
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // be able to bounds-check multiple arrays, and we can't throw an exception
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // after we've called GetPrimitiveArrayCritical.
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Return true if the bounds check succeeded
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Else instruct the runtime to throw an exception
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool check() {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( ! mRef) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnv->ThrowNew(gIAEClass, "array == null");
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( mOffset < 0) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnv->ThrowNew(gIAEClass, "offset < 0");
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLength = mEnv->GetArrayLength(mRef) - mOffset;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLength < mMinSize ) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnv->ThrowNew(gIAEClass, "length - offset < n");
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Bind the array.
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void bind() {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBase = (T*) mEnv->GetPrimitiveArrayCritical(mRef, (jboolean *) 0);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mData = mBase + mOffset;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void commitChanges() {
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mReleaseParam = 0;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    T* mData;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLength;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    T* mBase;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    JNIEnv* mEnv;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    JArray mRef;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jint mOffset;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jint mMinSize;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mReleaseParam;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef ArrayHelper<jfloatArray, float> FloatArrayHelper;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef ArrayHelper<jcharArray, unsigned short> UnsignedShortArrayHelper;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef ArrayHelper<jintArray, int> IntArrayHelper;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef ArrayHelper<jbyteArray, unsigned char> ByteArrayHelper;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectinline float distance2(float x, float y, float z) {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return x * x + y * y + z * z;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectinline float distance(float x, float y, float z) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return sqrtf(distance2(x, y, z));
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid util_computeBoundingSphere(JNIEnv *env, jclass clazz,
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray positions_ref, jint positionsOffset, jint positionsCount,
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray sphere_ref, jint sphereOffset) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper sphere(env, sphere_ref, sphereOffset, 4);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = positions.check() && sphere.check();
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (! checkOK) {
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    positions.bind();
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sphere.bind();
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( positionsCount < 1 ) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->ThrowNew(gIAEClass, "positionsCount < 1");
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const float* pSrc = positions.mData;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // find bounding box
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float x0 = *pSrc++;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float x1 = x0;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float y0 = *pSrc++;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float y1 = y0;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float z0 = *pSrc++;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float z1 = z0;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 1; i < positionsCount; i++) {
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = *pSrc++;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (x < x0) {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                x0 = x;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (x > x1) {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                x1 = x;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = *pSrc++;
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (y < y0) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                y0 = y;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (y > y1) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                y1 = y;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = *pSrc++;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (z < z0) {
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                z0 = z;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (z > z1) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                z1 = z;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Because we know our input meshes fit pretty well into bounding boxes,
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // just take the diagonal of the box as defining our sphere.
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pSphere = sphere.mData;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float dx = x1 - x0;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float dy = y1 - y0;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float dz = z1 - z0;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = x0 + dx * 0.5f;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = y0 + dy * 0.5f;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = z0 + dz * 0.5f;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pSphere++ = distance(dx, dy, dz) * 0.5f;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sphere.commitChanges();
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void normalizePlane(float* p) {
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float rdist = 1.0f / distance(p[0], p[1], p[2]);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < 4; i++) {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p[i] *= rdist;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline float dot3(float x0, float y0, float z0, float x1, float y1, float z1) {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return x0 * x1 + y0 * y1 + z0 * z1;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline float signedDistance(const float* pPlane, float x, float y, float z) {
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return dot3(pPlane[0], pPlane[1], pPlane[2], x, y, z) + pPlane[3];
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Return true if the sphere intersects or is inside the frustum
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool sphereHitsFrustum(const float* pFrustum, const float* pSphere) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float x = pSphere[0];
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float y = pSphere[1];
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float z = pSphere[2];
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float negRadius = -pSphere[3];
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < 6; i++, pFrustum += 4) {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (signedDistance(pFrustum, x, y, z) <= negRadius) {
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void computeFrustum(const float* m, float* f) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m3 = m[3];
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m7 = m[7];
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m11 = m[11];
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float m15 = m[15];
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // right
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  - m[0];
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  - m[4];
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 - m[8];
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 - m[12];
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // left
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  + m[0];
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  + m[4];
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 + m[8];
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 + m[12];
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // top
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  - m[1];
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  - m[5];
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 - m[9];
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 - m[13];
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // bottom
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  + m[1];
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  + m[5];
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 + m[9];
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 + m[13];
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // far
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  - m[2];
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  - m[6];
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 - m[10];
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 - m[14];
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f+= 4;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // near
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[0] = m3  + m[2];
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[1] = m7  + m[6];
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[2] = m11 + m[10];
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    f[3] = m15 + m[14];
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    normalizePlane(f);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint util_frustumCullSpheres(JNIEnv *env, jclass clazz,
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray mvp_ref, jint mvpOffset,
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray spheres_ref, jint spheresOffset, jint spheresCount,
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jintArray results_ref, jint resultsOffset, jint resultsCapacity) {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float frustum[6*4];
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int outputCount;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int* pResults;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* pSphere;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper mvp(env, mvp_ref, mvpOffset, 16);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper spheres(env, spheres_ref, spheresOffset, spheresCount * 4);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IntArrayHelper results(env, results_ref, resultsOffset, resultsCapacity);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool initializedOK = mvp.check() && spheres.check() && results.check();
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (! initializedOK) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mvp.bind();
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    spheres.bind();
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    results.bind();
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    computeFrustum(mvp.mData, frustum);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Cull the spheres
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pSphere = spheres.mData;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pResults = results.mData;
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    outputCount = 0;
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(int i = 0; i < spheresCount; i++, pSphere += 4) {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sphereHitsFrustum(frustum, pSphere)) {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outputCount < resultsCapacity) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *pResults++ = i;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outputCount++;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    results.commitChanges();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return outputCount;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public native int visibilityTest(float[] ws, int wsOffset,
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float[] positions, int positionsOffset,
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] indices, int indicesOffset, int indexCount);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint util_visibilityTest(JNIEnv *env, jclass clazz,
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray ws_ref, jint wsOffset,
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jfloatArray positions_ref, jint positionsOffset,
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jcharArray indices_ref, jint indicesOffset, jint indexCount) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper ws(env, ws_ref, wsOffset, 16);
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    UnsignedShortArrayHelper indices(env, indices_ref, indicesOffset, 0);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = ws.check() && positions.check() && indices.check();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (! checkOK) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Return value will be ignored, because an exception has been thrown.
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (indices.mLength < indexCount) {
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->ThrowNew(gIAEClass, "length < offset + indexCount");
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Return value will be ignored, because an exception has been thrown.
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ws.bind();
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    positions.bind();
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    indices.bind();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return visibilityTest(ws.mData,
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            positions.mData, positions.mLength,
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            indices.mData, indexCount);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define I(_i, _j) ((_j)+ 4*(_i))
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid multiplyMM(float* r, const float* lhs, const float* rhs)
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        register const float rhs_i0 = rhs[ I(i,0) ];
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        register float ri0 = lhs[ I(0,0) ] * rhs_i0;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        register float ri1 = lhs[ I(0,1) ] * rhs_i0;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        register float ri2 = lhs[ I(0,2) ] * rhs_i0;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        register float ri3 = lhs[ I(0,3) ] * rhs_i0;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=1 ; j<4 ; j++) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register const float rhs_ij = rhs[ I(i,j) ];
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri0 += lhs[ I(j,0) ] * rhs_ij;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri1 += lhs[ I(j,1) ] * rhs_ij;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri2 += lhs[ I(j,2) ] * rhs_ij;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ri3 += lhs[ I(j,3) ] * rhs_ij;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,0) ] = ri0;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,1) ] = ri1;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,2) ] = ri2;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r[ I(i,3) ] = ri3;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid util_multiplyMM(JNIEnv *env, jclass clazz,
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray result_ref, jint resultOffset,
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray lhs_ref, jint lhsOffset,
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray rhs_ref, jint rhsOffset) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper resultMat(env, result_ref, resultOffset, 16);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = resultMat.check() && lhs.check() && rhs.check();
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( !checkOK ) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultMat.bind();
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lhs.bind();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    rhs.bind();
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    multiplyMM(resultMat.mData, lhs.mData, rhs.mData);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultMat.commitChanges();
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid multiplyMV(float* r, const float* lhs, const float* rhs)
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid util_multiplyMV(JNIEnv *env, jclass clazz,
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray result_ref, jint resultOffset,
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray lhs_ref, jint lhsOffset,
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfloatArray rhs_ref, jint rhsOffset) {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper resultV(env, result_ref, resultOffset, 4);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4);
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool checkOK = resultV.check() && lhs.check() && rhs.check();
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ( !checkOK ) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultV.bind();
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lhs.bind();
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    rhs.bind();
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    multiplyMV(resultV.mData, lhs.mData, rhs.mData);
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    resultV.commitChanges();
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativeBitmapID = 0;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid nativeUtilsClassInit(JNIEnv *env, jclass clazz)
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    nativeBitmapID = env->GetFieldID(bitmapClass, "mNativeBitmap", "I");
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int checkFormat(SkBitmap::Config config, int format, int type)
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    switch(config) {
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kIndex8_Config:
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (format == GL_PALETTE8_RGBA8_OES)
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kARGB_8888_Config:
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kA8_Config:
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type == GL_UNSIGNED_BYTE)
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kARGB_4444_Config:
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kRGB_565_Config:
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (type) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_SHORT_4_4_4_4:
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_SHORT_5_6_5:
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_SHORT_5_5_5_1:
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return 0;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case GL_UNSIGNED_BYTE:
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (format == GL_LUMINANCE_ALPHA)
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return 0;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int getInternalFormat(SkBitmap::Config config)
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    switch(config) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kA8_Config:
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_ALPHA;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kARGB_4444_Config:
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_RGBA;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kARGB_8888_Config:
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_RGBA;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kIndex8_Config:
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_PALETTE8_RGBA8_OES;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case SkBitmap::kRGB_565_Config:
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return GL_RGB;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint util_texImage2D(JNIEnv *env, jclass clazz,
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint target, jint level, jint internalformat,
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jobject jbitmap, jint type, jint border)
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkBitmap const * nativeBitmap =
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID);
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkBitmap& bitmap(*nativeBitmap);
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkBitmap::Config config = bitmap.getConfig();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (internalformat < 0) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        internalformat = getInternalFormat(config);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int err = checkFormat(config, internalformat, type);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err)
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return err;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.lockPixels();
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int w = bitmap.width();
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int h = bitmap.height();
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* p = bitmap.getPixels();
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (internalformat == GL_PALETTE8_RGBA8_OES) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sizeof(SkPMColor) != sizeof(uint32_t)) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            err = -1;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto error;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t size = bitmap.getSize();
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t palette_size = 256*sizeof(SkPMColor);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void* const data = malloc(size + palette_size);
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (data) {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            void* const pixels = (char*)data + palette_size;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SkColorTable* ctable = bitmap.getColorTable();
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            memcpy(data, ctable->lockColors(), ctable->count() * sizeof(SkPMColor));
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            memcpy(pixels, p, size);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ctable->unlockColors(false);
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glCompressedTexImage2D(target, level, internalformat, w, h, border, 0, data);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            free(data);
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            err = -1;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexImage2D(target, level, internalformat, w, h, border, internalformat, type, p);
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecterror:
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.unlockPixels();
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return err;
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint util_texSubImage2D(JNIEnv *env, jclass clazz,
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint target, jint level, jint xoffset, jint yoffset,
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jobject jbitmap, jint format, jint type)
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkBitmap const * nativeBitmap =
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkBitmap& bitmap(*nativeBitmap);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkBitmap::Config config = bitmap.getConfig();
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (format < 0) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        format = getInternalFormat(config);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (format == GL_PALETTE8_RGBA8_OES)
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1; // glCompressedTexSubImage2D() not supported
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int err = checkFormat(config, format, type);
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err)
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return err;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.lockPixels();
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int w = bitmap.width();
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int h = bitmap.height();
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* p = bitmap.getPixels();
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexSubImage2D(target, level, xoffset, yoffset, w, h, format, type, p);
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.unlockPixels();
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectlookupClasses(JNIEnv* env) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gIAEClass = (jclass) env->NewGlobalRef(
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->FindClass("java/lang/IllegalArgumentException"));
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gUOEClass = (jclass) env->NewGlobalRef(
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->FindClass("java/lang/UnsupportedOperationException"));
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMatrixMethods[] = {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gVisiblityMethods[] = {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest },
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gUtilsMethods[] = {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"nativeClassInit", "()V",                          (void*)nativeUtilsClassInit },
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D },
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef struct _ClassRegistrationInfo {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* classPath;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    JNINativeMethod* methods;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t methodCount;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} ClassRegistrationInfo;
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic ClassRegistrationInfo gClasses[] = {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {"android/opengl/Visibility", gVisiblityMethods, NELEM(gVisiblityMethods)},
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_opengl_classes(JNIEnv* env)
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lookupClasses(env);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result = 0;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gClasses); i++) {
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClassRegistrationInfo* cri = &gClasses[i];
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = AndroidRuntime::registerNativeMethods(env,
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cri->classPath, cri->methods, cri->methodCount);
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result < 0) {
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Failed to register %s: %d", cri->classPath, result);
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
731