blob: ebaca908d14b0acdad9ef7d9a3fcae7f0034ac93 [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 {
61 throw new RuntimeException("Uknown 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 }
203 out.println(iii + indent +
204 (mUseCPlusPlus ? "_env" : "(*_env)") +
205 "->ThrowNew(" +
206 (mUseCPlusPlus ? "" : "_env, ") +
207 "IAEClass, " +
208 "\"" +
209 (isBuffer ?
210 "remaining()" : "length - " + offset) +
211 " < needed\");");
212 out.println(iii + indent + "goto exit;");
213 needsExit = true;
214 out.println(iii + "}");
215 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216
217 boolean isNullAllowed(CFunc cfunc) {
218 String[] checks = mChecker.getChecks(cfunc.getName());
219 int index = 1;
220 if (checks != null) {
221 while (index < checks.length) {
222 if (checks[index].equals("return")) {
223 index += 2;
224 } else if (checks[index].startsWith("check")) {
225 index += 3;
226 } else if (checks[index].equals("ifcheck")) {
227 index += 5;
228 } else if (checks[index].equals("unsupported")) {
229 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800230 } else if (checks[index].equals("requires")) {
231 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800232 } else if (checks[index].equals("nullAllowed")) {
233 return true;
234 } else {
235 System.out.println("Error: unknown keyword \"" +
236 checks[index] + "\"");
237 System.exit(0);
238 }
239 }
240 }
241 return false;
242 }
243
244 String getErrorReturnValue(CFunc cfunc) {
245 CType returnType = cfunc.getType();
246 boolean isVoid = returnType.isVoid();
247 if (isVoid) {
248 return null;
249 }
250
251 String[] checks = mChecker.getChecks(cfunc.getName());
252
253 int index = 1;
254 if (checks != null) {
255 while (index < checks.length) {
256 if (checks[index].equals("return")) {
257 return checks[index + 1];
258 } else if (checks[index].startsWith("check")) {
259 index += 3;
260 } else if (checks[index].equals("ifcheck")) {
261 index += 5;
262 } else if (checks[index].equals("unsupported")) {
263 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800264 } else if (checks[index].equals("requires")) {
265 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800266 } else if (checks[index].equals("nullAllowed")) {
267 index += 1;
268 } else {
269 System.out.println("Error: unknown keyword \"" +
270 checks[index] + "\"");
271 System.exit(0);
272 }
273 }
274 }
275
276 return null;
277 }
278
279 boolean isUnsupportedFunc(CFunc cfunc) {
280 String[] checks = mChecker.getChecks(cfunc.getName());
281 int index = 1;
282 if (checks != null) {
283 while (index < checks.length) {
284 if (checks[index].equals("unsupported")) {
285 return true;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800286 } else if (checks[index].equals("requires")) {
287 index += 2;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800288 } else if (checks[index].equals("return")) {
289 index += 2;
290 } else if (checks[index].startsWith("check")) {
291 index += 3;
292 } else if (checks[index].equals("ifcheck")) {
293 index += 5;
294 } else if (checks[index].equals("nullAllowed")) {
295 index += 1;
296 } else {
297 System.out.println("Error: unknown keyword \"" +
298 checks[index] + "\"");
299 System.exit(0);
300 }
301 }
302 }
303 return false;
304 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800305
306 String isRequiresFunc(CFunc cfunc) {
307 String[] checks = mChecker.getChecks(cfunc.getName());
308 int index = 1;
309 if (checks != null) {
310 while (index < checks.length) {
311 if (checks[index].equals("unsupported")) {
312 index += 1;
313 } else if (checks[index].equals("requires")) {
314 return checks[index+1];
315 } else if (checks[index].equals("return")) {
316 index += 2;
317 } else if (checks[index].startsWith("check")) {
318 index += 3;
319 } else if (checks[index].equals("ifcheck")) {
320 index += 5;
321 } else if (checks[index].equals("nullAllowed")) {
322 index += 1;
323 } else {
324 System.out.println("Error: unknown keyword \"" +
325 checks[index] + "\"");
326 System.exit(0);
327 }
328 }
329 }
330 return null;
331 }
332
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700334 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800335
Jack Palevichffac1ef2009-04-14 19:00:09 -0700336 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337
Jack Palevichffac1ef2009-04-14 19:00:09 -0700338 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339
Jack Palevichffac1ef2009-04-14 19:00:09 -0700340 int index = 1;
341 if (checks != null) {
342 while (index < checks.length) {
343 if (checks[index].startsWith("check")) {
344 if (lastWasIfcheck) {
345 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
346 offset, remaining, iii);
347 }
348 lastWasIfcheck = false;
349 if (cname != null && !cname.equals(checks[index + 1])) {
350 index += 3;
351 continue;
352 }
353 out.println(iii + "if (" + remaining + " < " +
354 checks[index + 2] +
355 ") {");
356 if (emitExceptionCheck) {
357 out.println(iii + indent + "_exception = 1;");
358 }
359 String exceptionClassName = "IAEClass";
360 // If the "check" keyword was of the form
361 // "check_<class name>", use the class name in the
362 // exception to be thrown
363 int underscore = checks[index].indexOf('_');
364 if (underscore >= 0) {
365 exceptionClassName = checks[index].substring(underscore + 1) + "Class";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800366 }
Jack Palevichffac1ef2009-04-14 19:00:09 -0700367 out.println(iii + indent +
368 (mUseCPlusPlus ? "_env" : "(*_env)") +
369 "->ThrowNew(" +
370 (mUseCPlusPlus ? "" : "_env, ") +
371 exceptionClassName + ", " +
372 "\"" +
373 (isBuffer ?
374 "remaining()" : "length - " + offset) +
375 " < " + checks[index + 2] +
376 "\");");
377
378 out.println(iii + indent + "goto exit;");
379 needsExit = true;
380 out.println(iii + "}");
381
382 index += 3;
383 } else if (checks[index].equals("ifcheck")) {
384 String[] matches = checks[index + 4].split(",");
385
386 if (!lastWasIfcheck) {
387 out.println(iii + "int _needed;");
388 out.println(iii +
389 "switch (" +
390 checks[index + 3] +
391 ") {");
392 }
393
394 for (int i = 0; i < matches.length; i++) {
395 out.println("#if defined(" + matches[i] + ")");
396 out.println(iii +
397 " case " +
398 matches[i] +
399 ":");
400 out.println("#endif // defined(" + matches[i] + ")");
401 }
402 out.println(iii +
403 " _needed = " +
404 checks[index + 2] +
405 ";");
406 out.println(iii +
407 " break;");
408
409 lastWasIfcheck = true;
410 index += 5;
411 } else if (checks[index].equals("return")) {
412 // ignore
413 index += 2;
414 } else if (checks[index].equals("unsupported")) {
415 // ignore
416 index += 1;
Jack Paleviche44e45c2010-01-28 20:28:32 +0800417 } else if (checks[index].equals("requires")) {
418 // ignore
419 index += 2;
Jack Palevichffac1ef2009-04-14 19:00:09 -0700420 } else if (checks[index].equals("nullAllowed")) {
421 // ignore
422 index += 1;
423 } else {
424 System.out.println("Error: unknown keyword \"" +
425 checks[index] + "\"");
426 System.exit(0);
427 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800428 }
Jack Palevichffac1ef2009-04-14 19:00:09 -0700429 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800430
Jack Palevichffac1ef2009-04-14 19:00:09 -0700431 if (lastWasIfcheck) {
432 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800433 }
434 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800435
Jack Palevichffac1ef2009-04-14 19:00:09 -0700436 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437 if (nonPrimitiveArgs.size() > 0) {
438 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
439 int idx = nonPrimitiveArgs.get(i).intValue();
440 int cIndex = jfunc.getArgCIndex(idx);
441 if (jfunc.getArgType(idx).isArray()) {
442 if (!cfunc.getArgType(cIndex).isConst()) {
443 return true;
444 }
445 } else if (jfunc.getArgType(idx).isBuffer()) {
446 if (!cfunc.getArgType(cIndex).isConst()) {
447 return true;
448 }
449 }
450 }
451 }
452
453 return false;
454 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700455
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800456 /**
457 * Emit a function in several variants:
458 *
459 * if nativeDecl: public native <returntype> func(args);
460 *
461 * if !nativeDecl:
462 * if interfaceDecl: public <returntype> func(args);
463 * if !interfaceDecl: public <returntype> func(args) { body }
464 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700465 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800466 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800467
468 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
469 // If it's not a pointer function, we've already emitted it
470 // with nativeDecl == true
471 return;
472 }
473
Jack Palevich427f5852009-04-15 19:13:17 -0700474 String maybeStatic = mUseStaticMethods ? "static " : "";
475
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800476 if (isPointerFunc) {
477 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700478 (nativeDecl ? "private " + maybeStatic +"native " :
479 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800480 jfunc.getType() + " " +
481 jfunc.getName() +
482 (nativeDecl ? "Bounds" : "") +
483 "(");
484 } else {
485 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700486 (nativeDecl ? "public " + maybeStatic +"native " :
487 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800488 jfunc.getType() + " " +
489 jfunc.getName() +
490 "(");
491 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700492
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 int numArgs = jfunc.getNumArgs();
494 for (int i = 0; i < numArgs; i++) {
495 String argName = jfunc.getArgName(i);
496 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700497
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800498 out.print(indent + indent + argType + " " + argName);
499 if (i == numArgs - 1) {
500 if (isPointerFunc && nativeDecl) {
501 out.println(",");
502 out.println(indent + indent + "int remaining");
503 } else {
504 out.println();
505 }
506 } else {
507 out.println(",");
508 }
509 }
510
511 if (nativeDecl || interfaceDecl) {
512 out.println(indent + ");");
513 } else {
514 out.println(indent + ") {");
515
516 String iii = indent + indent;
517
Jack Palevich46d25a32009-05-07 18:28:29 -0700518 // emitBoundsChecks(jfunc, out, iii);
519 emitFunctionCall(jfunc, out, iii, false);
520
521 // Set the pointer after we call the native code, so that if
522 // the native code throws an exception we don't modify the
523 // pointer. We assume that the native code is written so that
524 // if an exception is thrown, then the underlying glXXXPointer
525 // function will not have been called.
526
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800527 String fname = jfunc.getName();
528 if (isPointerFunc) {
529 // TODO - deal with VBO variants
530 if (fname.equals("glColorPointer")) {
531 out.println(iii + "if ((size == 4) &&");
532 out.println(iii + " ((type == GL_FLOAT) ||");
533 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
534 out.println(iii + " (type == GL_FIXED)) &&");
535 out.println(iii + " (stride >= 0)) {");
536 out.println(iii + indent + "_colorPointer = pointer;");
537 out.println(iii + "}");
538 } else if (fname.equals("glNormalPointer")) {
539 out.println(iii + "if (((type == GL_FLOAT) ||");
540 out.println(iii + " (type == GL_BYTE) ||");
541 out.println(iii + " (type == GL_SHORT) ||");
542 out.println(iii + " (type == GL_FIXED)) &&");
543 out.println(iii + " (stride >= 0)) {");
544 out.println(iii + indent + "_normalPointer = pointer;");
545 out.println(iii + "}");
546 } else if (fname.equals("glTexCoordPointer")) {
547 out.println(iii + "if (((size == 2) ||");
548 out.println(iii + " (size == 3) ||");
549 out.println(iii + " (size == 4)) &&");
550 out.println(iii + " ((type == GL_FLOAT) ||");
551 out.println(iii + " (type == GL_BYTE) ||");
552 out.println(iii + " (type == GL_SHORT) ||");
553 out.println(iii + " (type == GL_FIXED)) &&");
554 out.println(iii + " (stride >= 0)) {");
555 out.println(iii + indent + "_texCoordPointer = pointer;");
556 out.println(iii + "}");
557 } else if (fname.equals("glVertexPointer")) {
558 out.println(iii + "if (((size == 2) ||");
559 out.println(iii + " (size == 3) ||");
560 out.println(iii + " (size == 4)) &&");
561 out.println(iii + " ((type == GL_FLOAT) ||");
562 out.println(iii + " (type == GL_BYTE) ||");
563 out.println(iii + " (type == GL_SHORT) ||");
564 out.println(iii + " (type == GL_FIXED)) &&");
565 out.println(iii + " (stride >= 0)) {");
566 out.println(iii + indent + "_vertexPointer = pointer;");
567 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800568 } else if (fname.equals("glPointSizePointerOES")) {
569 out.println(iii + "if (((type == GL_FLOAT) ||");
570 out.println(iii + " (type == GL_FIXED)) &&");
571 out.println(iii + " (stride >= 0)) {");
572 out.println(iii + indent + "_pointSizePointerOES = pointer;");
573 out.println(iii + "}");
574 } else if (fname.equals("glMatrixIndexPointerOES")) {
575 out.println(iii + "if (((size == 2) ||");
576 out.println(iii + " (size == 3) ||");
577 out.println(iii + " (size == 4)) &&");
578 out.println(iii + " ((type == GL_FLOAT) ||");
579 out.println(iii + " (type == GL_BYTE) ||");
580 out.println(iii + " (type == GL_SHORT) ||");
581 out.println(iii + " (type == GL_FIXED)) &&");
582 out.println(iii + " (stride >= 0)) {");
583 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
584 out.println(iii + "}");
585 } else if (fname.equals("glWeightPointer")) {
586 out.println(iii + "if (((size == 2) ||");
587 out.println(iii + " (size == 3) ||");
588 out.println(iii + " (size == 4)) &&");
589 out.println(iii + " ((type == GL_FLOAT) ||");
590 out.println(iii + " (type == GL_BYTE) ||");
591 out.println(iii + " (type == GL_SHORT) ||");
592 out.println(iii + " (type == GL_FIXED)) &&");
593 out.println(iii + " (stride >= 0)) {");
594 out.println(iii + indent + "_weightPointerOES = pointer;");
595 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800596 }
597 }
598
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800599 boolean isVoid = jfunc.getType().isVoid();
600
601 if (!isVoid) {
602 out.println(indent + indent + "return _returnValue;");
603 }
604 out.println(indent + "}");
605 }
606 out.println();
607 }
608
Jack Palevichffac1ef2009-04-14 19:00:09 -0700609 public void addNativeRegistration(String s) {
610 nativeRegistrations.add(s);
611 }
612
Jack Palevich427f5852009-04-15 19:13:17 -0700613 public void emitNativeRegistration(String registrationFunctionName,
614 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700615 cStream.println("static const char *classPathName = \"" +
616 mClassPathName +
617 "\";");
618 cStream.println();
619
620 cStream.println("static JNINativeMethod methods[] = {");
621
622 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
623
624 Iterator<String> i = nativeRegistrations.iterator();
625 while (i.hasNext()) {
626 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800627 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700628
Jack Palevichffac1ef2009-04-14 19:00:09 -0700629 cStream.println("};");
630 cStream.println();
631
632
Jack Palevich427f5852009-04-15 19:13:17 -0700633 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700634 cStream.println("{");
635 cStream.println(indent +
636 "int err;");
637
638 cStream.println(indent +
639 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
640
641 cStream.println(indent + "return err;");
642 cStream.println("}");
643 }
644
645 public JniCodeEmitter() {
646 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800647 }
648
649 String getJniType(JType jType) {
650 if (jType.isVoid()) {
651 return "void";
652 }
653
654 String baseType = jType.getBaseType();
655 if (jType.isPrimitive()) {
656 if (baseType.equals("String")) {
657 return "jstring";
658 } else {
659 return "j" + baseType;
660 }
661 } else if (jType.isArray()) {
662 return "j" + baseType + "Array";
663 } else {
664 return "jobject";
665 }
666 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700667
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800668 String getJniMangledName(String name) {
669 name = name.replaceAll("_", "_1");
670 name = name.replaceAll(";", "_2");
671 name = name.replaceAll("\\[", "_3");
672 return name;
673 }
674
675 public void emitJniCode(JFunc jfunc, PrintStream out) {
676 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700677
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800678 // Emit comment identifying original C function
679 //
680 // Example:
681 //
682 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
683 //
684 out.println("/* " + cfunc.getOriginal() + " */");
685
686 // Emit JNI signature (name)
687 //
688 // Example:
689 //
690 // void
691 // android_glClipPlanef__I_3FI
692 //
693
694 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800695 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800696 boolean isVBOPointerFunc = (outName.endsWith("Pointer") ||
Jack Palevich66089a32009-12-08 15:43:51 +0800697 outName.endsWith("PointerOES") ||
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800698 outName.endsWith("DrawElements")) &&
699 !jfunc.getCFunc().hasPointerArg();
700 if (isPointerFunc) {
701 outName += "Bounds";
702 }
703
704 out.print("static ");
705 out.println(getJniType(jfunc.getType()));
706 out.print(outName);
707
708 String rsignature = getJniName(jfunc.getType());
709
710 String signature = "";
711 int numArgs = jfunc.getNumArgs();
712 for (int i = 0; i < numArgs; i++) {
713 JType argType = jfunc.getArgType(i);
714 signature += getJniName(argType);
715 }
716 if (isPointerFunc) {
717 signature += "I";
718 }
719
720 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800721 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800722 out.print("__" + sig);
723 outName += "__" + sig;
Jack Palevich6cbca502009-04-13 16:22:25 -0700724
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800725 signature = signature.replace('.', '/');
726 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700727
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800728 out.println();
729 if (rsignature.length() == 0) {
730 rsignature = "V";
731 }
732
733 String s = "{\"" +
734 jfunc.getName() +
735 (isPointerFunc ? "Bounds" : "") +
736 "\", \"(" + signature +")" +
737 rsignature +
738 "\", (void *) " +
739 outName +
740 " },";
741 nativeRegistrations.add(s);
742
743 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800744 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800745 int numBufferArgs = 0;
746 List<String> bufferArgNames = new ArrayList<String>();
747
748 // Emit JNI signature (arguments)
749 //
750 // Example:
751 //
752 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
753 //
754 out.print(" (JNIEnv *_env, jobject _this");
755 for (int i = 0; i < numArgs; i++) {
756 out.print(", ");
757 JType argType = jfunc.getArgType(i);
758 String suffix;
759 if (!argType.isPrimitive()) {
760 if (argType.isArray()) {
761 suffix = "_ref";
762 } else {
763 suffix = "_buf";
764 }
765 nonPrimitiveArgs.add(new Integer(i));
766 if (jfunc.getArgType(i).isBuffer()) {
767 int cIndex = jfunc.getArgCIndex(i);
768 String cname = cfunc.getArgName(cIndex);
769 bufferArgNames.add(cname);
770 numBufferArgs++;
771 }
772 } else {
773 suffix = "";
774 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800775 if (argType.isString()) {
776 stringArgs.add(new Integer(i));
777 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800778
779 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
780 }
781 if (isPointerFunc) {
782 out.print(", jint remaining");
783 }
784 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700785
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800786 int numArrays = 0;
787 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800788 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800789 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
790 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800791 JType argType = jfunc.getArgType(idx);
792 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800793 ++numArrays;
794 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800795 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800796 ++numBuffers;
797 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800798 if (argType.isString()) {
799 ++numStrings;
800 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800801 }
802
803 // Emit method body
804
805 // Emit local variable declarations for _exception and _returnValue
806 //
807 // Example:
808 //
809 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700810 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800811 // jint _exception;
812 // GLenum _returnValue;
813 //
814 CType returnType = cfunc.getType();
815 boolean isVoid = returnType.isVoid();
816
817 boolean isUnsupported = isUnsupportedFunc(cfunc);
818 if (isUnsupported) {
819 out.println(indent +
820 "_env->ThrowNew(UOEClass,");
821 out.println(indent +
822 " \"" + cfunc.getName() + "\");");
823 if (!isVoid) {
824 String retval = getErrorReturnValue(cfunc);
825 out.println(indent + "return " + retval + ";");
826 }
827 out.println("}");
828 out.println();
829 return;
830 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800831
832 String requiresExtension = isRequiresFunc(cfunc);
833 if (requiresExtension != null) {
834 out.println(indent +
835 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
836 out.println(indent + indent +
837 "_env->ThrowNew(UOEClass,");
838 out.println(indent + indent +
839 " \"" + cfunc.getName() + "\");");
840 if (isVoid) {
841 out.println(indent + indent + " return;");
842 } else {
843 String retval = getErrorReturnValue(cfunc);
844 out.println(indent + indent + " return " + retval + ";");
845 }
846 out.println(indent + "}");
847 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800848 if (mUseContextPointer) {
849 out.println(indent +
850 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
851 }
852
Jack Palevich50d0b142009-11-19 16:34:55 +0800853 boolean initializeReturnValue = stringArgs.size() > 0;
854
855 boolean emitExceptionCheck = (numArrays > 0 || numBuffers > 0 || numStrings > 0) &&
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800856 hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs);
857 // mChecker.getChecks(cfunc.getName()) != null
858
859 // Emit an _exeption variable if there will be error checks
860 if (emitExceptionCheck) {
861 out.println(indent + "jint _exception = 0;");
862 }
863
864 // Emit a single _array or multiple _XXXArray variables
865 if (numBufferArgs == 1) {
866 out.println(indent + "jarray _array = (jarray) 0;");
867 } else {
868 for (int i = 0; i < numBufferArgs; i++) {
869 out.println(indent + "jarray _" + bufferArgNames.get(i) +
870 "Array = (jarray) 0;");
871 }
872 }
873 if (!isVoid) {
874 String retval = getErrorReturnValue(cfunc);
875 if (retval != null) {
876 out.println(indent + returnType.getDeclaration() +
877 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +0800878 } else if (initializeReturnValue) {
879 out.println(indent + returnType.getDeclaration() +
880 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800881 } else {
882 out.println(indent + returnType.getDeclaration() +
883 " _returnValue;");
884 }
885 }
886
887 // Emit local variable declarations for pointer arguments
888 //
889 // Example:
890 //
891 // GLfixed *eqn_base;
892 // GLfixed *eqn;
893 //
894 String offset = "offset";
895 String remaining = "_remaining";
896 if (nonPrimitiveArgs.size() > 0) {
897 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
898 int idx = nonPrimitiveArgs.get(i).intValue();
899 int cIndex = jfunc.getArgCIndex(idx);
900 String cname = cfunc.getArgName(cIndex);
901
902 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
903 String decl = type.getDeclaration();
904 if (jfunc.getArgType(idx).isArray()) {
905 out.println(indent +
906 decl +
907 (decl.endsWith("*") ? "" : " ") +
908 jfunc.getArgName(idx) +
909 "_base = (" + decl + ") 0;");
910 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800911 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800912 "_" + cname + "Remaining";
913 out.println(indent +
914 "jint " + remaining + ";");
915 out.println(indent +
916 decl +
917 (decl.endsWith("*") ? "" : " ") +
Jack Palevich6cbca502009-04-13 16:22:25 -0700918 jfunc.getArgName(idx) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800919 " = (" + decl + ") 0;");
920 }
921
922 out.println();
923 }
924
Jack Palevich50d0b142009-11-19 16:34:55 +0800925 // Emit local variable declaration for strings
926 if (stringArgs.size() > 0) {
927 for (int i = 0; i < stringArgs.size(); i++) {
928 int idx = stringArgs.get(i).intValue();
929 int cIndex = jfunc.getArgCIndex(idx);
930 String cname = cfunc.getArgName(cIndex);
931
932 out.println(indent + "const char* _native" + cname + " = 0;");
933 }
934
935 out.println();
936 }
937
938 // Null pointer checks and GetStringUTFChars
939 if (stringArgs.size() > 0) {
940 for (int i = 0; i < stringArgs.size(); i++) {
941 int idx = stringArgs.get(i).intValue();
942 int cIndex = jfunc.getArgCIndex(idx);
943 String cname = cfunc.getArgName(cIndex);
944
945 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
946 String decl = type.getDeclaration();
947 out.println(indent + "if (!" + cname + ") {");
948 out.println(indent + " _env->ThrowNew(IAEClass, \"" + cname + " == null\");");
949 out.println(indent + " goto exit;");
950 needsExit = true;
951 out.println(indent + "}");
952
953 out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
954 }
955
956 out.println();
957 }
958
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800959 // Emit 'GetPrimitiveArrayCritical' for arrays
960 // Emit 'GetPointer' calls for Buffer pointers
961 int bufArgIdx = 0;
962 if (nonPrimitiveArgs.size() > 0) {
963 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
964 int idx = nonPrimitiveArgs.get(i).intValue();
965 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -0700966
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800967 String cname = cfunc.getArgName(cIndex);
968 offset = numArrays <= 1 ? "offset" :
969 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +0800970 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800971 "_" + cname + "Remaining";
972
973 if (jfunc.getArgType(idx).isArray()) {
974 out.println(indent +
Jack Palevich6cbca502009-04-13 16:22:25 -0700975 "if (!" +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800976 cname +
977 "_ref) {");
978 if (emitExceptionCheck) {
979 out.println(indent + indent + "_exception = 1;");
980 }
981 out.println(indent + " " +
982 (mUseCPlusPlus ? "_env" : "(*_env)") +
983 "->ThrowNew(" +
984 (mUseCPlusPlus ? "" : "_env, ") +
985 "IAEClass, " +
986 "\"" + cname +
987 " == null\");");
988 out.println(indent + " goto exit;");
989 needsExit = true;
990 out.println(indent + "}");
991
992 out.println(indent + "if (" + offset + " < 0) {");
993 if (emitExceptionCheck) {
994 out.println(indent + indent + "_exception = 1;");
995 }
996 out.println(indent + " " +
997 (mUseCPlusPlus ? "_env" : "(*_env)") +
998 "->ThrowNew(" +
999 (mUseCPlusPlus ? "" : "_env, ") +
1000 "IAEClass, " +
1001 "\"" + offset + " < 0\");");
1002 out.println(indent + " goto exit;");
1003 needsExit = true;
1004 out.println(indent + "}");
1005
1006 out.println(indent + remaining + " = " +
Jack Palevich6cbca502009-04-13 16:22:25 -07001007 (mUseCPlusPlus ? "_env" : "(*_env)") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001008 "->GetArrayLength(" +
1009 (mUseCPlusPlus ? "" : "_env, ") +
1010 cname + "_ref) - " + offset + ";");
1011
1012 emitNativeBoundsChecks(cfunc, cname, out, false,
1013 emitExceptionCheck,
1014 offset, remaining, " ");
1015
1016 out.println(indent +
1017 cname +
1018 "_base = (" +
1019 cfunc.getArgType(cIndex).getDeclaration() +
1020 ")");
1021 out.println(indent + " " +
1022 (mUseCPlusPlus ? "_env" : "(*_env)") +
1023 "->GetPrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001024 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001025 jfunc.getArgName(idx) +
1026 "_ref, (jboolean *)0);");
1027 out.println(indent +
1028 cname + " = " + cname + "_base + " + offset +
1029 ";");
1030 out.println();
1031 } else {
1032 String array = numBufferArgs <= 1 ? "_array" :
1033 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1034
Jack Palevich46d25a32009-05-07 18:28:29 -07001035 boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001036 if (nullAllowed) {
1037 out.println(indent + "if (" + cname + "_buf) {");
1038 out.print(indent);
1039 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001040
Jack Palevich46d25a32009-05-07 18:28:29 -07001041 if (isPointerFunc) {
1042 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001043 cname +
1044 " = (" +
1045 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001046 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001047 cname + "_buf);");
1048 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001049 out.println(iii + indent + "if ( ! " + cname + " ) {");
Jack Palevich46d25a32009-05-07 18:28:29 -07001050 out.println(iii + iii + indent + "return;");
1051 out.println(iii + indent + "}");
1052 } else {
1053 out.println(indent +
1054 cname +
1055 " = (" +
1056 cfunc.getArgType(cIndex).getDeclaration() +
1057 ")getPointer(_env, " +
1058 cname +
1059 "_buf, &" + array + ", &" + remaining +
1060 ");");
1061 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001062
Jack Palevich5afdc872009-10-21 11:02:44 -07001063 emitNativeBoundsChecks(cfunc, cname, out, true,
1064 emitExceptionCheck,
1065 offset, remaining, nullAllowed ? " " : " ");
1066
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001067 if (nullAllowed) {
1068 out.println(indent + "}");
1069 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001070 }
1071 }
1072 }
1073
1074 if (!isVoid) {
1075 out.print(indent + "_returnValue = ");
1076 } else {
1077 out.print(indent);
1078 }
1079 String name = cfunc.getName();
1080
1081 if (mUseContextPointer) {
1082 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1083 name = name.substring(0, 1).toLowerCase() +
1084 name.substring(1, name.length());
1085 out.print("ctx->procs.");
1086 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001087
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001088 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1089
Jack Palevich6cbca502009-04-13 16:22:25 -07001090 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001091 if (numArgs == 0) {
1092 if (mUseContextPointer) {
1093 out.println("ctx);");
1094 } else {
1095 out.println(");");
1096 }
1097 } else {
1098 if (mUseContextPointer) {
1099 out.println("ctx,");
1100 } else {
1101 out.println();
1102 }
1103 for (int i = 0; i < numArgs; i++) {
1104 String typecast;
1105 if (i == numArgs - 1 && isVBOPointerFunc) {
1106 typecast = "const GLvoid *";
1107 } else {
1108 typecast = cfunc.getArgType(i).getDeclaration();
1109 }
1110 out.print(indent + indent +
1111 "(" +
1112 typecast +
Jack Palevich50d0b142009-11-19 16:34:55 +08001113 ")");
1114 if (cfunc.getArgType(i).isConstCharPointer()) {
1115 out.print("_native");
1116 }
1117 out.print(cfunc.getArgName(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001118
1119 if (i == numArgs - 1) {
1120 if (isPointerFunc) {
1121 out.println(",");
1122 out.println(indent + indent + "(GLsizei)remaining");
1123 } else {
1124 out.println();
1125 }
1126 } else {
1127 out.println(",");
1128 }
1129 }
1130 out.println(indent + ");");
1131 }
1132
1133 if (needsExit) {
1134 out.println();
1135 out.println("exit:");
1136 needsExit = false;
1137 }
1138
1139 bufArgIdx = 0;
1140 if (nonPrimitiveArgs.size() > 0) {
1141 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1142 int idx = nonPrimitiveArgs.get(i).intValue();
1143
1144 int cIndex = jfunc.getArgCIndex(idx);
1145 if (jfunc.getArgType(idx).isArray()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001146
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001147 // If the argument is 'const', GL will not write to it.
1148 // In this case, we can use the 'JNI_ABORT' flag to avoid
1149 // the need to write back to the Java array
1150 out.println(indent +
1151 "if (" + jfunc.getArgName(idx) + "_base) {");
1152 out.println(indent + indent +
1153 (mUseCPlusPlus ? "_env" : "(*_env)") +
1154 "->ReleasePrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001155 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001156 jfunc.getArgName(idx) + "_ref, " +
1157 cfunc.getArgName(cIndex) +
1158 "_base,");
1159 out.println(indent + indent + indent +
1160 (cfunc.getArgType(cIndex).isConst() ?
1161 "JNI_ABORT" :
1162 "_exception ? JNI_ABORT: 0") +
1163 ");");
1164 out.println(indent + "}");
1165 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001166 if (! isPointerFunc) {
1167 String array = numBufferArgs <= 1 ? "_array" :
1168 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1169 out.println(indent + "if (" + array + ") {");
1170 out.println(indent + indent +
1171 "releasePointer(_env, " + array + ", " +
1172 cfunc.getArgName(cIndex) +
1173 ", " +
1174 (cfunc.getArgType(cIndex).isConst() ?
1175 "JNI_FALSE" : "_exception ? JNI_FALSE :" +
1176 " JNI_TRUE") +
1177 ");");
1178 out.println(indent + "}");
1179 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001180 }
1181 }
1182 }
1183
Jack Palevich50d0b142009-11-19 16:34:55 +08001184 // Emit local variable declaration for strings
1185 if (stringArgs.size() > 0) {
1186 for (int i = 0; i < stringArgs.size(); i++) {
1187 int idx = stringArgs.get(i).intValue();
1188 int cIndex = jfunc.getArgCIndex(idx);
1189 String cname = cfunc.getArgName(cIndex);
1190
1191 out.println(indent + "if (_native" + cname + ") {");
1192 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1193 out.println(indent + "}");
1194 }
1195
1196 out.println();
1197 }
1198
1199
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001200 if (!isVoid) {
1201 out.println(indent + "return _returnValue;");
1202 }
1203
1204 out.println("}");
1205 out.println();
1206 }
1207
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001208}