blob: 5a412bf85f4221670bc174eb2da926216bc30656 [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
225 boolean isNullAllowed(CFunc cfunc) {
226 String[] checks = mChecker.getChecks(cfunc.getName());
227 int index = 1;
228 if (checks != null) {
229 while (index < checks.length) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700230 if (checks[index].equals("nullAllowed")) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231 return true;
232 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700233 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800234 }
235 }
236 }
237 return false;
238 }
239
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700240 boolean hasCheckTest(CFunc cfunc) {
241 String[] checks = mChecker.getChecks(cfunc.getName());
242 int index = 1;
243 if (checks != null) {
244 while (index < checks.length) {
245 if (checks[index].startsWith("check")) {
246 return true;
247 } else {
248 index = skipOneCheck(checks, index);
249 }
250 }
251 }
252 return false;
253 }
254
255 boolean hasIfTest(CFunc cfunc) {
256 String[] checks = mChecker.getChecks(cfunc.getName());
257 int index = 1;
258 if (checks != null) {
259 while (index < checks.length) {
260 if (checks[index].startsWith("ifcheck")) {
261 return true;
262 } else {
263 index = skipOneCheck(checks, index);
264 }
265 }
266 }
267 return false;
268 }
269
270 int skipOneCheck(String[] checks, int index) {
271 if (checks[index].equals("return")) {
272 index += 2;
273 } else if (checks[index].startsWith("check")) {
274 index += 3;
275 } else if (checks[index].startsWith("sentinel")) {
276 index += 3;
277 } else if (checks[index].equals("ifcheck")) {
278 index += 5;
279 } else if (checks[index].equals("unsupported")) {
280 index += 1;
281 } else if (checks[index].equals("requires")) {
282 index += 2;
283 } else if (checks[index].equals("nullAllowed")) {
284 index += 1;
285 } else {
286 System.out.println("Error: unknown keyword \"" +
287 checks[index] + "\"");
288 System.exit(0);
289 }
290
291 return index;
292 }
293
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800294 String getErrorReturnValue(CFunc cfunc) {
295 CType returnType = cfunc.getType();
296 boolean isVoid = returnType.isVoid();
297 if (isVoid) {
298 return null;
299 }
300
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700301 if (returnType.getBaseType().startsWith("EGL")) {
302 return "(" + returnType.getDeclaration() + ") 0";
303 }
304
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800305 String[] checks = mChecker.getChecks(cfunc.getName());
306
307 int index = 1;
308 if (checks != null) {
309 while (index < checks.length) {
310 if (checks[index].equals("return")) {
311 return checks[index + 1];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800312 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700313 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800314 }
315 }
316 }
317
318 return null;
319 }
320
321 boolean isUnsupportedFunc(CFunc cfunc) {
322 String[] checks = mChecker.getChecks(cfunc.getName());
323 int index = 1;
324 if (checks != null) {
325 while (index < checks.length) {
326 if (checks[index].equals("unsupported")) {
327 return true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800328 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700329 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800330 }
331 }
332 }
333 return false;
334 }
Elliott Hughes98757502011-04-08 20:01:01 -0700335
Jack Paleviche44e45c2010-01-28 20:28:32 +0800336 String isRequiresFunc(CFunc cfunc) {
337 String[] checks = mChecker.getChecks(cfunc.getName());
338 int index = 1;
339 if (checks != null) {
340 while (index < checks.length) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700341 if (checks[index].equals("requires")) {
Jack Paleviche44e45c2010-01-28 20:28:32 +0800342 return checks[index+1];
Jack Paleviche44e45c2010-01-28 20:28:32 +0800343 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700344 index = skipOneCheck(checks, index);
Jack Paleviche44e45c2010-01-28 20:28:32 +0800345 }
346 }
347 }
348 return null;
349 }
Elliott Hughes98757502011-04-08 20:01:01 -0700350
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700352 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800353
Elliott Hughes98757502011-04-08 20:01:01 -0700354 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800355
Elliott Hughes98757502011-04-08 20:01:01 -0700356 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800357
Elliott Hughes98757502011-04-08 20:01:01 -0700358 int index = 1;
359 if (checks != null) {
360 while (index < checks.length) {
361 if (checks[index].startsWith("check")) {
362 if (lastWasIfcheck) {
363 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
364 offset, remaining, iii);
365 }
366 lastWasIfcheck = false;
367 if (cname != null && !cname.equals(checks[index + 1])) {
368 index += 3;
369 continue;
370 }
371 out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700372 out.println(iii + indent + "_exception = 1;");
Elliott Hughes98757502011-04-08 20:01:01 -0700373 String exceptionClassName = "java/lang/IllegalArgumentException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700374 // If the "check" keyword was of the form
375 // "check_<class name>", use the class name in the
376 // exception to be thrown
377 int underscore = checks[index].indexOf('_');
378 if (underscore >= 0) {
Elliott Hughes98757502011-04-08 20:01:01 -0700379 String abbr = checks[index].substring(underscore + 1);
380 if (abbr.equals("AIOOBE")) {
381 exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700382 } else {
Elliott Hughes98757502011-04-08 20:01:01 -0700383 throw new RuntimeException("unknown exception abbreviation: " + abbr);
Jack Palevichffac1ef2009-04-14 19:00:09 -0700384 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800385 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700386 out.println(iii + indent +
387 "_exceptionType = \""+exceptionClassName+"\";");
388 out.println(iii + indent +
389 "_exceptionMessage = \"" +
390 (isBuffer ? "remaining()" : "length - " +
391 offset) + " < " + checks[index + 2] +
392 " < needed\";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800393
Elliott Hughes98757502011-04-08 20:01:01 -0700394 out.println(iii + indent + "goto exit;");
Elliott Hughes98757502011-04-08 20:01:01 -0700395 out.println(iii + "}");
396
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700397 needsExit = true;
398
Elliott Hughes98757502011-04-08 20:01:01 -0700399 index += 3;
400 } else if (checks[index].equals("ifcheck")) {
401 String[] matches = checks[index + 4].split(",");
402
403 if (!lastWasIfcheck) {
404 out.println(iii + "int _needed;");
405 out.println(iii + "switch (" + checks[index + 3] + ") {");
406 }
407
408 for (int i = 0; i < matches.length; i++) {
409 out.println("#if defined(" + matches[i] + ")");
410 out.println(iii + " case " + matches[i] + ":");
411 out.println("#endif // defined(" + matches[i] + ")");
412 }
413 out.println(iii + " _needed = " + checks[index + 2] + ";");
414 out.println(iii + " break;");
415
416 lastWasIfcheck = true;
417 index += 5;
Elliott Hughes98757502011-04-08 20:01:01 -0700418 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700419 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800420 }
421 }
Elliott Hughes98757502011-04-08 20:01:01 -0700422 }
423
424 if (lastWasIfcheck) {
425 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
426 }
427 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800428
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700429 void emitSentinelCheck(CFunc cfunc, String cname, PrintStream out,
430 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
431
432 String[] checks = mChecker.getChecks(cfunc.getName());
433
434 int index = 1;
435 if (checks != null) {
436 while (index < checks.length) {
437 if (checks[index].startsWith("sentinel")) {
438 if (cname != null && !cname.equals(checks[index + 1])) {
439 index += 3;
440 continue;
441 }
442
443 out.println(iii + cname + "_sentinel = false;");
444 out.println(iii + "for (int i = " + remaining +
445 " - 1; i >= 0; i--) {");
446 out.println(iii + indent + "if (" + cname +
447 "[i] == " + checks[index + 2] + "){");
448 out.println(iii + indent + indent +
449 cname + "_sentinel = true;");
450 out.println(iii + indent + indent + "break;");
451 out.println(iii + indent + "}");
452 out.println(iii + "}");
453 out.println(iii +
454 "if (" + cname + "_sentinel == false) {");
455 out.println(iii + indent + "_exception = 1;");
456 out.println(iii + indent +
457 "_exceptionType = \"java/lang/IllegalArgumentException\";");
458 out.println(iii + indent + "_exceptionMessage = \"" + cname +
459 " must contain " + checks[index + 2] + "!\";");
460 out.println(iii + indent + "goto exit;");
461 out.println(iii + "}");
462
463 needsExit = true;
464 index += 3;
465 } else {
466 index = skipOneCheck(checks, index);
467 }
468 }
469 }
470 }
471
472 void emitLocalVariablesForSentinel(CFunc cfunc, PrintStream out) {
473
474 String[] checks = mChecker.getChecks(cfunc.getName());
475
476 int index = 1;
477 if (checks != null) {
478 while (index < checks.length) {
479 if (checks[index].startsWith("sentinel")) {
480 String cname = checks[index + 1];
481 out.println(indent + "bool " + cname + "_sentinel = false;");
482
483 index += 3;
484
485 } else {
486 index = skipOneCheck(checks, index);
487 }
488 }
489 }
490 }
491
Jack Palevichffac1ef2009-04-14 19:00:09 -0700492 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 if (nonPrimitiveArgs.size() > 0) {
494 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
495 int idx = nonPrimitiveArgs.get(i).intValue();
496 int cIndex = jfunc.getArgCIndex(idx);
497 if (jfunc.getArgType(idx).isArray()) {
498 if (!cfunc.getArgType(cIndex).isConst()) {
499 return true;
500 }
501 } else if (jfunc.getArgType(idx).isBuffer()) {
502 if (!cfunc.getArgType(cIndex).isConst()) {
503 return true;
504 }
505 }
506 }
507 }
508
509 return false;
510 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700511
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800512 /**
513 * Emit a function in several variants:
514 *
515 * if nativeDecl: public native <returntype> func(args);
516 *
517 * if !nativeDecl:
518 * if interfaceDecl: public <returntype> func(args);
519 * if !interfaceDecl: public <returntype> func(args) { body }
520 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700521 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800522 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800523
524 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
525 // If it's not a pointer function, we've already emitted it
526 // with nativeDecl == true
527 return;
528 }
529
Jack Palevich427f5852009-04-15 19:13:17 -0700530 String maybeStatic = mUseStaticMethods ? "static " : "";
531
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800532 if (isPointerFunc) {
533 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700534 (nativeDecl ? "private " + maybeStatic +"native " :
535 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800536 jfunc.getType() + " " +
537 jfunc.getName() +
538 (nativeDecl ? "Bounds" : "") +
539 "(");
540 } else {
541 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700542 (nativeDecl ? "public " + maybeStatic +"native " :
543 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800544 jfunc.getType() + " " +
545 jfunc.getName() +
546 "(");
547 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700548
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800549 int numArgs = jfunc.getNumArgs();
550 for (int i = 0; i < numArgs; i++) {
551 String argName = jfunc.getArgName(i);
552 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700553
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800554 out.print(indent + indent + argType + " " + argName);
555 if (i == numArgs - 1) {
556 if (isPointerFunc && nativeDecl) {
557 out.println(",");
558 out.println(indent + indent + "int remaining");
559 } else {
560 out.println();
561 }
562 } else {
563 out.println(",");
564 }
565 }
566
567 if (nativeDecl || interfaceDecl) {
568 out.println(indent + ");");
569 } else {
570 out.println(indent + ") {");
571
572 String iii = indent + indent;
573
Jack Palevich46d25a32009-05-07 18:28:29 -0700574 // emitBoundsChecks(jfunc, out, iii);
575 emitFunctionCall(jfunc, out, iii, false);
576
577 // Set the pointer after we call the native code, so that if
578 // the native code throws an exception we don't modify the
579 // pointer. We assume that the native code is written so that
580 // if an exception is thrown, then the underlying glXXXPointer
581 // function will not have been called.
582
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800583 String fname = jfunc.getName();
584 if (isPointerFunc) {
585 // TODO - deal with VBO variants
586 if (fname.equals("glColorPointer")) {
587 out.println(iii + "if ((size == 4) &&");
588 out.println(iii + " ((type == GL_FLOAT) ||");
589 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
590 out.println(iii + " (type == GL_FIXED)) &&");
591 out.println(iii + " (stride >= 0)) {");
592 out.println(iii + indent + "_colorPointer = pointer;");
593 out.println(iii + "}");
594 } else if (fname.equals("glNormalPointer")) {
595 out.println(iii + "if (((type == GL_FLOAT) ||");
596 out.println(iii + " (type == GL_BYTE) ||");
597 out.println(iii + " (type == GL_SHORT) ||");
598 out.println(iii + " (type == GL_FIXED)) &&");
599 out.println(iii + " (stride >= 0)) {");
600 out.println(iii + indent + "_normalPointer = pointer;");
601 out.println(iii + "}");
602 } else if (fname.equals("glTexCoordPointer")) {
603 out.println(iii + "if (((size == 2) ||");
604 out.println(iii + " (size == 3) ||");
605 out.println(iii + " (size == 4)) &&");
606 out.println(iii + " ((type == GL_FLOAT) ||");
607 out.println(iii + " (type == GL_BYTE) ||");
608 out.println(iii + " (type == GL_SHORT) ||");
609 out.println(iii + " (type == GL_FIXED)) &&");
610 out.println(iii + " (stride >= 0)) {");
611 out.println(iii + indent + "_texCoordPointer = pointer;");
612 out.println(iii + "}");
613 } else if (fname.equals("glVertexPointer")) {
614 out.println(iii + "if (((size == 2) ||");
615 out.println(iii + " (size == 3) ||");
616 out.println(iii + " (size == 4)) &&");
617 out.println(iii + " ((type == GL_FLOAT) ||");
618 out.println(iii + " (type == GL_BYTE) ||");
619 out.println(iii + " (type == GL_SHORT) ||");
620 out.println(iii + " (type == GL_FIXED)) &&");
621 out.println(iii + " (stride >= 0)) {");
622 out.println(iii + indent + "_vertexPointer = pointer;");
623 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800624 } else if (fname.equals("glPointSizePointerOES")) {
625 out.println(iii + "if (((type == GL_FLOAT) ||");
626 out.println(iii + " (type == GL_FIXED)) &&");
627 out.println(iii + " (stride >= 0)) {");
628 out.println(iii + indent + "_pointSizePointerOES = pointer;");
629 out.println(iii + "}");
630 } else if (fname.equals("glMatrixIndexPointerOES")) {
631 out.println(iii + "if (((size == 2) ||");
632 out.println(iii + " (size == 3) ||");
633 out.println(iii + " (size == 4)) &&");
634 out.println(iii + " ((type == GL_FLOAT) ||");
635 out.println(iii + " (type == GL_BYTE) ||");
636 out.println(iii + " (type == GL_SHORT) ||");
637 out.println(iii + " (type == GL_FIXED)) &&");
638 out.println(iii + " (stride >= 0)) {");
639 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
640 out.println(iii + "}");
641 } else if (fname.equals("glWeightPointer")) {
642 out.println(iii + "if (((size == 2) ||");
643 out.println(iii + " (size == 3) ||");
644 out.println(iii + " (size == 4)) &&");
645 out.println(iii + " ((type == GL_FLOAT) ||");
646 out.println(iii + " (type == GL_BYTE) ||");
647 out.println(iii + " (type == GL_SHORT) ||");
648 out.println(iii + " (type == GL_FIXED)) &&");
649 out.println(iii + " (stride >= 0)) {");
650 out.println(iii + indent + "_weightPointerOES = pointer;");
651 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800652 }
653 }
654
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800655 boolean isVoid = jfunc.getType().isVoid();
656
657 if (!isVoid) {
658 out.println(indent + indent + "return _returnValue;");
659 }
660 out.println(indent + "}");
661 }
662 out.println();
663 }
664
Jack Palevichffac1ef2009-04-14 19:00:09 -0700665 public void addNativeRegistration(String s) {
666 nativeRegistrations.add(s);
667 }
668
Jack Palevich427f5852009-04-15 19:13:17 -0700669 public void emitNativeRegistration(String registrationFunctionName,
670 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700671 cStream.println("static const char *classPathName = \"" +
672 mClassPathName +
673 "\";");
674 cStream.println();
675
Daniel Micayc4e95a32015-09-21 13:17:57 -0400676 cStream.println("static const JNINativeMethod methods[] = {");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700677
678 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
679
680 Iterator<String> i = nativeRegistrations.iterator();
681 while (i.hasNext()) {
682 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800683 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700684
Jack Palevichffac1ef2009-04-14 19:00:09 -0700685 cStream.println("};");
686 cStream.println();
687
688
Jack Palevich427f5852009-04-15 19:13:17 -0700689 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700690 cStream.println("{");
691 cStream.println(indent +
692 "int err;");
693
694 cStream.println(indent +
695 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
696
697 cStream.println(indent + "return err;");
698 cStream.println("}");
699 }
700
701 public JniCodeEmitter() {
702 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800703 }
704
705 String getJniType(JType jType) {
706 if (jType.isVoid()) {
707 return "void";
708 }
709
710 String baseType = jType.getBaseType();
711 if (jType.isPrimitive()) {
712 if (baseType.equals("String")) {
713 return "jstring";
714 } else {
715 return "j" + baseType;
716 }
717 } else if (jType.isArray()) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700718 return jType.isClass() ? "jobjectArray" : "j" + baseType + "Array";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800719 } else {
720 return "jobject";
721 }
722 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700723
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800724 String getJniMangledName(String name) {
725 name = name.replaceAll("_", "_1");
726 name = name.replaceAll(";", "_2");
727 name = name.replaceAll("\\[", "_3");
728 return name;
729 }
730
731 public void emitJniCode(JFunc jfunc, PrintStream out) {
732 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700733
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734 // Emit comment identifying original C function
735 //
736 // Example:
737 //
738 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
739 //
740 out.println("/* " + cfunc.getOriginal() + " */");
741
742 // Emit JNI signature (name)
743 //
744 // Example:
745 //
746 // void
747 // android_glClipPlanef__I_3FI
748 //
749
750 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800751 boolean isPointerFunc = isPointerFunc(jfunc);
Jesse Hall071fc662013-04-10 01:17:34 -0700752 boolean isPointerOffsetFunc =
753 (outName.endsWith("Pointer") || outName.endsWith("PointerOES") ||
754 outName.endsWith("glDrawElements") ||
755 outName.endsWith("glDrawRangeElements") ||
756 outName.endsWith("glTexImage2D") ||
757 outName.endsWith("glTexSubImage2D") ||
758 outName.endsWith("glCompressedTexImage2D") ||
759 outName.endsWith("glCompressedTexSubImage2D") ||
760 outName.endsWith("glTexImage3D") ||
761 outName.endsWith("glTexSubImage3D") ||
762 outName.endsWith("glCompressedTexImage3D") ||
763 outName.endsWith("glCompressedTexSubImage3D") ||
764 outName.endsWith("glReadPixels"))
765 && !jfunc.getCFunc().hasPointerArg();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800766 if (isPointerFunc) {
767 outName += "Bounds";
768 }
769
770 out.print("static ");
771 out.println(getJniType(jfunc.getType()));
772 out.print(outName);
773
774 String rsignature = getJniName(jfunc.getType());
775
776 String signature = "";
777 int numArgs = jfunc.getNumArgs();
778 for (int i = 0; i < numArgs; i++) {
779 JType argType = jfunc.getArgType(i);
780 signature += getJniName(argType);
781 }
782 if (isPointerFunc) {
783 signature += "I";
784 }
785
786 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800787 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700788 if (!mUseSimpleMethodNames) {
789 out.print("__" + sig);
790 outName += "__" + sig;
791 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700792
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800793 signature = signature.replace('.', '/');
794 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700795
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800796 out.println();
797 if (rsignature.length() == 0) {
798 rsignature = "V";
799 }
800
801 String s = "{\"" +
802 jfunc.getName() +
803 (isPointerFunc ? "Bounds" : "") +
804 "\", \"(" + signature +")" +
805 rsignature +
806 "\", (void *) " +
807 outName +
808 " },";
809 nativeRegistrations.add(s);
810
811 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800812 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800813 int numBufferArgs = 0;
814 List<String> bufferArgNames = new ArrayList<String>();
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700815 List<JType> bufferArgTypes = new ArrayList<JType>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800816
817 // Emit JNI signature (arguments)
818 //
819 // Example:
820 //
821 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
822 //
823 out.print(" (JNIEnv *_env, jobject _this");
824 for (int i = 0; i < numArgs; i++) {
825 out.print(", ");
826 JType argType = jfunc.getArgType(i);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700827 String suffix = "";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800828 if (!argType.isPrimitive()) {
829 if (argType.isArray()) {
830 suffix = "_ref";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700831 } else if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800832 suffix = "_buf";
833 }
834 nonPrimitiveArgs.add(new Integer(i));
835 if (jfunc.getArgType(i).isBuffer()) {
836 int cIndex = jfunc.getArgCIndex(i);
837 String cname = cfunc.getArgName(cIndex);
838 bufferArgNames.add(cname);
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700839 bufferArgTypes.add(jfunc.getArgType(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800840 numBufferArgs++;
841 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800842 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700843
Jack Palevich50d0b142009-11-19 16:34:55 +0800844 if (argType.isString()) {
845 stringArgs.add(new Integer(i));
846 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800847
848 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
849 }
850 if (isPointerFunc) {
851 out.print(", jint remaining");
852 }
853 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700854
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800855 int numArrays = 0;
856 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800857 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800858 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
859 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800860 JType argType = jfunc.getArgType(idx);
861 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800862 ++numArrays;
863 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800864 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800865 ++numBuffers;
866 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800867 if (argType.isString()) {
868 ++numStrings;
869 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800870 }
871
872 // Emit method body
873
874 // Emit local variable declarations for _exception and _returnValue
875 //
876 // Example:
877 //
878 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700879 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800880 // jint _exception;
881 // GLenum _returnValue;
882 //
883 CType returnType = cfunc.getType();
884 boolean isVoid = returnType.isVoid();
885
886 boolean isUnsupported = isUnsupportedFunc(cfunc);
887 if (isUnsupported) {
888 out.println(indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700889 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800890 out.println(indent +
891 " \"" + cfunc.getName() + "\");");
892 if (!isVoid) {
893 String retval = getErrorReturnValue(cfunc);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700894 if (cfunc.getType().isEGLHandle()) {
895 String baseType = cfunc.getType().getBaseType().toLowerCase();
896 out.println(indent +
897 "return toEGLHandle(_env, " + baseType + "Class, " +
898 baseType + "Constructor, " + retval + ");");
899 } else {
900 out.println(indent + "return " + retval + ";");
901 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800902 }
903 out.println("}");
904 out.println();
905 return;
906 }
Elliott Hughes98757502011-04-08 20:01:01 -0700907
Jack Paleviche44e45c2010-01-28 20:28:32 +0800908 String requiresExtension = isRequiresFunc(cfunc);
909 if (requiresExtension != null) {
910 out.println(indent +
911 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
912 out.println(indent + indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700913 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
Jack Paleviche44e45c2010-01-28 20:28:32 +0800914 out.println(indent + indent +
915 " \"" + cfunc.getName() + "\");");
916 if (isVoid) {
917 out.println(indent + indent + " return;");
918 } else {
919 String retval = getErrorReturnValue(cfunc);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700920 if (cfunc.getType().isEGLHandle()) {
921 String baseType = cfunc.getType().getBaseType().toLowerCase();
922 out.println(indent +
923 "return toEGLHandle(_env, " + baseType + "Class, " +
924 baseType + "Constructor, " + retval + ");");
925 } else {
926 out.println(indent + "return " + retval + ";");
927 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800928 }
929 out.println(indent + "}");
930 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800931 if (mUseContextPointer) {
932 out.println(indent +
933 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
934 }
935
Jack Palevich50d0b142009-11-19 16:34:55 +0800936 boolean initializeReturnValue = stringArgs.size() > 0;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700937 boolean emitExceptionCheck = ((numArrays > 0 || numStrings > 0)
938 && (hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs)
939 || (cfunc.hasPointerArg() && numArrays > 0))
940 || hasCheckTest(cfunc)
941 || hasIfTest(cfunc))
942 || (stringArgs.size() > 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800943 // mChecker.getChecks(cfunc.getName()) != null
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800944 // Emit an _exeption variable if there will be error checks
945 if (emitExceptionCheck) {
946 out.println(indent + "jint _exception = 0;");
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800947 out.println(indent + "const char * _exceptionType = NULL;");
948 out.println(indent + "const char * _exceptionMessage = NULL;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800949 }
950
951 // Emit a single _array or multiple _XXXArray variables
952 if (numBufferArgs == 1) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700953 JType bufferType = bufferArgTypes.get(0);
954 if (bufferType.isTypedBuffer()) {
955 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
956 out.println(indent + typedArrayType + " _array = (" + typedArrayType + ") 0;");
957 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800958 out.println(indent + "jarray _array = (jarray) 0;");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700959 }
960 out.println(indent + "jint _bufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800961 } else {
962 for (int i = 0; i < numBufferArgs; i++) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700963 JType bufferType = bufferArgTypes.get(0);
964 if (bufferType.isTypedBuffer()) {
965 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
966 out.println(indent + typedArrayType + " _" + bufferArgNames.get(i) +
967 "Array = (" + typedArrayType + ") 0;");
968 } else {
969 out.println(indent + "jarray _" + bufferArgNames.get(i) +
970 "Array = (jarray) 0;");
971 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -0700972 out.println(indent + "jint _" + bufferArgNames.get(i) +
973 "BufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800974 }
975 }
976 if (!isVoid) {
977 String retval = getErrorReturnValue(cfunc);
978 if (retval != null) {
979 out.println(indent + returnType.getDeclaration() +
980 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +0800981 } else if (initializeReturnValue) {
982 out.println(indent + returnType.getDeclaration() +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700983 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800984 } else {
985 out.println(indent + returnType.getDeclaration() +
986 " _returnValue;");
987 }
988 }
989
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700990 // Emit local variable declarations for EGL Handles
991 //
992 // Example:
993 //
994 // EGLSurface surface_native = (EGLHandle)fromEGLHandle(_env, surfaceClass, surfaceConstructor, surface);
995 //
996 if (nonPrimitiveArgs.size() > 0) {
997 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
998 int idx = nonPrimitiveArgs.get(i).intValue();
999 int cIndex = jfunc.getArgCIndex(idx);
1000 String cname = cfunc.getArgName(cIndex);
1001
1002 if (jfunc.getArgType(idx).isBuffer()
1003 || jfunc.getArgType(idx).isArray()
1004 || !jfunc.getArgType(idx).isEGLHandle())
1005 continue;
1006
1007 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1008 String decl = type.getDeclaration();
1009 out.println(indent +
1010 decl + " " + cname + "_native = (" +
1011 decl + ") fromEGLHandle(_env, " +
1012 type.getBaseType().toLowerCase() +
1013 "GetHandleID, " + jfunc.getArgName(idx) +
1014 ");");
1015 }
1016 }
1017
1018 // Emit local variable declarations for element/sentinel checks
1019 //
1020 // Example:
1021 //
1022 // bool attrib_list_sentinel_found = false;
1023 //
1024 emitLocalVariablesForSentinel(cfunc, out);
1025
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001026 // Emit local variable declarations for pointer arguments
1027 //
1028 // Example:
1029 //
1030 // GLfixed *eqn_base;
1031 // GLfixed *eqn;
1032 //
1033 String offset = "offset";
1034 String remaining = "_remaining";
1035 if (nonPrimitiveArgs.size() > 0) {
1036 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1037 int idx = nonPrimitiveArgs.get(i).intValue();
1038 int cIndex = jfunc.getArgCIndex(idx);
1039 String cname = cfunc.getArgName(cIndex);
1040
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001041 if (!jfunc.getArgType(idx).isBuffer() && !jfunc.getArgType(idx).isArray())
1042 continue;
1043
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001044 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1045 String decl = type.getDeclaration();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001046 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001047 out.println(indent +
1048 decl +
1049 (decl.endsWith("*") ? "" : " ") +
1050 jfunc.getArgName(idx) +
1051 "_base = (" + decl + ") 0;");
1052 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001053 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054 "_" + cname + "Remaining";
1055 out.println(indent +
1056 "jint " + remaining + ";");
1057 out.println(indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001058 decl +
1059 (decl.endsWith("*") ? "" : " ") +
1060 jfunc.getArgName(idx) +
1061 " = (" + decl + ") 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001062 }
1063
1064 out.println();
1065 }
1066
Jack Palevich50d0b142009-11-19 16:34:55 +08001067 // Emit local variable declaration for strings
1068 if (stringArgs.size() > 0) {
1069 for (int i = 0; i < stringArgs.size(); i++) {
1070 int idx = stringArgs.get(i).intValue();
1071 int cIndex = jfunc.getArgCIndex(idx);
1072 String cname = cfunc.getArgName(cIndex);
1073
1074 out.println(indent + "const char* _native" + cname + " = 0;");
1075 }
1076
1077 out.println();
1078 }
1079
1080 // Null pointer checks and GetStringUTFChars
1081 if (stringArgs.size() > 0) {
1082 for (int i = 0; i < stringArgs.size(); i++) {
1083 int idx = stringArgs.get(i).intValue();
1084 int cIndex = jfunc.getArgCIndex(idx);
1085 String cname = cfunc.getArgName(cIndex);
1086
1087 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1088 String decl = type.getDeclaration();
Jack Palevich50d0b142009-11-19 16:34:55 +08001089 needsExit = true;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001090 out.println(indent + "if (!" + cname + ") {");
Elliott Hughes2adde7c2013-09-24 17:18:05 -07001091 out.println(indent + indent + "_exception = 1;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001092 out.println(indent + indent +
1093 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1094 out.println(indent + indent +
1095 "_exceptionMessage = \"" + cname + " == null\";");
1096 out.println(indent + indent + "goto exit;");
Jack Palevich50d0b142009-11-19 16:34:55 +08001097 out.println(indent + "}");
1098
1099 out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
1100 }
1101
1102 out.println();
1103 }
1104
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001105 // Emit 'GetPrimitiveArrayCritical' for non-object arrays
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001106 // Emit 'GetPointer' calls for Buffer pointers
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001107 if (nonPrimitiveArgs.size() > 0) {
1108 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1109 int idx = nonPrimitiveArgs.get(i).intValue();
1110 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -07001111
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001112 String cname = cfunc.getArgName(cIndex);
1113 offset = numArrays <= 1 ? "offset" :
1114 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +08001115 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001116 "_" + cname + "Remaining";
1117
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001118 if (jfunc.getArgType(idx).isArray()
1119 && !jfunc.getArgType(idx).isEGLHandle()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001120 needsExit = true;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001121 out.println(indent + "if (!" + cname + "_ref) {");
1122 out.println(indent + indent + "_exception = 1;");
1123 out.println(indent + indent +
1124 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1125 out.println(indent + indent +
1126 "_exceptionMessage = \"" + cname +" == null\";");
1127 out.println(indent + indent + "goto exit;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 out.println(indent + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001129 out.println(indent + "if (" + offset + " < 0) {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001130 out.println(indent + indent + "_exception = 1;");
1131 out.println(indent + indent +
1132 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1133 out.println(indent + indent +
1134 "_exceptionMessage = \"" + offset +" < 0\";");
1135 out.println(indent + indent + "goto exit;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001136 out.println(indent + "}");
1137
1138 out.println(indent + remaining + " = " +
Jack Palevich6cbca502009-04-13 16:22:25 -07001139 (mUseCPlusPlus ? "_env" : "(*_env)") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001140 "->GetArrayLength(" +
1141 (mUseCPlusPlus ? "" : "_env, ") +
1142 cname + "_ref) - " + offset + ";");
1143
1144 emitNativeBoundsChecks(cfunc, cname, out, false,
1145 emitExceptionCheck,
1146 offset, remaining, " ");
1147
1148 out.println(indent +
1149 cname +
1150 "_base = (" +
1151 cfunc.getArgType(cIndex).getDeclaration() +
1152 ")");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001153 String arrayGetter = jfunc.getArgType(idx).getArrayGetterForPrimitiveArray();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001154 out.println(indent + " " +
1155 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001156 "->" + arrayGetter + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001157 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001158 jfunc.getArgName(idx) +
1159 "_ref, (jboolean *)0);");
1160 out.println(indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001161 cname + " = " + cname + "_base + " + offset + ";");
1162
1163 emitSentinelCheck(cfunc, cname, out, false,
1164 emitExceptionCheck, offset,
1165 remaining, indent);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001166 out.println();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001167 } else if (jfunc.getArgType(idx).isArray()
1168 && jfunc.getArgType(idx).isEGLHandle()) {
1169 needsExit = true;
1170 out.println(indent + "if (!" + cname + "_ref) {");
1171 out.println(indent + indent + "_exception = 1;");
1172 out.println(indent + indent +
1173 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1174 out.println(indent + indent + "_exceptionMessage = \"" + cname +" == null\";");
1175 out.println(indent + indent + "goto exit;");
1176 out.println(indent + "}");
1177 out.println(indent + "if (" + offset + " < 0) {");
1178 out.println(indent + indent + "_exception = 1;");
1179 out.println(indent + indent +
1180 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1181 out.println(indent + indent + "_exceptionMessage = \"" + offset +" < 0\";");
1182 out.println(indent + indent + "goto exit;");
1183 out.println(indent + "}");
1184
1185 out.println(indent + remaining + " = " +
1186 (mUseCPlusPlus ? "_env" : "(*_env)") +
1187 "->GetArrayLength(" +
1188 (mUseCPlusPlus ? "" : "_env, ") +
1189 cname + "_ref) - " + offset + ";");
1190 emitNativeBoundsChecks(cfunc, cname, out, false,
1191 emitExceptionCheck,
1192 offset, remaining, " ");
1193 out.println(indent +
1194 jfunc.getArgName(idx) + " = new " +
1195 cfunc.getArgType(cIndex).getBaseType() +
1196 "["+ remaining + "];");
1197 out.println();
1198 } else if (jfunc.getArgType(idx).isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001199 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001200 "_" + cfunc.getArgName(cIndex) + "Array";
1201 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1202 "_" + cfunc.getArgName(cIndex) + "BufferOffset";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001203
Jack Palevich46d25a32009-05-07 18:28:29 -07001204 boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001205 if (nullAllowed) {
1206 out.println(indent + "if (" + cname + "_buf) {");
1207 out.print(indent);
1208 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001209
Jack Palevich46d25a32009-05-07 18:28:29 -07001210 if (isPointerFunc) {
1211 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001212 cname +
1213 " = (" +
1214 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001215 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001216 cname + "_buf);");
1217 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001218 out.println(iii + indent + "if ( ! " + cname + " ) {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001219 out.println(iii + indent + indent + "return;");
Jack Palevich46d25a32009-05-07 18:28:29 -07001220 out.println(iii + indent + "}");
1221 } else {
1222 out.println(indent +
1223 cname +
1224 " = (" +
1225 cfunc.getArgType(cIndex).getDeclaration() +
1226 ")getPointer(_env, " +
1227 cname +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001228 "_buf, (jarray*)&" + array + ", &" + remaining + ", &" + bufferOffset +
Jack Palevich46d25a32009-05-07 18:28:29 -07001229 ");");
1230 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001231
Jack Palevich5afdc872009-10-21 11:02:44 -07001232 emitNativeBoundsChecks(cfunc, cname, out, true,
1233 emitExceptionCheck,
1234 offset, remaining, nullAllowed ? " " : " ");
1235
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001236 if (nullAllowed) {
1237 out.println(indent + "}");
1238 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001239 }
1240 }
1241 }
1242
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001243 // Emit 'GetPrimitiveArrayCritical' for pointers if needed
1244 if (nonPrimitiveArgs.size() > 0) {
1245 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1246 int idx = nonPrimitiveArgs.get(i).intValue();
1247 int cIndex = jfunc.getArgCIndex(idx);
1248
1249 if(!jfunc.getArgType(idx).isBuffer() || isPointerFunc) continue;
1250
1251 String cname = cfunc.getArgName(cIndex);
1252 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1253 "_" + cname + "BufferOffset";
1254 String array = numBufferArgs <= 1 ? "_array" :
1255 "_" + cfunc.getArgName(cIndex) + "Array";
1256
Thomas Tafertshofer36b285e2012-07-23 16:52:32 -07001257 boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
1258 if (nullAllowed) {
1259 out.println(indent + "if (" + cname + "_buf && " + cname +" == NULL) {");
1260 } else {
1261 out.println(indent + "if (" + cname +" == NULL) {");
1262 }
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001263 JType argType = jfunc.getArgType(idx);
1264 if (argType.isTypedBuffer()) {
1265 String arrayGetter = argType.getArrayTypeForTypedBuffer().getArrayGetterForPrimitiveArray();
1266 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->" + arrayGetter + "(" + array + ", (jboolean *) 0);");
1267 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1268 out.println(indent + "}");
1269 } else {
1270 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->GetPrimitiveArrayCritical(" + array + ", (jboolean *) 0);");
1271 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1272 out.println(indent + "}");
1273 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001274 }
1275 }
1276
1277
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001278 if (!isVoid) {
1279 out.print(indent + "_returnValue = ");
1280 } else {
1281 out.print(indent);
1282 }
1283 String name = cfunc.getName();
1284
1285 if (mUseContextPointer) {
1286 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1287 name = name.substring(0, 1).toLowerCase() +
1288 name.substring(1, name.length());
1289 out.print("ctx->procs.");
1290 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001291
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001292 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1293
Jack Palevich6cbca502009-04-13 16:22:25 -07001294 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001295 if (numArgs == 0) {
1296 if (mUseContextPointer) {
1297 out.println("ctx);");
1298 } else {
1299 out.println(");");
1300 }
1301 } else {
1302 if (mUseContextPointer) {
1303 out.println("ctx,");
1304 } else {
1305 out.println();
1306 }
1307 for (int i = 0; i < numArgs; i++) {
1308 String typecast;
Jesse Hall071fc662013-04-10 01:17:34 -07001309 if (i == numArgs - 1 && isPointerOffsetFunc) {
Ashok Bhatd8f09612014-02-15 12:51:43 +00001310 typecast = "reinterpret_cast<GLvoid *>";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001311 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001312 typecast = "(" + cfunc.getArgType(i).getDeclaration() + ")";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001313 }
1314 out.print(indent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001315 typecast);
1316
Jack Palevich50d0b142009-11-19 16:34:55 +08001317 if (cfunc.getArgType(i).isConstCharPointer()) {
1318 out.print("_native");
1319 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001320
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001321 if (cfunc.getArgType(i).isEGLHandle() &&
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001322 !cfunc.getArgType(i).isPointer()){
1323 out.print(cfunc.getArgName(i)+"_native");
Ashok Bhatd8f09612014-02-15 12:51:43 +00001324 } else if (i == numArgs - 1 && isPointerOffsetFunc){
1325 out.print("("+cfunc.getArgName(i)+")");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001326 } else {
1327 out.print(cfunc.getArgName(i));
1328 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001329
1330 if (i == numArgs - 1) {
1331 if (isPointerFunc) {
1332 out.println(",");
1333 out.println(indent + indent + "(GLsizei)remaining");
1334 } else {
1335 out.println();
1336 }
1337 } else {
1338 out.println(",");
1339 }
1340 }
1341 out.println(indent + ");");
1342 }
1343
1344 if (needsExit) {
1345 out.println();
1346 out.println("exit:");
1347 needsExit = false;
1348 }
1349
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001350
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001351 if (nonPrimitiveArgs.size() > 0) {
1352 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1353 int idx = nonPrimitiveArgs.get(i).intValue();
1354
1355 int cIndex = jfunc.getArgCIndex(idx);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001356 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001357
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001358 // If the argument is 'const', GL will not write to it.
1359 // In this case, we can use the 'JNI_ABORT' flag to avoid
1360 // the need to write back to the Java array
1361 out.println(indent +
1362 "if (" + jfunc.getArgName(idx) + "_base) {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001363 String arrayReleaser = jfunc.getArgType(idx).getArrayReleaserForPrimitiveArray();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001364 out.println(indent + indent +
1365 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001366 "->" + arrayReleaser + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001367 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001368 jfunc.getArgName(idx) + "_ref, " +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001369 "(j" + jfunc.getArgType(idx).getBaseType() + "*)" + cfunc.getArgName(cIndex) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001370 "_base,");
1371 out.println(indent + indent + indent +
1372 (cfunc.getArgType(cIndex).isConst() ?
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001373 "JNI_ABORT" : "_exception ? JNI_ABORT: 0" ) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001374 ");");
1375 out.println(indent + "}");
1376 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001377 if (! isPointerFunc) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001378 JType argType = jfunc.getArgType(idx);
Jack Palevich46d25a32009-05-07 18:28:29 -07001379 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001380 "_" + cfunc.getArgName(cIndex) + "Array";
Jack Palevich46d25a32009-05-07 18:28:29 -07001381 out.println(indent + "if (" + array + ") {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001382 if (argType.isTypedBuffer()) {
1383 String arrayReleaser =
1384 argType.getArrayTypeForTypedBuffer().getArrayReleaserForPrimitiveArray();
1385 out.println(indent + indent +
1386 "_env->" + arrayReleaser + "(" + array + ", " +
1387 "(j" + argType.getArrayTypeForTypedBuffer().getBaseType() + "*)" +
1388 cfunc.getArgName(cIndex) +
1389 ", " +
1390 (cfunc.getArgType(cIndex).isConst() ?
1391 "JNI_ABORT" : (emitExceptionCheck ?
1392 "_exception ? JNI_ABORT : 0" : "0")) +
1393 ");");
1394 } else {
1395 out.println(indent + indent +
1396 "releasePointer(_env, " + array + ", " +
1397 cfunc.getArgName(cIndex) +
1398 ", " +
1399 (cfunc.getArgType(cIndex).isConst() ?
1400 "JNI_FALSE" : (emitExceptionCheck ?
1401 "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
1402 ");");
1403 }
Jack Palevich46d25a32009-05-07 18:28:29 -07001404 out.println(indent + "}");
1405 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001406 }
1407 }
1408 }
1409
Jack Palevich50d0b142009-11-19 16:34:55 +08001410 // Emit local variable declaration for strings
1411 if (stringArgs.size() > 0) {
1412 for (int i = 0; i < stringArgs.size(); i++) {
1413 int idx = stringArgs.get(i).intValue();
1414 int cIndex = jfunc.getArgCIndex(idx);
1415 String cname = cfunc.getArgName(cIndex);
1416
1417 out.println(indent + "if (_native" + cname + ") {");
1418 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1419 out.println(indent + "}");
1420 }
1421
1422 out.println();
1423 }
1424
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001425 // Copy results back to java arrays
1426 if (nonPrimitiveArgs.size() > 0) {
1427 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1428 int idx = nonPrimitiveArgs.get(i).intValue();
1429 int cIndex = jfunc.getArgCIndex(idx);
1430 String baseType = cfunc.getArgType(cIndex).getBaseType().toLowerCase();
1431 if (jfunc.getArgType(idx).isArray() && jfunc.getArgType(idx).isClass()) {
1432 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
1433 "_" + cfunc.getArgName(cIndex) + "Remaining";
1434 offset = numArrays <= 1 ? "offset" : cfunc.getArgName(cIndex) + "Offset";
1435 out.println(indent +
1436 "if (" + jfunc.getArgName(idx) + ") {");
1437 out.println(indent + indent +
1438 "for (int i = 0; i < " + remaining + "; i++) {");
1439 out.println(indent + indent + indent +
1440 "jobject " + cfunc.getArgName(cIndex) +
1441 "_new = toEGLHandle(_env, " + baseType +
1442 "Class, " + baseType + "Constructor, " +
1443 cfunc.getArgName(cIndex) + "[i]);");
1444 out.println(indent + indent + indent +
1445 (mUseCPlusPlus ? "_env" : "(*_env)") +
1446 "->SetObjectArrayElement(" +
1447 (mUseCPlusPlus ? "" : "_env, ") +
1448 cfunc.getArgName(cIndex) +
1449 "_ref, i + " + offset + ", " +
1450 cfunc.getArgName(cIndex) + "_new);");
1451 out.println(indent + indent + "}");
1452 out.println(indent + indent +
1453 "delete[] " + jfunc.getArgName(idx) + ";");
1454 out.println(indent + "}");
1455 }
1456 }
1457 }
1458
1459
1460 // Throw exception if there is one
1461 if (emitExceptionCheck) {
1462 out.println(indent + "if (_exception) {");
1463 out.println(indent + indent +
1464 "jniThrowException(_env, _exceptionType, _exceptionMessage);");
1465 out.println(indent + "}");
1466
1467 }
1468
Jack Palevich50d0b142009-11-19 16:34:55 +08001469
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001470 if (!isVoid) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001471 if (cfunc.getType().isEGLHandle()) {
1472 String baseType = cfunc.getType().getBaseType().toLowerCase();
1473 out.println(indent +
1474 "return toEGLHandle(_env, " + baseType + "Class, " +
1475 baseType + "Constructor, _returnValue);");
1476 } else {
Jesse Hall68fc8bb2013-04-10 01:01:00 -07001477 out.println(indent + "return (" +
1478 getJniType(jfunc.getType()) + ")_returnValue;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001479 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001480 }
1481
1482 out.println("}");
1483 out.println();
1484 }
1485
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001486}