blob: 9c80212011b0cfd7a2b335d5e4f42cb11147a036 [file] [log] [blame]
Kenny Rootbd393b72010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017import java.io.PrintStream;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080018import java.util.ArrayList;
19import java.util.HashSet;
20import java.util.Iterator;
21import java.util.List;
22
Jack Palevichffac1ef2009-04-14 19:00:09 -070023public class JniCodeEmitter {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080024
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025 static final boolean mUseCPlusPlus = true;
Jack Palevichffac1ef2009-04-14 19:00:09 -070026 protected boolean mUseContextPointer = true;
Jack Palevich427f5852009-04-15 19:13:17 -070027 protected boolean mUseStaticMethods = false;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -070028 protected boolean mUseSimpleMethodNames = false;
29 protected boolean mUseHideCommentForAPI = false;
Jack Palevichffac1ef2009-04-14 19:00:09 -070030 protected String mClassPathName;
31 protected ParameterChecker mChecker;
32 protected List<String> nativeRegistrations = new ArrayList<String>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033 boolean needsExit;
Jack Palevichffac1ef2009-04-14 19:00:09 -070034 protected static String indent = " ";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080035 HashSet<String> mFunctionsEmitted = new HashSet<String>();
36
Jack Palevichffac1ef2009-04-14 19:00:09 -070037 public static String getJniName(JType jType) {
38 String jniName = "";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -070039 if (jType.isEGLHandle()) {
40 return (jType.isArray() ? "[" : "" ) + "Landroid/opengl/" + jType.getBaseType() + ";";
41 } else if (jType.isClass()) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070042 return "L" + jType.getBaseType() + ";";
43 } else if (jType.isArray()) {
44 jniName = "[";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080045 }
Jack Palevichffac1ef2009-04-14 19:00:09 -070046
47 String baseType = jType.getBaseType();
48 if (baseType.equals("int")) {
49 jniName += "I";
50 } else if (baseType.equals("float")) {
51 jniName += "F";
52 } else if (baseType.equals("boolean")) {
53 jniName += "Z";
54 } else if (baseType.equals("short")) {
55 jniName += "S";
56 } else if (baseType.equals("long")) {
Andy McFadden72841452013-03-01 16:25:32 -080057 jniName += "J";
Jack Palevichffac1ef2009-04-14 19:00:09 -070058 } else if (baseType.equals("byte")) {
59 jniName += "B";
Jack Palevich50d0b142009-11-19 16:34:55 +080060 } else if (baseType.equals("String")) {
61 jniName += "Ljava/lang/String;";
62 } else if (baseType.equals("void")) {
63 // nothing.
64 } else {
Elliott Hughes98757502011-04-08 20:01:01 -070065 throw new RuntimeException("Unknown primitive basetype " + baseType);
Jack Palevichffac1ef2009-04-14 19:00:09 -070066 }
67 return jniName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080068 }
69
Jack Palevichffac1ef2009-04-14 19:00:09 -070070 public void emitCode(CFunc cfunc, String original,
71 PrintStream javaInterfaceStream,
72 PrintStream javaImplStream,
73 PrintStream cStream) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080074 JFunc jfunc;
75 String signature;
76 boolean duplicate;
Jack Palevich6cbca502009-04-13 16:22:25 -070077
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080078 if (cfunc.hasTypedPointerArg()) {
79 jfunc = JFunc.convert(cfunc, true);
80
81 // Don't emit duplicate functions
82 // These may appear because they are defined in multiple
83 // Java interfaces (e.g., GL11/GL11ExtensionPack)
84 signature = jfunc.toString();
85 duplicate = false;
86 if (mFunctionsEmitted.contains(signature)) {
87 duplicate = true;
88 } else {
89 mFunctionsEmitted.add(signature);
90 }
91
92 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070093 emitNativeDeclaration(jfunc, javaImplStream);
94 emitJavaCode(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080095 }
Jack Palevich427f5852009-04-15 19:13:17 -070096 if (javaInterfaceStream != null) {
97 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
98 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080099 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700100 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800101 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700102 // Don't create IOBuffer versions of the EGL functions
103 if (cfunc.hasEGLHandleArg()) {
104 return;
105 }
Courtney Goeltzenleuchterb28648c2018-07-18 09:38:47 -0600106 // eglGetPlatformDisplay does not have any EGLHandleArgs
107 // but we do not want to create IOBuffers of this, so
108 // exit
109 if (cfunc.getName().equals("eglGetPlatformDisplay")) {
110 return;
111 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800112 }
113
114 jfunc = JFunc.convert(cfunc, false);
115
116 signature = jfunc.toString();
117 duplicate = false;
118 if (mFunctionsEmitted.contains(signature)) {
119 duplicate = true;
120 } else {
121 mFunctionsEmitted.add(signature);
122 }
123
124 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700125 emitNativeDeclaration(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800126 }
Jack Palevich427f5852009-04-15 19:13:17 -0700127 if (javaInterfaceStream != null) {
128 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
129 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800130 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700131 emitJavaCode(jfunc, javaImplStream);
132 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800133 }
134 }
135
136 public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700137 if (mUseHideCommentForAPI) {
138 out.println(" /* @hide C function " + jfunc.getCFunc().getOriginal() + " */");
139 out.println();
140 } else {
141 out.println(" // C function " + jfunc.getCFunc().getOriginal());
142 out.println();
143 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800144
145 emitFunction(jfunc, out, true, false);
146 }
147
148 public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
149 emitFunction(jfunc, out, false, true);
150 }
151
152 public void emitJavaCode(JFunc jfunc, PrintStream out) {
153 emitFunction(jfunc, out, false, false);
154 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700155
Jack Palevich66089a32009-12-08 15:43:51 +0800156 boolean isPointerFunc(JFunc jfunc) {
157 String name = jfunc.getName();
158 return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
159 && jfunc.getCFunc().hasPointerArg();
160 }
161
Jack Palevichffac1ef2009-04-14 19:00:09 -0700162 void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800163 boolean isVoid = jfunc.getType().isVoid();
Jack Palevich66089a32009-12-08 15:43:51 +0800164 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800165
166 if (!isVoid) {
167 out.println(iii +
168 jfunc.getType() + " _returnValue;");
169 }
170 out.println(iii +
171 (isVoid ? "" : "_returnValue = ") +
172 jfunc.getName() +
173 (isPointerFunc ? "Bounds" : "" ) +
174 "(");
Jack Palevich6cbca502009-04-13 16:22:25 -0700175
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176 int numArgs = jfunc.getNumArgs();
177 for (int i = 0; i < numArgs; i++) {
178 String argName = jfunc.getArgName(i);
179 JType argType = jfunc.getArgType(i);
180
181 if (grabArray && argType.isTypedBuffer()) {
182 String typeName = argType.getBaseType();
183 typeName = typeName.substring(9, typeName.length() - 6);
184 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
Jack Palevich6cbca502009-04-13 16:22:25 -0700185 out.print(iii + indent + "getOffset(" + argName + ")");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186 } else {
187 out.print(iii + indent + argName);
188 }
189 if (i == numArgs - 1) {
190 if (isPointerFunc) {
191 out.println(",");
192 out.println(iii + indent + argName + ".remaining()");
193 } else {
194 out.println();
195 }
196 } else {
197 out.println(",");
198 }
199 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700200
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201 out.println(iii + ");");
202 }
203
Jack Palevichffac1ef2009-04-14 19:00:09 -0700204 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
205 String iii) {
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800206 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
207 "offset", "_remaining", iii);
208 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209
Jack Palevichffac1ef2009-04-14 19:00:09 -0700210 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
211 String offset, String remaining, String iii) {
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800212 out.println(iii + " default:");
213 out.println(iii + " _needed = 1;");
214 out.println(iii + " break;");
215 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800217 out.println(iii + "if (" + remaining + " < _needed) {");
218 out.println(iii + indent + "_exception = 1;");
219 out.println(iii + indent +
220 "_exceptionType = \"java/lang/IllegalArgumentException\";");
221 out.println(iii + indent +
222 "_exceptionMessage = \"" +
223 (isBuffer ? "remaining()" : "length - " + offset) +
224 " < needed\";");
225 out.println(iii + indent + "goto exit;");
226 out.println(iii + "}");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700227
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800228 needsExit = true;
229 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700231 boolean isNullAllowed(CFunc cfunc, String cname) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800232 String[] checks = mChecker.getChecks(cfunc.getName());
233 int index = 1;
234 if (checks != null) {
235 while (index < checks.length) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700236 if (checks[index].equals("nullAllowed") &&
237 checks[index + 1].equals(cname)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 return true;
239 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700240 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800241 }
242 }
243 }
244 return false;
245 }
246
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700247 boolean hasCheckTest(CFunc cfunc) {
248 String[] checks = mChecker.getChecks(cfunc.getName());
249 int index = 1;
250 if (checks != null) {
251 while (index < checks.length) {
252 if (checks[index].startsWith("check")) {
253 return true;
254 } else {
255 index = skipOneCheck(checks, index);
256 }
257 }
258 }
259 return false;
260 }
261
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700262 boolean hasCheckTest(CFunc cfunc, String cname) {
263 String[] checks = mChecker.getChecks(cfunc.getName());
264 int index = 1;
265 if (checks != null) {
266 while (index < checks.length) {
267 if (checks[index].startsWith("check") &&
268 cname != null && cname.equals(checks[index + 1])) {
269 return true;
270 } else {
271 index = skipOneCheck(checks, index);
272 }
273 }
274 }
275 return false;
276 }
277
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700278 boolean hasIfTest(CFunc cfunc) {
279 String[] checks = mChecker.getChecks(cfunc.getName());
280 int index = 1;
281 if (checks != null) {
282 while (index < checks.length) {
283 if (checks[index].startsWith("ifcheck")) {
284 return true;
285 } else {
286 index = skipOneCheck(checks, index);
287 }
288 }
289 }
290 return false;
291 }
292
293 int skipOneCheck(String[] checks, int index) {
294 if (checks[index].equals("return")) {
295 index += 2;
296 } else if (checks[index].startsWith("check")) {
297 index += 3;
298 } else if (checks[index].startsWith("sentinel")) {
299 index += 3;
300 } else if (checks[index].equals("ifcheck")) {
301 index += 5;
302 } else if (checks[index].equals("unsupported")) {
303 index += 1;
304 } else if (checks[index].equals("requires")) {
305 index += 2;
306 } else if (checks[index].equals("nullAllowed")) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700307 index += 2;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700308 } else {
309 System.out.println("Error: unknown keyword \"" +
310 checks[index] + "\"");
311 System.exit(0);
312 }
313
314 return index;
315 }
316
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317 String getErrorReturnValue(CFunc cfunc) {
318 CType returnType = cfunc.getType();
319 boolean isVoid = returnType.isVoid();
320 if (isVoid) {
321 return null;
322 }
323
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700324 if (returnType.getBaseType().startsWith("EGL")) {
325 return "(" + returnType.getDeclaration() + ") 0";
326 }
327
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800328 String[] checks = mChecker.getChecks(cfunc.getName());
329
330 int index = 1;
331 if (checks != null) {
332 while (index < checks.length) {
333 if (checks[index].equals("return")) {
334 return checks[index + 1];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800335 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700336 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337 }
338 }
339 }
340
341 return null;
342 }
343
344 boolean isUnsupportedFunc(CFunc cfunc) {
345 String[] checks = mChecker.getChecks(cfunc.getName());
346 int index = 1;
347 if (checks != null) {
348 while (index < checks.length) {
349 if (checks[index].equals("unsupported")) {
350 return true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700352 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800353 }
354 }
355 }
356 return false;
357 }
Elliott Hughes98757502011-04-08 20:01:01 -0700358
Jack Paleviche44e45c2010-01-28 20:28:32 +0800359 String isRequiresFunc(CFunc cfunc) {
360 String[] checks = mChecker.getChecks(cfunc.getName());
361 int index = 1;
362 if (checks != null) {
363 while (index < checks.length) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700364 if (checks[index].equals("requires")) {
Jack Paleviche44e45c2010-01-28 20:28:32 +0800365 return checks[index+1];
Jack Paleviche44e45c2010-01-28 20:28:32 +0800366 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700367 index = skipOneCheck(checks, index);
Jack Paleviche44e45c2010-01-28 20:28:32 +0800368 }
369 }
370 }
371 return null;
372 }
Elliott Hughes98757502011-04-08 20:01:01 -0700373
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800374 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700375 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800376
Elliott Hughes98757502011-04-08 20:01:01 -0700377 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378
Elliott Hughes98757502011-04-08 20:01:01 -0700379 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800380
Elliott Hughes98757502011-04-08 20:01:01 -0700381 int index = 1;
382 if (checks != null) {
383 while (index < checks.length) {
384 if (checks[index].startsWith("check")) {
385 if (lastWasIfcheck) {
386 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
387 offset, remaining, iii);
388 }
389 lastWasIfcheck = false;
390 if (cname != null && !cname.equals(checks[index + 1])) {
391 index += 3;
392 continue;
393 }
394 out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700395 out.println(iii + indent + "_exception = 1;");
Elliott Hughes98757502011-04-08 20:01:01 -0700396 String exceptionClassName = "java/lang/IllegalArgumentException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700397 // If the "check" keyword was of the form
398 // "check_<class name>", use the class name in the
399 // exception to be thrown
400 int underscore = checks[index].indexOf('_');
401 if (underscore >= 0) {
Elliott Hughes98757502011-04-08 20:01:01 -0700402 String abbr = checks[index].substring(underscore + 1);
403 if (abbr.equals("AIOOBE")) {
404 exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700405 } else {
Elliott Hughes98757502011-04-08 20:01:01 -0700406 throw new RuntimeException("unknown exception abbreviation: " + abbr);
Jack Palevichffac1ef2009-04-14 19:00:09 -0700407 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800408 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700409 out.println(iii + indent +
410 "_exceptionType = \""+exceptionClassName+"\";");
411 out.println(iii + indent +
412 "_exceptionMessage = \"" +
413 (isBuffer ? "remaining()" : "length - " +
414 offset) + " < " + checks[index + 2] +
415 " < needed\";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416
Elliott Hughes98757502011-04-08 20:01:01 -0700417 out.println(iii + indent + "goto exit;");
Elliott Hughes98757502011-04-08 20:01:01 -0700418 out.println(iii + "}");
419
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700420 needsExit = true;
421
Elliott Hughes98757502011-04-08 20:01:01 -0700422 index += 3;
423 } else if (checks[index].equals("ifcheck")) {
424 String[] matches = checks[index + 4].split(",");
425
426 if (!lastWasIfcheck) {
427 out.println(iii + "int _needed;");
428 out.println(iii + "switch (" + checks[index + 3] + ") {");
429 }
430
431 for (int i = 0; i < matches.length; i++) {
432 out.println("#if defined(" + matches[i] + ")");
433 out.println(iii + " case " + matches[i] + ":");
434 out.println("#endif // defined(" + matches[i] + ")");
435 }
436 out.println(iii + " _needed = " + checks[index + 2] + ";");
437 out.println(iii + " break;");
438
439 lastWasIfcheck = true;
440 index += 5;
Elliott Hughes98757502011-04-08 20:01:01 -0700441 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700442 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443 }
444 }
Elliott Hughes98757502011-04-08 20:01:01 -0700445 }
446
447 if (lastWasIfcheck) {
448 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
449 }
450 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800451
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700452 void emitSentinelCheck(CFunc cfunc, String cname, PrintStream out,
453 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
454
455 String[] checks = mChecker.getChecks(cfunc.getName());
456
457 int index = 1;
458 if (checks != null) {
459 while (index < checks.length) {
460 if (checks[index].startsWith("sentinel")) {
461 if (cname != null && !cname.equals(checks[index + 1])) {
462 index += 3;
463 continue;
464 }
465
466 out.println(iii + cname + "_sentinel = false;");
467 out.println(iii + "for (int i = " + remaining +
468 " - 1; i >= 0; i--) {");
469 out.println(iii + indent + "if (" + cname +
470 "[i] == " + checks[index + 2] + "){");
471 out.println(iii + indent + indent +
472 cname + "_sentinel = true;");
473 out.println(iii + indent + indent + "break;");
474 out.println(iii + indent + "}");
475 out.println(iii + "}");
476 out.println(iii +
477 "if (" + cname + "_sentinel == false) {");
478 out.println(iii + indent + "_exception = 1;");
479 out.println(iii + indent +
480 "_exceptionType = \"java/lang/IllegalArgumentException\";");
481 out.println(iii + indent + "_exceptionMessage = \"" + cname +
482 " must contain " + checks[index + 2] + "!\";");
483 out.println(iii + indent + "goto exit;");
484 out.println(iii + "}");
485
486 needsExit = true;
487 index += 3;
488 } else {
489 index = skipOneCheck(checks, index);
490 }
491 }
492 }
493 }
494
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700495 void emitStringCheck(CFunc cfunc, String cname, PrintStream out, String iii) {
496
497 String[] checks = mChecker.getChecks(cfunc.getName());
498
499 int index = 1;
500 if (checks != null) {
501 while (index < checks.length) {
502 if (checks[index].startsWith("check")) {
503 if (cname != null && !cname.equals(checks[index + 1])) {
504 index += 3;
505 continue;
506 }
507 out.println(iii + "_stringlen = _env->GetStringUTFLength(" + cname + ");");
508 out.println(iii + "if (" + checks[index + 2] + " > _stringlen) {");
509 out.println(iii + indent + "_exception = 1;");
510 out.println(iii + indent +
511 "_exceptionType = \"java/lang/ArrayIndexOutOfBoundsException\";");
512 out.println(iii + indent +
513 "_exceptionMessage = \"length of " + cname + " is shorter than " +
514 checks[index + 2] + " argument\";");
515 out.println(iii + indent + "goto exit;");
516 out.println(iii + "}");
517 index += 3;
518 needsExit = true;
519 } else {
520 index = skipOneCheck(checks, index);
521 }
522 }
523 }
524 }
525
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700526 void emitLocalVariablesForSentinel(CFunc cfunc, PrintStream out) {
527
528 String[] checks = mChecker.getChecks(cfunc.getName());
529
530 int index = 1;
531 if (checks != null) {
532 while (index < checks.length) {
533 if (checks[index].startsWith("sentinel")) {
534 String cname = checks[index + 1];
535 out.println(indent + "bool " + cname + "_sentinel = false;");
536
537 index += 3;
538
539 } else {
540 index = skipOneCheck(checks, index);
541 }
542 }
543 }
544 }
545
Jack Palevichffac1ef2009-04-14 19:00:09 -0700546 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800547 if (nonPrimitiveArgs.size() > 0) {
548 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
549 int idx = nonPrimitiveArgs.get(i).intValue();
550 int cIndex = jfunc.getArgCIndex(idx);
551 if (jfunc.getArgType(idx).isArray()) {
552 if (!cfunc.getArgType(cIndex).isConst()) {
553 return true;
554 }
555 } else if (jfunc.getArgType(idx).isBuffer()) {
556 if (!cfunc.getArgType(cIndex).isConst()) {
557 return true;
558 }
559 }
560 }
561 }
562
563 return false;
564 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700565
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800566 /**
567 * Emit a function in several variants:
568 *
569 * if nativeDecl: public native <returntype> func(args);
570 *
571 * if !nativeDecl:
572 * if interfaceDecl: public <returntype> func(args);
573 * if !interfaceDecl: public <returntype> func(args) { body }
574 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700575 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800576 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800577
578 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
579 // If it's not a pointer function, we've already emitted it
580 // with nativeDecl == true
581 return;
582 }
583
Jack Palevich427f5852009-04-15 19:13:17 -0700584 String maybeStatic = mUseStaticMethods ? "static " : "";
585
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800586 if (isPointerFunc) {
587 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700588 (nativeDecl ? "private " + maybeStatic +"native " :
589 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800590 jfunc.getType() + " " +
591 jfunc.getName() +
592 (nativeDecl ? "Bounds" : "") +
593 "(");
594 } else {
595 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700596 (nativeDecl ? "public " + maybeStatic +"native " :
597 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800598 jfunc.getType() + " " +
599 jfunc.getName() +
600 "(");
601 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700602
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800603 int numArgs = jfunc.getNumArgs();
604 for (int i = 0; i < numArgs; i++) {
605 String argName = jfunc.getArgName(i);
606 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700607
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800608 out.print(indent + indent + argType + " " + argName);
609 if (i == numArgs - 1) {
610 if (isPointerFunc && nativeDecl) {
611 out.println(",");
612 out.println(indent + indent + "int remaining");
613 } else {
614 out.println();
615 }
616 } else {
617 out.println(",");
618 }
619 }
620
621 if (nativeDecl || interfaceDecl) {
622 out.println(indent + ");");
623 } else {
624 out.println(indent + ") {");
625
626 String iii = indent + indent;
627
Jack Palevich46d25a32009-05-07 18:28:29 -0700628 // emitBoundsChecks(jfunc, out, iii);
629 emitFunctionCall(jfunc, out, iii, false);
630
631 // Set the pointer after we call the native code, so that if
632 // the native code throws an exception we don't modify the
633 // pointer. We assume that the native code is written so that
634 // if an exception is thrown, then the underlying glXXXPointer
635 // function will not have been called.
636
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800637 String fname = jfunc.getName();
638 if (isPointerFunc) {
639 // TODO - deal with VBO variants
640 if (fname.equals("glColorPointer")) {
641 out.println(iii + "if ((size == 4) &&");
642 out.println(iii + " ((type == GL_FLOAT) ||");
643 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
644 out.println(iii + " (type == GL_FIXED)) &&");
645 out.println(iii + " (stride >= 0)) {");
646 out.println(iii + indent + "_colorPointer = pointer;");
647 out.println(iii + "}");
648 } else if (fname.equals("glNormalPointer")) {
649 out.println(iii + "if (((type == GL_FLOAT) ||");
650 out.println(iii + " (type == GL_BYTE) ||");
651 out.println(iii + " (type == GL_SHORT) ||");
652 out.println(iii + " (type == GL_FIXED)) &&");
653 out.println(iii + " (stride >= 0)) {");
654 out.println(iii + indent + "_normalPointer = pointer;");
655 out.println(iii + "}");
656 } else if (fname.equals("glTexCoordPointer")) {
657 out.println(iii + "if (((size == 2) ||");
658 out.println(iii + " (size == 3) ||");
659 out.println(iii + " (size == 4)) &&");
660 out.println(iii + " ((type == GL_FLOAT) ||");
661 out.println(iii + " (type == GL_BYTE) ||");
662 out.println(iii + " (type == GL_SHORT) ||");
663 out.println(iii + " (type == GL_FIXED)) &&");
664 out.println(iii + " (stride >= 0)) {");
665 out.println(iii + indent + "_texCoordPointer = pointer;");
666 out.println(iii + "}");
667 } else if (fname.equals("glVertexPointer")) {
668 out.println(iii + "if (((size == 2) ||");
669 out.println(iii + " (size == 3) ||");
670 out.println(iii + " (size == 4)) &&");
671 out.println(iii + " ((type == GL_FLOAT) ||");
672 out.println(iii + " (type == GL_BYTE) ||");
673 out.println(iii + " (type == GL_SHORT) ||");
674 out.println(iii + " (type == GL_FIXED)) &&");
675 out.println(iii + " (stride >= 0)) {");
676 out.println(iii + indent + "_vertexPointer = pointer;");
677 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800678 } else if (fname.equals("glPointSizePointerOES")) {
679 out.println(iii + "if (((type == GL_FLOAT) ||");
680 out.println(iii + " (type == GL_FIXED)) &&");
681 out.println(iii + " (stride >= 0)) {");
682 out.println(iii + indent + "_pointSizePointerOES = pointer;");
683 out.println(iii + "}");
684 } else if (fname.equals("glMatrixIndexPointerOES")) {
685 out.println(iii + "if (((size == 2) ||");
686 out.println(iii + " (size == 3) ||");
687 out.println(iii + " (size == 4)) &&");
688 out.println(iii + " ((type == GL_FLOAT) ||");
689 out.println(iii + " (type == GL_BYTE) ||");
690 out.println(iii + " (type == GL_SHORT) ||");
691 out.println(iii + " (type == GL_FIXED)) &&");
692 out.println(iii + " (stride >= 0)) {");
693 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
694 out.println(iii + "}");
695 } else if (fname.equals("glWeightPointer")) {
696 out.println(iii + "if (((size == 2) ||");
697 out.println(iii + " (size == 3) ||");
698 out.println(iii + " (size == 4)) &&");
699 out.println(iii + " ((type == GL_FLOAT) ||");
700 out.println(iii + " (type == GL_BYTE) ||");
701 out.println(iii + " (type == GL_SHORT) ||");
702 out.println(iii + " (type == GL_FIXED)) &&");
703 out.println(iii + " (stride >= 0)) {");
704 out.println(iii + indent + "_weightPointerOES = pointer;");
705 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800706 }
707 }
708
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800709 boolean isVoid = jfunc.getType().isVoid();
710
711 if (!isVoid) {
712 out.println(indent + indent + "return _returnValue;");
713 }
714 out.println(indent + "}");
715 }
716 out.println();
717 }
718
Jack Palevichffac1ef2009-04-14 19:00:09 -0700719 public void addNativeRegistration(String s) {
720 nativeRegistrations.add(s);
721 }
722
Jack Palevich427f5852009-04-15 19:13:17 -0700723 public void emitNativeRegistration(String registrationFunctionName,
724 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700725 cStream.println("static const char *classPathName = \"" +
726 mClassPathName +
727 "\";");
728 cStream.println();
729
Daniel Micayc4e95a32015-09-21 13:17:57 -0400730 cStream.println("static const JNINativeMethod methods[] = {");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700731
732 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
733
734 Iterator<String> i = nativeRegistrations.iterator();
735 while (i.hasNext()) {
736 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800737 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700738
Jack Palevichffac1ef2009-04-14 19:00:09 -0700739 cStream.println("};");
740 cStream.println();
741
742
Jack Palevich427f5852009-04-15 19:13:17 -0700743 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700744 cStream.println("{");
745 cStream.println(indent +
746 "int err;");
747
748 cStream.println(indent +
749 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
750
751 cStream.println(indent + "return err;");
752 cStream.println("}");
753 }
754
755 public JniCodeEmitter() {
756 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800757 }
758
759 String getJniType(JType jType) {
760 if (jType.isVoid()) {
761 return "void";
762 }
763
764 String baseType = jType.getBaseType();
765 if (jType.isPrimitive()) {
766 if (baseType.equals("String")) {
767 return "jstring";
768 } else {
769 return "j" + baseType;
770 }
771 } else if (jType.isArray()) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700772 return jType.isClass() ? "jobjectArray" : "j" + baseType + "Array";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800773 } else {
774 return "jobject";
775 }
776 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700777
Orion Hodson91f564d2019-02-26 16:57:18 +0000778 String getJniDefaultReturn(JType jType) {
779 if (jType.isPrimitive()) {
780 String baseType = jType.getBaseType();
781 if (baseType.equals("boolean")) {
782 return "JNI_FALSE";
783 } else {
784 return "(" + getJniType(jType) + ")0";
785 }
786 } else {
787 return "nullptr";
788 }
789 }
790
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800791 String getJniMangledName(String name) {
792 name = name.replaceAll("_", "_1");
793 name = name.replaceAll(";", "_2");
794 name = name.replaceAll("\\[", "_3");
795 return name;
796 }
797
798 public void emitJniCode(JFunc jfunc, PrintStream out) {
799 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700800
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800801 // Emit comment identifying original C function
802 //
803 // Example:
804 //
805 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
806 //
807 out.println("/* " + cfunc.getOriginal() + " */");
808
809 // Emit JNI signature (name)
810 //
811 // Example:
812 //
813 // void
814 // android_glClipPlanef__I_3FI
815 //
816
817 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800818 boolean isPointerFunc = isPointerFunc(jfunc);
Jesse Hall071fc662013-04-10 01:17:34 -0700819 boolean isPointerOffsetFunc =
820 (outName.endsWith("Pointer") || outName.endsWith("PointerOES") ||
821 outName.endsWith("glDrawElements") ||
822 outName.endsWith("glDrawRangeElements") ||
823 outName.endsWith("glTexImage2D") ||
824 outName.endsWith("glTexSubImage2D") ||
825 outName.endsWith("glCompressedTexImage2D") ||
826 outName.endsWith("glCompressedTexSubImage2D") ||
827 outName.endsWith("glTexImage3D") ||
828 outName.endsWith("glTexSubImage3D") ||
829 outName.endsWith("glCompressedTexImage3D") ||
830 outName.endsWith("glCompressedTexSubImage3D") ||
831 outName.endsWith("glReadPixels"))
832 && !jfunc.getCFunc().hasPointerArg();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800833 if (isPointerFunc) {
834 outName += "Bounds";
835 }
836
837 out.print("static ");
838 out.println(getJniType(jfunc.getType()));
839 out.print(outName);
840
841 String rsignature = getJniName(jfunc.getType());
842
843 String signature = "";
844 int numArgs = jfunc.getNumArgs();
845 for (int i = 0; i < numArgs; i++) {
846 JType argType = jfunc.getArgType(i);
847 signature += getJniName(argType);
848 }
849 if (isPointerFunc) {
850 signature += "I";
851 }
852
853 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800854 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700855 if (!mUseSimpleMethodNames) {
856 out.print("__" + sig);
857 outName += "__" + sig;
858 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700859
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800860 signature = signature.replace('.', '/');
861 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700862
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800863 out.println();
864 if (rsignature.length() == 0) {
865 rsignature = "V";
866 }
867
868 String s = "{\"" +
869 jfunc.getName() +
870 (isPointerFunc ? "Bounds" : "") +
871 "\", \"(" + signature +")" +
872 rsignature +
873 "\", (void *) " +
874 outName +
875 " },";
876 nativeRegistrations.add(s);
877
878 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800879 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800880 int numBufferArgs = 0;
881 List<String> bufferArgNames = new ArrayList<String>();
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700882 List<JType> bufferArgTypes = new ArrayList<JType>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800883
884 // Emit JNI signature (arguments)
885 //
886 // Example:
887 //
888 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
889 //
890 out.print(" (JNIEnv *_env, jobject _this");
891 for (int i = 0; i < numArgs; i++) {
892 out.print(", ");
893 JType argType = jfunc.getArgType(i);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700894 String suffix = "";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800895 if (!argType.isPrimitive()) {
896 if (argType.isArray()) {
897 suffix = "_ref";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700898 } else if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800899 suffix = "_buf";
900 }
901 nonPrimitiveArgs.add(new Integer(i));
902 if (jfunc.getArgType(i).isBuffer()) {
903 int cIndex = jfunc.getArgCIndex(i);
904 String cname = cfunc.getArgName(cIndex);
905 bufferArgNames.add(cname);
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700906 bufferArgTypes.add(jfunc.getArgType(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800907 numBufferArgs++;
908 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800909 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700910
Jack Palevich50d0b142009-11-19 16:34:55 +0800911 if (argType.isString()) {
912 stringArgs.add(new Integer(i));
913 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800914
915 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
916 }
917 if (isPointerFunc) {
918 out.print(", jint remaining");
919 }
920 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700921
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800922 int numArrays = 0;
923 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800924 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800925 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
926 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800927 JType argType = jfunc.getArgType(idx);
928 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800929 ++numArrays;
930 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800931 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800932 ++numBuffers;
933 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800934 if (argType.isString()) {
935 ++numStrings;
936 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800937 }
938
939 // Emit method body
940
941 // Emit local variable declarations for _exception and _returnValue
942 //
943 // Example:
944 //
945 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700946 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800947 // jint _exception;
948 // GLenum _returnValue;
949 //
950 CType returnType = cfunc.getType();
951 boolean isVoid = returnType.isVoid();
952
953 boolean isUnsupported = isUnsupportedFunc(cfunc);
954 if (isUnsupported) {
955 out.println(indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700956 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800957 out.println(indent +
958 " \"" + cfunc.getName() + "\");");
Orion Hodson91f564d2019-02-26 16:57:18 +0000959 if (isVoid) {
960 out.println(indent + "return;");
961 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700962 if (cfunc.getType().isEGLHandle()) {
963 String baseType = cfunc.getType().getBaseType().toLowerCase();
Orion Hodson91f564d2019-02-26 16:57:18 +0000964 out.println(indent + indent + "return nullptr;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700965 } else {
Orion Hodson91f564d2019-02-26 16:57:18 +0000966 out.println(indent + indent + "return " +
967 getJniDefaultReturn(jfunc.getType()) + ";");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700968 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800969 }
970 out.println("}");
971 out.println();
972 return;
973 }
Elliott Hughes98757502011-04-08 20:01:01 -0700974
Jack Paleviche44e45c2010-01-28 20:28:32 +0800975 String requiresExtension = isRequiresFunc(cfunc);
976 if (requiresExtension != null) {
977 out.println(indent +
978 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
979 out.println(indent + indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700980 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
Jack Paleviche44e45c2010-01-28 20:28:32 +0800981 out.println(indent + indent +
982 " \"" + cfunc.getName() + "\");");
983 if (isVoid) {
984 out.println(indent + indent + " return;");
985 } else {
986 String retval = getErrorReturnValue(cfunc);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700987 if (cfunc.getType().isEGLHandle()) {
988 String baseType = cfunc.getType().getBaseType().toLowerCase();
989 out.println(indent +
990 "return toEGLHandle(_env, " + baseType + "Class, " +
991 baseType + "Constructor, " + retval + ");");
992 } else {
993 out.println(indent + "return " + retval + ";");
994 }
Jack Paleviche44e45c2010-01-28 20:28:32 +0800995 }
996 out.println(indent + "}");
997 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800998 if (mUseContextPointer) {
999 out.println(indent +
1000 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
1001 }
1002
Jack Palevich50d0b142009-11-19 16:34:55 +08001003 boolean initializeReturnValue = stringArgs.size() > 0;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001004 boolean emitExceptionCheck = ((numArrays > 0 || numStrings > 0)
1005 && (hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs)
1006 || (cfunc.hasPointerArg() && numArrays > 0))
Romain Guy79699992016-12-05 12:26:42 -08001007 || (numBufferArgs > 0)
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001008 || hasCheckTest(cfunc)
1009 || hasIfTest(cfunc))
1010 || (stringArgs.size() > 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001011 // mChecker.getChecks(cfunc.getName()) != null
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001012 // Emit an _exeption variable if there will be error checks
1013 if (emitExceptionCheck) {
1014 out.println(indent + "jint _exception = 0;");
Mathias Agopianbf13ba52013-02-22 19:34:06 -08001015 out.println(indent + "const char * _exceptionType = NULL;");
1016 out.println(indent + "const char * _exceptionMessage = NULL;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001017 }
1018
1019 // Emit a single _array or multiple _XXXArray variables
1020 if (numBufferArgs == 1) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001021 JType bufferType = bufferArgTypes.get(0);
1022 if (bufferType.isTypedBuffer()) {
1023 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
1024 out.println(indent + typedArrayType + " _array = (" + typedArrayType + ") 0;");
1025 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001026 out.println(indent + "jarray _array = (jarray) 0;");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001027 }
1028 out.println(indent + "jint _bufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001029 } else {
1030 for (int i = 0; i < numBufferArgs; i++) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001031 JType bufferType = bufferArgTypes.get(0);
1032 if (bufferType.isTypedBuffer()) {
1033 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
1034 out.println(indent + typedArrayType + " _" + bufferArgNames.get(i) +
1035 "Array = (" + typedArrayType + ") 0;");
1036 } else {
1037 out.println(indent + "jarray _" + bufferArgNames.get(i) +
1038 "Array = (jarray) 0;");
1039 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001040 out.println(indent + "jint _" + bufferArgNames.get(i) +
1041 "BufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001042 }
1043 }
1044 if (!isVoid) {
1045 String retval = getErrorReturnValue(cfunc);
1046 if (retval != null) {
1047 out.println(indent + returnType.getDeclaration() +
1048 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +08001049 } else if (initializeReturnValue) {
1050 out.println(indent + returnType.getDeclaration() +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001051 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001052 } else {
1053 out.println(indent + returnType.getDeclaration() +
1054 " _returnValue;");
1055 }
1056 }
1057
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001058 // Emit local variable declarations for EGL Handles
1059 //
1060 // Example:
1061 //
1062 // EGLSurface surface_native = (EGLHandle)fromEGLHandle(_env, surfaceClass, surfaceConstructor, surface);
1063 //
1064 if (nonPrimitiveArgs.size() > 0) {
1065 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1066 int idx = nonPrimitiveArgs.get(i).intValue();
1067 int cIndex = jfunc.getArgCIndex(idx);
1068 String cname = cfunc.getArgName(cIndex);
1069
1070 if (jfunc.getArgType(idx).isBuffer()
1071 || jfunc.getArgType(idx).isArray()
1072 || !jfunc.getArgType(idx).isEGLHandle())
1073 continue;
1074
1075 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1076 String decl = type.getDeclaration();
1077 out.println(indent +
1078 decl + " " + cname + "_native = (" +
1079 decl + ") fromEGLHandle(_env, " +
1080 type.getBaseType().toLowerCase() +
1081 "GetHandleID, " + jfunc.getArgName(idx) +
1082 ");");
1083 }
1084 }
1085
1086 // Emit local variable declarations for element/sentinel checks
1087 //
1088 // Example:
1089 //
1090 // bool attrib_list_sentinel_found = false;
1091 //
1092 emitLocalVariablesForSentinel(cfunc, out);
1093
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001094 // Emit local variable declarations for pointer arguments
1095 //
1096 // Example:
1097 //
1098 // GLfixed *eqn_base;
1099 // GLfixed *eqn;
1100 //
1101 String offset = "offset";
1102 String remaining = "_remaining";
1103 if (nonPrimitiveArgs.size() > 0) {
1104 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1105 int idx = nonPrimitiveArgs.get(i).intValue();
1106 int cIndex = jfunc.getArgCIndex(idx);
1107 String cname = cfunc.getArgName(cIndex);
1108
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001109 if (!jfunc.getArgType(idx).isBuffer() && !jfunc.getArgType(idx).isArray())
1110 continue;
1111
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001112 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1113 String decl = type.getDeclaration();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001114 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001115 out.println(indent +
1116 decl +
1117 (decl.endsWith("*") ? "" : " ") +
1118 jfunc.getArgName(idx) +
1119 "_base = (" + decl + ") 0;");
1120 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001121 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001122 "_" + cname + "Remaining";
1123 out.println(indent +
1124 "jint " + remaining + ";");
1125 out.println(indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001126 decl +
1127 (decl.endsWith("*") ? "" : " ") +
1128 jfunc.getArgName(idx) +
1129 " = (" + decl + ") 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001130 }
1131
1132 out.println();
1133 }
1134
Jack Palevich50d0b142009-11-19 16:34:55 +08001135 // Emit local variable declaration for strings
1136 if (stringArgs.size() > 0) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001137 boolean requiresStringLengthCheck = false;
Jack Palevich50d0b142009-11-19 16:34:55 +08001138 for (int i = 0; i < stringArgs.size(); i++) {
1139 int idx = stringArgs.get(i).intValue();
1140 int cIndex = jfunc.getArgCIndex(idx);
1141 String cname = cfunc.getArgName(cIndex);
1142
1143 out.println(indent + "const char* _native" + cname + " = 0;");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001144 if (hasCheckTest(cfunc, cname)) {
1145 requiresStringLengthCheck = true;
1146 }
1147 }
1148
1149 if (requiresStringLengthCheck) {
1150 out.println(indent + "jsize _stringlen = 0;");
Jack Palevich50d0b142009-11-19 16:34:55 +08001151 }
1152
1153 out.println();
1154 }
1155
1156 // Null pointer checks and GetStringUTFChars
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
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001163 boolean nullAllowed = isNullAllowed(cfunc, cname);
1164 String nullAllowedIndent = nullAllowed ? indent : "";
1165
Jack Palevich50d0b142009-11-19 16:34:55 +08001166 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1167 String decl = type.getDeclaration();
Jack Palevich50d0b142009-11-19 16:34:55 +08001168
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001169 if (nullAllowed) {
1170 out.println(indent + "if (" + cname + ") {");
1171 } else {
1172 needsExit = true;
1173 out.println(indent + "if (!" + cname + ") {");
1174 out.println(indent + indent + "_exception = 1;");
1175 out.println(indent + indent +
1176 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1177 out.println(indent + indent +
1178 "_exceptionMessage = \"" + cname + " == null\";");
1179 out.println(indent + indent + "goto exit;");
1180 out.println(indent + "}");
1181 }
1182
1183 out.println(nullAllowedIndent + indent + "_native" + cname +
1184 " = _env->GetStringUTFChars(" + cname + ", 0);");
1185
1186 emitStringCheck(cfunc, cname, out, nullAllowedIndent + indent);
1187
1188 if (nullAllowed) {
1189 out.println(indent + "}");
1190 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001191 }
1192
1193 out.println();
1194 }
1195
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001196 // Emit 'GetPrimitiveArrayCritical' for non-object arrays
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001197 // Emit 'GetPointer' calls for Buffer pointers
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001198 if (nonPrimitiveArgs.size() > 0) {
1199 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1200 int idx = nonPrimitiveArgs.get(i).intValue();
1201 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -07001202
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001203 String cname = cfunc.getArgName(cIndex);
1204 offset = numArrays <= 1 ? "offset" :
1205 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +08001206 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001207 "_" + cname + "Remaining";
1208
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001209 boolean nullAllowed = isNullAllowed(cfunc, cname);
1210 String nullAllowedIndent = nullAllowed ? indent : "";
1211
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001212 if (jfunc.getArgType(idx).isArray()
1213 && !jfunc.getArgType(idx).isEGLHandle()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001214 needsExit = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001215
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001216 if (nullAllowed) {
1217 out.println(indent + "if (" + cname + "_ref) {");
1218 }
1219 else
1220 {
1221 out.println(indent + "if (!" + cname + "_ref) {");
1222 out.println(indent + indent + "_exception = 1;");
1223 out.println(indent + indent +
1224 "_exceptionType = " +
1225 "\"java/lang/IllegalArgumentException\";");
1226 out.println(indent + indent +
1227 "_exceptionMessage = \"" + cname +
1228 " == null\";");
1229 out.println(indent + indent + "goto exit;");
1230 out.println(indent + "}");
1231 }
1232
1233 out.println(nullAllowedIndent + indent + "if (" + offset +
1234 " < 0) {");
1235 out.println(nullAllowedIndent + indent + indent +
1236 "_exception = 1;");
1237 out.println(nullAllowedIndent + indent + indent +
1238 "_exceptionType = " +
1239 "\"java/lang/IllegalArgumentException\";");
1240 out.println(nullAllowedIndent + indent + indent +
1241 "_exceptionMessage = \"" + offset +" < 0\";");
1242 out.println(nullAllowedIndent + indent + indent +
1243 "goto exit;");
1244 out.println(nullAllowedIndent + indent + "}");
1245
1246 out.println(nullAllowedIndent + indent + remaining + " = " +
1247 (mUseCPlusPlus ? "_env" : "(*_env)") +
1248 "->GetArrayLength(" +
1249 (mUseCPlusPlus ? "" : "_env, ") +
1250 cname + "_ref) - " + offset + ";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001251
1252 emitNativeBoundsChecks(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001253 emitExceptionCheck, offset, remaining,
1254 nullAllowedIndent + indent);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001255
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001256 out.println(nullAllowedIndent + indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001257 cname +
1258 "_base = (" +
1259 cfunc.getArgType(cIndex).getDeclaration() +
1260 ")");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001261 String arrayGetter = jfunc.getArgType(idx).getArrayGetterForPrimitiveArray();
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001262 out.println(nullAllowedIndent + indent + " " +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001263 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001264 "->" + arrayGetter + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001265 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001266 jfunc.getArgName(idx) +
1267 "_ref, (jboolean *)0);");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001268 out.println(nullAllowedIndent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001269 cname + " = " + cname + "_base + " + offset + ";");
1270
1271 emitSentinelCheck(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001272 emitExceptionCheck, offset, remaining,
1273 nullAllowedIndent + indent);
1274
1275 if (nullAllowed) {
1276 out.println(indent + "}");
1277 }
1278
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001279 out.println();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001280 } else if (jfunc.getArgType(idx).isArray()
1281 && jfunc.getArgType(idx).isEGLHandle()) {
1282 needsExit = true;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001283
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001284 if (nullAllowed) {
1285 out.println(indent + "if (" + cname + "_ref) {");
1286 }
1287 else
1288 {
1289 out.println(indent + "if (!" + cname + "_ref) {");
1290 out.println(indent + indent + "_exception = 1;");
1291 out.println(indent + indent + "_exceptionType = " +
1292 "\"java/lang/IllegalArgumentException\";");
1293 out.println(indent + indent + "_exceptionMessage = \"" +
1294 cname +" == null\";");
1295 out.println(indent + indent + "goto exit;");
1296 out.println(indent + "}");
1297 }
1298
1299 out.println(nullAllowedIndent + indent + "if (" + offset +
1300 " < 0) {");
1301 out.println(nullAllowedIndent + indent + indent +
1302 "_exception = 1;");
1303 out.println(nullAllowedIndent + indent + indent +
1304 "_exceptionType = " +
1305 "\"java/lang/IllegalArgumentException\";");
1306 out.println(nullAllowedIndent + indent + indent +
1307 "_exceptionMessage = \"" + offset +" < 0\";");
1308 out.println(nullAllowedIndent + indent + indent +
1309 "goto exit;");
1310 out.println(nullAllowedIndent + indent + "}");
1311
1312 out.println(nullAllowedIndent + indent + remaining + " = " +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001313 (mUseCPlusPlus ? "_env" : "(*_env)") +
1314 "->GetArrayLength(" +
1315 (mUseCPlusPlus ? "" : "_env, ") +
1316 cname + "_ref) - " + offset + ";");
1317 emitNativeBoundsChecks(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001318 emitExceptionCheck, offset, remaining,
1319 nullAllowedIndent + indent);
1320 out.println(nullAllowedIndent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001321 jfunc.getArgName(idx) + " = new " +
1322 cfunc.getArgType(cIndex).getBaseType() +
1323 "["+ remaining + "];");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001324
1325 if (nullAllowed) {
1326 out.println(indent + "}");
1327 }
1328
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001329 out.println();
1330 } else if (jfunc.getArgType(idx).isBuffer()) {
Romain Guy79699992016-12-05 12:26:42 -08001331 needsExit = needsExit || (!nullAllowed && !isPointerFunc);
1332
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001333 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001334 "_" + cfunc.getArgName(cIndex) + "Array";
1335 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1336 "_" + cfunc.getArgName(cIndex) + "BufferOffset";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001337
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001338 nullAllowed = nullAllowed || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001339 if (nullAllowed) {
1340 out.println(indent + "if (" + cname + "_buf) {");
1341 out.print(indent);
1342 }
Romain Guy79699992016-12-05 12:26:42 -08001343 else
1344 {
1345 out.println(indent + "if (!" + cname + "_buf) {");
1346 out.println(indent + indent + "_exception = 1;");
1347 out.println(indent + indent + "_exceptionType = " +
1348 "\"java/lang/IllegalArgumentException\";");
1349 out.println(indent + indent + "_exceptionMessage = \"" +
1350 cname +" == null\";");
1351 out.println(indent + indent + "goto exit;");
1352 out.println(indent + "}");
1353 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001354
Jack Palevich46d25a32009-05-07 18:28:29 -07001355 if (isPointerFunc) {
1356 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001357 cname +
1358 " = (" +
1359 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001360 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001361 cname + "_buf);");
1362 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001363 out.println(iii + indent + "if ( ! " + cname + " ) {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001364 out.println(iii + indent + indent + "return;");
Jack Palevich46d25a32009-05-07 18:28:29 -07001365 out.println(iii + indent + "}");
1366 } else {
1367 out.println(indent +
1368 cname +
1369 " = (" +
1370 cfunc.getArgType(cIndex).getDeclaration() +
1371 ")getPointer(_env, " +
1372 cname +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001373 "_buf, (jarray*)&" + array + ", &" + remaining + ", &" + bufferOffset +
Jack Palevich46d25a32009-05-07 18:28:29 -07001374 ");");
1375 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001376
Jack Palevich5afdc872009-10-21 11:02:44 -07001377 emitNativeBoundsChecks(cfunc, cname, out, true,
1378 emitExceptionCheck,
1379 offset, remaining, nullAllowed ? " " : " ");
1380
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001381 if (nullAllowed) {
1382 out.println(indent + "}");
1383 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001384 }
1385 }
1386 }
1387
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001388 // Emit 'GetPrimitiveArrayCritical' for pointers if needed
1389 if (nonPrimitiveArgs.size() > 0) {
1390 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1391 int idx = nonPrimitiveArgs.get(i).intValue();
1392 int cIndex = jfunc.getArgCIndex(idx);
1393
1394 if(!jfunc.getArgType(idx).isBuffer() || isPointerFunc) continue;
1395
1396 String cname = cfunc.getArgName(cIndex);
1397 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1398 "_" + cname + "BufferOffset";
1399 String array = numBufferArgs <= 1 ? "_array" :
1400 "_" + cfunc.getArgName(cIndex) + "Array";
1401
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001402 boolean nullAllowed = isNullAllowed(cfunc, cname) ||
1403 isPointerFunc;
Thomas Tafertshofer36b285e2012-07-23 16:52:32 -07001404 if (nullAllowed) {
1405 out.println(indent + "if (" + cname + "_buf && " + cname +" == NULL) {");
1406 } else {
1407 out.println(indent + "if (" + cname +" == NULL) {");
1408 }
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001409 JType argType = jfunc.getArgType(idx);
1410 if (argType.isTypedBuffer()) {
1411 String arrayGetter = argType.getArrayTypeForTypedBuffer().getArrayGetterForPrimitiveArray();
1412 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->" + arrayGetter + "(" + array + ", (jboolean *) 0);");
1413 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1414 out.println(indent + "}");
1415 } else {
1416 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->GetPrimitiveArrayCritical(" + array + ", (jboolean *) 0);");
1417 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1418 out.println(indent + "}");
1419 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001420 }
1421 }
1422
1423
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001424 if (!isVoid) {
1425 out.print(indent + "_returnValue = ");
1426 } else {
1427 out.print(indent);
1428 }
1429 String name = cfunc.getName();
1430
1431 if (mUseContextPointer) {
1432 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1433 name = name.substring(0, 1).toLowerCase() +
1434 name.substring(1, name.length());
1435 out.print("ctx->procs.");
1436 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001437
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001438 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1439
Jack Palevich6cbca502009-04-13 16:22:25 -07001440 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001441 if (numArgs == 0) {
1442 if (mUseContextPointer) {
1443 out.println("ctx);");
1444 } else {
1445 out.println(");");
1446 }
1447 } else {
1448 if (mUseContextPointer) {
1449 out.println("ctx,");
1450 } else {
1451 out.println();
1452 }
1453 for (int i = 0; i < numArgs; i++) {
1454 String typecast;
Jesse Hall071fc662013-04-10 01:17:34 -07001455 if (i == numArgs - 1 && isPointerOffsetFunc) {
Ashok Bhatd8f09612014-02-15 12:51:43 +00001456 typecast = "reinterpret_cast<GLvoid *>";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001457 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001458 typecast = "(" + cfunc.getArgType(i).getDeclaration() + ")";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001459 }
1460 out.print(indent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001461 typecast);
1462
Jack Palevich50d0b142009-11-19 16:34:55 +08001463 if (cfunc.getArgType(i).isConstCharPointer()) {
1464 out.print("_native");
1465 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001466
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001467 if (cfunc.getArgType(i).isEGLHandle() &&
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001468 !cfunc.getArgType(i).isPointer()){
1469 out.print(cfunc.getArgName(i)+"_native");
Ashok Bhatd8f09612014-02-15 12:51:43 +00001470 } else if (i == numArgs - 1 && isPointerOffsetFunc){
1471 out.print("("+cfunc.getArgName(i)+")");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001472 } else {
1473 out.print(cfunc.getArgName(i));
1474 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001475
1476 if (i == numArgs - 1) {
1477 if (isPointerFunc) {
1478 out.println(",");
1479 out.println(indent + indent + "(GLsizei)remaining");
1480 } else {
1481 out.println();
1482 }
1483 } else {
1484 out.println(",");
1485 }
1486 }
1487 out.println(indent + ");");
1488 }
1489
1490 if (needsExit) {
1491 out.println();
1492 out.println("exit:");
1493 needsExit = false;
1494 }
1495
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001496
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001497 if (nonPrimitiveArgs.size() > 0) {
1498 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1499 int idx = nonPrimitiveArgs.get(i).intValue();
1500
1501 int cIndex = jfunc.getArgCIndex(idx);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001502 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001503
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001504 // If the argument is 'const', GL will not write to it.
1505 // In this case, we can use the 'JNI_ABORT' flag to avoid
1506 // the need to write back to the Java array
1507 out.println(indent +
1508 "if (" + jfunc.getArgName(idx) + "_base) {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001509 String arrayReleaser = jfunc.getArgType(idx).getArrayReleaserForPrimitiveArray();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001510 out.println(indent + indent +
1511 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001512 "->" + arrayReleaser + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001513 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001514 jfunc.getArgName(idx) + "_ref, " +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001515 "(j" + jfunc.getArgType(idx).getBaseType() + "*)" + cfunc.getArgName(cIndex) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001516 "_base,");
1517 out.println(indent + indent + indent +
1518 (cfunc.getArgType(cIndex).isConst() ?
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001519 "JNI_ABORT" : "_exception ? JNI_ABORT: 0" ) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001520 ");");
1521 out.println(indent + "}");
1522 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001523 if (! isPointerFunc) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001524 JType argType = jfunc.getArgType(idx);
Jack Palevich46d25a32009-05-07 18:28:29 -07001525 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001526 "_" + cfunc.getArgName(cIndex) + "Array";
Jack Palevich46d25a32009-05-07 18:28:29 -07001527 out.println(indent + "if (" + array + ") {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001528 if (argType.isTypedBuffer()) {
1529 String arrayReleaser =
1530 argType.getArrayTypeForTypedBuffer().getArrayReleaserForPrimitiveArray();
1531 out.println(indent + indent +
1532 "_env->" + arrayReleaser + "(" + array + ", " +
1533 "(j" + argType.getArrayTypeForTypedBuffer().getBaseType() + "*)" +
1534 cfunc.getArgName(cIndex) +
1535 ", " +
1536 (cfunc.getArgType(cIndex).isConst() ?
1537 "JNI_ABORT" : (emitExceptionCheck ?
1538 "_exception ? JNI_ABORT : 0" : "0")) +
1539 ");");
1540 } else {
1541 out.println(indent + indent +
1542 "releasePointer(_env, " + array + ", " +
1543 cfunc.getArgName(cIndex) +
1544 ", " +
1545 (cfunc.getArgType(cIndex).isConst() ?
1546 "JNI_FALSE" : (emitExceptionCheck ?
1547 "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
1548 ");");
1549 }
Jack Palevich46d25a32009-05-07 18:28:29 -07001550 out.println(indent + "}");
1551 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001552 }
1553 }
1554 }
1555
Jack Palevich50d0b142009-11-19 16:34:55 +08001556 // Emit local variable declaration for strings
1557 if (stringArgs.size() > 0) {
1558 for (int i = 0; i < stringArgs.size(); i++) {
1559 int idx = stringArgs.get(i).intValue();
1560 int cIndex = jfunc.getArgCIndex(idx);
1561 String cname = cfunc.getArgName(cIndex);
1562
1563 out.println(indent + "if (_native" + cname + ") {");
1564 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1565 out.println(indent + "}");
1566 }
1567
1568 out.println();
1569 }
1570
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001571 // Copy results back to java arrays
1572 if (nonPrimitiveArgs.size() > 0) {
1573 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1574 int idx = nonPrimitiveArgs.get(i).intValue();
1575 int cIndex = jfunc.getArgCIndex(idx);
1576 String baseType = cfunc.getArgType(cIndex).getBaseType().toLowerCase();
1577 if (jfunc.getArgType(idx).isArray() && jfunc.getArgType(idx).isClass()) {
1578 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
1579 "_" + cfunc.getArgName(cIndex) + "Remaining";
1580 offset = numArrays <= 1 ? "offset" : cfunc.getArgName(cIndex) + "Offset";
1581 out.println(indent +
1582 "if (" + jfunc.getArgName(idx) + ") {");
1583 out.println(indent + indent +
1584 "for (int i = 0; i < " + remaining + "; i++) {");
1585 out.println(indent + indent + indent +
1586 "jobject " + cfunc.getArgName(cIndex) +
1587 "_new = toEGLHandle(_env, " + baseType +
1588 "Class, " + baseType + "Constructor, " +
1589 cfunc.getArgName(cIndex) + "[i]);");
1590 out.println(indent + indent + indent +
1591 (mUseCPlusPlus ? "_env" : "(*_env)") +
1592 "->SetObjectArrayElement(" +
1593 (mUseCPlusPlus ? "" : "_env, ") +
1594 cfunc.getArgName(cIndex) +
1595 "_ref, i + " + offset + ", " +
1596 cfunc.getArgName(cIndex) + "_new);");
1597 out.println(indent + indent + "}");
1598 out.println(indent + indent +
1599 "delete[] " + jfunc.getArgName(idx) + ";");
1600 out.println(indent + "}");
1601 }
1602 }
1603 }
1604
1605
1606 // Throw exception if there is one
1607 if (emitExceptionCheck) {
1608 out.println(indent + "if (_exception) {");
1609 out.println(indent + indent +
1610 "jniThrowException(_env, _exceptionType, _exceptionMessage);");
Orion Hodson91f564d2019-02-26 16:57:18 +00001611 if (!isVoid) {
1612 if (cfunc.getType().isEGLHandle()) {
1613 String baseType = cfunc.getType().getBaseType().toLowerCase();
1614 out.println(indent + indent + "return nullptr;");
1615 } else {
1616 out.println(indent + indent + "return " +
1617 getJniDefaultReturn(jfunc.getType()) + ";");
1618 }
1619 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001620
Orion Hodson91f564d2019-02-26 16:57:18 +00001621 out.println(indent + "}");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001622 }
1623
Jack Palevich50d0b142009-11-19 16:34:55 +08001624
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001625 if (!isVoid) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001626 if (cfunc.getType().isEGLHandle()) {
1627 String baseType = cfunc.getType().getBaseType().toLowerCase();
1628 out.println(indent +
1629 "return toEGLHandle(_env, " + baseType + "Class, " +
1630 baseType + "Constructor, _returnValue);");
1631 } else {
Jesse Hall68fc8bb2013-04-10 01:01:00 -07001632 out.println(indent + "return (" +
1633 getJniType(jfunc.getType()) + ")_returnValue;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001634 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001635 }
1636
1637 out.println("}");
1638 out.println();
1639 }
1640
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001641}