1**
2** Copyright 2006, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8**     http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17// This source file is automatically generated
18
19#pragma GCC diagnostic ignored "-Wunused-variable"
20#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
21#pragma GCC diagnostic ignored "-Wunused-function"
22
23#include "jni.h"
24#include "JNIHelp.h"
25#include <android_runtime/AndroidRuntime.h>
26#include <utils/misc.h>
27
28#include <assert.h>
29#include <GLES/gl.h>
30#include <GLES/glext.h>
31
32// Work around differences between the generated name and the actual name.
33
34#define glBlendEquation glBlendEquationOES
35#define glBlendEquationSeparate glBlendEquationSeparateOES
36#define glBlendFuncSeparate glBlendFuncSeparateOES
37#define glGetTexGenfv glGetTexGenfvOES
38#define glGetTexGeniv glGetTexGenivOES
39#define glGetTexGenxv glGetTexGenxvOES
40#define glTexGenf glTexGenfOES
41#define glTexGenfv glTexGenfvOES
42#define glTexGeni glTexGeniOES
43#define glTexGeniv glTexGenivOES
44#define glTexGenx glTexGenxOES
45#define glTexGenxv glTexGenxvOES
46
47
48
49/* special calls implemented in Android's GLES wrapper used to more
50 * efficiently bound-check passed arrays */
51extern "C" {
52GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
53        const GLvoid *ptr, GLsizei count);
54GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
55        const GLvoid *pointer, GLsizei count);
56GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
57        GLsizei stride, const GLvoid *pointer, GLsizei count);
58GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
59        GLsizei stride, const GLvoid *pointer, GLsizei count);
60GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
61        GLsizei stride, const GLvoid *pointer, GLsizei count);
62GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
63        GLsizei stride, const GLvoid *pointer, GLsizei count);
64GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
65        GLsizei stride, const GLvoid *pointer, GLsizei count);
66}
67
68static int initialized = 0;
69
70static jclass nioAccessClass;
71static jclass bufferClass;
72static jclass G11ImplClass;
73static jmethodID getBasePointerID;
74static jmethodID getBaseArrayID;
75static jmethodID getBaseArrayOffsetID;
76static jmethodID allowIndirectBuffersID;
77static jfieldID positionID;
78static jfieldID limitID;
79static jfieldID elementSizeShiftID;
80static jfieldID haveCheckedExtensionsID;
81static jfieldID have_OES_blend_equation_separateID;
82static jfieldID have_OES_blend_subtractID;
83static jfieldID have_OES_framebuffer_objectID;
84static jfieldID have_OES_texture_cube_mapID;
85
86/* Cache method IDs each time the class is loaded. */
87
88static void
89nativeClassInit(JNIEnv *_env, jclass glImplClass)
90{
91    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
92    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
93
94    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
95    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
96
97    jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
98    G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
99    haveCheckedExtensionsID =  _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
100    have_OES_blend_equation_separateID =  _env->GetFieldID(G11ImplClass, "have_OES_blend_equation_separate", "Z");
101    have_OES_blend_subtractID =  _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
102    have_OES_framebuffer_objectID =  _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
103    have_OES_texture_cube_mapID =  _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
104
105    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
106            "getBasePointer", "(Ljava/nio/Buffer;)J");
107    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
108            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
109    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
110            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
111    allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
112            "allowIndirectBuffers", "(Ljava/lang/String;)Z");
113    positionID = _env->GetFieldID(bufferClass, "position", "I");
114    limitID = _env->GetFieldID(bufferClass, "limit", "I");
115    elementSizeShiftID =
116        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
117}
118
119static void *
120getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
121{
122    jint position;
123    jint limit;
124    jint elementSizeShift;
125    jlong pointer;
126
127    position = _env->GetIntField(buffer, positionID);
128    limit = _env->GetIntField(buffer, limitID);
129    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
130    *remaining = (limit - position) << elementSizeShift;
131    pointer = _env->CallStaticLongMethod(nioAccessClass,
132            getBasePointerID, buffer);
133    if (pointer != 0L) {
134        *offset = 0;
135        *array = NULL;
136        return reinterpret_cast<void *>(pointer);
137    }
138
139    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
140            getBaseArrayID, buffer);
141    if (*array == NULL) {
142        *offset = 0;
143        return (void*) NULL;
144    }
145    *offset = _env->CallStaticIntMethod(nioAccessClass,
146            getBaseArrayOffsetID, buffer);
147
148    return NULL;
149}
150
151static void
152releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
153{
154    _env->ReleasePrimitiveArrayCritical(array, data,
155					   commit ? 0 : JNI_ABORT);
156}
157
158extern "C" {
159extern char*  __progname;
160}
161
162static bool
163allowIndirectBuffers(JNIEnv *_env) {
164    static jint sIndirectBufferCompatability;
165    if (sIndirectBufferCompatability == 0) {
166        jobject appName = _env->NewStringUTF(::__progname);
167        sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
168    }
169    return sIndirectBufferCompatability == 2;
170}
171
172static void *
173getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
174    if (!buffer) {
175        return NULL;
176    }
177    void* buf = _env->GetDirectBufferAddress(buffer);
178    if (buf) {
179        jint position = _env->GetIntField(buffer, positionID);
180        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
181        buf = ((char*) buf) + (position << elementSizeShift);
182    } else {
183        if (allowIndirectBuffers(_env)) {
184            jarray array = 0;
185            jint remaining;
186            jint offset;
187            buf = getPointer(_env, buffer, &array, &remaining, &offset);
188            if (array) {
189                releasePointer(_env, array, buf, 0);
190            }
191            buf = (char*)buf + offset;
192        } else {
193            jniThrowException(_env, "java/lang/IllegalArgumentException",
194                              "Must use a native order direct Buffer");
195        }
196    }
197    return buf;
198}
199
200static int
201getNumCompressedTextureFormats() {
202    int numCompressedTextureFormats = 0;
203    glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedTextureFormats);
204    return numCompressedTextureFormats;
205}
206
207// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
208// terminated by either 0 or space, while pExtension is terminated by 0.
209
210static bool
211extensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
212    while (true) {
213        char a = *pExtensions++;
214        char b = *pExtension++;
215        bool aEnd = a == '\0' || a == ' ';
216        bool bEnd = b == '\0';
217        if ( aEnd || bEnd) {
218            return aEnd == bEnd;
219        }
220        if ( a != b ) {
221            return false;
222        }
223    }
224}
225
226static const GLubyte*
227nextExtension(const GLubyte* pExtensions) {
228    while (true) {
229        char a = *pExtensions++;
230        if ( a == '\0') {
231            return pExtensions-1;
232        } else if ( a == ' ') {
233            return pExtensions;
234        }
235    }
236}
237
238static bool
239checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
240    for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
241        if (extensionEqual(pExtensions, pExtension)) {
242            return true;
243        }
244    }
245    return false;
246}
247
248static bool
249supportsExtension(JNIEnv *_env, jobject impl, jfieldID fieldId) {
250    if (!_env->GetBooleanField(impl, haveCheckedExtensionsID)) {
251        _env->SetBooleanField(impl, haveCheckedExtensionsID, true);
252        const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
253        _env->SetBooleanField(impl, have_OES_blend_equation_separateID,
254            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_equation_separate"));
255        _env->SetBooleanField(impl, have_OES_blend_subtractID,
256            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_subtract"));
257        _env->SetBooleanField(impl, have_OES_framebuffer_objectID,
258            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_framebuffer_object"));
259        _env->SetBooleanField(impl, have_OES_texture_cube_mapID,
260            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_texture_cube_map"));
261    }
262    return _env->GetBooleanField(impl, fieldId);
263}
264
265// --------------------------------------------------------------------------
266