blob: e8691bb7f8dd1f36fad5639c7ae70296f6d12703 [file] [log] [blame]
Kenny Rootbd393b72010-03-11 18:20:12 -08001/*
2 * Copyright (C) 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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017import java.io.PrintStream;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080018import java.util.ArrayList;
19import java.util.HashSet;
20import java.util.Iterator;
21import java.util.List;
22
Jack Palevichffac1ef2009-04-14 19:00:09 -070023public class JniCodeEmitter {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080024
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025 static final boolean mUseCPlusPlus = true;
Jack Palevichffac1ef2009-04-14 19:00:09 -070026 protected boolean mUseContextPointer = true;
Jack Palevich427f5852009-04-15 19:13:17 -070027 protected boolean mUseStaticMethods = false;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -070028 protected boolean mUseSimpleMethodNames = false;
29 protected boolean mUseHideCommentForAPI = false;
Jack Palevichffac1ef2009-04-14 19:00:09 -070030 protected String mClassPathName;
31 protected ParameterChecker mChecker;
32 protected List<String> nativeRegistrations = new ArrayList<String>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033 boolean needsExit;
Jack Palevichffac1ef2009-04-14 19:00:09 -070034 protected static String indent = " ";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080035 HashSet<String> mFunctionsEmitted = new HashSet<String>();
36
Jack Palevichffac1ef2009-04-14 19:00:09 -070037 public static String getJniName(JType jType) {
38 String jniName = "";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -070039 if (jType.isEGLHandle()) {
40 return (jType.isArray() ? "[" : "" ) + "Landroid/opengl/" + jType.getBaseType() + ";";
41 } else if (jType.isClass()) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070042 return "L" + jType.getBaseType() + ";";
43 } else if (jType.isArray()) {
44 jniName = "[";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080045 }
Jack Palevichffac1ef2009-04-14 19:00:09 -070046
47 String baseType = jType.getBaseType();
48 if (baseType.equals("int")) {
49 jniName += "I";
50 } else if (baseType.equals("float")) {
51 jniName += "F";
52 } else if (baseType.equals("boolean")) {
53 jniName += "Z";
54 } else if (baseType.equals("short")) {
55 jniName += "S";
56 } else if (baseType.equals("long")) {
Andy McFadden72841452013-03-01 16:25:32 -080057 jniName += "J";
Jack Palevichffac1ef2009-04-14 19:00:09 -070058 } else if (baseType.equals("byte")) {
59 jniName += "B";
Jack Palevich50d0b142009-11-19 16:34:55 +080060 } else if (baseType.equals("String")) {
61 jniName += "Ljava/lang/String;";
62 } else if (baseType.equals("void")) {
63 // nothing.
64 } else {
Elliott Hughes98757502011-04-08 20:01:01 -070065 throw new RuntimeException("Unknown primitive basetype " + baseType);
Jack Palevichffac1ef2009-04-14 19:00:09 -070066 }
67 return jniName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080068 }
69
Jack Palevichffac1ef2009-04-14 19:00:09 -070070 public void emitCode(CFunc cfunc, String original,
71 PrintStream javaInterfaceStream,
72 PrintStream javaImplStream,
73 PrintStream cStream) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080074 JFunc jfunc;
75 String signature;
76 boolean duplicate;
Jack Palevich6cbca502009-04-13 16:22:25 -070077
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080078 if (cfunc.hasTypedPointerArg()) {
79 jfunc = JFunc.convert(cfunc, true);
80
81 // Don't emit duplicate functions
82 // These may appear because they are defined in multiple
83 // Java interfaces (e.g., GL11/GL11ExtensionPack)
84 signature = jfunc.toString();
85 duplicate = false;
86 if (mFunctionsEmitted.contains(signature)) {
87 duplicate = true;
88 } else {
89 mFunctionsEmitted.add(signature);
90 }
91
92 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070093 emitNativeDeclaration(jfunc, javaImplStream);
94 emitJavaCode(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080095 }
Jack Palevich427f5852009-04-15 19:13:17 -070096 if (javaInterfaceStream != null) {
97 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
98 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080099 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700100 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800101 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700102 // Don't create IOBuffer versions of the EGL functions
103 if (cfunc.hasEGLHandleArg()) {
104 return;
105 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800106 }
107
108 jfunc = JFunc.convert(cfunc, false);
109
110 signature = jfunc.toString();
111 duplicate = false;
112 if (mFunctionsEmitted.contains(signature)) {
113 duplicate = true;
114 } else {
115 mFunctionsEmitted.add(signature);
116 }
117
118 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700119 emitNativeDeclaration(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800120 }
Jack Palevich427f5852009-04-15 19:13:17 -0700121 if (javaInterfaceStream != null) {
122 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
123 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800124 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700125 emitJavaCode(jfunc, javaImplStream);
126 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800127 }
128 }
129
130 public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700131 if (mUseHideCommentForAPI) {
132 out.println(" /* @hide C function " + jfunc.getCFunc().getOriginal() + " */");
133 out.println();
134 } else {
135 out.println(" // C function " + jfunc.getCFunc().getOriginal());
136 out.println();
137 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800138
139 emitFunction(jfunc, out, true, false);
140 }
141
142 public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
143 emitFunction(jfunc, out, false, true);
144 }
145
146 public void emitJavaCode(JFunc jfunc, PrintStream out) {
147 emitFunction(jfunc, out, false, false);
148 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700149
Jack Palevich66089a32009-12-08 15:43:51 +0800150 boolean isPointerFunc(JFunc jfunc) {
151 String name = jfunc.getName();
152 return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
153 && jfunc.getCFunc().hasPointerArg();
154 }
155
Jack Palevichffac1ef2009-04-14 19:00:09 -0700156 void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800157 boolean isVoid = jfunc.getType().isVoid();
Jack Palevich66089a32009-12-08 15:43:51 +0800158 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800159
160 if (!isVoid) {
161 out.println(iii +
162 jfunc.getType() + " _returnValue;");
163 }
164 out.println(iii +
165 (isVoid ? "" : "_returnValue = ") +
166 jfunc.getName() +
167 (isPointerFunc ? "Bounds" : "" ) +
168 "(");
Jack Palevich6cbca502009-04-13 16:22:25 -0700169
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800170 int numArgs = jfunc.getNumArgs();
171 for (int i = 0; i < numArgs; i++) {
172 String argName = jfunc.getArgName(i);
173 JType argType = jfunc.getArgType(i);
174
175 if (grabArray && argType.isTypedBuffer()) {
176 String typeName = argType.getBaseType();
177 typeName = typeName.substring(9, typeName.length() - 6);
178 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
Jack Palevich6cbca502009-04-13 16:22:25 -0700179 out.print(iii + indent + "getOffset(" + argName + ")");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180 } else {
181 out.print(iii + indent + argName);
182 }
183 if (i == numArgs - 1) {
184 if (isPointerFunc) {
185 out.println(",");
186 out.println(iii + indent + argName + ".remaining()");
187 } else {
188 out.println();
189 }
190 } else {
191 out.println(",");
192 }
193 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700194
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800195 out.println(iii + ");");
196 }
197
Jack Palevichffac1ef2009-04-14 19:00:09 -0700198 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
199 String iii) {
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800200 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
201 "offset", "_remaining", iii);
202 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203
Jack Palevichffac1ef2009-04-14 19:00:09 -0700204 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
205 String offset, String remaining, String iii) {
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800206 out.println(iii + " default:");
207 out.println(iii + " _needed = 1;");
208 out.println(iii + " break;");
209 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800211 out.println(iii + "if (" + remaining + " < _needed) {");
212 out.println(iii + indent + "_exception = 1;");
213 out.println(iii + indent +
214 "_exceptionType = \"java/lang/IllegalArgumentException\";");
215 out.println(iii + indent +
216 "_exceptionMessage = \"" +
217 (isBuffer ? "remaining()" : "length - " + offset) +
218 " < needed\";");
219 out.println(iii + indent + "goto exit;");
220 out.println(iii + "}");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700221
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800222 needsExit = true;
223 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700225 boolean isNullAllowed(CFunc cfunc, String cname) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226 String[] checks = mChecker.getChecks(cfunc.getName());
227 int index = 1;
228 if (checks != null) {
229 while (index < checks.length) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700230 if (checks[index].equals("nullAllowed") &&
231 checks[index + 1].equals(cname)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800232 return true;
233 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700234 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800235 }
236 }
237 }
238 return false;
239 }
240
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700241 boolean hasCheckTest(CFunc cfunc) {
242 String[] checks = mChecker.getChecks(cfunc.getName());
243 int index = 1;
244 if (checks != null) {
245 while (index < checks.length) {
246 if (checks[index].startsWith("check")) {
247 return true;
248 } else {
249 index = skipOneCheck(checks, index);
250 }
251 }
252 }
253 return false;
254 }
255
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700256 boolean hasCheckTest(CFunc cfunc, String cname) {
257 String[] checks = mChecker.getChecks(cfunc.getName());
258 int index = 1;
259 if (checks != null) {
260 while (index < checks.length) {
261 if (checks[index].startsWith("check") &&
262 cname != null && cname.equals(checks[index + 1])) {
263 return true;
264 } else {
265 index = skipOneCheck(checks, index);
266 }
267 }
268 }
269 return false;
270 }
271
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700272 boolean hasIfTest(CFunc cfunc) {
273 String[] checks = mChecker.getChecks(cfunc.getName());
274 int index = 1;
275 if (checks != null) {
276 while (index < checks.length) {
277 if (checks[index].startsWith("ifcheck")) {
278 return true;
279 } else {
280 index = skipOneCheck(checks, index);
281 }
282 }
283 }
284 return false;
285 }
286
287 int skipOneCheck(String[] checks, int index) {
288 if (checks[index].equals("return")) {
289 index += 2;
290 } else if (checks[index].startsWith("check")) {
291 index += 3;
292 } else if (checks[index].startsWith("sentinel")) {
293 index += 3;
294 } else if (checks[index].equals("ifcheck")) {
295 index += 5;
296 } else if (checks[index].equals("unsupported")) {
297 index += 1;
298 } else if (checks[index].equals("requires")) {
299 index += 2;
300 } else if (checks[index].equals("nullAllowed")) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700301 index += 2;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700302 } else {
303 System.out.println("Error: unknown keyword \"" +
304 checks[index] + "\"");
305 System.exit(0);
306 }
307
308 return index;
309 }
310
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800311 String getErrorReturnValue(CFunc cfunc) {
312 CType returnType = cfunc.getType();
313 boolean isVoid = returnType.isVoid();
314 if (isVoid) {
315 return null;
316 }
317
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700318 if (returnType.getBaseType().startsWith("EGL")) {
319 return "(" + returnType.getDeclaration() + ") 0";
320 }
321
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800322 String[] checks = mChecker.getChecks(cfunc.getName());
323
324 int index = 1;
325 if (checks != null) {
326 while (index < checks.length) {
327 if (checks[index].equals("return")) {
328 return checks[index + 1];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800329 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700330 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800331 }
332 }
333 }
334
335 return null;
336 }
337
338 boolean isUnsupportedFunc(CFunc cfunc) {
339 String[] checks = mChecker.getChecks(cfunc.getName());
340 int index = 1;
341 if (checks != null) {
342 while (index < checks.length) {
343 if (checks[index].equals("unsupported")) {
344 return true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800345 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700346 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800347 }
348 }
349 }
350 return false;
351 }
Elliott Hughes98757502011-04-08 20:01:01 -0700352
Jack Paleviche44e45c2010-01-28 20:28:32 +0800353 String isRequiresFunc(CFunc cfunc) {
354 String[] checks = mChecker.getChecks(cfunc.getName());
355 int index = 1;
356 if (checks != null) {
357 while (index < checks.length) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700358 if (checks[index].equals("requires")) {
Jack Paleviche44e45c2010-01-28 20:28:32 +0800359 return checks[index+1];
Jack Paleviche44e45c2010-01-28 20:28:32 +0800360 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700361 index = skipOneCheck(checks, index);
Jack Paleviche44e45c2010-01-28 20:28:32 +0800362 }
363 }
364 }
365 return null;
366 }
Elliott Hughes98757502011-04-08 20:01:01 -0700367
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800368 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700369 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800370
Elliott Hughes98757502011-04-08 20:01:01 -0700371 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800372
Elliott Hughes98757502011-04-08 20:01:01 -0700373 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800374
Elliott Hughes98757502011-04-08 20:01:01 -0700375 int index = 1;
376 if (checks != null) {
377 while (index < checks.length) {
378 if (checks[index].startsWith("check")) {
379 if (lastWasIfcheck) {
380 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
381 offset, remaining, iii);
382 }
383 lastWasIfcheck = false;
384 if (cname != null && !cname.equals(checks[index + 1])) {
385 index += 3;
386 continue;
387 }
388 out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700389 out.println(iii + indent + "_exception = 1;");
Elliott Hughes98757502011-04-08 20:01:01 -0700390 String exceptionClassName = "java/lang/IllegalArgumentException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700391 // If the "check" keyword was of the form
392 // "check_<class name>", use the class name in the
393 // exception to be thrown
394 int underscore = checks[index].indexOf('_');
395 if (underscore >= 0) {
Elliott Hughes98757502011-04-08 20:01:01 -0700396 String abbr = checks[index].substring(underscore + 1);
397 if (abbr.equals("AIOOBE")) {
398 exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700399 } else {
Elliott Hughes98757502011-04-08 20:01:01 -0700400 throw new RuntimeException("unknown exception abbreviation: " + abbr);
Jack Palevichffac1ef2009-04-14 19:00:09 -0700401 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800402 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700403 out.println(iii + indent +
404 "_exceptionType = \""+exceptionClassName+"\";");
405 out.println(iii + indent +
406 "_exceptionMessage = \"" +
407 (isBuffer ? "remaining()" : "length - " +
408 offset) + " < " + checks[index + 2] +
409 " < needed\";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800410
Elliott Hughes98757502011-04-08 20:01:01 -0700411 out.println(iii + indent + "goto exit;");
Elliott Hughes98757502011-04-08 20:01:01 -0700412 out.println(iii + "}");
413
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700414 needsExit = true;
415
Elliott Hughes98757502011-04-08 20:01:01 -0700416 index += 3;
417 } else if (checks[index].equals("ifcheck")) {
418 String[] matches = checks[index + 4].split(",");
419
420 if (!lastWasIfcheck) {
421 out.println(iii + "int _needed;");
422 out.println(iii + "switch (" + checks[index + 3] + ") {");
423 }
424
425 for (int i = 0; i < matches.length; i++) {
426 out.println("#if defined(" + matches[i] + ")");
427 out.println(iii + " case " + matches[i] + ":");
428 out.println("#endif // defined(" + matches[i] + ")");
429 }
430 out.println(iii + " _needed = " + checks[index + 2] + ";");
431 out.println(iii + " break;");
432
433 lastWasIfcheck = true;
434 index += 5;
Elliott Hughes98757502011-04-08 20:01:01 -0700435 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700436 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437 }
438 }
Elliott Hughes98757502011-04-08 20:01:01 -0700439 }
440
441 if (lastWasIfcheck) {
442 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
443 }
444 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800445
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700446 void emitSentinelCheck(CFunc cfunc, String cname, PrintStream out,
447 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
448
449 String[] checks = mChecker.getChecks(cfunc.getName());
450
451 int index = 1;
452 if (checks != null) {
453 while (index < checks.length) {
454 if (checks[index].startsWith("sentinel")) {
455 if (cname != null && !cname.equals(checks[index + 1])) {
456 index += 3;
457 continue;
458 }
459
460 out.println(iii + cname + "_sentinel = false;");
461 out.println(iii + "for (int i = " + remaining +
462 " - 1; i >= 0; i--) {");
463 out.println(iii + indent + "if (" + cname +
464 "[i] == " + checks[index + 2] + "){");
465 out.println(iii + indent + indent +
466 cname + "_sentinel = true;");
467 out.println(iii + indent + indent + "break;");
468 out.println(iii + indent + "}");
469 out.println(iii + "}");
470 out.println(iii +
471 "if (" + cname + "_sentinel == false) {");
472 out.println(iii + indent + "_exception = 1;");
473 out.println(iii + indent +
474 "_exceptionType = \"java/lang/IllegalArgumentException\";");
475 out.println(iii + indent + "_exceptionMessage = \"" + cname +
476 " must contain " + checks[index + 2] + "!\";");
477 out.println(iii + indent + "goto exit;");
478 out.println(iii + "}");
479
480 needsExit = true;
481 index += 3;
482 } else {
483 index = skipOneCheck(checks, index);
484 }
485 }
486 }
487 }
488
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700489 void emitStringCheck(CFunc cfunc, String cname, PrintStream out, String iii) {
490
491 String[] checks = mChecker.getChecks(cfunc.getName());
492
493 int index = 1;
494 if (checks != null) {
495 while (index < checks.length) {
496 if (checks[index].startsWith("check")) {
497 if (cname != null && !cname.equals(checks[index + 1])) {
498 index += 3;
499 continue;
500 }
501 out.println(iii + "_stringlen = _env->GetStringUTFLength(" + cname + ");");
502 out.println(iii + "if (" + checks[index + 2] + " > _stringlen) {");
503 out.println(iii + indent + "_exception = 1;");
504 out.println(iii + indent +
505 "_exceptionType = \"java/lang/ArrayIndexOutOfBoundsException\";");
506 out.println(iii + indent +
507 "_exceptionMessage = \"length of " + cname + " is shorter than " +
508 checks[index + 2] + " argument\";");
509 out.println(iii + indent + "goto exit;");
510 out.println(iii + "}");
511 index += 3;
512 needsExit = true;
513 } else {
514 index = skipOneCheck(checks, index);
515 }
516 }
517 }
518 }
519
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700520 void emitLocalVariablesForSentinel(CFunc cfunc, PrintStream out) {
521
522 String[] checks = mChecker.getChecks(cfunc.getName());
523
524 int index = 1;
525 if (checks != null) {
526 while (index < checks.length) {
527 if (checks[index].startsWith("sentinel")) {
528 String cname = checks[index + 1];
529 out.println(indent + "bool " + cname + "_sentinel = false;");
530
531 index += 3;
532
533 } else {
534 index = skipOneCheck(checks, index);
535 }
536 }
537 }
538 }
539
Jack Palevichffac1ef2009-04-14 19:00:09 -0700540 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800541 if (nonPrimitiveArgs.size() > 0) {
542 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
543 int idx = nonPrimitiveArgs.get(i).intValue();
544 int cIndex = jfunc.getArgCIndex(idx);
545 if (jfunc.getArgType(idx).isArray()) {
546 if (!cfunc.getArgType(cIndex).isConst()) {
547 return true;
548 }
549 } else if (jfunc.getArgType(idx).isBuffer()) {
550 if (!cfunc.getArgType(cIndex).isConst()) {
551 return true;
552 }
553 }
554 }
555 }
556
557 return false;
558 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700559
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800560 /**
561 * Emit a function in several variants:
562 *
563 * if nativeDecl: public native <returntype> func(args);
564 *
565 * if !nativeDecl:
566 * if interfaceDecl: public <returntype> func(args);
567 * if !interfaceDecl: public <returntype> func(args) { body }
568 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700569 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800570 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800571
572 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
573 // If it's not a pointer function, we've already emitted it
574 // with nativeDecl == true
575 return;
576 }
577
Jack Palevich427f5852009-04-15 19:13:17 -0700578 String maybeStatic = mUseStaticMethods ? "static " : "";
579
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800580 if (isPointerFunc) {
581 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700582 (nativeDecl ? "private " + maybeStatic +"native " :
583 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800584 jfunc.getType() + " " +
585 jfunc.getName() +
586 (nativeDecl ? "Bounds" : "") +
587 "(");
588 } else {
589 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700590 (nativeDecl ? "public " + maybeStatic +"native " :
591 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800592 jfunc.getType() + " " +
593 jfunc.getName() +
594 "(");
595 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700596
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800597 int numArgs = jfunc.getNumArgs();
598 for (int i = 0; i < numArgs; i++) {
599 String argName = jfunc.getArgName(i);
600 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700601
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800602 out.print(indent + indent + argType + " " + argName);
603 if (i == numArgs - 1) {
604 if (isPointerFunc && nativeDecl) {
605 out.println(",");
606 out.println(indent + indent + "int remaining");
607 } else {
608 out.println();
609 }
610 } else {
611 out.println(",");
612 }
613 }
614
615 if (nativeDecl || interfaceDecl) {
616 out.println(indent + ");");
617 } else {
618 out.println(indent + ") {");
619
620 String iii = indent + indent;
621
Jack Palevich46d25a32009-05-07 18:28:29 -0700622 // emitBoundsChecks(jfunc, out, iii);
623 emitFunctionCall(jfunc, out, iii, false);
624
625 // Set the pointer after we call the native code, so that if
626 // the native code throws an exception we don't modify the
627 // pointer. We assume that the native code is written so that
628 // if an exception is thrown, then the underlying glXXXPointer
629 // function will not have been called.
630
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800631 String fname = jfunc.getName();
632 if (isPointerFunc) {
633 // TODO - deal with VBO variants
634 if (fname.equals("glColorPointer")) {
635 out.println(iii + "if ((size == 4) &&");
636 out.println(iii + " ((type == GL_FLOAT) ||");
637 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
638 out.println(iii + " (type == GL_FIXED)) &&");
639 out.println(iii + " (stride >= 0)) {");
640 out.println(iii + indent + "_colorPointer = pointer;");
641 out.println(iii + "}");
642 } else if (fname.equals("glNormalPointer")) {
643 out.println(iii + "if (((type == GL_FLOAT) ||");
644 out.println(iii + " (type == GL_BYTE) ||");
645 out.println(iii + " (type == GL_SHORT) ||");
646 out.println(iii + " (type == GL_FIXED)) &&");
647 out.println(iii + " (stride >= 0)) {");
648 out.println(iii + indent + "_normalPointer = pointer;");
649 out.println(iii + "}");
650 } else if (fname.equals("glTexCoordPointer")) {
651 out.println(iii + "if (((size == 2) ||");
652 out.println(iii + " (size == 3) ||");
653 out.println(iii + " (size == 4)) &&");
654 out.println(iii + " ((type == GL_FLOAT) ||");
655 out.println(iii + " (type == GL_BYTE) ||");
656 out.println(iii + " (type == GL_SHORT) ||");
657 out.println(iii + " (type == GL_FIXED)) &&");
658 out.println(iii + " (stride >= 0)) {");
659 out.println(iii + indent + "_texCoordPointer = pointer;");
660 out.println(iii + "}");
661 } else if (fname.equals("glVertexPointer")) {
662 out.println(iii + "if (((size == 2) ||");
663 out.println(iii + " (size == 3) ||");
664 out.println(iii + " (size == 4)) &&");
665 out.println(iii + " ((type == GL_FLOAT) ||");
666 out.println(iii + " (type == GL_BYTE) ||");
667 out.println(iii + " (type == GL_SHORT) ||");
668 out.println(iii + " (type == GL_FIXED)) &&");
669 out.println(iii + " (stride >= 0)) {");
670 out.println(iii + indent + "_vertexPointer = pointer;");
671 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800672 } else if (fname.equals("glPointSizePointerOES")) {
673 out.println(iii + "if (((type == GL_FLOAT) ||");
674 out.println(iii + " (type == GL_FIXED)) &&");
675 out.println(iii + " (stride >= 0)) {");
676 out.println(iii + indent + "_pointSizePointerOES = pointer;");
677 out.println(iii + "}");
678 } else if (fname.equals("glMatrixIndexPointerOES")) {
679 out.println(iii + "if (((size == 2) ||");
680 out.println(iii + " (size == 3) ||");
681 out.println(iii + " (size == 4)) &&");
682 out.println(iii + " ((type == GL_FLOAT) ||");
683 out.println(iii + " (type == GL_BYTE) ||");
684 out.println(iii + " (type == GL_SHORT) ||");
685 out.println(iii + " (type == GL_FIXED)) &&");
686 out.println(iii + " (stride >= 0)) {");
687 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
688 out.println(iii + "}");
689 } else if (fname.equals("glWeightPointer")) {
690 out.println(iii + "if (((size == 2) ||");
691 out.println(iii + " (size == 3) ||");
692 out.println(iii + " (size == 4)) &&");
693 out.println(iii + " ((type == GL_FLOAT) ||");
694 out.println(iii + " (type == GL_BYTE) ||");
695 out.println(iii + " (type == GL_SHORT) ||");
696 out.println(iii + " (type == GL_FIXED)) &&");
697 out.println(iii + " (stride >= 0)) {");
698 out.println(iii + indent + "_weightPointerOES = pointer;");
699 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800700 }
701 }
702
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800703 boolean isVoid = jfunc.getType().isVoid();
704
705 if (!isVoid) {
706 out.println(indent + indent + "return _returnValue;");
707 }
708 out.println(indent + "}");
709 }
710 out.println();
711 }
712
Jack Palevichffac1ef2009-04-14 19:00:09 -0700713 public void addNativeRegistration(String s) {
714 nativeRegistrations.add(s);
715 }
716
Jack Palevich427f5852009-04-15 19:13:17 -0700717 public void emitNativeRegistration(String registrationFunctionName,
718 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700719 cStream.println("static const char *classPathName = \"" +
720 mClassPathName +
721 "\";");
722 cStream.println();
723
Daniel Micayc4e95a32015-09-21 13:17:57 -0400724 cStream.println("static const JNINativeMethod methods[] = {");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700725
726 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
727
728 Iterator<String> i = nativeRegistrations.iterator();
729 while (i.hasNext()) {
730 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800731 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700732
Jack Palevichffac1ef2009-04-14 19:00:09 -0700733 cStream.println("};");
734 cStream.println();
735
736
Jack Palevich427f5852009-04-15 19:13:17 -0700737 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700738 cStream.println("{");
739 cStream.println(indent +
740 "int err;");
741
742 cStream.println(indent +
743 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
744
745 cStream.println(indent + "return err;");
746 cStream.println("}");
747 }
748
749 public JniCodeEmitter() {
750 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800751 }
752
753 String getJniType(JType jType) {
754 if (jType.isVoid()) {
755 return "void";
756 }
757
758 String baseType = jType.getBaseType();
759 if (jType.isPrimitive()) {
760 if (baseType.equals("String")) {
761 return "jstring";
762 } else {
763 return "j" + baseType;
764 }
765 } else if (jType.isArray()) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700766 return jType.isClass() ? "jobjectArray" : "j" + baseType + "Array";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800767 } else {
768 return "jobject";
769 }
770 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700771
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800772 String getJniMangledName(String name) {
773 name = name.replaceAll("_", "_1");
774 name = name.replaceAll(";", "_2");
775 name = name.replaceAll("\\[", "_3");
776 return name;
777 }
778
779 public void emitJniCode(JFunc jfunc, PrintStream out) {
780 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700781
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800782 // Emit comment identifying original C function
783 //
784 // Example:
785 //
786 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
787 //
788 out.println("/* " + cfunc.getOriginal() + " */");
789
790 // Emit JNI signature (name)
791 //
792 // Example:
793 //
794 // void
795 // android_glClipPlanef__I_3FI
796 //
797
798 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800799 boolean isPointerFunc = isPointerFunc(jfunc);
Jesse Hall071fc662013-04-10 01:17:34 -0700800 boolean isPointerOffsetFunc =
801 (outName.endsWith("Pointer") || outName.endsWith("PointerOES") ||
802 outName.endsWith("glDrawElements") ||
803 outName.endsWith("glDrawRangeElements") ||
804 outName.endsWith("glTexImage2D") ||
805 outName.endsWith("glTexSubImage2D") ||
806 outName.endsWith("glCompressedTexImage2D") ||
807 outName.endsWith("glCompressedTexSubImage2D") ||
808 outName.endsWith("glTexImage3D") ||
809 outName.endsWith("glTexSubImage3D") ||
810 outName.endsWith("glCompressedTexImage3D") ||
811 outName.endsWith("glCompressedTexSubImage3D") ||
812 outName.endsWith("glReadPixels"))
813 && !jfunc.getCFunc().hasPointerArg();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800814 if (isPointerFunc) {
815 outName += "Bounds";
816 }
817
818 out.print("static ");
819 out.println(getJniType(jfunc.getType()));
820 out.print(outName);
821
822 String rsignature = getJniName(jfunc.getType());
823
824 String signature = "";
825 int numArgs = jfunc.getNumArgs();
826 for (int i = 0; i < numArgs; i++) {
827 JType argType = jfunc.getArgType(i);
828 signature += getJniName(argType);
829 }
830 if (isPointerFunc) {
831 signature += "I";
832 }
833
834 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800835 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700836 if (!mUseSimpleMethodNames) {
837 out.print("__" + sig);
838 outName += "__" + sig;
839 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700840
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800841 signature = signature.replace('.', '/');
842 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700843
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800844 out.println();
845 if (rsignature.length() == 0) {
846 rsignature = "V";
847 }
848
849 String s = "{\"" +
850 jfunc.getName() +
851 (isPointerFunc ? "Bounds" : "") +
852 "\", \"(" + signature +")" +
853 rsignature +
854 "\", (void *) " +
855 outName +
856 " },";
857 nativeRegistrations.add(s);
858
859 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800860 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800861 int numBufferArgs = 0;
862 List<String> bufferArgNames = new ArrayList<String>();
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700863 List<JType> bufferArgTypes = new ArrayList<JType>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800864
865 // Emit JNI signature (arguments)
866 //
867 // Example:
868 //
869 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
870 //
871 out.print(" (JNIEnv *_env, jobject _this");
872 for (int i = 0; i < numArgs; i++) {
873 out.print(", ");
874 JType argType = jfunc.getArgType(i);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700875 String suffix = "";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800876 if (!argType.isPrimitive()) {
877 if (argType.isArray()) {
878 suffix = "_ref";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700879 } else if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800880 suffix = "_buf";
881 }
882 nonPrimitiveArgs.add(new Integer(i));
883 if (jfunc.getArgType(i).isBuffer()) {
884 int cIndex = jfunc.getArgCIndex(i);
885 String cname = cfunc.getArgName(cIndex);
886 bufferArgNames.add(cname);
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700887 bufferArgTypes.add(jfunc.getArgType(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800888 numBufferArgs++;
889 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800890 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700891
Jack Palevich50d0b142009-11-19 16:34:55 +0800892 if (argType.isString()) {
893 stringArgs.add(new Integer(i));
894 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800895
896 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
897 }
898 if (isPointerFunc) {
899 out.print(", jint remaining");
900 }
901 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700902
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800903 int numArrays = 0;
904 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800905 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800906 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
907 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800908 JType argType = jfunc.getArgType(idx);
909 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800910 ++numArrays;
911 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800912 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800913 ++numBuffers;
914 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800915 if (argType.isString()) {
916 ++numStrings;
917 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800918 }
919
920 // Emit method body
921
922 // Emit local variable declarations for _exception and _returnValue
923 //
924 // Example:
925 //
926 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700927 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800928 // jint _exception;
929 // GLenum _returnValue;
930 //
931 CType returnType = cfunc.getType();
932 boolean isVoid = returnType.isVoid();
933
934 boolean isUnsupported = isUnsupportedFunc(cfunc);
935 if (isUnsupported) {
936 out.println(indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700937 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800938 out.println(indent +
939 " \"" + cfunc.getName() + "\");");
940 if (!isVoid) {
941 String retval = getErrorReturnValue(cfunc);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700942 if (cfunc.getType().isEGLHandle()) {
943 String baseType = cfunc.getType().getBaseType().toLowerCase();
944 out.println(indent +
945 "return toEGLHandle(_env, " + baseType + "Class, " +
946 baseType + "Constructor, " + retval + ");");
947 } else {
948 out.println(indent + "return " + retval + ";");
949 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800950 }
951 out.println("}");
952 out.println();
953 return;
954 }
Elliott Hughes98757502011-04-08 20:01:01 -0700955
Jack Paleviche44e45c2010-01-28 20:28:32 +0800956 String requiresExtension = isRequiresFunc(cfunc);
957 if (requiresExtension != null) {
958 out.println(indent +
959 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
960 out.println(indent + indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700961 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
Jack Paleviche44e45c2010-01-28 20:28:32 +0800962 out.println(indent + indent +
963 " \"" + cfunc.getName() + "\");");
964 if (isVoid) {
965 out.println(indent + indent + " return;");
966 } else {
967 String retval = getErrorReturnValue(cfunc);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700968 if (cfunc.getType().isEGLHandle()) {
969 String baseType = cfunc.getType().getBaseType().toLowerCase();
970 out.println(indent +
971 "return toEGLHandle(_env, " + baseType + "Class, " +
972 baseType + "Constructor, " + retval + ");");
973 } else {
974 out.println(indent + "return " + retval + ";");
975 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800976 }
977 out.println(indent + "}");
978 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800979 if (mUseContextPointer) {
980 out.println(indent +
981 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
982 }
983
Jack Palevich50d0b142009-11-19 16:34:55 +0800984 boolean initializeReturnValue = stringArgs.size() > 0;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700985 boolean emitExceptionCheck = ((numArrays > 0 || numStrings > 0)
986 && (hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs)
987 || (cfunc.hasPointerArg() && numArrays > 0))
Romain Guy79699992016-12-05 12:26:42 -0800988 || (numBufferArgs > 0)
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700989 || hasCheckTest(cfunc)
990 || hasIfTest(cfunc))
991 || (stringArgs.size() > 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800992 // mChecker.getChecks(cfunc.getName()) != null
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800993 // Emit an _exeption variable if there will be error checks
994 if (emitExceptionCheck) {
995 out.println(indent + "jint _exception = 0;");
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800996 out.println(indent + "const char * _exceptionType = NULL;");
997 out.println(indent + "const char * _exceptionMessage = NULL;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800998 }
999
1000 // Emit a single _array or multiple _XXXArray variables
1001 if (numBufferArgs == 1) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001002 JType bufferType = bufferArgTypes.get(0);
1003 if (bufferType.isTypedBuffer()) {
1004 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
1005 out.println(indent + typedArrayType + " _array = (" + typedArrayType + ") 0;");
1006 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001007 out.println(indent + "jarray _array = (jarray) 0;");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001008 }
1009 out.println(indent + "jint _bufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001010 } else {
1011 for (int i = 0; i < numBufferArgs; i++) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001012 JType bufferType = bufferArgTypes.get(0);
1013 if (bufferType.isTypedBuffer()) {
1014 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
1015 out.println(indent + typedArrayType + " _" + bufferArgNames.get(i) +
1016 "Array = (" + typedArrayType + ") 0;");
1017 } else {
1018 out.println(indent + "jarray _" + bufferArgNames.get(i) +
1019 "Array = (jarray) 0;");
1020 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001021 out.println(indent + "jint _" + bufferArgNames.get(i) +
1022 "BufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001023 }
1024 }
1025 if (!isVoid) {
1026 String retval = getErrorReturnValue(cfunc);
1027 if (retval != null) {
1028 out.println(indent + returnType.getDeclaration() +
1029 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +08001030 } else if (initializeReturnValue) {
1031 out.println(indent + returnType.getDeclaration() +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001032 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001033 } else {
1034 out.println(indent + returnType.getDeclaration() +
1035 " _returnValue;");
1036 }
1037 }
1038
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001039 // Emit local variable declarations for EGL Handles
1040 //
1041 // Example:
1042 //
1043 // EGLSurface surface_native = (EGLHandle)fromEGLHandle(_env, surfaceClass, surfaceConstructor, surface);
1044 //
1045 if (nonPrimitiveArgs.size() > 0) {
1046 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1047 int idx = nonPrimitiveArgs.get(i).intValue();
1048 int cIndex = jfunc.getArgCIndex(idx);
1049 String cname = cfunc.getArgName(cIndex);
1050
1051 if (jfunc.getArgType(idx).isBuffer()
1052 || jfunc.getArgType(idx).isArray()
1053 || !jfunc.getArgType(idx).isEGLHandle())
1054 continue;
1055
1056 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1057 String decl = type.getDeclaration();
1058 out.println(indent +
1059 decl + " " + cname + "_native = (" +
1060 decl + ") fromEGLHandle(_env, " +
1061 type.getBaseType().toLowerCase() +
1062 "GetHandleID, " + jfunc.getArgName(idx) +
1063 ");");
1064 }
1065 }
1066
1067 // Emit local variable declarations for element/sentinel checks
1068 //
1069 // Example:
1070 //
1071 // bool attrib_list_sentinel_found = false;
1072 //
1073 emitLocalVariablesForSentinel(cfunc, out);
1074
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001075 // Emit local variable declarations for pointer arguments
1076 //
1077 // Example:
1078 //
1079 // GLfixed *eqn_base;
1080 // GLfixed *eqn;
1081 //
1082 String offset = "offset";
1083 String remaining = "_remaining";
1084 if (nonPrimitiveArgs.size() > 0) {
1085 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1086 int idx = nonPrimitiveArgs.get(i).intValue();
1087 int cIndex = jfunc.getArgCIndex(idx);
1088 String cname = cfunc.getArgName(cIndex);
1089
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001090 if (!jfunc.getArgType(idx).isBuffer() && !jfunc.getArgType(idx).isArray())
1091 continue;
1092
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001093 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1094 String decl = type.getDeclaration();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001095 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001096 out.println(indent +
1097 decl +
1098 (decl.endsWith("*") ? "" : " ") +
1099 jfunc.getArgName(idx) +
1100 "_base = (" + decl + ") 0;");
1101 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001102 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001103 "_" + cname + "Remaining";
1104 out.println(indent +
1105 "jint " + remaining + ";");
1106 out.println(indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001107 decl +
1108 (decl.endsWith("*") ? "" : " ") +
1109 jfunc.getArgName(idx) +
1110 " = (" + decl + ") 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001111 }
1112
1113 out.println();
1114 }
1115
Jack Palevich50d0b142009-11-19 16:34:55 +08001116 // Emit local variable declaration for strings
1117 if (stringArgs.size() > 0) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001118 boolean requiresStringLengthCheck = false;
Jack Palevich50d0b142009-11-19 16:34:55 +08001119 for (int i = 0; i < stringArgs.size(); i++) {
1120 int idx = stringArgs.get(i).intValue();
1121 int cIndex = jfunc.getArgCIndex(idx);
1122 String cname = cfunc.getArgName(cIndex);
1123
1124 out.println(indent + "const char* _native" + cname + " = 0;");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001125 if (hasCheckTest(cfunc, cname)) {
1126 requiresStringLengthCheck = true;
1127 }
1128 }
1129
1130 if (requiresStringLengthCheck) {
1131 out.println(indent + "jsize _stringlen = 0;");
Jack Palevich50d0b142009-11-19 16:34:55 +08001132 }
1133
1134 out.println();
1135 }
1136
1137 // Null pointer checks and GetStringUTFChars
1138 if (stringArgs.size() > 0) {
1139 for (int i = 0; i < stringArgs.size(); i++) {
1140 int idx = stringArgs.get(i).intValue();
1141 int cIndex = jfunc.getArgCIndex(idx);
1142 String cname = cfunc.getArgName(cIndex);
1143
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001144 boolean nullAllowed = isNullAllowed(cfunc, cname);
1145 String nullAllowedIndent = nullAllowed ? indent : "";
1146
Jack Palevich50d0b142009-11-19 16:34:55 +08001147 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1148 String decl = type.getDeclaration();
Jack Palevich50d0b142009-11-19 16:34:55 +08001149
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001150 if (nullAllowed) {
1151 out.println(indent + "if (" + cname + ") {");
1152 } else {
1153 needsExit = true;
1154 out.println(indent + "if (!" + cname + ") {");
1155 out.println(indent + indent + "_exception = 1;");
1156 out.println(indent + indent +
1157 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1158 out.println(indent + indent +
1159 "_exceptionMessage = \"" + cname + " == null\";");
1160 out.println(indent + indent + "goto exit;");
1161 out.println(indent + "}");
1162 }
1163
1164 out.println(nullAllowedIndent + indent + "_native" + cname +
1165 " = _env->GetStringUTFChars(" + cname + ", 0);");
1166
1167 emitStringCheck(cfunc, cname, out, nullAllowedIndent + indent);
1168
1169 if (nullAllowed) {
1170 out.println(indent + "}");
1171 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001172 }
1173
1174 out.println();
1175 }
1176
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001177 // Emit 'GetPrimitiveArrayCritical' for non-object arrays
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001178 // Emit 'GetPointer' calls for Buffer pointers
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001179 if (nonPrimitiveArgs.size() > 0) {
1180 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1181 int idx = nonPrimitiveArgs.get(i).intValue();
1182 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -07001183
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001184 String cname = cfunc.getArgName(cIndex);
1185 offset = numArrays <= 1 ? "offset" :
1186 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +08001187 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001188 "_" + cname + "Remaining";
1189
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001190 boolean nullAllowed = isNullAllowed(cfunc, cname);
1191 String nullAllowedIndent = nullAllowed ? indent : "";
1192
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001193 if (jfunc.getArgType(idx).isArray()
1194 && !jfunc.getArgType(idx).isEGLHandle()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001195 needsExit = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001196
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001197 if (nullAllowed) {
1198 out.println(indent + "if (" + cname + "_ref) {");
1199 }
1200 else
1201 {
1202 out.println(indent + "if (!" + cname + "_ref) {");
1203 out.println(indent + indent + "_exception = 1;");
1204 out.println(indent + indent +
1205 "_exceptionType = " +
1206 "\"java/lang/IllegalArgumentException\";");
1207 out.println(indent + indent +
1208 "_exceptionMessage = \"" + cname +
1209 " == null\";");
1210 out.println(indent + indent + "goto exit;");
1211 out.println(indent + "}");
1212 }
1213
1214 out.println(nullAllowedIndent + indent + "if (" + offset +
1215 " < 0) {");
1216 out.println(nullAllowedIndent + indent + indent +
1217 "_exception = 1;");
1218 out.println(nullAllowedIndent + indent + indent +
1219 "_exceptionType = " +
1220 "\"java/lang/IllegalArgumentException\";");
1221 out.println(nullAllowedIndent + indent + indent +
1222 "_exceptionMessage = \"" + offset +" < 0\";");
1223 out.println(nullAllowedIndent + indent + indent +
1224 "goto exit;");
1225 out.println(nullAllowedIndent + indent + "}");
1226
1227 out.println(nullAllowedIndent + indent + remaining + " = " +
1228 (mUseCPlusPlus ? "_env" : "(*_env)") +
1229 "->GetArrayLength(" +
1230 (mUseCPlusPlus ? "" : "_env, ") +
1231 cname + "_ref) - " + offset + ";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001232
1233 emitNativeBoundsChecks(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001234 emitExceptionCheck, offset, remaining,
1235 nullAllowedIndent + indent);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001236
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001237 out.println(nullAllowedIndent + indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001238 cname +
1239 "_base = (" +
1240 cfunc.getArgType(cIndex).getDeclaration() +
1241 ")");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001242 String arrayGetter = jfunc.getArgType(idx).getArrayGetterForPrimitiveArray();
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001243 out.println(nullAllowedIndent + indent + " " +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001244 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001245 "->" + arrayGetter + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001246 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001247 jfunc.getArgName(idx) +
1248 "_ref, (jboolean *)0);");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001249 out.println(nullAllowedIndent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001250 cname + " = " + cname + "_base + " + offset + ";");
1251
1252 emitSentinelCheck(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001253 emitExceptionCheck, offset, remaining,
1254 nullAllowedIndent + indent);
1255
1256 if (nullAllowed) {
1257 out.println(indent + "}");
1258 }
1259
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001260 out.println();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001261 } else if (jfunc.getArgType(idx).isArray()
1262 && jfunc.getArgType(idx).isEGLHandle()) {
1263 needsExit = true;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001264
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001265 if (nullAllowed) {
1266 out.println(indent + "if (" + cname + "_ref) {");
1267 }
1268 else
1269 {
1270 out.println(indent + "if (!" + cname + "_ref) {");
1271 out.println(indent + indent + "_exception = 1;");
1272 out.println(indent + indent + "_exceptionType = " +
1273 "\"java/lang/IllegalArgumentException\";");
1274 out.println(indent + indent + "_exceptionMessage = \"" +
1275 cname +" == null\";");
1276 out.println(indent + indent + "goto exit;");
1277 out.println(indent + "}");
1278 }
1279
1280 out.println(nullAllowedIndent + indent + "if (" + offset +
1281 " < 0) {");
1282 out.println(nullAllowedIndent + indent + indent +
1283 "_exception = 1;");
1284 out.println(nullAllowedIndent + indent + indent +
1285 "_exceptionType = " +
1286 "\"java/lang/IllegalArgumentException\";");
1287 out.println(nullAllowedIndent + indent + indent +
1288 "_exceptionMessage = \"" + offset +" < 0\";");
1289 out.println(nullAllowedIndent + indent + indent +
1290 "goto exit;");
1291 out.println(nullAllowedIndent + indent + "}");
1292
1293 out.println(nullAllowedIndent + indent + remaining + " = " +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001294 (mUseCPlusPlus ? "_env" : "(*_env)") +
1295 "->GetArrayLength(" +
1296 (mUseCPlusPlus ? "" : "_env, ") +
1297 cname + "_ref) - " + offset + ";");
1298 emitNativeBoundsChecks(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001299 emitExceptionCheck, offset, remaining,
1300 nullAllowedIndent + indent);
1301 out.println(nullAllowedIndent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001302 jfunc.getArgName(idx) + " = new " +
1303 cfunc.getArgType(cIndex).getBaseType() +
1304 "["+ remaining + "];");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001305
1306 if (nullAllowed) {
1307 out.println(indent + "}");
1308 }
1309
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001310 out.println();
1311 } else if (jfunc.getArgType(idx).isBuffer()) {
Romain Guy79699992016-12-05 12:26:42 -08001312 needsExit = needsExit || (!nullAllowed && !isPointerFunc);
1313
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001314 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001315 "_" + cfunc.getArgName(cIndex) + "Array";
1316 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1317 "_" + cfunc.getArgName(cIndex) + "BufferOffset";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001318
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001319 nullAllowed = nullAllowed || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001320 if (nullAllowed) {
1321 out.println(indent + "if (" + cname + "_buf) {");
1322 out.print(indent);
1323 }
Romain Guy79699992016-12-05 12:26:42 -08001324 else
1325 {
1326 out.println(indent + "if (!" + cname + "_buf) {");
1327 out.println(indent + indent + "_exception = 1;");
1328 out.println(indent + indent + "_exceptionType = " +
1329 "\"java/lang/IllegalArgumentException\";");
1330 out.println(indent + indent + "_exceptionMessage = \"" +
1331 cname +" == null\";");
1332 out.println(indent + indent + "goto exit;");
1333 out.println(indent + "}");
1334 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001335
Jack Palevich46d25a32009-05-07 18:28:29 -07001336 if (isPointerFunc) {
1337 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001338 cname +
1339 " = (" +
1340 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001341 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001342 cname + "_buf);");
1343 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001344 out.println(iii + indent + "if ( ! " + cname + " ) {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001345 out.println(iii + indent + indent + "return;");
Jack Palevich46d25a32009-05-07 18:28:29 -07001346 out.println(iii + indent + "}");
1347 } else {
1348 out.println(indent +
1349 cname +
1350 " = (" +
1351 cfunc.getArgType(cIndex).getDeclaration() +
1352 ")getPointer(_env, " +
1353 cname +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001354 "_buf, (jarray*)&" + array + ", &" + remaining + ", &" + bufferOffset +
Jack Palevich46d25a32009-05-07 18:28:29 -07001355 ");");
1356 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001357
Jack Palevich5afdc872009-10-21 11:02:44 -07001358 emitNativeBoundsChecks(cfunc, cname, out, true,
1359 emitExceptionCheck,
1360 offset, remaining, nullAllowed ? " " : " ");
1361
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001362 if (nullAllowed) {
1363 out.println(indent + "}");
1364 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001365 }
1366 }
1367 }
1368
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001369 // Emit 'GetPrimitiveArrayCritical' for pointers if needed
1370 if (nonPrimitiveArgs.size() > 0) {
1371 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1372 int idx = nonPrimitiveArgs.get(i).intValue();
1373 int cIndex = jfunc.getArgCIndex(idx);
1374
1375 if(!jfunc.getArgType(idx).isBuffer() || isPointerFunc) continue;
1376
1377 String cname = cfunc.getArgName(cIndex);
1378 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1379 "_" + cname + "BufferOffset";
1380 String array = numBufferArgs <= 1 ? "_array" :
1381 "_" + cfunc.getArgName(cIndex) + "Array";
1382
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001383 boolean nullAllowed = isNullAllowed(cfunc, cname) ||
1384 isPointerFunc;
Thomas Tafertshofer36b285e2012-07-23 16:52:32 -07001385 if (nullAllowed) {
1386 out.println(indent + "if (" + cname + "_buf && " + cname +" == NULL) {");
1387 } else {
1388 out.println(indent + "if (" + cname +" == NULL) {");
1389 }
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001390 JType argType = jfunc.getArgType(idx);
1391 if (argType.isTypedBuffer()) {
1392 String arrayGetter = argType.getArrayTypeForTypedBuffer().getArrayGetterForPrimitiveArray();
1393 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->" + arrayGetter + "(" + array + ", (jboolean *) 0);");
1394 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1395 out.println(indent + "}");
1396 } else {
1397 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->GetPrimitiveArrayCritical(" + array + ", (jboolean *) 0);");
1398 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1399 out.println(indent + "}");
1400 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001401 }
1402 }
1403
1404
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001405 if (!isVoid) {
1406 out.print(indent + "_returnValue = ");
1407 } else {
1408 out.print(indent);
1409 }
1410 String name = cfunc.getName();
1411
1412 if (mUseContextPointer) {
1413 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1414 name = name.substring(0, 1).toLowerCase() +
1415 name.substring(1, name.length());
1416 out.print("ctx->procs.");
1417 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001418
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001419 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1420
Jack Palevich6cbca502009-04-13 16:22:25 -07001421 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001422 if (numArgs == 0) {
1423 if (mUseContextPointer) {
1424 out.println("ctx);");
1425 } else {
1426 out.println(");");
1427 }
1428 } else {
1429 if (mUseContextPointer) {
1430 out.println("ctx,");
1431 } else {
1432 out.println();
1433 }
1434 for (int i = 0; i < numArgs; i++) {
1435 String typecast;
Jesse Hall071fc662013-04-10 01:17:34 -07001436 if (i == numArgs - 1 && isPointerOffsetFunc) {
Ashok Bhatd8f09612014-02-15 12:51:43 +00001437 typecast = "reinterpret_cast<GLvoid *>";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001438 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001439 typecast = "(" + cfunc.getArgType(i).getDeclaration() + ")";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001440 }
1441 out.print(indent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001442 typecast);
1443
Jack Palevich50d0b142009-11-19 16:34:55 +08001444 if (cfunc.getArgType(i).isConstCharPointer()) {
1445 out.print("_native");
1446 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001447
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001448 if (cfunc.getArgType(i).isEGLHandle() &&
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001449 !cfunc.getArgType(i).isPointer()){
1450 out.print(cfunc.getArgName(i)+"_native");
Ashok Bhatd8f09612014-02-15 12:51:43 +00001451 } else if (i == numArgs - 1 && isPointerOffsetFunc){
1452 out.print("("+cfunc.getArgName(i)+")");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001453 } else {
1454 out.print(cfunc.getArgName(i));
1455 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001456
1457 if (i == numArgs - 1) {
1458 if (isPointerFunc) {
1459 out.println(",");
1460 out.println(indent + indent + "(GLsizei)remaining");
1461 } else {
1462 out.println();
1463 }
1464 } else {
1465 out.println(",");
1466 }
1467 }
1468 out.println(indent + ");");
1469 }
1470
1471 if (needsExit) {
1472 out.println();
1473 out.println("exit:");
1474 needsExit = false;
1475 }
1476
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001477
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001478 if (nonPrimitiveArgs.size() > 0) {
1479 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1480 int idx = nonPrimitiveArgs.get(i).intValue();
1481
1482 int cIndex = jfunc.getArgCIndex(idx);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001483 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001484
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001485 // If the argument is 'const', GL will not write to it.
1486 // In this case, we can use the 'JNI_ABORT' flag to avoid
1487 // the need to write back to the Java array
1488 out.println(indent +
1489 "if (" + jfunc.getArgName(idx) + "_base) {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001490 String arrayReleaser = jfunc.getArgType(idx).getArrayReleaserForPrimitiveArray();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001491 out.println(indent + indent +
1492 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001493 "->" + arrayReleaser + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001494 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001495 jfunc.getArgName(idx) + "_ref, " +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001496 "(j" + jfunc.getArgType(idx).getBaseType() + "*)" + cfunc.getArgName(cIndex) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001497 "_base,");
1498 out.println(indent + indent + indent +
1499 (cfunc.getArgType(cIndex).isConst() ?
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001500 "JNI_ABORT" : "_exception ? JNI_ABORT: 0" ) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001501 ");");
1502 out.println(indent + "}");
1503 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001504 if (! isPointerFunc) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001505 JType argType = jfunc.getArgType(idx);
Jack Palevich46d25a32009-05-07 18:28:29 -07001506 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001507 "_" + cfunc.getArgName(cIndex) + "Array";
Jack Palevich46d25a32009-05-07 18:28:29 -07001508 out.println(indent + "if (" + array + ") {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001509 if (argType.isTypedBuffer()) {
1510 String arrayReleaser =
1511 argType.getArrayTypeForTypedBuffer().getArrayReleaserForPrimitiveArray();
1512 out.println(indent + indent +
1513 "_env->" + arrayReleaser + "(" + array + ", " +
1514 "(j" + argType.getArrayTypeForTypedBuffer().getBaseType() + "*)" +
1515 cfunc.getArgName(cIndex) +
1516 ", " +
1517 (cfunc.getArgType(cIndex).isConst() ?
1518 "JNI_ABORT" : (emitExceptionCheck ?
1519 "_exception ? JNI_ABORT : 0" : "0")) +
1520 ");");
1521 } else {
1522 out.println(indent + indent +
1523 "releasePointer(_env, " + array + ", " +
1524 cfunc.getArgName(cIndex) +
1525 ", " +
1526 (cfunc.getArgType(cIndex).isConst() ?
1527 "JNI_FALSE" : (emitExceptionCheck ?
1528 "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
1529 ");");
1530 }
Jack Palevich46d25a32009-05-07 18:28:29 -07001531 out.println(indent + "}");
1532 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001533 }
1534 }
1535 }
1536
Jack Palevich50d0b142009-11-19 16:34:55 +08001537 // Emit local variable declaration for strings
1538 if (stringArgs.size() > 0) {
1539 for (int i = 0; i < stringArgs.size(); i++) {
1540 int idx = stringArgs.get(i).intValue();
1541 int cIndex = jfunc.getArgCIndex(idx);
1542 String cname = cfunc.getArgName(cIndex);
1543
1544 out.println(indent + "if (_native" + cname + ") {");
1545 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1546 out.println(indent + "}");
1547 }
1548
1549 out.println();
1550 }
1551
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001552 // Copy results back to java arrays
1553 if (nonPrimitiveArgs.size() > 0) {
1554 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1555 int idx = nonPrimitiveArgs.get(i).intValue();
1556 int cIndex = jfunc.getArgCIndex(idx);
1557 String baseType = cfunc.getArgType(cIndex).getBaseType().toLowerCase();
1558 if (jfunc.getArgType(idx).isArray() && jfunc.getArgType(idx).isClass()) {
1559 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
1560 "_" + cfunc.getArgName(cIndex) + "Remaining";
1561 offset = numArrays <= 1 ? "offset" : cfunc.getArgName(cIndex) + "Offset";
1562 out.println(indent +
1563 "if (" + jfunc.getArgName(idx) + ") {");
1564 out.println(indent + indent +
1565 "for (int i = 0; i < " + remaining + "; i++) {");
1566 out.println(indent + indent + indent +
1567 "jobject " + cfunc.getArgName(cIndex) +
1568 "_new = toEGLHandle(_env, " + baseType +
1569 "Class, " + baseType + "Constructor, " +
1570 cfunc.getArgName(cIndex) + "[i]);");
1571 out.println(indent + indent + indent +
1572 (mUseCPlusPlus ? "_env" : "(*_env)") +
1573 "->SetObjectArrayElement(" +
1574 (mUseCPlusPlus ? "" : "_env, ") +
1575 cfunc.getArgName(cIndex) +
1576 "_ref, i + " + offset + ", " +
1577 cfunc.getArgName(cIndex) + "_new);");
1578 out.println(indent + indent + "}");
1579 out.println(indent + indent +
1580 "delete[] " + jfunc.getArgName(idx) + ";");
1581 out.println(indent + "}");
1582 }
1583 }
1584 }
1585
1586
1587 // Throw exception if there is one
1588 if (emitExceptionCheck) {
1589 out.println(indent + "if (_exception) {");
1590 out.println(indent + indent +
1591 "jniThrowException(_env, _exceptionType, _exceptionMessage);");
1592 out.println(indent + "}");
1593
1594 }
1595
Jack Palevich50d0b142009-11-19 16:34:55 +08001596
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001597 if (!isVoid) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001598 if (cfunc.getType().isEGLHandle()) {
1599 String baseType = cfunc.getType().getBaseType().toLowerCase();
1600 out.println(indent +
1601 "return toEGLHandle(_env, " + baseType + "Class, " +
1602 baseType + "Constructor, _returnValue);");
1603 } else {
Jesse Hall68fc8bb2013-04-10 01:01:00 -07001604 out.println(indent + "return (" +
1605 getJniType(jfunc.getType()) + ")_returnValue;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001606 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001607 }
1608
1609 out.println("}");
1610 out.println();
1611 }
1612
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001613}