blob: 2db4e8d2e243056fd13c1c3f0e4afbf369231bf9 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001import java.io.PrintStream;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002import java.util.ArrayList;
3import java.util.HashSet;
4import java.util.Iterator;
5import java.util.List;
6
Jack Palevichffac1ef2009-04-14 19:00:09 -07007public class JniCodeEmitter {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08008
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08009 static final boolean mUseCPlusPlus = true;
Jack Palevichffac1ef2009-04-14 19:00:09 -070010 protected boolean mUseContextPointer = true;
Jack Palevich427f5852009-04-15 19:13:17 -070011 protected boolean mUseStaticMethods = false;
Jack Palevichffac1ef2009-04-14 19:00:09 -070012 protected String mClassPathName;
13 protected ParameterChecker mChecker;
14 protected List<String> nativeRegistrations = new ArrayList<String>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080015 boolean needsExit;
Jack Palevichffac1ef2009-04-14 19:00:09 -070016 protected static String indent = " ";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017 HashSet<String> mFunctionsEmitted = new HashSet<String>();
18
Jack Palevichffac1ef2009-04-14 19:00:09 -070019 public static String getJniName(JType jType) {
20 String jniName = "";
21 if (jType.isClass()) {
22 return "L" + jType.getBaseType() + ";";
23 } else if (jType.isArray()) {
24 jniName = "[";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025 }
Jack Palevichffac1ef2009-04-14 19:00:09 -070026
27 String baseType = jType.getBaseType();
28 if (baseType.equals("int")) {
29 jniName += "I";
30 } else if (baseType.equals("float")) {
31 jniName += "F";
32 } else if (baseType.equals("boolean")) {
33 jniName += "Z";
34 } else if (baseType.equals("short")) {
35 jniName += "S";
36 } else if (baseType.equals("long")) {
37 jniName += "L";
38 } else if (baseType.equals("byte")) {
39 jniName += "B";
Jack Palevich50d0b142009-11-19 16:34:55 +080040 } else if (baseType.equals("String")) {
41 jniName += "Ljava/lang/String;";
42 } else if (baseType.equals("void")) {
43 // nothing.
44 } else {
45 throw new RuntimeException("Uknown primitive basetype " + baseType);
Jack Palevichffac1ef2009-04-14 19:00:09 -070046 }
47 return jniName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048 }
49
Jack Palevichffac1ef2009-04-14 19:00:09 -070050
51 public void emitCode(CFunc cfunc, String original,
52 PrintStream javaInterfaceStream,
53 PrintStream javaImplStream,
54 PrintStream cStream) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080055 JFunc jfunc;
56 String signature;
57 boolean duplicate;
Jack Palevich6cbca502009-04-13 16:22:25 -070058
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059 if (cfunc.hasTypedPointerArg()) {
60 jfunc = JFunc.convert(cfunc, true);
61
62 // Don't emit duplicate functions
63 // These may appear because they are defined in multiple
64 // Java interfaces (e.g., GL11/GL11ExtensionPack)
65 signature = jfunc.toString();
66 duplicate = false;
67 if (mFunctionsEmitted.contains(signature)) {
68 duplicate = true;
69 } else {
70 mFunctionsEmitted.add(signature);
71 }
72
73 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070074 emitNativeDeclaration(jfunc, javaImplStream);
75 emitJavaCode(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080076 }
Jack Palevich427f5852009-04-15 19:13:17 -070077 if (javaInterfaceStream != null) {
78 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
79 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080080 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070081 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080082 }
83 }
84
85 jfunc = JFunc.convert(cfunc, false);
86
87 signature = jfunc.toString();
88 duplicate = false;
89 if (mFunctionsEmitted.contains(signature)) {
90 duplicate = true;
91 } else {
92 mFunctionsEmitted.add(signature);
93 }
94
95 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070096 emitNativeDeclaration(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080097 }
Jack Palevich427f5852009-04-15 19:13:17 -070098 if (javaInterfaceStream != null) {
99 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
100 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800101 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700102 emitJavaCode(jfunc, javaImplStream);
103 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800104 }
105 }
106
107 public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
108 out.println(" // C function " + jfunc.getCFunc().getOriginal());
109 out.println();
110
111 emitFunction(jfunc, out, true, false);
112 }
113
114 public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
115 emitFunction(jfunc, out, false, true);
116 }
117
118 public void emitJavaCode(JFunc jfunc, PrintStream out) {
119 emitFunction(jfunc, out, false, false);
120 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700121
Jack Palevich66089a32009-12-08 15:43:51 +0800122 boolean isPointerFunc(JFunc jfunc) {
123 String name = jfunc.getName();
124 return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
125 && jfunc.getCFunc().hasPointerArg();
126 }
127
Jack Palevichffac1ef2009-04-14 19:00:09 -0700128 void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800129 boolean isVoid = jfunc.getType().isVoid();
Jack Palevich66089a32009-12-08 15:43:51 +0800130 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800131
132 if (!isVoid) {
133 out.println(iii +
134 jfunc.getType() + " _returnValue;");
135 }
136 out.println(iii +
137 (isVoid ? "" : "_returnValue = ") +
138 jfunc.getName() +
139 (isPointerFunc ? "Bounds" : "" ) +
140 "(");
Jack Palevich6cbca502009-04-13 16:22:25 -0700141
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800142 int numArgs = jfunc.getNumArgs();
143 for (int i = 0; i < numArgs; i++) {
144 String argName = jfunc.getArgName(i);
145 JType argType = jfunc.getArgType(i);
146
147 if (grabArray && argType.isTypedBuffer()) {
148 String typeName = argType.getBaseType();
149 typeName = typeName.substring(9, typeName.length() - 6);
150 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
Jack Palevich6cbca502009-04-13 16:22:25 -0700151 out.print(iii + indent + "getOffset(" + argName + ")");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800152 } else {
153 out.print(iii + indent + argName);
154 }
155 if (i == numArgs - 1) {
156 if (isPointerFunc) {
157 out.println(",");
158 out.println(iii + indent + argName + ".remaining()");
159 } else {
160 out.println();
161 }
162 } else {
163 out.println(",");
164 }
165 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700166
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800167 out.println(iii + ");");
168 }
169
Jack Palevichffac1ef2009-04-14 19:00:09 -0700170 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
171 String iii) {
172 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
173 "offset", "_remaining", iii);
174 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800175
Jack Palevichffac1ef2009-04-14 19:00:09 -0700176 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
177 String offset, String remaining, String iii) {
178 out.println(iii + " default:");
179 out.println(iii + " _needed = 0;");
180 out.println(iii + " break;");
181 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800182
Jack Palevichffac1ef2009-04-14 19:00:09 -0700183 out.println(iii + "if (" + remaining + " < _needed) {");
184 if (emitExceptionCheck) {
185 out.println(iii + indent + "_exception = 1;");
186 }
187 out.println(iii + indent +
188 (mUseCPlusPlus ? "_env" : "(*_env)") +
189 "->ThrowNew(" +
190 (mUseCPlusPlus ? "" : "_env, ") +
191 "IAEClass, " +
192 "\"" +
193 (isBuffer ?
194 "remaining()" : "length - " + offset) +
195 " < needed\");");
196 out.println(iii + indent + "goto exit;");
197 needsExit = true;
198 out.println(iii + "}");
199 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200
201 boolean isNullAllowed(CFunc cfunc) {
202 String[] checks = mChecker.getChecks(cfunc.getName());
203 int index = 1;
204 if (checks != null) {
205 while (index < checks.length) {
206 if (checks[index].equals("return")) {
207 index += 2;
208 } else if (checks[index].startsWith("check")) {
209 index += 3;
210 } else if (checks[index].equals("ifcheck")) {
211 index += 5;
212 } else if (checks[index].equals("unsupported")) {
213 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800214 } else if (checks[index].equals("requires")) {
215 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216 } else if (checks[index].equals("nullAllowed")) {
217 return true;
218 } else {
219 System.out.println("Error: unknown keyword \"" +
220 checks[index] + "\"");
221 System.exit(0);
222 }
223 }
224 }
225 return false;
226 }
227
228 String getErrorReturnValue(CFunc cfunc) {
229 CType returnType = cfunc.getType();
230 boolean isVoid = returnType.isVoid();
231 if (isVoid) {
232 return null;
233 }
234
235 String[] checks = mChecker.getChecks(cfunc.getName());
236
237 int index = 1;
238 if (checks != null) {
239 while (index < checks.length) {
240 if (checks[index].equals("return")) {
241 return checks[index + 1];
242 } else if (checks[index].startsWith("check")) {
243 index += 3;
244 } else if (checks[index].equals("ifcheck")) {
245 index += 5;
246 } else if (checks[index].equals("unsupported")) {
247 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800248 } else if (checks[index].equals("requires")) {
249 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800250 } else if (checks[index].equals("nullAllowed")) {
251 index += 1;
252 } else {
253 System.out.println("Error: unknown keyword \"" +
254 checks[index] + "\"");
255 System.exit(0);
256 }
257 }
258 }
259
260 return null;
261 }
262
263 boolean isUnsupportedFunc(CFunc cfunc) {
264 String[] checks = mChecker.getChecks(cfunc.getName());
265 int index = 1;
266 if (checks != null) {
267 while (index < checks.length) {
268 if (checks[index].equals("unsupported")) {
269 return true;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800270 } else if (checks[index].equals("requires")) {
271 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800272 } else if (checks[index].equals("return")) {
273 index += 2;
274 } else if (checks[index].startsWith("check")) {
275 index += 3;
276 } else if (checks[index].equals("ifcheck")) {
277 index += 5;
278 } else if (checks[index].equals("nullAllowed")) {
279 index += 1;
280 } else {
281 System.out.println("Error: unknown keyword \"" +
282 checks[index] + "\"");
283 System.exit(0);
284 }
285 }
286 }
287 return false;
288 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800289
290 String isRequiresFunc(CFunc cfunc) {
291 String[] checks = mChecker.getChecks(cfunc.getName());
292 int index = 1;
293 if (checks != null) {
294 while (index < checks.length) {
295 if (checks[index].equals("unsupported")) {
296 index += 1;
297 } else if (checks[index].equals("requires")) {
298 return checks[index+1];
299 } else if (checks[index].equals("return")) {
300 index += 2;
301 } else if (checks[index].startsWith("check")) {
302 index += 3;
303 } else if (checks[index].equals("ifcheck")) {
304 index += 5;
305 } else if (checks[index].equals("nullAllowed")) {
306 index += 1;
307 } else {
308 System.out.println("Error: unknown keyword \"" +
309 checks[index] + "\"");
310 System.exit(0);
311 }
312 }
313 }
314 return null;
315 }
316
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700318 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800319
Jack Palevichffac1ef2009-04-14 19:00:09 -0700320 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800321
Jack Palevichffac1ef2009-04-14 19:00:09 -0700322 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800323
Jack Palevichffac1ef2009-04-14 19:00:09 -0700324 int index = 1;
325 if (checks != null) {
326 while (index < checks.length) {
327 if (checks[index].startsWith("check")) {
328 if (lastWasIfcheck) {
329 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
330 offset, remaining, iii);
331 }
332 lastWasIfcheck = false;
333 if (cname != null && !cname.equals(checks[index + 1])) {
334 index += 3;
335 continue;
336 }
337 out.println(iii + "if (" + remaining + " < " +
338 checks[index + 2] +
339 ") {");
340 if (emitExceptionCheck) {
341 out.println(iii + indent + "_exception = 1;");
342 }
343 String exceptionClassName = "IAEClass";
344 // If the "check" keyword was of the form
345 // "check_<class name>", use the class name in the
346 // exception to be thrown
347 int underscore = checks[index].indexOf('_');
348 if (underscore >= 0) {
349 exceptionClassName = checks[index].substring(underscore + 1) + "Class";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800350 }
Jack Palevichffac1ef2009-04-14 19:00:09 -0700351 out.println(iii + indent +
352 (mUseCPlusPlus ? "_env" : "(*_env)") +
353 "->ThrowNew(" +
354 (mUseCPlusPlus ? "" : "_env, ") +
355 exceptionClassName + ", " +
356 "\"" +
357 (isBuffer ?
358 "remaining()" : "length - " + offset) +
359 " < " + checks[index + 2] +
360 "\");");
361
362 out.println(iii + indent + "goto exit;");
363 needsExit = true;
364 out.println(iii + "}");
365
366 index += 3;
367 } else if (checks[index].equals("ifcheck")) {
368 String[] matches = checks[index + 4].split(",");
369
370 if (!lastWasIfcheck) {
371 out.println(iii + "int _needed;");
372 out.println(iii +
373 "switch (" +
374 checks[index + 3] +
375 ") {");
376 }
377
378 for (int i = 0; i < matches.length; i++) {
379 out.println("#if defined(" + matches[i] + ")");
380 out.println(iii +
381 " case " +
382 matches[i] +
383 ":");
384 out.println("#endif // defined(" + matches[i] + ")");
385 }
386 out.println(iii +
387 " _needed = " +
388 checks[index + 2] +
389 ";");
390 out.println(iii +
391 " break;");
392
393 lastWasIfcheck = true;
394 index += 5;
395 } else if (checks[index].equals("return")) {
396 // ignore
397 index += 2;
398 } else if (checks[index].equals("unsupported")) {
399 // ignore
400 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800401 } else if (checks[index].equals("requires")) {
402 // ignore
403 index += 2;
Jack Palevichffac1ef2009-04-14 19:00:09 -0700404 } else if (checks[index].equals("nullAllowed")) {
405 // ignore
406 index += 1;
407 } else {
408 System.out.println("Error: unknown keyword \"" +
409 checks[index] + "\"");
410 System.exit(0);
411 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800412 }
Jack Palevichffac1ef2009-04-14 19:00:09 -0700413 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800414
Jack Palevichffac1ef2009-04-14 19:00:09 -0700415 if (lastWasIfcheck) {
416 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417 }
418 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800419
Jack Palevichffac1ef2009-04-14 19:00:09 -0700420 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800421 if (nonPrimitiveArgs.size() > 0) {
422 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
423 int idx = nonPrimitiveArgs.get(i).intValue();
424 int cIndex = jfunc.getArgCIndex(idx);
425 if (jfunc.getArgType(idx).isArray()) {
426 if (!cfunc.getArgType(cIndex).isConst()) {
427 return true;
428 }
429 } else if (jfunc.getArgType(idx).isBuffer()) {
430 if (!cfunc.getArgType(cIndex).isConst()) {
431 return true;
432 }
433 }
434 }
435 }
436
437 return false;
438 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700439
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800440 /**
441 * Emit a function in several variants:
442 *
443 * if nativeDecl: public native <returntype> func(args);
444 *
445 * if !nativeDecl:
446 * if interfaceDecl: public <returntype> func(args);
447 * if !interfaceDecl: public <returntype> func(args) { body }
448 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700449 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800450 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800451
452 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
453 // If it's not a pointer function, we've already emitted it
454 // with nativeDecl == true
455 return;
456 }
457
Jack Palevich427f5852009-04-15 19:13:17 -0700458 String maybeStatic = mUseStaticMethods ? "static " : "";
459
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800460 if (isPointerFunc) {
461 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700462 (nativeDecl ? "private " + maybeStatic +"native " :
463 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800464 jfunc.getType() + " " +
465 jfunc.getName() +
466 (nativeDecl ? "Bounds" : "") +
467 "(");
468 } else {
469 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700470 (nativeDecl ? "public " + maybeStatic +"native " :
471 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800472 jfunc.getType() + " " +
473 jfunc.getName() +
474 "(");
475 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700476
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800477 int numArgs = jfunc.getNumArgs();
478 for (int i = 0; i < numArgs; i++) {
479 String argName = jfunc.getArgName(i);
480 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700481
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800482 out.print(indent + indent + argType + " " + argName);
483 if (i == numArgs - 1) {
484 if (isPointerFunc && nativeDecl) {
485 out.println(",");
486 out.println(indent + indent + "int remaining");
487 } else {
488 out.println();
489 }
490 } else {
491 out.println(",");
492 }
493 }
494
495 if (nativeDecl || interfaceDecl) {
496 out.println(indent + ");");
497 } else {
498 out.println(indent + ") {");
499
500 String iii = indent + indent;
501
Jack Palevich46d25a32009-05-07 18:28:29 -0700502 // emitBoundsChecks(jfunc, out, iii);
503 emitFunctionCall(jfunc, out, iii, false);
504
505 // Set the pointer after we call the native code, so that if
506 // the native code throws an exception we don't modify the
507 // pointer. We assume that the native code is written so that
508 // if an exception is thrown, then the underlying glXXXPointer
509 // function will not have been called.
510
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800511 String fname = jfunc.getName();
512 if (isPointerFunc) {
513 // TODO - deal with VBO variants
514 if (fname.equals("glColorPointer")) {
515 out.println(iii + "if ((size == 4) &&");
516 out.println(iii + " ((type == GL_FLOAT) ||");
517 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
518 out.println(iii + " (type == GL_FIXED)) &&");
519 out.println(iii + " (stride >= 0)) {");
520 out.println(iii + indent + "_colorPointer = pointer;");
521 out.println(iii + "}");
522 } else if (fname.equals("glNormalPointer")) {
523 out.println(iii + "if (((type == GL_FLOAT) ||");
524 out.println(iii + " (type == GL_BYTE) ||");
525 out.println(iii + " (type == GL_SHORT) ||");
526 out.println(iii + " (type == GL_FIXED)) &&");
527 out.println(iii + " (stride >= 0)) {");
528 out.println(iii + indent + "_normalPointer = pointer;");
529 out.println(iii + "}");
530 } else if (fname.equals("glTexCoordPointer")) {
531 out.println(iii + "if (((size == 2) ||");
532 out.println(iii + " (size == 3) ||");
533 out.println(iii + " (size == 4)) &&");
534 out.println(iii + " ((type == GL_FLOAT) ||");
535 out.println(iii + " (type == GL_BYTE) ||");
536 out.println(iii + " (type == GL_SHORT) ||");
537 out.println(iii + " (type == GL_FIXED)) &&");
538 out.println(iii + " (stride >= 0)) {");
539 out.println(iii + indent + "_texCoordPointer = pointer;");
540 out.println(iii + "}");
541 } else if (fname.equals("glVertexPointer")) {
542 out.println(iii + "if (((size == 2) ||");
543 out.println(iii + " (size == 3) ||");
544 out.println(iii + " (size == 4)) &&");
545 out.println(iii + " ((type == GL_FLOAT) ||");
546 out.println(iii + " (type == GL_BYTE) ||");
547 out.println(iii + " (type == GL_SHORT) ||");
548 out.println(iii + " (type == GL_FIXED)) &&");
549 out.println(iii + " (stride >= 0)) {");
550 out.println(iii + indent + "_vertexPointer = pointer;");
551 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800552 } else if (fname.equals("glPointSizePointerOES")) {
553 out.println(iii + "if (((type == GL_FLOAT) ||");
554 out.println(iii + " (type == GL_FIXED)) &&");
555 out.println(iii + " (stride >= 0)) {");
556 out.println(iii + indent + "_pointSizePointerOES = pointer;");
557 out.println(iii + "}");
558 } else if (fname.equals("glMatrixIndexPointerOES")) {
559 out.println(iii + "if (((size == 2) ||");
560 out.println(iii + " (size == 3) ||");
561 out.println(iii + " (size == 4)) &&");
562 out.println(iii + " ((type == GL_FLOAT) ||");
563 out.println(iii + " (type == GL_BYTE) ||");
564 out.println(iii + " (type == GL_SHORT) ||");
565 out.println(iii + " (type == GL_FIXED)) &&");
566 out.println(iii + " (stride >= 0)) {");
567 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
568 out.println(iii + "}");
569 } else if (fname.equals("glWeightPointer")) {
570 out.println(iii + "if (((size == 2) ||");
571 out.println(iii + " (size == 3) ||");
572 out.println(iii + " (size == 4)) &&");
573 out.println(iii + " ((type == GL_FLOAT) ||");
574 out.println(iii + " (type == GL_BYTE) ||");
575 out.println(iii + " (type == GL_SHORT) ||");
576 out.println(iii + " (type == GL_FIXED)) &&");
577 out.println(iii + " (stride >= 0)) {");
578 out.println(iii + indent + "_weightPointerOES = pointer;");
579 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800580 }
581 }
582
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800583 boolean isVoid = jfunc.getType().isVoid();
584
585 if (!isVoid) {
586 out.println(indent + indent + "return _returnValue;");
587 }
588 out.println(indent + "}");
589 }
590 out.println();
591 }
592
Jack Palevichffac1ef2009-04-14 19:00:09 -0700593 public void addNativeRegistration(String s) {
594 nativeRegistrations.add(s);
595 }
596
Jack Palevich427f5852009-04-15 19:13:17 -0700597 public void emitNativeRegistration(String registrationFunctionName,
598 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700599 cStream.println("static const char *classPathName = \"" +
600 mClassPathName +
601 "\";");
602 cStream.println();
603
604 cStream.println("static JNINativeMethod methods[] = {");
605
606 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
607
608 Iterator<String> i = nativeRegistrations.iterator();
609 while (i.hasNext()) {
610 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800611 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700612
Jack Palevichffac1ef2009-04-14 19:00:09 -0700613 cStream.println("};");
614 cStream.println();
615
616
Jack Palevich427f5852009-04-15 19:13:17 -0700617 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700618 cStream.println("{");
619 cStream.println(indent +
620 "int err;");
621
622 cStream.println(indent +
623 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
624
625 cStream.println(indent + "return err;");
626 cStream.println("}");
627 }
628
629 public JniCodeEmitter() {
630 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800631 }
632
633 String getJniType(JType jType) {
634 if (jType.isVoid()) {
635 return "void";
636 }
637
638 String baseType = jType.getBaseType();
639 if (jType.isPrimitive()) {
640 if (baseType.equals("String")) {
641 return "jstring";
642 } else {
643 return "j" + baseType;
644 }
645 } else if (jType.isArray()) {
646 return "j" + baseType + "Array";
647 } else {
648 return "jobject";
649 }
650 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700651
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800652 String getJniMangledName(String name) {
653 name = name.replaceAll("_", "_1");
654 name = name.replaceAll(";", "_2");
655 name = name.replaceAll("\\[", "_3");
656 return name;
657 }
658
659 public void emitJniCode(JFunc jfunc, PrintStream out) {
660 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700661
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800662 // Emit comment identifying original C function
663 //
664 // Example:
665 //
666 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
667 //
668 out.println("/* " + cfunc.getOriginal() + " */");
669
670 // Emit JNI signature (name)
671 //
672 // Example:
673 //
674 // void
675 // android_glClipPlanef__I_3FI
676 //
677
678 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800679 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800680 boolean isVBOPointerFunc = (outName.endsWith("Pointer") ||
Jack Palevich66089a32009-12-08 15:43:51 +0800681 outName.endsWith("PointerOES") ||
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800682 outName.endsWith("DrawElements")) &&
683 !jfunc.getCFunc().hasPointerArg();
684 if (isPointerFunc) {
685 outName += "Bounds";
686 }
687
688 out.print("static ");
689 out.println(getJniType(jfunc.getType()));
690 out.print(outName);
691
692 String rsignature = getJniName(jfunc.getType());
693
694 String signature = "";
695 int numArgs = jfunc.getNumArgs();
696 for (int i = 0; i < numArgs; i++) {
697 JType argType = jfunc.getArgType(i);
698 signature += getJniName(argType);
699 }
700 if (isPointerFunc) {
701 signature += "I";
702 }
703
704 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800705 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800706 out.print("__" + sig);
707 outName += "__" + sig;
Jack Palevich6cbca502009-04-13 16:22:25 -0700708
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800709 signature = signature.replace('.', '/');
710 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700711
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800712 out.println();
713 if (rsignature.length() == 0) {
714 rsignature = "V";
715 }
716
717 String s = "{\"" +
718 jfunc.getName() +
719 (isPointerFunc ? "Bounds" : "") +
720 "\", \"(" + signature +")" +
721 rsignature +
722 "\", (void *) " +
723 outName +
724 " },";
725 nativeRegistrations.add(s);
726
727 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800728 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800729 int numBufferArgs = 0;
730 List<String> bufferArgNames = new ArrayList<String>();
731
732 // Emit JNI signature (arguments)
733 //
734 // Example:
735 //
736 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
737 //
738 out.print(" (JNIEnv *_env, jobject _this");
739 for (int i = 0; i < numArgs; i++) {
740 out.print(", ");
741 JType argType = jfunc.getArgType(i);
742 String suffix;
743 if (!argType.isPrimitive()) {
744 if (argType.isArray()) {
745 suffix = "_ref";
746 } else {
747 suffix = "_buf";
748 }
749 nonPrimitiveArgs.add(new Integer(i));
750 if (jfunc.getArgType(i).isBuffer()) {
751 int cIndex = jfunc.getArgCIndex(i);
752 String cname = cfunc.getArgName(cIndex);
753 bufferArgNames.add(cname);
754 numBufferArgs++;
755 }
756 } else {
757 suffix = "";
758 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800759 if (argType.isString()) {
760 stringArgs.add(new Integer(i));
761 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800762
763 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
764 }
765 if (isPointerFunc) {
766 out.print(", jint remaining");
767 }
768 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700769
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800770 int numArrays = 0;
771 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800772 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800773 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
774 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800775 JType argType = jfunc.getArgType(idx);
776 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800777 ++numArrays;
778 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800779 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800780 ++numBuffers;
781 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800782 if (argType.isString()) {
783 ++numStrings;
784 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800785 }
786
787 // Emit method body
788
789 // Emit local variable declarations for _exception and _returnValue
790 //
791 // Example:
792 //
793 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700794 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800795 // jint _exception;
796 // GLenum _returnValue;
797 //
798 CType returnType = cfunc.getType();
799 boolean isVoid = returnType.isVoid();
800
801 boolean isUnsupported = isUnsupportedFunc(cfunc);
802 if (isUnsupported) {
803 out.println(indent +
804 "_env->ThrowNew(UOEClass,");
805 out.println(indent +
806 " \"" + cfunc.getName() + "\");");
807 if (!isVoid) {
808 String retval = getErrorReturnValue(cfunc);
809 out.println(indent + "return " + retval + ";");
810 }
811 out.println("}");
812 out.println();
813 return;
814 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800815
816 String requiresExtension = isRequiresFunc(cfunc);
817 if (requiresExtension != null) {
818 out.println(indent +
819 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
820 out.println(indent + indent +
821 "_env->ThrowNew(UOEClass,");
822 out.println(indent + indent +
823 " \"" + cfunc.getName() + "\");");
824 if (isVoid) {
825 out.println(indent + indent + " return;");
826 } else {
827 String retval = getErrorReturnValue(cfunc);
828 out.println(indent + indent + " return " + retval + ";");
829 }
830 out.println(indent + "}");
831 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800832 if (mUseContextPointer) {
833 out.println(indent +
834 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
835 }
836
Jack Palevich50d0b142009-11-19 16:34:55 +0800837 boolean initializeReturnValue = stringArgs.size() > 0;
838
839 boolean emitExceptionCheck = (numArrays > 0 || numBuffers > 0 || numStrings > 0) &&
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800840 hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs);
841 // mChecker.getChecks(cfunc.getName()) != null
842
843 // Emit an _exeption variable if there will be error checks
844 if (emitExceptionCheck) {
845 out.println(indent + "jint _exception = 0;");
846 }
847
848 // Emit a single _array or multiple _XXXArray variables
849 if (numBufferArgs == 1) {
850 out.println(indent + "jarray _array = (jarray) 0;");
851 } else {
852 for (int i = 0; i < numBufferArgs; i++) {
853 out.println(indent + "jarray _" + bufferArgNames.get(i) +
854 "Array = (jarray) 0;");
855 }
856 }
857 if (!isVoid) {
858 String retval = getErrorReturnValue(cfunc);
859 if (retval != null) {
860 out.println(indent + returnType.getDeclaration() +
861 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +0800862 } else if (initializeReturnValue) {
863 out.println(indent + returnType.getDeclaration() +
864 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800865 } else {
866 out.println(indent + returnType.getDeclaration() +
867 " _returnValue;");
868 }
869 }
870
871 // Emit local variable declarations for pointer arguments
872 //
873 // Example:
874 //
875 // GLfixed *eqn_base;
876 // GLfixed *eqn;
877 //
878 String offset = "offset";
879 String remaining = "_remaining";
880 if (nonPrimitiveArgs.size() > 0) {
881 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
882 int idx = nonPrimitiveArgs.get(i).intValue();
883 int cIndex = jfunc.getArgCIndex(idx);
884 String cname = cfunc.getArgName(cIndex);
885
886 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
887 String decl = type.getDeclaration();
888 if (jfunc.getArgType(idx).isArray()) {
889 out.println(indent +
890 decl +
891 (decl.endsWith("*") ? "" : " ") +
892 jfunc.getArgName(idx) +
893 "_base = (" + decl + ") 0;");
894 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800895 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800896 "_" + cname + "Remaining";
897 out.println(indent +
898 "jint " + remaining + ";");
899 out.println(indent +
900 decl +
901 (decl.endsWith("*") ? "" : " ") +
Jack Palevich6cbca502009-04-13 16:22:25 -0700902 jfunc.getArgName(idx) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800903 " = (" + decl + ") 0;");
904 }
905
906 out.println();
907 }
908
Jack Palevich50d0b142009-11-19 16:34:55 +0800909 // Emit local variable declaration for strings
910 if (stringArgs.size() > 0) {
911 for (int i = 0; i < stringArgs.size(); i++) {
912 int idx = stringArgs.get(i).intValue();
913 int cIndex = jfunc.getArgCIndex(idx);
914 String cname = cfunc.getArgName(cIndex);
915
916 out.println(indent + "const char* _native" + cname + " = 0;");
917 }
918
919 out.println();
920 }
921
922 // Null pointer checks and GetStringUTFChars
923 if (stringArgs.size() > 0) {
924 for (int i = 0; i < stringArgs.size(); i++) {
925 int idx = stringArgs.get(i).intValue();
926 int cIndex = jfunc.getArgCIndex(idx);
927 String cname = cfunc.getArgName(cIndex);
928
929 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
930 String decl = type.getDeclaration();
931 out.println(indent + "if (!" + cname + ") {");
932 out.println(indent + " _env->ThrowNew(IAEClass, \"" + cname + " == null\");");
933 out.println(indent + " goto exit;");
934 needsExit = true;
935 out.println(indent + "}");
936
937 out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
938 }
939
940 out.println();
941 }
942
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800943 // Emit 'GetPrimitiveArrayCritical' for arrays
944 // Emit 'GetPointer' calls for Buffer pointers
945 int bufArgIdx = 0;
946 if (nonPrimitiveArgs.size() > 0) {
947 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
948 int idx = nonPrimitiveArgs.get(i).intValue();
949 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -0700950
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800951 String cname = cfunc.getArgName(cIndex);
952 offset = numArrays <= 1 ? "offset" :
953 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +0800954 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800955 "_" + cname + "Remaining";
956
957 if (jfunc.getArgType(idx).isArray()) {
958 out.println(indent +
Jack Palevich6cbca502009-04-13 16:22:25 -0700959 "if (!" +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800960 cname +
961 "_ref) {");
962 if (emitExceptionCheck) {
963 out.println(indent + indent + "_exception = 1;");
964 }
965 out.println(indent + " " +
966 (mUseCPlusPlus ? "_env" : "(*_env)") +
967 "->ThrowNew(" +
968 (mUseCPlusPlus ? "" : "_env, ") +
969 "IAEClass, " +
970 "\"" + cname +
971 " == null\");");
972 out.println(indent + " goto exit;");
973 needsExit = true;
974 out.println(indent + "}");
975
976 out.println(indent + "if (" + offset + " < 0) {");
977 if (emitExceptionCheck) {
978 out.println(indent + indent + "_exception = 1;");
979 }
980 out.println(indent + " " +
981 (mUseCPlusPlus ? "_env" : "(*_env)") +
982 "->ThrowNew(" +
983 (mUseCPlusPlus ? "" : "_env, ") +
984 "IAEClass, " +
985 "\"" + offset + " < 0\");");
986 out.println(indent + " goto exit;");
987 needsExit = true;
988 out.println(indent + "}");
989
990 out.println(indent + remaining + " = " +
Jack Palevich6cbca502009-04-13 16:22:25 -0700991 (mUseCPlusPlus ? "_env" : "(*_env)") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800992 "->GetArrayLength(" +
993 (mUseCPlusPlus ? "" : "_env, ") +
994 cname + "_ref) - " + offset + ";");
995
996 emitNativeBoundsChecks(cfunc, cname, out, false,
997 emitExceptionCheck,
998 offset, remaining, " ");
999
1000 out.println(indent +
1001 cname +
1002 "_base = (" +
1003 cfunc.getArgType(cIndex).getDeclaration() +
1004 ")");
1005 out.println(indent + " " +
1006 (mUseCPlusPlus ? "_env" : "(*_env)") +
1007 "->GetPrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001008 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001009 jfunc.getArgName(idx) +
1010 "_ref, (jboolean *)0);");
1011 out.println(indent +
1012 cname + " = " + cname + "_base + " + offset +
1013 ";");
1014 out.println();
1015 } else {
1016 String array = numBufferArgs <= 1 ? "_array" :
1017 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1018
Jack Palevich46d25a32009-05-07 18:28:29 -07001019 boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001020 if (nullAllowed) {
1021 out.println(indent + "if (" + cname + "_buf) {");
1022 out.print(indent);
1023 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001024
Jack Palevich46d25a32009-05-07 18:28:29 -07001025 if (isPointerFunc) {
1026 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001027 cname +
1028 " = (" +
1029 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001030 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001031 cname + "_buf);");
1032 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001033 out.println(iii + indent + "if ( ! " + cname + " ) {");
Jack Palevich46d25a32009-05-07 18:28:29 -07001034 out.println(iii + iii + indent + "return;");
1035 out.println(iii + indent + "}");
1036 } else {
1037 out.println(indent +
1038 cname +
1039 " = (" +
1040 cfunc.getArgType(cIndex).getDeclaration() +
1041 ")getPointer(_env, " +
1042 cname +
1043 "_buf, &" + array + ", &" + remaining +
1044 ");");
1045 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001046
Jack Palevich5afdc872009-10-21 11:02:44 -07001047 emitNativeBoundsChecks(cfunc, cname, out, true,
1048 emitExceptionCheck,
1049 offset, remaining, nullAllowed ? " " : " ");
1050
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001051 if (nullAllowed) {
1052 out.println(indent + "}");
1053 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054 }
1055 }
1056 }
1057
1058 if (!isVoid) {
1059 out.print(indent + "_returnValue = ");
1060 } else {
1061 out.print(indent);
1062 }
1063 String name = cfunc.getName();
1064
1065 if (mUseContextPointer) {
1066 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1067 name = name.substring(0, 1).toLowerCase() +
1068 name.substring(1, name.length());
1069 out.print("ctx->procs.");
1070 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001071
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001072 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1073
Jack Palevich6cbca502009-04-13 16:22:25 -07001074 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001075 if (numArgs == 0) {
1076 if (mUseContextPointer) {
1077 out.println("ctx);");
1078 } else {
1079 out.println(");");
1080 }
1081 } else {
1082 if (mUseContextPointer) {
1083 out.println("ctx,");
1084 } else {
1085 out.println();
1086 }
1087 for (int i = 0; i < numArgs; i++) {
1088 String typecast;
1089 if (i == numArgs - 1 && isVBOPointerFunc) {
1090 typecast = "const GLvoid *";
1091 } else {
1092 typecast = cfunc.getArgType(i).getDeclaration();
1093 }
1094 out.print(indent + indent +
1095 "(" +
1096 typecast +
Jack Palevich50d0b142009-11-19 16:34:55 +08001097 ")");
1098 if (cfunc.getArgType(i).isConstCharPointer()) {
1099 out.print("_native");
1100 }
1101 out.print(cfunc.getArgName(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001102
1103 if (i == numArgs - 1) {
1104 if (isPointerFunc) {
1105 out.println(",");
1106 out.println(indent + indent + "(GLsizei)remaining");
1107 } else {
1108 out.println();
1109 }
1110 } else {
1111 out.println(",");
1112 }
1113 }
1114 out.println(indent + ");");
1115 }
1116
1117 if (needsExit) {
1118 out.println();
1119 out.println("exit:");
1120 needsExit = false;
1121 }
1122
1123 bufArgIdx = 0;
1124 if (nonPrimitiveArgs.size() > 0) {
1125 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1126 int idx = nonPrimitiveArgs.get(i).intValue();
1127
1128 int cIndex = jfunc.getArgCIndex(idx);
1129 if (jfunc.getArgType(idx).isArray()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001130
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001131 // If the argument is 'const', GL will not write to it.
1132 // In this case, we can use the 'JNI_ABORT' flag to avoid
1133 // the need to write back to the Java array
1134 out.println(indent +
1135 "if (" + jfunc.getArgName(idx) + "_base) {");
1136 out.println(indent + indent +
1137 (mUseCPlusPlus ? "_env" : "(*_env)") +
1138 "->ReleasePrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001139 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001140 jfunc.getArgName(idx) + "_ref, " +
1141 cfunc.getArgName(cIndex) +
1142 "_base,");
1143 out.println(indent + indent + indent +
1144 (cfunc.getArgType(cIndex).isConst() ?
1145 "JNI_ABORT" :
1146 "_exception ? JNI_ABORT: 0") +
1147 ");");
1148 out.println(indent + "}");
1149 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001150 if (! isPointerFunc) {
1151 String array = numBufferArgs <= 1 ? "_array" :
1152 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1153 out.println(indent + "if (" + array + ") {");
1154 out.println(indent + indent +
1155 "releasePointer(_env, " + array + ", " +
1156 cfunc.getArgName(cIndex) +
1157 ", " +
1158 (cfunc.getArgType(cIndex).isConst() ?
1159 "JNI_FALSE" : "_exception ? JNI_FALSE :" +
1160 " JNI_TRUE") +
1161 ");");
1162 out.println(indent + "}");
1163 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001164 }
1165 }
1166 }
1167
Jack Palevich50d0b142009-11-19 16:34:55 +08001168 // Emit local variable declaration for strings
1169 if (stringArgs.size() > 0) {
1170 for (int i = 0; i < stringArgs.size(); i++) {
1171 int idx = stringArgs.get(i).intValue();
1172 int cIndex = jfunc.getArgCIndex(idx);
1173 String cname = cfunc.getArgName(cIndex);
1174
1175 out.println(indent + "if (_native" + cname + ") {");
1176 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1177 out.println(indent + "}");
1178 }
1179
1180 out.println();
1181 }
1182
1183
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001184 if (!isVoid) {
1185 out.println(indent + "return _returnValue;");
1186 }
1187
1188 out.println("}");
1189 out.println();
1190 }
1191
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001192}