blob: 9fa2b7418ccab9396ff857d1ec11404c15d6f637 [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;
Jack Palevichffac1ef2009-04-14 19:00:09 -070028 protected String mClassPathName;
29 protected ParameterChecker mChecker;
30 protected List<String> nativeRegistrations = new ArrayList<String>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080031 boolean needsExit;
Jack Palevichffac1ef2009-04-14 19:00:09 -070032 protected static String indent = " ";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033 HashSet<String> mFunctionsEmitted = new HashSet<String>();
34
Jack Palevichffac1ef2009-04-14 19:00:09 -070035 public static String getJniName(JType jType) {
36 String jniName = "";
37 if (jType.isClass()) {
38 return "L" + jType.getBaseType() + ";";
39 } else if (jType.isArray()) {
40 jniName = "[";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041 }
Jack Palevichffac1ef2009-04-14 19:00:09 -070042
43 String baseType = jType.getBaseType();
44 if (baseType.equals("int")) {
45 jniName += "I";
46 } else if (baseType.equals("float")) {
47 jniName += "F";
48 } else if (baseType.equals("boolean")) {
49 jniName += "Z";
50 } else if (baseType.equals("short")) {
51 jniName += "S";
52 } else if (baseType.equals("long")) {
53 jniName += "L";
54 } else if (baseType.equals("byte")) {
55 jniName += "B";
Jack Palevich50d0b142009-11-19 16:34:55 +080056 } else if (baseType.equals("String")) {
57 jniName += "Ljava/lang/String;";
58 } else if (baseType.equals("void")) {
59 // nothing.
60 } else {
Elliott Hughes98757502011-04-08 20:01:01 -070061 throw new RuntimeException("Unknown primitive basetype " + baseType);
Jack Palevichffac1ef2009-04-14 19:00:09 -070062 }
63 return jniName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080064 }
65
Jack Palevichffac1ef2009-04-14 19:00:09 -070066
67 public void emitCode(CFunc cfunc, String original,
68 PrintStream javaInterfaceStream,
69 PrintStream javaImplStream,
70 PrintStream cStream) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080071 JFunc jfunc;
72 String signature;
73 boolean duplicate;
Jack Palevich6cbca502009-04-13 16:22:25 -070074
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080075 if (cfunc.hasTypedPointerArg()) {
76 jfunc = JFunc.convert(cfunc, true);
77
78 // Don't emit duplicate functions
79 // These may appear because they are defined in multiple
80 // Java interfaces (e.g., GL11/GL11ExtensionPack)
81 signature = jfunc.toString();
82 duplicate = false;
83 if (mFunctionsEmitted.contains(signature)) {
84 duplicate = true;
85 } else {
86 mFunctionsEmitted.add(signature);
87 }
88
89 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070090 emitNativeDeclaration(jfunc, javaImplStream);
91 emitJavaCode(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080092 }
Jack Palevich427f5852009-04-15 19:13:17 -070093 if (javaInterfaceStream != null) {
94 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
95 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080096 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070097 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080098 }
99 }
100
101 jfunc = JFunc.convert(cfunc, false);
102
103 signature = jfunc.toString();
104 duplicate = false;
105 if (mFunctionsEmitted.contains(signature)) {
106 duplicate = true;
107 } else {
108 mFunctionsEmitted.add(signature);
109 }
110
111 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700112 emitNativeDeclaration(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800113 }
Jack Palevich427f5852009-04-15 19:13:17 -0700114 if (javaInterfaceStream != null) {
115 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
116 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800117 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700118 emitJavaCode(jfunc, javaImplStream);
119 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800120 }
121 }
122
123 public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
124 out.println(" // C function " + jfunc.getCFunc().getOriginal());
125 out.println();
126
127 emitFunction(jfunc, out, true, false);
128 }
129
130 public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
131 emitFunction(jfunc, out, false, true);
132 }
133
134 public void emitJavaCode(JFunc jfunc, PrintStream out) {
135 emitFunction(jfunc, out, false, false);
136 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700137
Jack Palevich66089a32009-12-08 15:43:51 +0800138 boolean isPointerFunc(JFunc jfunc) {
139 String name = jfunc.getName();
140 return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
141 && jfunc.getCFunc().hasPointerArg();
142 }
143
Jack Palevichffac1ef2009-04-14 19:00:09 -0700144 void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800145 boolean isVoid = jfunc.getType().isVoid();
Jack Palevich66089a32009-12-08 15:43:51 +0800146 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800147
148 if (!isVoid) {
149 out.println(iii +
150 jfunc.getType() + " _returnValue;");
151 }
152 out.println(iii +
153 (isVoid ? "" : "_returnValue = ") +
154 jfunc.getName() +
155 (isPointerFunc ? "Bounds" : "" ) +
156 "(");
Jack Palevich6cbca502009-04-13 16:22:25 -0700157
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800158 int numArgs = jfunc.getNumArgs();
159 for (int i = 0; i < numArgs; i++) {
160 String argName = jfunc.getArgName(i);
161 JType argType = jfunc.getArgType(i);
162
163 if (grabArray && argType.isTypedBuffer()) {
164 String typeName = argType.getBaseType();
165 typeName = typeName.substring(9, typeName.length() - 6);
166 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
Jack Palevich6cbca502009-04-13 16:22:25 -0700167 out.print(iii + indent + "getOffset(" + argName + ")");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800168 } else {
169 out.print(iii + indent + argName);
170 }
171 if (i == numArgs - 1) {
172 if (isPointerFunc) {
173 out.println(",");
174 out.println(iii + indent + argName + ".remaining()");
175 } else {
176 out.println();
177 }
178 } else {
179 out.println(",");
180 }
181 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700182
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183 out.println(iii + ");");
184 }
185
Jack Palevichffac1ef2009-04-14 19:00:09 -0700186 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
187 String iii) {
188 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
189 "offset", "_remaining", iii);
190 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800191
Jack Palevichffac1ef2009-04-14 19:00:09 -0700192 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
193 String offset, String remaining, String iii) {
194 out.println(iii + " default:");
195 out.println(iii + " _needed = 0;");
196 out.println(iii + " break;");
197 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800198
Jack Palevichffac1ef2009-04-14 19:00:09 -0700199 out.println(iii + "if (" + remaining + " < _needed) {");
200 if (emitExceptionCheck) {
201 out.println(iii + indent + "_exception = 1;");
202 }
Elliott Hughes98757502011-04-08 20:01:01 -0700203 out.println(iii + indent + "jniThrowException(_env, " +
204 "\"java/lang/IllegalArgumentException\", " +
205 "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < needed\");");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700206 out.println(iii + indent + "goto exit;");
207 needsExit = true;
208 out.println(iii + "}");
209 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210
211 boolean isNullAllowed(CFunc cfunc) {
212 String[] checks = mChecker.getChecks(cfunc.getName());
213 int index = 1;
214 if (checks != null) {
215 while (index < checks.length) {
216 if (checks[index].equals("return")) {
217 index += 2;
218 } else if (checks[index].startsWith("check")) {
219 index += 3;
220 } else if (checks[index].equals("ifcheck")) {
221 index += 5;
222 } else if (checks[index].equals("unsupported")) {
223 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800224 } else if (checks[index].equals("requires")) {
225 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226 } else if (checks[index].equals("nullAllowed")) {
227 return true;
228 } else {
229 System.out.println("Error: unknown keyword \"" +
230 checks[index] + "\"");
231 System.exit(0);
232 }
233 }
234 }
235 return false;
236 }
237
238 String getErrorReturnValue(CFunc cfunc) {
239 CType returnType = cfunc.getType();
240 boolean isVoid = returnType.isVoid();
241 if (isVoid) {
242 return null;
243 }
244
245 String[] checks = mChecker.getChecks(cfunc.getName());
246
247 int index = 1;
248 if (checks != null) {
249 while (index < checks.length) {
250 if (checks[index].equals("return")) {
251 return checks[index + 1];
252 } else if (checks[index].startsWith("check")) {
253 index += 3;
254 } else if (checks[index].equals("ifcheck")) {
255 index += 5;
256 } else if (checks[index].equals("unsupported")) {
257 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800258 } else if (checks[index].equals("requires")) {
259 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800260 } else if (checks[index].equals("nullAllowed")) {
261 index += 1;
262 } else {
263 System.out.println("Error: unknown keyword \"" +
264 checks[index] + "\"");
265 System.exit(0);
266 }
267 }
268 }
269
270 return null;
271 }
272
273 boolean isUnsupportedFunc(CFunc cfunc) {
274 String[] checks = mChecker.getChecks(cfunc.getName());
275 int index = 1;
276 if (checks != null) {
277 while (index < checks.length) {
278 if (checks[index].equals("unsupported")) {
279 return true;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800280 } else if (checks[index].equals("requires")) {
281 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800282 } else if (checks[index].equals("return")) {
283 index += 2;
284 } else if (checks[index].startsWith("check")) {
285 index += 3;
286 } else if (checks[index].equals("ifcheck")) {
287 index += 5;
288 } else if (checks[index].equals("nullAllowed")) {
289 index += 1;
290 } else {
291 System.out.println("Error: unknown keyword \"" +
292 checks[index] + "\"");
293 System.exit(0);
294 }
295 }
296 }
297 return false;
298 }
Elliott Hughes98757502011-04-08 20:01:01 -0700299
Jack Paleviche44e45c2010-01-28 20:28:32 +0800300 String isRequiresFunc(CFunc cfunc) {
301 String[] checks = mChecker.getChecks(cfunc.getName());
302 int index = 1;
303 if (checks != null) {
304 while (index < checks.length) {
305 if (checks[index].equals("unsupported")) {
306 index += 1;
307 } else if (checks[index].equals("requires")) {
308 return checks[index+1];
309 } else if (checks[index].equals("return")) {
310 index += 2;
311 } else if (checks[index].startsWith("check")) {
312 index += 3;
313 } else if (checks[index].equals("ifcheck")) {
314 index += 5;
315 } else if (checks[index].equals("nullAllowed")) {
316 index += 1;
317 } else {
318 System.out.println("Error: unknown keyword \"" +
319 checks[index] + "\"");
320 System.exit(0);
321 }
322 }
323 }
324 return null;
325 }
Elliott Hughes98757502011-04-08 20:01:01 -0700326
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800327 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700328 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800329
Elliott Hughes98757502011-04-08 20:01:01 -0700330 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800331
Elliott Hughes98757502011-04-08 20:01:01 -0700332 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333
Elliott Hughes98757502011-04-08 20:01:01 -0700334 int index = 1;
335 if (checks != null) {
336 while (index < checks.length) {
337 if (checks[index].startsWith("check")) {
338 if (lastWasIfcheck) {
339 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
340 offset, remaining, iii);
341 }
342 lastWasIfcheck = false;
343 if (cname != null && !cname.equals(checks[index + 1])) {
344 index += 3;
345 continue;
346 }
347 out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
348 if (emitExceptionCheck) {
349 out.println(iii + indent + "_exception = 1;");
350 }
351 String exceptionClassName = "java/lang/IllegalArgumentException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700352 // If the "check" keyword was of the form
353 // "check_<class name>", use the class name in the
354 // exception to be thrown
355 int underscore = checks[index].indexOf('_');
356 if (underscore >= 0) {
Elliott Hughes98757502011-04-08 20:01:01 -0700357 String abbr = checks[index].substring(underscore + 1);
358 if (abbr.equals("AIOOBE")) {
359 exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700360 } else {
Elliott Hughes98757502011-04-08 20:01:01 -0700361 throw new RuntimeException("unknown exception abbreviation: " + abbr);
Jack Palevichffac1ef2009-04-14 19:00:09 -0700362 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800363 }
Elliott Hughes98757502011-04-08 20:01:01 -0700364 out.println(iii + indent + "jniThrowException(_env, " +
365 "\"" + exceptionClassName + "\", " +
366 "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < " + checks[index + 2] + "\");");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800367
Elliott Hughes98757502011-04-08 20:01:01 -0700368 out.println(iii + indent + "goto exit;");
369 needsExit = true;
370 out.println(iii + "}");
371
372 index += 3;
373 } else if (checks[index].equals("ifcheck")) {
374 String[] matches = checks[index + 4].split(",");
375
376 if (!lastWasIfcheck) {
377 out.println(iii + "int _needed;");
378 out.println(iii + "switch (" + checks[index + 3] + ") {");
379 }
380
381 for (int i = 0; i < matches.length; i++) {
382 out.println("#if defined(" + matches[i] + ")");
383 out.println(iii + " case " + matches[i] + ":");
384 out.println("#endif // defined(" + matches[i] + ")");
385 }
386 out.println(iii + " _needed = " + checks[index + 2] + ";");
387 out.println(iii + " break;");
388
389 lastWasIfcheck = true;
390 index += 5;
391 } else if (checks[index].equals("return")) {
392 // ignore
393 index += 2;
394 } else if (checks[index].equals("unsupported")) {
395 // ignore
396 index += 1;
397 } else if (checks[index].equals("requires")) {
398 // ignore
399 index += 2;
400 } else if (checks[index].equals("nullAllowed")) {
401 // ignore
402 index += 1;
403 } else {
404 System.out.println("Error: unknown keyword \"" + checks[index] + "\"");
405 System.exit(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800406 }
407 }
Elliott Hughes98757502011-04-08 20:01:01 -0700408 }
409
410 if (lastWasIfcheck) {
411 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
412 }
413 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800414
Jack Palevichffac1ef2009-04-14 19:00:09 -0700415 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416 if (nonPrimitiveArgs.size() > 0) {
417 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
418 int idx = nonPrimitiveArgs.get(i).intValue();
419 int cIndex = jfunc.getArgCIndex(idx);
420 if (jfunc.getArgType(idx).isArray()) {
421 if (!cfunc.getArgType(cIndex).isConst()) {
422 return true;
423 }
424 } else if (jfunc.getArgType(idx).isBuffer()) {
425 if (!cfunc.getArgType(cIndex).isConst()) {
426 return true;
427 }
428 }
429 }
430 }
431
432 return false;
433 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700434
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800435 /**
436 * Emit a function in several variants:
437 *
438 * if nativeDecl: public native <returntype> func(args);
439 *
440 * if !nativeDecl:
441 * if interfaceDecl: public <returntype> func(args);
442 * if !interfaceDecl: public <returntype> func(args) { body }
443 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700444 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800445 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446
447 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
448 // If it's not a pointer function, we've already emitted it
449 // with nativeDecl == true
450 return;
451 }
452
Jack Palevich427f5852009-04-15 19:13:17 -0700453 String maybeStatic = mUseStaticMethods ? "static " : "";
454
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800455 if (isPointerFunc) {
456 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700457 (nativeDecl ? "private " + maybeStatic +"native " :
458 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800459 jfunc.getType() + " " +
460 jfunc.getName() +
461 (nativeDecl ? "Bounds" : "") +
462 "(");
463 } else {
464 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700465 (nativeDecl ? "public " + maybeStatic +"native " :
466 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800467 jfunc.getType() + " " +
468 jfunc.getName() +
469 "(");
470 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700471
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800472 int numArgs = jfunc.getNumArgs();
473 for (int i = 0; i < numArgs; i++) {
474 String argName = jfunc.getArgName(i);
475 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700476
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800477 out.print(indent + indent + argType + " " + argName);
478 if (i == numArgs - 1) {
479 if (isPointerFunc && nativeDecl) {
480 out.println(",");
481 out.println(indent + indent + "int remaining");
482 } else {
483 out.println();
484 }
485 } else {
486 out.println(",");
487 }
488 }
489
490 if (nativeDecl || interfaceDecl) {
491 out.println(indent + ");");
492 } else {
493 out.println(indent + ") {");
494
495 String iii = indent + indent;
496
Jack Palevich46d25a32009-05-07 18:28:29 -0700497 // emitBoundsChecks(jfunc, out, iii);
498 emitFunctionCall(jfunc, out, iii, false);
499
500 // Set the pointer after we call the native code, so that if
501 // the native code throws an exception we don't modify the
502 // pointer. We assume that the native code is written so that
503 // if an exception is thrown, then the underlying glXXXPointer
504 // function will not have been called.
505
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800506 String fname = jfunc.getName();
507 if (isPointerFunc) {
508 // TODO - deal with VBO variants
509 if (fname.equals("glColorPointer")) {
510 out.println(iii + "if ((size == 4) &&");
511 out.println(iii + " ((type == GL_FLOAT) ||");
512 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
513 out.println(iii + " (type == GL_FIXED)) &&");
514 out.println(iii + " (stride >= 0)) {");
515 out.println(iii + indent + "_colorPointer = pointer;");
516 out.println(iii + "}");
517 } else if (fname.equals("glNormalPointer")) {
518 out.println(iii + "if (((type == GL_FLOAT) ||");
519 out.println(iii + " (type == GL_BYTE) ||");
520 out.println(iii + " (type == GL_SHORT) ||");
521 out.println(iii + " (type == GL_FIXED)) &&");
522 out.println(iii + " (stride >= 0)) {");
523 out.println(iii + indent + "_normalPointer = pointer;");
524 out.println(iii + "}");
525 } else if (fname.equals("glTexCoordPointer")) {
526 out.println(iii + "if (((size == 2) ||");
527 out.println(iii + " (size == 3) ||");
528 out.println(iii + " (size == 4)) &&");
529 out.println(iii + " ((type == GL_FLOAT) ||");
530 out.println(iii + " (type == GL_BYTE) ||");
531 out.println(iii + " (type == GL_SHORT) ||");
532 out.println(iii + " (type == GL_FIXED)) &&");
533 out.println(iii + " (stride >= 0)) {");
534 out.println(iii + indent + "_texCoordPointer = pointer;");
535 out.println(iii + "}");
536 } else if (fname.equals("glVertexPointer")) {
537 out.println(iii + "if (((size == 2) ||");
538 out.println(iii + " (size == 3) ||");
539 out.println(iii + " (size == 4)) &&");
540 out.println(iii + " ((type == GL_FLOAT) ||");
541 out.println(iii + " (type == GL_BYTE) ||");
542 out.println(iii + " (type == GL_SHORT) ||");
543 out.println(iii + " (type == GL_FIXED)) &&");
544 out.println(iii + " (stride >= 0)) {");
545 out.println(iii + indent + "_vertexPointer = pointer;");
546 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800547 } else if (fname.equals("glPointSizePointerOES")) {
548 out.println(iii + "if (((type == GL_FLOAT) ||");
549 out.println(iii + " (type == GL_FIXED)) &&");
550 out.println(iii + " (stride >= 0)) {");
551 out.println(iii + indent + "_pointSizePointerOES = pointer;");
552 out.println(iii + "}");
553 } else if (fname.equals("glMatrixIndexPointerOES")) {
554 out.println(iii + "if (((size == 2) ||");
555 out.println(iii + " (size == 3) ||");
556 out.println(iii + " (size == 4)) &&");
557 out.println(iii + " ((type == GL_FLOAT) ||");
558 out.println(iii + " (type == GL_BYTE) ||");
559 out.println(iii + " (type == GL_SHORT) ||");
560 out.println(iii + " (type == GL_FIXED)) &&");
561 out.println(iii + " (stride >= 0)) {");
562 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
563 out.println(iii + "}");
564 } else if (fname.equals("glWeightPointer")) {
565 out.println(iii + "if (((size == 2) ||");
566 out.println(iii + " (size == 3) ||");
567 out.println(iii + " (size == 4)) &&");
568 out.println(iii + " ((type == GL_FLOAT) ||");
569 out.println(iii + " (type == GL_BYTE) ||");
570 out.println(iii + " (type == GL_SHORT) ||");
571 out.println(iii + " (type == GL_FIXED)) &&");
572 out.println(iii + " (stride >= 0)) {");
573 out.println(iii + indent + "_weightPointerOES = pointer;");
574 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800575 }
576 }
577
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800578 boolean isVoid = jfunc.getType().isVoid();
579
580 if (!isVoid) {
581 out.println(indent + indent + "return _returnValue;");
582 }
583 out.println(indent + "}");
584 }
585 out.println();
586 }
587
Jack Palevichffac1ef2009-04-14 19:00:09 -0700588 public void addNativeRegistration(String s) {
589 nativeRegistrations.add(s);
590 }
591
Jack Palevich427f5852009-04-15 19:13:17 -0700592 public void emitNativeRegistration(String registrationFunctionName,
593 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700594 cStream.println("static const char *classPathName = \"" +
595 mClassPathName +
596 "\";");
597 cStream.println();
598
599 cStream.println("static JNINativeMethod methods[] = {");
600
601 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
602
603 Iterator<String> i = nativeRegistrations.iterator();
604 while (i.hasNext()) {
605 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800606 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700607
Jack Palevichffac1ef2009-04-14 19:00:09 -0700608 cStream.println("};");
609 cStream.println();
610
611
Jack Palevich427f5852009-04-15 19:13:17 -0700612 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700613 cStream.println("{");
614 cStream.println(indent +
615 "int err;");
616
617 cStream.println(indent +
618 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
619
620 cStream.println(indent + "return err;");
621 cStream.println("}");
622 }
623
624 public JniCodeEmitter() {
625 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800626 }
627
628 String getJniType(JType jType) {
629 if (jType.isVoid()) {
630 return "void";
631 }
632
633 String baseType = jType.getBaseType();
634 if (jType.isPrimitive()) {
635 if (baseType.equals("String")) {
636 return "jstring";
637 } else {
638 return "j" + baseType;
639 }
640 } else if (jType.isArray()) {
641 return "j" + baseType + "Array";
642 } else {
643 return "jobject";
644 }
645 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700646
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800647 String getJniMangledName(String name) {
648 name = name.replaceAll("_", "_1");
649 name = name.replaceAll(";", "_2");
650 name = name.replaceAll("\\[", "_3");
651 return name;
652 }
653
654 public void emitJniCode(JFunc jfunc, PrintStream out) {
655 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700656
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800657 // Emit comment identifying original C function
658 //
659 // Example:
660 //
661 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
662 //
663 out.println("/* " + cfunc.getOriginal() + " */");
664
665 // Emit JNI signature (name)
666 //
667 // Example:
668 //
669 // void
670 // android_glClipPlanef__I_3FI
671 //
672
673 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800674 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800675 boolean isVBOPointerFunc = (outName.endsWith("Pointer") ||
Jack Palevich66089a32009-12-08 15:43:51 +0800676 outName.endsWith("PointerOES") ||
Jack Palevichb3ffef92010-06-22 20:08:40 +0800677 outName.endsWith("DrawElements") || outName.endsWith("VertexAttribPointer")) &&
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800678 !jfunc.getCFunc().hasPointerArg();
679 if (isPointerFunc) {
680 outName += "Bounds";
681 }
682
683 out.print("static ");
684 out.println(getJniType(jfunc.getType()));
685 out.print(outName);
686
687 String rsignature = getJniName(jfunc.getType());
688
689 String signature = "";
690 int numArgs = jfunc.getNumArgs();
691 for (int i = 0; i < numArgs; i++) {
692 JType argType = jfunc.getArgType(i);
693 signature += getJniName(argType);
694 }
695 if (isPointerFunc) {
696 signature += "I";
697 }
698
699 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800700 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800701 out.print("__" + sig);
702 outName += "__" + sig;
Jack Palevich6cbca502009-04-13 16:22:25 -0700703
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800704 signature = signature.replace('.', '/');
705 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700706
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800707 out.println();
708 if (rsignature.length() == 0) {
709 rsignature = "V";
710 }
711
712 String s = "{\"" +
713 jfunc.getName() +
714 (isPointerFunc ? "Bounds" : "") +
715 "\", \"(" + signature +")" +
716 rsignature +
717 "\", (void *) " +
718 outName +
719 " },";
720 nativeRegistrations.add(s);
721
722 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800723 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800724 int numBufferArgs = 0;
725 List<String> bufferArgNames = new ArrayList<String>();
726
727 // Emit JNI signature (arguments)
728 //
729 // Example:
730 //
731 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
732 //
733 out.print(" (JNIEnv *_env, jobject _this");
734 for (int i = 0; i < numArgs; i++) {
735 out.print(", ");
736 JType argType = jfunc.getArgType(i);
737 String suffix;
738 if (!argType.isPrimitive()) {
739 if (argType.isArray()) {
740 suffix = "_ref";
741 } else {
742 suffix = "_buf";
743 }
744 nonPrimitiveArgs.add(new Integer(i));
745 if (jfunc.getArgType(i).isBuffer()) {
746 int cIndex = jfunc.getArgCIndex(i);
747 String cname = cfunc.getArgName(cIndex);
748 bufferArgNames.add(cname);
749 numBufferArgs++;
750 }
751 } else {
752 suffix = "";
753 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800754 if (argType.isString()) {
755 stringArgs.add(new Integer(i));
756 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800757
758 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
759 }
760 if (isPointerFunc) {
761 out.print(", jint remaining");
762 }
763 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700764
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800765 int numArrays = 0;
766 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800767 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800768 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
769 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800770 JType argType = jfunc.getArgType(idx);
771 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800772 ++numArrays;
773 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800774 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800775 ++numBuffers;
776 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800777 if (argType.isString()) {
778 ++numStrings;
779 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800780 }
781
782 // Emit method body
783
784 // Emit local variable declarations for _exception and _returnValue
785 //
786 // Example:
787 //
788 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700789 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790 // jint _exception;
791 // GLenum _returnValue;
792 //
793 CType returnType = cfunc.getType();
794 boolean isVoid = returnType.isVoid();
795
796 boolean isUnsupported = isUnsupportedFunc(cfunc);
797 if (isUnsupported) {
798 out.println(indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700799 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800800 out.println(indent +
801 " \"" + cfunc.getName() + "\");");
802 if (!isVoid) {
803 String retval = getErrorReturnValue(cfunc);
804 out.println(indent + "return " + retval + ";");
805 }
806 out.println("}");
807 out.println();
808 return;
809 }
Elliott Hughes98757502011-04-08 20:01:01 -0700810
Jack Paleviche44e45c2010-01-28 20:28:32 +0800811 String requiresExtension = isRequiresFunc(cfunc);
812 if (requiresExtension != null) {
813 out.println(indent +
814 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
815 out.println(indent + indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700816 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
Jack Paleviche44e45c2010-01-28 20:28:32 +0800817 out.println(indent + indent +
818 " \"" + cfunc.getName() + "\");");
819 if (isVoid) {
820 out.println(indent + indent + " return;");
821 } else {
822 String retval = getErrorReturnValue(cfunc);
823 out.println(indent + indent + " return " + retval + ";");
824 }
825 out.println(indent + "}");
826 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800827 if (mUseContextPointer) {
828 out.println(indent +
829 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
830 }
831
Jack Palevich50d0b142009-11-19 16:34:55 +0800832 boolean initializeReturnValue = stringArgs.size() > 0;
833
834 boolean emitExceptionCheck = (numArrays > 0 || numBuffers > 0 || numStrings > 0) &&
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800835 hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs);
836 // mChecker.getChecks(cfunc.getName()) != null
837
838 // Emit an _exeption variable if there will be error checks
839 if (emitExceptionCheck) {
840 out.println(indent + "jint _exception = 0;");
841 }
842
843 // Emit a single _array or multiple _XXXArray variables
844 if (numBufferArgs == 1) {
845 out.println(indent + "jarray _array = (jarray) 0;");
846 } else {
847 for (int i = 0; i < numBufferArgs; i++) {
848 out.println(indent + "jarray _" + bufferArgNames.get(i) +
849 "Array = (jarray) 0;");
850 }
851 }
852 if (!isVoid) {
853 String retval = getErrorReturnValue(cfunc);
854 if (retval != null) {
855 out.println(indent + returnType.getDeclaration() +
856 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +0800857 } else if (initializeReturnValue) {
858 out.println(indent + returnType.getDeclaration() +
859 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800860 } else {
861 out.println(indent + returnType.getDeclaration() +
862 " _returnValue;");
863 }
864 }
865
866 // Emit local variable declarations for pointer arguments
867 //
868 // Example:
869 //
870 // GLfixed *eqn_base;
871 // GLfixed *eqn;
872 //
873 String offset = "offset";
874 String remaining = "_remaining";
875 if (nonPrimitiveArgs.size() > 0) {
876 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
877 int idx = nonPrimitiveArgs.get(i).intValue();
878 int cIndex = jfunc.getArgCIndex(idx);
879 String cname = cfunc.getArgName(cIndex);
880
881 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
882 String decl = type.getDeclaration();
883 if (jfunc.getArgType(idx).isArray()) {
884 out.println(indent +
885 decl +
886 (decl.endsWith("*") ? "" : " ") +
887 jfunc.getArgName(idx) +
888 "_base = (" + decl + ") 0;");
889 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800890 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800891 "_" + cname + "Remaining";
892 out.println(indent +
893 "jint " + remaining + ";");
894 out.println(indent +
895 decl +
896 (decl.endsWith("*") ? "" : " ") +
Jack Palevich6cbca502009-04-13 16:22:25 -0700897 jfunc.getArgName(idx) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800898 " = (" + decl + ") 0;");
899 }
900
901 out.println();
902 }
903
Jack Palevich50d0b142009-11-19 16:34:55 +0800904 // Emit local variable declaration for strings
905 if (stringArgs.size() > 0) {
906 for (int i = 0; i < stringArgs.size(); i++) {
907 int idx = stringArgs.get(i).intValue();
908 int cIndex = jfunc.getArgCIndex(idx);
909 String cname = cfunc.getArgName(cIndex);
910
911 out.println(indent + "const char* _native" + cname + " = 0;");
912 }
913
914 out.println();
915 }
916
917 // Null pointer checks and GetStringUTFChars
918 if (stringArgs.size() > 0) {
919 for (int i = 0; i < stringArgs.size(); i++) {
920 int idx = stringArgs.get(i).intValue();
921 int cIndex = jfunc.getArgCIndex(idx);
922 String cname = cfunc.getArgName(cIndex);
923
924 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
925 String decl = type.getDeclaration();
926 out.println(indent + "if (!" + cname + ") {");
Elliott Hughes98757502011-04-08 20:01:01 -0700927 out.println(indent + " jniThrowException(_env, " +
928 "\"java/lang/IllegalArgumentException\", \"" + cname + " == null\");");
Jack Palevich50d0b142009-11-19 16:34:55 +0800929 out.println(indent + " goto exit;");
930 needsExit = true;
931 out.println(indent + "}");
932
933 out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
934 }
935
936 out.println();
937 }
938
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800939 // Emit 'GetPrimitiveArrayCritical' for arrays
940 // Emit 'GetPointer' calls for Buffer pointers
941 int bufArgIdx = 0;
942 if (nonPrimitiveArgs.size() > 0) {
943 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
944 int idx = nonPrimitiveArgs.get(i).intValue();
945 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -0700946
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800947 String cname = cfunc.getArgName(cIndex);
948 offset = numArrays <= 1 ? "offset" :
949 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +0800950 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800951 "_" + cname + "Remaining";
952
953 if (jfunc.getArgType(idx).isArray()) {
954 out.println(indent +
Jack Palevich6cbca502009-04-13 16:22:25 -0700955 "if (!" +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800956 cname +
957 "_ref) {");
958 if (emitExceptionCheck) {
959 out.println(indent + indent + "_exception = 1;");
960 }
Elliott Hughes98757502011-04-08 20:01:01 -0700961 out.println(indent + " jniThrowException(_env, " +
962 "\"java/lang/IllegalArgumentException\", " +
963 "\"" + cname + " == null\");");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800964 out.println(indent + " goto exit;");
965 needsExit = true;
966 out.println(indent + "}");
967
968 out.println(indent + "if (" + offset + " < 0) {");
969 if (emitExceptionCheck) {
970 out.println(indent + indent + "_exception = 1;");
971 }
Elliott Hughes98757502011-04-08 20:01:01 -0700972 out.println(indent + " jniThrowException(_env, " +
973 "\"java/lang/IllegalArgumentException\", \"" + offset + " < 0\");");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800974 out.println(indent + " goto exit;");
975 needsExit = true;
976 out.println(indent + "}");
977
978 out.println(indent + remaining + " = " +
Jack Palevich6cbca502009-04-13 16:22:25 -0700979 (mUseCPlusPlus ? "_env" : "(*_env)") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800980 "->GetArrayLength(" +
981 (mUseCPlusPlus ? "" : "_env, ") +
982 cname + "_ref) - " + offset + ";");
983
984 emitNativeBoundsChecks(cfunc, cname, out, false,
985 emitExceptionCheck,
986 offset, remaining, " ");
987
988 out.println(indent +
989 cname +
990 "_base = (" +
991 cfunc.getArgType(cIndex).getDeclaration() +
992 ")");
993 out.println(indent + " " +
994 (mUseCPlusPlus ? "_env" : "(*_env)") +
995 "->GetPrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -0700996 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800997 jfunc.getArgName(idx) +
998 "_ref, (jboolean *)0);");
999 out.println(indent +
1000 cname + " = " + cname + "_base + " + offset +
1001 ";");
1002 out.println();
1003 } else {
1004 String array = numBufferArgs <= 1 ? "_array" :
1005 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1006
Jack Palevich46d25a32009-05-07 18:28:29 -07001007 boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001008 if (nullAllowed) {
1009 out.println(indent + "if (" + cname + "_buf) {");
1010 out.print(indent);
1011 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001012
Jack Palevich46d25a32009-05-07 18:28:29 -07001013 if (isPointerFunc) {
1014 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001015 cname +
1016 " = (" +
1017 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001018 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001019 cname + "_buf);");
1020 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001021 out.println(iii + indent + "if ( ! " + cname + " ) {");
Jack Palevich46d25a32009-05-07 18:28:29 -07001022 out.println(iii + iii + indent + "return;");
1023 out.println(iii + indent + "}");
1024 } else {
1025 out.println(indent +
1026 cname +
1027 " = (" +
1028 cfunc.getArgType(cIndex).getDeclaration() +
1029 ")getPointer(_env, " +
1030 cname +
1031 "_buf, &" + array + ", &" + remaining +
1032 ");");
1033 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001034
Jack Palevich5afdc872009-10-21 11:02:44 -07001035 emitNativeBoundsChecks(cfunc, cname, out, true,
1036 emitExceptionCheck,
1037 offset, remaining, nullAllowed ? " " : " ");
1038
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039 if (nullAllowed) {
1040 out.println(indent + "}");
1041 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001042 }
1043 }
1044 }
1045
1046 if (!isVoid) {
1047 out.print(indent + "_returnValue = ");
1048 } else {
1049 out.print(indent);
1050 }
1051 String name = cfunc.getName();
1052
1053 if (mUseContextPointer) {
1054 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1055 name = name.substring(0, 1).toLowerCase() +
1056 name.substring(1, name.length());
1057 out.print("ctx->procs.");
1058 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001059
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001060 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1061
Jack Palevich6cbca502009-04-13 16:22:25 -07001062 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001063 if (numArgs == 0) {
1064 if (mUseContextPointer) {
1065 out.println("ctx);");
1066 } else {
1067 out.println(");");
1068 }
1069 } else {
1070 if (mUseContextPointer) {
1071 out.println("ctx,");
1072 } else {
1073 out.println();
1074 }
1075 for (int i = 0; i < numArgs; i++) {
1076 String typecast;
1077 if (i == numArgs - 1 && isVBOPointerFunc) {
1078 typecast = "const GLvoid *";
1079 } else {
1080 typecast = cfunc.getArgType(i).getDeclaration();
1081 }
1082 out.print(indent + indent +
1083 "(" +
1084 typecast +
Jack Palevich50d0b142009-11-19 16:34:55 +08001085 ")");
1086 if (cfunc.getArgType(i).isConstCharPointer()) {
1087 out.print("_native");
1088 }
1089 out.print(cfunc.getArgName(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001090
1091 if (i == numArgs - 1) {
1092 if (isPointerFunc) {
1093 out.println(",");
1094 out.println(indent + indent + "(GLsizei)remaining");
1095 } else {
1096 out.println();
1097 }
1098 } else {
1099 out.println(",");
1100 }
1101 }
1102 out.println(indent + ");");
1103 }
1104
1105 if (needsExit) {
1106 out.println();
1107 out.println("exit:");
1108 needsExit = false;
1109 }
1110
1111 bufArgIdx = 0;
1112 if (nonPrimitiveArgs.size() > 0) {
1113 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1114 int idx = nonPrimitiveArgs.get(i).intValue();
1115
1116 int cIndex = jfunc.getArgCIndex(idx);
1117 if (jfunc.getArgType(idx).isArray()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001118
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001119 // If the argument is 'const', GL will not write to it.
1120 // In this case, we can use the 'JNI_ABORT' flag to avoid
1121 // the need to write back to the Java array
1122 out.println(indent +
1123 "if (" + jfunc.getArgName(idx) + "_base) {");
1124 out.println(indent + indent +
1125 (mUseCPlusPlus ? "_env" : "(*_env)") +
1126 "->ReleasePrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001127 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 jfunc.getArgName(idx) + "_ref, " +
1129 cfunc.getArgName(cIndex) +
1130 "_base,");
1131 out.println(indent + indent + indent +
1132 (cfunc.getArgType(cIndex).isConst() ?
1133 "JNI_ABORT" :
1134 "_exception ? JNI_ABORT: 0") +
1135 ");");
1136 out.println(indent + "}");
1137 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001138 if (! isPointerFunc) {
1139 String array = numBufferArgs <= 1 ? "_array" :
1140 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1141 out.println(indent + "if (" + array + ") {");
1142 out.println(indent + indent +
1143 "releasePointer(_env, " + array + ", " +
1144 cfunc.getArgName(cIndex) +
1145 ", " +
1146 (cfunc.getArgType(cIndex).isConst() ?
1147 "JNI_FALSE" : "_exception ? JNI_FALSE :" +
1148 " JNI_TRUE") +
1149 ");");
1150 out.println(indent + "}");
1151 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001152 }
1153 }
1154 }
1155
Jack Palevich50d0b142009-11-19 16:34:55 +08001156 // Emit local variable declaration for strings
1157 if (stringArgs.size() > 0) {
1158 for (int i = 0; i < stringArgs.size(); i++) {
1159 int idx = stringArgs.get(i).intValue();
1160 int cIndex = jfunc.getArgCIndex(idx);
1161 String cname = cfunc.getArgName(cIndex);
1162
1163 out.println(indent + "if (_native" + cname + ") {");
1164 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1165 out.println(indent + "}");
1166 }
1167
1168 out.println();
1169 }
1170
1171
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001172 if (!isVoid) {
1173 out.println(indent + "return _returnValue;");
1174 }
1175
1176 out.println("}");
1177 out.println();
1178 }
1179
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001180}