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