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