blob: 59ef3c81c27c41aa46fb4da063e22463ad4426ca [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;
Adam Bodnara7ab5c72020-07-08 15:35:06 -070018import java.util.Arrays;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019import java.util.ArrayList;
20import java.util.HashSet;
21import java.util.Iterator;
22import java.util.List;
23
Jack Palevichffac1ef2009-04-14 19:00:09 -070024public class JniCodeEmitter {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026 static final boolean mUseCPlusPlus = true;
Jack Palevichffac1ef2009-04-14 19:00:09 -070027 protected boolean mUseContextPointer = true;
Jack Palevich427f5852009-04-15 19:13:17 -070028 protected boolean mUseStaticMethods = false;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -070029 protected boolean mUseSimpleMethodNames = false;
30 protected boolean mUseHideCommentForAPI = false;
Jack Palevichffac1ef2009-04-14 19:00:09 -070031 protected String mClassPathName;
32 protected ParameterChecker mChecker;
33 protected List<String> nativeRegistrations = new ArrayList<String>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034 boolean needsExit;
Jack Palevichffac1ef2009-04-14 19:00:09 -070035 protected static String indent = " ";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036 HashSet<String> mFunctionsEmitted = new HashSet<String>();
37
Jack Palevichffac1ef2009-04-14 19:00:09 -070038 public static String getJniName(JType jType) {
39 String jniName = "";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -070040 if (jType.isEGLHandle()) {
41 return (jType.isArray() ? "[" : "" ) + "Landroid/opengl/" + jType.getBaseType() + ";";
42 } else if (jType.isClass()) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070043 return "L" + jType.getBaseType() + ";";
44 } else if (jType.isArray()) {
45 jniName = "[";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080046 }
Jack Palevichffac1ef2009-04-14 19:00:09 -070047
48 String baseType = jType.getBaseType();
49 if (baseType.equals("int")) {
50 jniName += "I";
51 } else if (baseType.equals("float")) {
52 jniName += "F";
53 } else if (baseType.equals("boolean")) {
54 jniName += "Z";
55 } else if (baseType.equals("short")) {
56 jniName += "S";
57 } else if (baseType.equals("long")) {
Andy McFadden72841452013-03-01 16:25:32 -080058 jniName += "J";
Jack Palevichffac1ef2009-04-14 19:00:09 -070059 } else if (baseType.equals("byte")) {
60 jniName += "B";
Jack Palevich50d0b142009-11-19 16:34:55 +080061 } else if (baseType.equals("String")) {
62 jniName += "Ljava/lang/String;";
63 } else if (baseType.equals("void")) {
64 // nothing.
65 } else {
Elliott Hughes98757502011-04-08 20:01:01 -070066 throw new RuntimeException("Unknown primitive basetype " + baseType);
Jack Palevichffac1ef2009-04-14 19:00:09 -070067 }
68 return jniName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080069 }
70
Jack Palevichffac1ef2009-04-14 19:00:09 -070071 public void emitCode(CFunc cfunc, String original,
72 PrintStream javaInterfaceStream,
73 PrintStream javaImplStream,
74 PrintStream cStream) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080075 JFunc jfunc;
76 String signature;
77 boolean duplicate;
Jack Palevich6cbca502009-04-13 16:22:25 -070078
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080079 if (cfunc.hasTypedPointerArg()) {
80 jfunc = JFunc.convert(cfunc, true);
81
82 // Don't emit duplicate functions
83 // These may appear because they are defined in multiple
84 // Java interfaces (e.g., GL11/GL11ExtensionPack)
85 signature = jfunc.toString();
86 duplicate = false;
87 if (mFunctionsEmitted.contains(signature)) {
88 duplicate = true;
89 } else {
90 mFunctionsEmitted.add(signature);
91 }
92
93 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070094 emitNativeDeclaration(jfunc, javaImplStream);
95 emitJavaCode(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080096 }
Jack Palevich427f5852009-04-15 19:13:17 -070097 if (javaInterfaceStream != null) {
98 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
99 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800100 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700101 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800102 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700103 // Don't create IOBuffer versions of the EGL functions
104 if (cfunc.hasEGLHandleArg()) {
105 return;
106 }
Courtney Goeltzenleuchterb28648c2018-07-18 09:38:47 -0600107 // eglGetPlatformDisplay does not have any EGLHandleArgs
108 // but we do not want to create IOBuffers of this, so
109 // exit
110 if (cfunc.getName().equals("eglGetPlatformDisplay")) {
111 return;
112 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800113 }
114
115 jfunc = JFunc.convert(cfunc, false);
116
117 signature = jfunc.toString();
118 duplicate = false;
119 if (mFunctionsEmitted.contains(signature)) {
120 duplicate = true;
121 } else {
122 mFunctionsEmitted.add(signature);
123 }
124
125 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700126 emitNativeDeclaration(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800127 }
Jack Palevich427f5852009-04-15 19:13:17 -0700128 if (javaInterfaceStream != null) {
129 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
130 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800131 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700132 emitJavaCode(jfunc, javaImplStream);
133 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800134 }
135 }
136
137 public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700138 if (mUseHideCommentForAPI) {
139 out.println(" /* @hide C function " + jfunc.getCFunc().getOriginal() + " */");
140 out.println();
141 } else {
142 out.println(" // C function " + jfunc.getCFunc().getOriginal());
143 out.println();
144 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800145
146 emitFunction(jfunc, out, true, false);
147 }
148
149 public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
150 emitFunction(jfunc, out, false, true);
151 }
152
153 public void emitJavaCode(JFunc jfunc, PrintStream out) {
154 emitFunction(jfunc, out, false, false);
155 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700156
Jack Palevich66089a32009-12-08 15:43:51 +0800157 boolean isPointerFunc(JFunc jfunc) {
158 String name = jfunc.getName();
159 return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
160 && jfunc.getCFunc().hasPointerArg();
161 }
162
Jack Palevichffac1ef2009-04-14 19:00:09 -0700163 void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800164 boolean isVoid = jfunc.getType().isVoid();
Jack Palevich66089a32009-12-08 15:43:51 +0800165 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800166
167 if (!isVoid) {
168 out.println(iii +
169 jfunc.getType() + " _returnValue;");
170 }
171 out.println(iii +
172 (isVoid ? "" : "_returnValue = ") +
173 jfunc.getName() +
174 (isPointerFunc ? "Bounds" : "" ) +
175 "(");
Jack Palevich6cbca502009-04-13 16:22:25 -0700176
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800177 int numArgs = jfunc.getNumArgs();
178 for (int i = 0; i < numArgs; i++) {
179 String argName = jfunc.getArgName(i);
180 JType argType = jfunc.getArgType(i);
181
182 if (grabArray && argType.isTypedBuffer()) {
183 String typeName = argType.getBaseType();
184 typeName = typeName.substring(9, typeName.length() - 6);
185 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
Jack Palevich6cbca502009-04-13 16:22:25 -0700186 out.print(iii + indent + "getOffset(" + argName + ")");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800187 } else {
188 out.print(iii + indent + argName);
189 }
190 if (i == numArgs - 1) {
191 if (isPointerFunc) {
192 out.println(",");
193 out.println(iii + indent + argName + ".remaining()");
194 } else {
195 out.println();
196 }
197 } else {
198 out.println(",");
199 }
200 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700201
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800202 out.println(iii + ");");
203 }
204
Adam Bodnara7ab5c72020-07-08 15:35:06 -0700205 // Function to automatically generate properly formatted function calls that
206 // comply with clang format rules
207 public static String formatFunctionCall(String indent, String functionCall) {
208 final int MAXLEN = 100;
209 String tokens[] = functionCall.split("\\(|\\)", 2);
210 String params[] = tokens[1].split(",\\s*");
211 String formatted = indent + tokens[0] + "(";
212 char[] chars = new char[indent.length() + tokens[0].length() + 1];
213 Arrays.fill(chars, ' ');
214 String multiIndent = new String(chars);
215 ArrayList<String> lines = new ArrayList<String>();
216 for(int i = 0; i < params.length; i++) {
217 String terminator = ((i == params.length - 1) ? "" : ",");
218 if(indent.length() + formatted.length() + params[i].length() > MAXLEN) {
219 lines.add(formatted);
220 if (!indent.equals(multiIndent)) {
221 indent = multiIndent;
222 }
223 formatted = indent + params[i] + terminator;
224 } else {
225 formatted += (i == 0 ? "" : " ") + params[i] + terminator;
226 }
227 }
228 lines.add(formatted);
229 return String.join("\n", lines);
230 }
231
Jack Palevichffac1ef2009-04-14 19:00:09 -0700232 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
233 String iii) {
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800234 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
235 "offset", "_remaining", iii);
236 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800237
Jack Palevichffac1ef2009-04-14 19:00:09 -0700238 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
239 String offset, String remaining, String iii) {
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800240 out.println(iii + " default:");
241 out.println(iii + " _needed = 1;");
242 out.println(iii + " break;");
243 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800244
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800245 out.println(iii + "if (" + remaining + " < _needed) {");
246 out.println(iii + indent + "_exception = 1;");
247 out.println(iii + indent +
248 "_exceptionType = \"java/lang/IllegalArgumentException\";");
249 out.println(iii + indent +
250 "_exceptionMessage = \"" +
251 (isBuffer ? "remaining()" : "length - " + offset) +
252 " < needed\";");
253 out.println(iii + indent + "goto exit;");
254 out.println(iii + "}");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700255
Mathias Agopianbf13ba52013-02-22 19:34:06 -0800256 needsExit = true;
257 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800258
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700259 boolean isNullAllowed(CFunc cfunc, String cname) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800260 String[] checks = mChecker.getChecks(cfunc.getName());
261 int index = 1;
262 if (checks != null) {
263 while (index < checks.length) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700264 if (checks[index].equals("nullAllowed") &&
265 checks[index + 1].equals(cname)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800266 return true;
267 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700268 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800269 }
270 }
271 }
272 return false;
273 }
274
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700275 boolean hasCheckTest(CFunc cfunc) {
276 String[] checks = mChecker.getChecks(cfunc.getName());
277 int index = 1;
278 if (checks != null) {
279 while (index < checks.length) {
280 if (checks[index].startsWith("check")) {
281 return true;
282 } else {
283 index = skipOneCheck(checks, index);
284 }
285 }
286 }
287 return false;
288 }
289
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700290 boolean hasCheckTest(CFunc cfunc, String cname) {
291 String[] checks = mChecker.getChecks(cfunc.getName());
292 int index = 1;
293 if (checks != null) {
294 while (index < checks.length) {
295 if (checks[index].startsWith("check") &&
296 cname != null && cname.equals(checks[index + 1])) {
297 return true;
298 } else {
299 index = skipOneCheck(checks, index);
300 }
301 }
302 }
303 return false;
304 }
305
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700306 boolean hasIfTest(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].startsWith("ifcheck")) {
312 return true;
313 } else {
314 index = skipOneCheck(checks, index);
315 }
316 }
317 }
318 return false;
319 }
320
321 int skipOneCheck(String[] checks, int index) {
322 if (checks[index].equals("return")) {
323 index += 2;
324 } else if (checks[index].startsWith("check")) {
325 index += 3;
326 } else if (checks[index].startsWith("sentinel")) {
327 index += 3;
328 } else if (checks[index].equals("ifcheck")) {
329 index += 5;
330 } else if (checks[index].equals("unsupported")) {
331 index += 1;
332 } else if (checks[index].equals("requires")) {
333 index += 2;
334 } else if (checks[index].equals("nullAllowed")) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700335 index += 2;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700336 } else {
337 System.out.println("Error: unknown keyword \"" +
338 checks[index] + "\"");
339 System.exit(0);
340 }
341
342 return index;
343 }
344
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800345 String getErrorReturnValue(CFunc cfunc) {
346 CType returnType = cfunc.getType();
347 boolean isVoid = returnType.isVoid();
348 if (isVoid) {
349 return null;
350 }
351
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700352 if (returnType.getBaseType().startsWith("EGL")) {
353 return "(" + returnType.getDeclaration() + ") 0";
354 }
355
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800356 String[] checks = mChecker.getChecks(cfunc.getName());
357
358 int index = 1;
359 if (checks != null) {
360 while (index < checks.length) {
361 if (checks[index].equals("return")) {
362 return checks[index + 1];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800363 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700364 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800365 }
366 }
367 }
368
369 return null;
370 }
371
372 boolean isUnsupportedFunc(CFunc cfunc) {
373 String[] checks = mChecker.getChecks(cfunc.getName());
374 int index = 1;
375 if (checks != null) {
376 while (index < checks.length) {
377 if (checks[index].equals("unsupported")) {
378 return true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800379 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700380 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800381 }
382 }
383 }
384 return false;
385 }
Elliott Hughes98757502011-04-08 20:01:01 -0700386
Jack Paleviche44e45c2010-01-28 20:28:32 +0800387 String isRequiresFunc(CFunc cfunc) {
388 String[] checks = mChecker.getChecks(cfunc.getName());
389 int index = 1;
390 if (checks != null) {
391 while (index < checks.length) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700392 if (checks[index].equals("requires")) {
Jack Paleviche44e45c2010-01-28 20:28:32 +0800393 return checks[index+1];
Jack Paleviche44e45c2010-01-28 20:28:32 +0800394 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700395 index = skipOneCheck(checks, index);
Jack Paleviche44e45c2010-01-28 20:28:32 +0800396 }
397 }
398 }
399 return null;
400 }
Elliott Hughes98757502011-04-08 20:01:01 -0700401
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800402 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700403 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800404
Elliott Hughes98757502011-04-08 20:01:01 -0700405 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800406
Elliott Hughes98757502011-04-08 20:01:01 -0700407 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800408
Elliott Hughes98757502011-04-08 20:01:01 -0700409 int index = 1;
410 if (checks != null) {
411 while (index < checks.length) {
412 if (checks[index].startsWith("check")) {
413 if (lastWasIfcheck) {
414 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
415 offset, remaining, iii);
416 }
417 lastWasIfcheck = false;
418 if (cname != null && !cname.equals(checks[index + 1])) {
419 index += 3;
420 continue;
421 }
422 out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700423 out.println(iii + indent + "_exception = 1;");
Elliott Hughes98757502011-04-08 20:01:01 -0700424 String exceptionClassName = "java/lang/IllegalArgumentException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700425 // If the "check" keyword was of the form
426 // "check_<class name>", use the class name in the
427 // exception to be thrown
428 int underscore = checks[index].indexOf('_');
429 if (underscore >= 0) {
Elliott Hughes98757502011-04-08 20:01:01 -0700430 String abbr = checks[index].substring(underscore + 1);
431 if (abbr.equals("AIOOBE")) {
432 exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
Jack Palevichffac1ef2009-04-14 19:00:09 -0700433 } else {
Elliott Hughes98757502011-04-08 20:01:01 -0700434 throw new RuntimeException("unknown exception abbreviation: " + abbr);
Jack Palevichffac1ef2009-04-14 19:00:09 -0700435 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800436 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700437 out.println(iii + indent +
438 "_exceptionType = \""+exceptionClassName+"\";");
439 out.println(iii + indent +
440 "_exceptionMessage = \"" +
441 (isBuffer ? "remaining()" : "length - " +
442 offset) + " < " + checks[index + 2] +
443 " < needed\";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444
Elliott Hughes98757502011-04-08 20:01:01 -0700445 out.println(iii + indent + "goto exit;");
Elliott Hughes98757502011-04-08 20:01:01 -0700446 out.println(iii + "}");
447
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700448 needsExit = true;
449
Elliott Hughes98757502011-04-08 20:01:01 -0700450 index += 3;
451 } else if (checks[index].equals("ifcheck")) {
452 String[] matches = checks[index + 4].split(",");
453
454 if (!lastWasIfcheck) {
455 out.println(iii + "int _needed;");
456 out.println(iii + "switch (" + checks[index + 3] + ") {");
457 }
458
459 for (int i = 0; i < matches.length; i++) {
460 out.println("#if defined(" + matches[i] + ")");
461 out.println(iii + " case " + matches[i] + ":");
462 out.println("#endif // defined(" + matches[i] + ")");
463 }
464 out.println(iii + " _needed = " + checks[index + 2] + ";");
465 out.println(iii + " break;");
466
467 lastWasIfcheck = true;
468 index += 5;
Elliott Hughes98757502011-04-08 20:01:01 -0700469 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700470 index = skipOneCheck(checks, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800471 }
472 }
Elliott Hughes98757502011-04-08 20:01:01 -0700473 }
474
475 if (lastWasIfcheck) {
476 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
477 }
478 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800479
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700480 void emitSentinelCheck(CFunc cfunc, String cname, PrintStream out,
481 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
482
483 String[] checks = mChecker.getChecks(cfunc.getName());
484
485 int index = 1;
486 if (checks != null) {
487 while (index < checks.length) {
488 if (checks[index].startsWith("sentinel")) {
489 if (cname != null && !cname.equals(checks[index + 1])) {
490 index += 3;
491 continue;
492 }
493
494 out.println(iii + cname + "_sentinel = false;");
495 out.println(iii + "for (int i = " + remaining +
496 " - 1; i >= 0; i--) {");
497 out.println(iii + indent + "if (" + cname +
498 "[i] == " + checks[index + 2] + "){");
499 out.println(iii + indent + indent +
500 cname + "_sentinel = true;");
501 out.println(iii + indent + indent + "break;");
502 out.println(iii + indent + "}");
503 out.println(iii + "}");
504 out.println(iii +
505 "if (" + cname + "_sentinel == false) {");
506 out.println(iii + indent + "_exception = 1;");
507 out.println(iii + indent +
508 "_exceptionType = \"java/lang/IllegalArgumentException\";");
509 out.println(iii + indent + "_exceptionMessage = \"" + cname +
510 " must contain " + checks[index + 2] + "!\";");
511 out.println(iii + indent + "goto exit;");
512 out.println(iii + "}");
513
514 needsExit = true;
515 index += 3;
516 } else {
517 index = skipOneCheck(checks, index);
518 }
519 }
520 }
521 }
522
Pablo Ceballosb62e2422015-10-01 18:25:56 -0700523 void emitStringCheck(CFunc cfunc, String cname, PrintStream out, String iii) {
524
525 String[] checks = mChecker.getChecks(cfunc.getName());
526
527 int index = 1;
528 if (checks != null) {
529 while (index < checks.length) {
530 if (checks[index].startsWith("check")) {
531 if (cname != null && !cname.equals(checks[index + 1])) {
532 index += 3;
533 continue;
534 }
535 out.println(iii + "_stringlen = _env->GetStringUTFLength(" + cname + ");");
536 out.println(iii + "if (" + checks[index + 2] + " > _stringlen) {");
537 out.println(iii + indent + "_exception = 1;");
538 out.println(iii + indent +
539 "_exceptionType = \"java/lang/ArrayIndexOutOfBoundsException\";");
540 out.println(iii + indent +
541 "_exceptionMessage = \"length of " + cname + " is shorter than " +
542 checks[index + 2] + " argument\";");
543 out.println(iii + indent + "goto exit;");
544 out.println(iii + "}");
545 index += 3;
546 needsExit = true;
547 } else {
548 index = skipOneCheck(checks, index);
549 }
550 }
551 }
552 }
553
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700554 void emitLocalVariablesForSentinel(CFunc cfunc, PrintStream out) {
555
556 String[] checks = mChecker.getChecks(cfunc.getName());
557
558 int index = 1;
559 if (checks != null) {
560 while (index < checks.length) {
561 if (checks[index].startsWith("sentinel")) {
562 String cname = checks[index + 1];
563 out.println(indent + "bool " + cname + "_sentinel = false;");
564
565 index += 3;
566
567 } else {
568 index = skipOneCheck(checks, index);
569 }
570 }
571 }
572 }
573
Jack Palevichffac1ef2009-04-14 19:00:09 -0700574 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800575 if (nonPrimitiveArgs.size() > 0) {
576 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
577 int idx = nonPrimitiveArgs.get(i).intValue();
578 int cIndex = jfunc.getArgCIndex(idx);
579 if (jfunc.getArgType(idx).isArray()) {
580 if (!cfunc.getArgType(cIndex).isConst()) {
581 return true;
582 }
583 } else if (jfunc.getArgType(idx).isBuffer()) {
584 if (!cfunc.getArgType(cIndex).isConst()) {
585 return true;
586 }
587 }
588 }
589 }
590
591 return false;
592 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700593
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800594 /**
595 * Emit a function in several variants:
596 *
597 * if nativeDecl: public native <returntype> func(args);
598 *
599 * if !nativeDecl:
600 * if interfaceDecl: public <returntype> func(args);
601 * if !interfaceDecl: public <returntype> func(args) { body }
602 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700603 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800604 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800605
606 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
607 // If it's not a pointer function, we've already emitted it
608 // with nativeDecl == true
609 return;
610 }
611
Jack Palevich427f5852009-04-15 19:13:17 -0700612 String maybeStatic = mUseStaticMethods ? "static " : "";
613
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800614 if (isPointerFunc) {
615 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700616 (nativeDecl ? "private " + maybeStatic +"native " :
617 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800618 jfunc.getType() + " " +
619 jfunc.getName() +
620 (nativeDecl ? "Bounds" : "") +
621 "(");
622 } else {
623 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700624 (nativeDecl ? "public " + maybeStatic +"native " :
625 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800626 jfunc.getType() + " " +
627 jfunc.getName() +
628 "(");
629 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700630
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800631 int numArgs = jfunc.getNumArgs();
632 for (int i = 0; i < numArgs; i++) {
633 String argName = jfunc.getArgName(i);
634 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700635
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800636 out.print(indent + indent + argType + " " + argName);
637 if (i == numArgs - 1) {
638 if (isPointerFunc && nativeDecl) {
639 out.println(",");
640 out.println(indent + indent + "int remaining");
641 } else {
642 out.println();
643 }
644 } else {
645 out.println(",");
646 }
647 }
648
649 if (nativeDecl || interfaceDecl) {
650 out.println(indent + ");");
651 } else {
652 out.println(indent + ") {");
653
654 String iii = indent + indent;
655
Jack Palevich46d25a32009-05-07 18:28:29 -0700656 // emitBoundsChecks(jfunc, out, iii);
657 emitFunctionCall(jfunc, out, iii, false);
658
659 // Set the pointer after we call the native code, so that if
660 // the native code throws an exception we don't modify the
661 // pointer. We assume that the native code is written so that
662 // if an exception is thrown, then the underlying glXXXPointer
663 // function will not have been called.
664
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665 String fname = jfunc.getName();
666 if (isPointerFunc) {
667 // TODO - deal with VBO variants
668 if (fname.equals("glColorPointer")) {
669 out.println(iii + "if ((size == 4) &&");
670 out.println(iii + " ((type == GL_FLOAT) ||");
671 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
672 out.println(iii + " (type == GL_FIXED)) &&");
673 out.println(iii + " (stride >= 0)) {");
674 out.println(iii + indent + "_colorPointer = pointer;");
675 out.println(iii + "}");
676 } else if (fname.equals("glNormalPointer")) {
677 out.println(iii + "if (((type == GL_FLOAT) ||");
678 out.println(iii + " (type == GL_BYTE) ||");
679 out.println(iii + " (type == GL_SHORT) ||");
680 out.println(iii + " (type == GL_FIXED)) &&");
681 out.println(iii + " (stride >= 0)) {");
682 out.println(iii + indent + "_normalPointer = pointer;");
683 out.println(iii + "}");
684 } else if (fname.equals("glTexCoordPointer")) {
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 + "_texCoordPointer = pointer;");
694 out.println(iii + "}");
695 } else if (fname.equals("glVertexPointer")) {
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 + "_vertexPointer = pointer;");
705 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800706 } else if (fname.equals("glPointSizePointerOES")) {
707 out.println(iii + "if (((type == GL_FLOAT) ||");
708 out.println(iii + " (type == GL_FIXED)) &&");
709 out.println(iii + " (stride >= 0)) {");
710 out.println(iii + indent + "_pointSizePointerOES = pointer;");
711 out.println(iii + "}");
712 } else if (fname.equals("glMatrixIndexPointerOES")) {
713 out.println(iii + "if (((size == 2) ||");
714 out.println(iii + " (size == 3) ||");
715 out.println(iii + " (size == 4)) &&");
716 out.println(iii + " ((type == GL_FLOAT) ||");
717 out.println(iii + " (type == GL_BYTE) ||");
718 out.println(iii + " (type == GL_SHORT) ||");
719 out.println(iii + " (type == GL_FIXED)) &&");
720 out.println(iii + " (stride >= 0)) {");
721 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
722 out.println(iii + "}");
723 } else if (fname.equals("glWeightPointer")) {
724 out.println(iii + "if (((size == 2) ||");
725 out.println(iii + " (size == 3) ||");
726 out.println(iii + " (size == 4)) &&");
727 out.println(iii + " ((type == GL_FLOAT) ||");
728 out.println(iii + " (type == GL_BYTE) ||");
729 out.println(iii + " (type == GL_SHORT) ||");
730 out.println(iii + " (type == GL_FIXED)) &&");
731 out.println(iii + " (stride >= 0)) {");
732 out.println(iii + indent + "_weightPointerOES = pointer;");
733 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734 }
735 }
736
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800737 boolean isVoid = jfunc.getType().isVoid();
738
739 if (!isVoid) {
740 out.println(indent + indent + "return _returnValue;");
741 }
742 out.println(indent + "}");
743 }
744 out.println();
745 }
746
Jack Palevichffac1ef2009-04-14 19:00:09 -0700747 public void addNativeRegistration(String s) {
748 nativeRegistrations.add(s);
749 }
750
Jack Palevich427f5852009-04-15 19:13:17 -0700751 public void emitNativeRegistration(String registrationFunctionName,
752 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700753 cStream.println("static const char *classPathName = \"" +
754 mClassPathName +
755 "\";");
756 cStream.println();
757
Daniel Micayc4e95a32015-09-21 13:17:57 -0400758 cStream.println("static const JNINativeMethod methods[] = {");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700759
760 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
761
762 Iterator<String> i = nativeRegistrations.iterator();
763 while (i.hasNext()) {
764 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800765 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700766
Jack Palevichffac1ef2009-04-14 19:00:09 -0700767 cStream.println("};");
768 cStream.println();
769
770
Jack Palevich427f5852009-04-15 19:13:17 -0700771 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700772 cStream.println("{");
773 cStream.println(indent +
774 "int err;");
775
776 cStream.println(indent +
777 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
778
779 cStream.println(indent + "return err;");
780 cStream.println("}");
781 }
782
783 public JniCodeEmitter() {
784 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800785 }
786
787 String getJniType(JType jType) {
788 if (jType.isVoid()) {
789 return "void";
790 }
791
792 String baseType = jType.getBaseType();
793 if (jType.isPrimitive()) {
794 if (baseType.equals("String")) {
795 return "jstring";
796 } else {
797 return "j" + baseType;
798 }
799 } else if (jType.isArray()) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700800 return jType.isClass() ? "jobjectArray" : "j" + baseType + "Array";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800801 } else {
802 return "jobject";
803 }
804 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700805
Orion Hodson91f564d2019-02-26 16:57:18 +0000806 String getJniDefaultReturn(JType jType) {
807 if (jType.isPrimitive()) {
808 String baseType = jType.getBaseType();
809 if (baseType.equals("boolean")) {
810 return "JNI_FALSE";
811 } else {
812 return "(" + getJniType(jType) + ")0";
813 }
814 } else {
815 return "nullptr";
816 }
817 }
818
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800819 String getJniMangledName(String name) {
820 name = name.replaceAll("_", "_1");
821 name = name.replaceAll(";", "_2");
822 name = name.replaceAll("\\[", "_3");
823 return name;
824 }
825
826 public void emitJniCode(JFunc jfunc, PrintStream out) {
827 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700828
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800829 // Emit comment identifying original C function
830 //
831 // Example:
832 //
833 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
834 //
835 out.println("/* " + cfunc.getOriginal() + " */");
836
837 // Emit JNI signature (name)
838 //
839 // Example:
840 //
841 // void
842 // android_glClipPlanef__I_3FI
843 //
844
845 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800846 boolean isPointerFunc = isPointerFunc(jfunc);
Jesse Hall071fc662013-04-10 01:17:34 -0700847 boolean isPointerOffsetFunc =
848 (outName.endsWith("Pointer") || outName.endsWith("PointerOES") ||
849 outName.endsWith("glDrawElements") ||
850 outName.endsWith("glDrawRangeElements") ||
851 outName.endsWith("glTexImage2D") ||
852 outName.endsWith("glTexSubImage2D") ||
853 outName.endsWith("glCompressedTexImage2D") ||
854 outName.endsWith("glCompressedTexSubImage2D") ||
855 outName.endsWith("glTexImage3D") ||
856 outName.endsWith("glTexSubImage3D") ||
857 outName.endsWith("glCompressedTexImage3D") ||
858 outName.endsWith("glCompressedTexSubImage3D") ||
859 outName.endsWith("glReadPixels"))
860 && !jfunc.getCFunc().hasPointerArg();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800861 if (isPointerFunc) {
862 outName += "Bounds";
863 }
864
865 out.print("static ");
866 out.println(getJniType(jfunc.getType()));
867 out.print(outName);
868
869 String rsignature = getJniName(jfunc.getType());
870
871 String signature = "";
872 int numArgs = jfunc.getNumArgs();
873 for (int i = 0; i < numArgs; i++) {
874 JType argType = jfunc.getArgType(i);
875 signature += getJniName(argType);
876 }
877 if (isPointerFunc) {
878 signature += "I";
879 }
880
881 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800882 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700883 if (!mUseSimpleMethodNames) {
884 out.print("__" + sig);
885 outName += "__" + sig;
886 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700887
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800888 signature = signature.replace('.', '/');
889 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700890
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800891 out.println();
892 if (rsignature.length() == 0) {
893 rsignature = "V";
894 }
895
896 String s = "{\"" +
897 jfunc.getName() +
898 (isPointerFunc ? "Bounds" : "") +
899 "\", \"(" + signature +")" +
900 rsignature +
901 "\", (void *) " +
902 outName +
903 " },";
904 nativeRegistrations.add(s);
905
906 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800907 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800908 int numBufferArgs = 0;
909 List<String> bufferArgNames = new ArrayList<String>();
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700910 List<JType> bufferArgTypes = new ArrayList<JType>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800911
912 // Emit JNI signature (arguments)
913 //
914 // Example:
915 //
916 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
917 //
918 out.print(" (JNIEnv *_env, jobject _this");
919 for (int i = 0; i < numArgs; i++) {
920 out.print(", ");
921 JType argType = jfunc.getArgType(i);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700922 String suffix = "";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800923 if (!argType.isPrimitive()) {
924 if (argType.isArray()) {
925 suffix = "_ref";
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700926 } else if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800927 suffix = "_buf";
928 }
929 nonPrimitiveArgs.add(new Integer(i));
930 if (jfunc.getArgType(i).isBuffer()) {
931 int cIndex = jfunc.getArgCIndex(i);
932 String cname = cfunc.getArgName(cIndex);
933 bufferArgNames.add(cname);
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -0700934 bufferArgTypes.add(jfunc.getArgType(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800935 numBufferArgs++;
936 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800937 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700938
Jack Palevich50d0b142009-11-19 16:34:55 +0800939 if (argType.isString()) {
940 stringArgs.add(new Integer(i));
941 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800942
943 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
944 }
945 if (isPointerFunc) {
946 out.print(", jint remaining");
947 }
948 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700949
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800950 int numArrays = 0;
951 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800952 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800953 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
954 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800955 JType argType = jfunc.getArgType(idx);
956 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800957 ++numArrays;
958 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800959 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800960 ++numBuffers;
961 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800962 if (argType.isString()) {
963 ++numStrings;
964 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800965 }
966
967 // Emit method body
968
969 // Emit local variable declarations for _exception and _returnValue
970 //
971 // Example:
972 //
973 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700974 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800975 // jint _exception;
976 // GLenum _returnValue;
977 //
978 CType returnType = cfunc.getType();
979 boolean isVoid = returnType.isVoid();
980
981 boolean isUnsupported = isUnsupportedFunc(cfunc);
982 if (isUnsupported) {
983 out.println(indent +
Elliott Hughes98757502011-04-08 20:01:01 -0700984 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800985 out.println(indent +
986 " \"" + cfunc.getName() + "\");");
Orion Hodson91f564d2019-02-26 16:57:18 +0000987 if (isVoid) {
988 out.println(indent + "return;");
989 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700990 if (cfunc.getType().isEGLHandle()) {
991 String baseType = cfunc.getType().getBaseType().toLowerCase();
Orion Hodson91f564d2019-02-26 16:57:18 +0000992 out.println(indent + indent + "return nullptr;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700993 } else {
Orion Hodson91f564d2019-02-26 16:57:18 +0000994 out.println(indent + indent + "return " +
995 getJniDefaultReturn(jfunc.getType()) + ";");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -0700996 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800997 }
998 out.println("}");
999 out.println();
1000 return;
1001 }
Elliott Hughes98757502011-04-08 20:01:01 -07001002
Jack Paleviche44e45c2010-01-28 20:28:32 +08001003 String requiresExtension = isRequiresFunc(cfunc);
1004 if (requiresExtension != null) {
1005 out.println(indent +
1006 "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
1007 out.println(indent + indent +
Elliott Hughes98757502011-04-08 20:01:01 -07001008 "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
Jack Paleviche44e45c2010-01-28 20:28:32 +08001009 out.println(indent + indent +
1010 " \"" + cfunc.getName() + "\");");
1011 if (isVoid) {
1012 out.println(indent + indent + " return;");
1013 } else {
1014 String retval = getErrorReturnValue(cfunc);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001015 if (cfunc.getType().isEGLHandle()) {
1016 String baseType = cfunc.getType().getBaseType().toLowerCase();
1017 out.println(indent +
1018 "return toEGLHandle(_env, " + baseType + "Class, " +
1019 baseType + "Constructor, " + retval + ");");
1020 } else {
1021 out.println(indent + "return " + retval + ";");
1022 }
Jack Paleviche44e45c2010-01-28 20:28:32 +08001023 }
1024 out.println(indent + "}");
1025 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001026 if (mUseContextPointer) {
1027 out.println(indent +
1028 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
1029 }
1030
Jack Palevich50d0b142009-11-19 16:34:55 +08001031 boolean initializeReturnValue = stringArgs.size() > 0;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001032 boolean emitExceptionCheck = ((numArrays > 0 || numStrings > 0)
1033 && (hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs)
1034 || (cfunc.hasPointerArg() && numArrays > 0))
Romain Guy79699992016-12-05 12:26:42 -08001035 || (numBufferArgs > 0)
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001036 || hasCheckTest(cfunc)
1037 || hasIfTest(cfunc))
1038 || (stringArgs.size() > 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039 // mChecker.getChecks(cfunc.getName()) != null
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001040 // Emit an _exeption variable if there will be error checks
1041 if (emitExceptionCheck) {
1042 out.println(indent + "jint _exception = 0;");
Mathias Agopianbf13ba52013-02-22 19:34:06 -08001043 out.println(indent + "const char * _exceptionType = NULL;");
1044 out.println(indent + "const char * _exceptionMessage = NULL;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001045 }
1046
1047 // Emit a single _array or multiple _XXXArray variables
1048 if (numBufferArgs == 1) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001049 JType bufferType = bufferArgTypes.get(0);
1050 if (bufferType.isTypedBuffer()) {
1051 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
1052 out.println(indent + typedArrayType + " _array = (" + typedArrayType + ") 0;");
1053 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054 out.println(indent + "jarray _array = (jarray) 0;");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001055 }
1056 out.println(indent + "jint _bufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001057 } else {
1058 for (int i = 0; i < numBufferArgs; i++) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001059 JType bufferType = bufferArgTypes.get(0);
1060 if (bufferType.isTypedBuffer()) {
1061 String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
1062 out.println(indent + typedArrayType + " _" + bufferArgNames.get(i) +
1063 "Array = (" + typedArrayType + ") 0;");
1064 } else {
1065 out.println(indent + "jarray _" + bufferArgNames.get(i) +
1066 "Array = (jarray) 0;");
1067 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001068 out.println(indent + "jint _" + bufferArgNames.get(i) +
1069 "BufferOffset = (jint) 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001070 }
1071 }
1072 if (!isVoid) {
1073 String retval = getErrorReturnValue(cfunc);
1074 if (retval != null) {
1075 out.println(indent + returnType.getDeclaration() +
1076 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +08001077 } else if (initializeReturnValue) {
1078 out.println(indent + returnType.getDeclaration() +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001079 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001080 } else {
1081 out.println(indent + returnType.getDeclaration() +
1082 " _returnValue;");
1083 }
1084 }
1085
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001086 // Emit local variable declarations for EGL Handles
1087 //
1088 // Example:
1089 //
1090 // EGLSurface surface_native = (EGLHandle)fromEGLHandle(_env, surfaceClass, surfaceConstructor, surface);
1091 //
1092 if (nonPrimitiveArgs.size() > 0) {
1093 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1094 int idx = nonPrimitiveArgs.get(i).intValue();
1095 int cIndex = jfunc.getArgCIndex(idx);
1096 String cname = cfunc.getArgName(cIndex);
1097
1098 if (jfunc.getArgType(idx).isBuffer()
1099 || jfunc.getArgType(idx).isArray()
1100 || !jfunc.getArgType(idx).isEGLHandle())
1101 continue;
1102
1103 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1104 String decl = type.getDeclaration();
1105 out.println(indent +
1106 decl + " " + cname + "_native = (" +
1107 decl + ") fromEGLHandle(_env, " +
1108 type.getBaseType().toLowerCase() +
1109 "GetHandleID, " + jfunc.getArgName(idx) +
1110 ");");
1111 }
1112 }
1113
1114 // Emit local variable declarations for element/sentinel checks
1115 //
1116 // Example:
1117 //
1118 // bool attrib_list_sentinel_found = false;
1119 //
1120 emitLocalVariablesForSentinel(cfunc, out);
1121
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001122 // Emit local variable declarations for pointer arguments
1123 //
1124 // Example:
1125 //
1126 // GLfixed *eqn_base;
1127 // GLfixed *eqn;
1128 //
1129 String offset = "offset";
1130 String remaining = "_remaining";
1131 if (nonPrimitiveArgs.size() > 0) {
1132 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1133 int idx = nonPrimitiveArgs.get(i).intValue();
1134 int cIndex = jfunc.getArgCIndex(idx);
1135 String cname = cfunc.getArgName(cIndex);
1136
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001137 if (!jfunc.getArgType(idx).isBuffer() && !jfunc.getArgType(idx).isArray())
1138 continue;
1139
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001140 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1141 String decl = type.getDeclaration();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001142 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001143 out.println(indent +
1144 decl +
1145 (decl.endsWith("*") ? "" : " ") +
1146 jfunc.getArgName(idx) +
1147 "_base = (" + decl + ") 0;");
1148 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001149 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001150 "_" + cname + "Remaining";
1151 out.println(indent +
1152 "jint " + remaining + ";");
1153 out.println(indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001154 decl +
1155 (decl.endsWith("*") ? "" : " ") +
1156 jfunc.getArgName(idx) +
1157 " = (" + decl + ") 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001158 }
1159
1160 out.println();
1161 }
1162
Jack Palevich50d0b142009-11-19 16:34:55 +08001163 // Emit local variable declaration for strings
1164 if (stringArgs.size() > 0) {
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001165 boolean requiresStringLengthCheck = false;
Jack Palevich50d0b142009-11-19 16:34:55 +08001166 for (int i = 0; i < stringArgs.size(); i++) {
1167 int idx = stringArgs.get(i).intValue();
1168 int cIndex = jfunc.getArgCIndex(idx);
1169 String cname = cfunc.getArgName(cIndex);
1170
1171 out.println(indent + "const char* _native" + cname + " = 0;");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001172 if (hasCheckTest(cfunc, cname)) {
1173 requiresStringLengthCheck = true;
1174 }
1175 }
1176
1177 if (requiresStringLengthCheck) {
1178 out.println(indent + "jsize _stringlen = 0;");
Jack Palevich50d0b142009-11-19 16:34:55 +08001179 }
1180
1181 out.println();
1182 }
1183
1184 // Null pointer checks and GetStringUTFChars
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
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001191 boolean nullAllowed = isNullAllowed(cfunc, cname);
1192 String nullAllowedIndent = nullAllowed ? indent : "";
1193
Jack Palevich50d0b142009-11-19 16:34:55 +08001194 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
1195 String decl = type.getDeclaration();
Jack Palevich50d0b142009-11-19 16:34:55 +08001196
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001197 if (nullAllowed) {
1198 out.println(indent + "if (" + cname + ") {");
1199 } else {
1200 needsExit = true;
1201 out.println(indent + "if (!" + cname + ") {");
1202 out.println(indent + indent + "_exception = 1;");
1203 out.println(indent + indent +
1204 "_exceptionType = \"java/lang/IllegalArgumentException\";");
1205 out.println(indent + indent +
1206 "_exceptionMessage = \"" + cname + " == null\";");
1207 out.println(indent + indent + "goto exit;");
1208 out.println(indent + "}");
1209 }
1210
1211 out.println(nullAllowedIndent + indent + "_native" + cname +
1212 " = _env->GetStringUTFChars(" + cname + ", 0);");
1213
1214 emitStringCheck(cfunc, cname, out, nullAllowedIndent + indent);
1215
1216 if (nullAllowed) {
1217 out.println(indent + "}");
1218 }
Jack Palevich50d0b142009-11-19 16:34:55 +08001219 }
1220
1221 out.println();
1222 }
1223
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001224 // Emit 'GetPrimitiveArrayCritical' for non-object arrays
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001225 // Emit 'GetPointer' calls for Buffer pointers
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001226 if (nonPrimitiveArgs.size() > 0) {
1227 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1228 int idx = nonPrimitiveArgs.get(i).intValue();
1229 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -07001230
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001231 String cname = cfunc.getArgName(cIndex);
1232 offset = numArrays <= 1 ? "offset" :
1233 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +08001234 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001235 "_" + cname + "Remaining";
1236
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001237 boolean nullAllowed = isNullAllowed(cfunc, cname);
1238 String nullAllowedIndent = nullAllowed ? indent : "";
1239
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001240 if (jfunc.getArgType(idx).isArray()
1241 && !jfunc.getArgType(idx).isEGLHandle()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001242 needsExit = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001243
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001244 if (nullAllowed) {
1245 out.println(indent + "if (" + cname + "_ref) {");
1246 }
1247 else
1248 {
1249 out.println(indent + "if (!" + cname + "_ref) {");
1250 out.println(indent + indent + "_exception = 1;");
1251 out.println(indent + indent +
1252 "_exceptionType = " +
1253 "\"java/lang/IllegalArgumentException\";");
1254 out.println(indent + indent +
1255 "_exceptionMessage = \"" + cname +
1256 " == null\";");
1257 out.println(indent + indent + "goto exit;");
1258 out.println(indent + "}");
1259 }
1260
1261 out.println(nullAllowedIndent + indent + "if (" + offset +
1262 " < 0) {");
1263 out.println(nullAllowedIndent + indent + indent +
1264 "_exception = 1;");
1265 out.println(nullAllowedIndent + indent + indent +
1266 "_exceptionType = " +
1267 "\"java/lang/IllegalArgumentException\";");
1268 out.println(nullAllowedIndent + indent + indent +
1269 "_exceptionMessage = \"" + offset +" < 0\";");
1270 out.println(nullAllowedIndent + indent + indent +
1271 "goto exit;");
1272 out.println(nullAllowedIndent + indent + "}");
1273
1274 out.println(nullAllowedIndent + indent + remaining + " = " +
1275 (mUseCPlusPlus ? "_env" : "(*_env)") +
1276 "->GetArrayLength(" +
1277 (mUseCPlusPlus ? "" : "_env, ") +
1278 cname + "_ref) - " + offset + ";");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001279
1280 emitNativeBoundsChecks(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001281 emitExceptionCheck, offset, remaining,
1282 nullAllowedIndent + indent);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001283
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001284 out.println(nullAllowedIndent + indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001285 cname +
1286 "_base = (" +
1287 cfunc.getArgType(cIndex).getDeclaration() +
1288 ")");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001289 String arrayGetter = jfunc.getArgType(idx).getArrayGetterForPrimitiveArray();
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001290 out.println(nullAllowedIndent + indent + " " +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001291 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001292 "->" + arrayGetter + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001293 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001294 jfunc.getArgName(idx) +
1295 "_ref, (jboolean *)0);");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001296 out.println(nullAllowedIndent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001297 cname + " = " + cname + "_base + " + offset + ";");
1298
1299 emitSentinelCheck(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001300 emitExceptionCheck, offset, remaining,
1301 nullAllowedIndent + indent);
1302
1303 if (nullAllowed) {
1304 out.println(indent + "}");
1305 }
1306
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001307 out.println();
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001308 } else if (jfunc.getArgType(idx).isArray()
1309 && jfunc.getArgType(idx).isEGLHandle()) {
1310 needsExit = true;
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001311
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001312 if (nullAllowed) {
1313 out.println(indent + "if (" + cname + "_ref) {");
1314 }
1315 else
1316 {
1317 out.println(indent + "if (!" + cname + "_ref) {");
1318 out.println(indent + indent + "_exception = 1;");
1319 out.println(indent + indent + "_exceptionType = " +
1320 "\"java/lang/IllegalArgumentException\";");
1321 out.println(indent + indent + "_exceptionMessage = \"" +
1322 cname +" == null\";");
1323 out.println(indent + indent + "goto exit;");
1324 out.println(indent + "}");
1325 }
1326
1327 out.println(nullAllowedIndent + indent + "if (" + offset +
1328 " < 0) {");
1329 out.println(nullAllowedIndent + indent + indent +
1330 "_exception = 1;");
1331 out.println(nullAllowedIndent + indent + indent +
1332 "_exceptionType = " +
1333 "\"java/lang/IllegalArgumentException\";");
1334 out.println(nullAllowedIndent + indent + indent +
1335 "_exceptionMessage = \"" + offset +" < 0\";");
1336 out.println(nullAllowedIndent + indent + indent +
1337 "goto exit;");
1338 out.println(nullAllowedIndent + indent + "}");
1339
1340 out.println(nullAllowedIndent + indent + remaining + " = " +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001341 (mUseCPlusPlus ? "_env" : "(*_env)") +
1342 "->GetArrayLength(" +
1343 (mUseCPlusPlus ? "" : "_env, ") +
1344 cname + "_ref) - " + offset + ";");
1345 emitNativeBoundsChecks(cfunc, cname, out, false,
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001346 emitExceptionCheck, offset, remaining,
1347 nullAllowedIndent + indent);
1348 out.println(nullAllowedIndent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001349 jfunc.getArgName(idx) + " = new " +
1350 cfunc.getArgType(cIndex).getBaseType() +
1351 "["+ remaining + "];");
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001352
1353 if (nullAllowed) {
1354 out.println(indent + "}");
1355 }
1356
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001357 out.println();
1358 } else if (jfunc.getArgType(idx).isBuffer()) {
Romain Guy79699992016-12-05 12:26:42 -08001359 needsExit = needsExit || (!nullAllowed && !isPointerFunc);
1360
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001361 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001362 "_" + cfunc.getArgName(cIndex) + "Array";
1363 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1364 "_" + cfunc.getArgName(cIndex) + "BufferOffset";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001365
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001366 nullAllowed = nullAllowed || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001367 if (nullAllowed) {
1368 out.println(indent + "if (" + cname + "_buf) {");
1369 out.print(indent);
1370 }
Romain Guy79699992016-12-05 12:26:42 -08001371 else
1372 {
1373 out.println(indent + "if (!" + cname + "_buf) {");
1374 out.println(indent + indent + "_exception = 1;");
1375 out.println(indent + indent + "_exceptionType = " +
1376 "\"java/lang/IllegalArgumentException\";");
1377 out.println(indent + indent + "_exceptionMessage = \"" +
1378 cname +" == null\";");
1379 out.println(indent + indent + "goto exit;");
1380 out.println(indent + "}");
1381 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001382
Jack Palevich46d25a32009-05-07 18:28:29 -07001383 if (isPointerFunc) {
1384 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001385 cname +
1386 " = (" +
1387 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -07001388 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -07001389 cname + "_buf);");
1390 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -07001391 out.println(iii + indent + "if ( ! " + cname + " ) {");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001392 out.println(iii + indent + indent + "return;");
Jack Palevich46d25a32009-05-07 18:28:29 -07001393 out.println(iii + indent + "}");
1394 } else {
1395 out.println(indent +
1396 cname +
1397 " = (" +
1398 cfunc.getArgType(cIndex).getDeclaration() +
1399 ")getPointer(_env, " +
1400 cname +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001401 "_buf, (jarray*)&" + array + ", &" + remaining + ", &" + bufferOffset +
Jack Palevich46d25a32009-05-07 18:28:29 -07001402 ");");
1403 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001404
Jack Palevich5afdc872009-10-21 11:02:44 -07001405 emitNativeBoundsChecks(cfunc, cname, out, true,
1406 emitExceptionCheck,
1407 offset, remaining, nullAllowed ? " " : " ");
1408
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001409 if (nullAllowed) {
1410 out.println(indent + "}");
1411 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001412 }
1413 }
1414 }
1415
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001416 // Emit 'GetPrimitiveArrayCritical' for pointers if needed
1417 if (nonPrimitiveArgs.size() > 0) {
1418 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
1419 int idx = nonPrimitiveArgs.get(i).intValue();
1420 int cIndex = jfunc.getArgCIndex(idx);
1421
1422 if(!jfunc.getArgType(idx).isBuffer() || isPointerFunc) continue;
1423
1424 String cname = cfunc.getArgName(cIndex);
1425 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1426 "_" + cname + "BufferOffset";
1427 String array = numBufferArgs <= 1 ? "_array" :
1428 "_" + cfunc.getArgName(cIndex) + "Array";
1429
Pablo Ceballosb62e2422015-10-01 18:25:56 -07001430 boolean nullAllowed = isNullAllowed(cfunc, cname) ||
1431 isPointerFunc;
Thomas Tafertshofer36b285e2012-07-23 16:52:32 -07001432 if (nullAllowed) {
1433 out.println(indent + "if (" + cname + "_buf && " + cname +" == NULL) {");
1434 } else {
1435 out.println(indent + "if (" + cname +" == NULL) {");
1436 }
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001437 JType argType = jfunc.getArgType(idx);
1438 if (argType.isTypedBuffer()) {
1439 String arrayGetter = argType.getArrayTypeForTypedBuffer().getArrayGetterForPrimitiveArray();
1440 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->" + arrayGetter + "(" + array + ", (jboolean *) 0);");
1441 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1442 out.println(indent + "}");
1443 } else {
1444 out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->GetPrimitiveArrayCritical(" + array + ", (jboolean *) 0);");
1445 out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
1446 out.println(indent + "}");
1447 }
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001448 }
1449 }
1450
1451
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001452 if (!isVoid) {
1453 out.print(indent + "_returnValue = ");
1454 } else {
1455 out.print(indent);
1456 }
1457 String name = cfunc.getName();
1458
1459 if (mUseContextPointer) {
1460 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1461 name = name.substring(0, 1).toLowerCase() +
1462 name.substring(1, name.length());
1463 out.print("ctx->procs.");
1464 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001465
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001466 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1467
Jack Palevich6cbca502009-04-13 16:22:25 -07001468 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001469 if (numArgs == 0) {
1470 if (mUseContextPointer) {
1471 out.println("ctx);");
1472 } else {
1473 out.println(");");
1474 }
1475 } else {
1476 if (mUseContextPointer) {
1477 out.println("ctx,");
1478 } else {
1479 out.println();
1480 }
1481 for (int i = 0; i < numArgs; i++) {
1482 String typecast;
Jesse Hall071fc662013-04-10 01:17:34 -07001483 if (i == numArgs - 1 && isPointerOffsetFunc) {
Ashok Bhatd8f09612014-02-15 12:51:43 +00001484 typecast = "reinterpret_cast<GLvoid *>";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001485 } else {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001486 typecast = "(" + cfunc.getArgType(i).getDeclaration() + ")";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001487 }
1488 out.print(indent + indent +
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001489 typecast);
1490
Jack Palevich50d0b142009-11-19 16:34:55 +08001491 if (cfunc.getArgType(i).isConstCharPointer()) {
1492 out.print("_native");
1493 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001494
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001495 if (cfunc.getArgType(i).isEGLHandle() &&
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001496 !cfunc.getArgType(i).isPointer()){
1497 out.print(cfunc.getArgName(i)+"_native");
Ashok Bhatd8f09612014-02-15 12:51:43 +00001498 } else if (i == numArgs - 1 && isPointerOffsetFunc){
1499 out.print("("+cfunc.getArgName(i)+")");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001500 } else {
1501 out.print(cfunc.getArgName(i));
1502 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001503
1504 if (i == numArgs - 1) {
1505 if (isPointerFunc) {
1506 out.println(",");
1507 out.println(indent + indent + "(GLsizei)remaining");
1508 } else {
1509 out.println();
1510 }
1511 } else {
1512 out.println(",");
1513 }
1514 }
1515 out.println(indent + ");");
1516 }
1517
1518 if (needsExit) {
1519 out.println();
1520 out.println("exit:");
1521 needsExit = false;
1522 }
1523
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001524
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001525 if (nonPrimitiveArgs.size() > 0) {
1526 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1527 int idx = nonPrimitiveArgs.get(i).intValue();
1528
1529 int cIndex = jfunc.getArgCIndex(idx);
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001530 if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001531
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001532 // If the argument is 'const', GL will not write to it.
1533 // In this case, we can use the 'JNI_ABORT' flag to avoid
1534 // the need to write back to the Java array
1535 out.println(indent +
1536 "if (" + jfunc.getArgName(idx) + "_base) {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001537 String arrayReleaser = jfunc.getArgType(idx).getArrayReleaserForPrimitiveArray();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001538 out.println(indent + indent +
1539 (mUseCPlusPlus ? "_env" : "(*_env)") +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001540 "->" + arrayReleaser + "(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001541 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001542 jfunc.getArgName(idx) + "_ref, " +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001543 "(j" + jfunc.getArgType(idx).getBaseType() + "*)" + cfunc.getArgName(cIndex) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001544 "_base,");
1545 out.println(indent + indent + indent +
1546 (cfunc.getArgType(cIndex).isConst() ?
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001547 "JNI_ABORT" : "_exception ? JNI_ABORT: 0" ) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001548 ");");
1549 out.println(indent + "}");
1550 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001551 if (! isPointerFunc) {
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001552 JType argType = jfunc.getArgType(idx);
Jack Palevich46d25a32009-05-07 18:28:29 -07001553 String array = numBufferArgs <= 1 ? "_array" :
Thomas Tafertshofere58a97b2012-07-12 11:16:20 -07001554 "_" + cfunc.getArgName(cIndex) + "Array";
Jack Palevich46d25a32009-05-07 18:28:29 -07001555 out.println(indent + "if (" + array + ") {");
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001556 if (argType.isTypedBuffer()) {
1557 String arrayReleaser =
1558 argType.getArrayTypeForTypedBuffer().getArrayReleaserForPrimitiveArray();
1559 out.println(indent + indent +
1560 "_env->" + arrayReleaser + "(" + array + ", " +
1561 "(j" + argType.getArrayTypeForTypedBuffer().getBaseType() + "*)" +
1562 cfunc.getArgName(cIndex) +
1563 ", " +
1564 (cfunc.getArgType(cIndex).isConst() ?
1565 "JNI_ABORT" : (emitExceptionCheck ?
1566 "_exception ? JNI_ABORT : 0" : "0")) +
1567 ");");
1568 } else {
Adam Bodnara7ab5c72020-07-08 15:35:06 -07001569 String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
1570 "_" + cfunc.getArgName(cIndex) + "BufferOffset";
1571 String typeCast = "(char *)" + cfunc.getArgName(cIndex);
1572 String withOffset = "(void *)(" + typeCast + " - " + bufferOffset + ")";
1573 String releasePointerCall = (
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001574 "releasePointer(_env, " + array + ", " +
Adam Bodnara7ab5c72020-07-08 15:35:06 -07001575 withOffset +
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001576 ", " +
1577 (cfunc.getArgType(cIndex).isConst() ?
1578 "JNI_FALSE" : (emitExceptionCheck ?
1579 "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
1580 ");");
Adam Bodnara7ab5c72020-07-08 15:35:06 -07001581 out.println(formatFunctionCall(indent + indent, releasePointerCall));
Hiroshi Yamauchi569bc1b2015-05-13 13:11:30 -07001582 }
Jack Palevich46d25a32009-05-07 18:28:29 -07001583 out.println(indent + "}");
1584 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001585 }
1586 }
1587 }
1588
Jack Palevich50d0b142009-11-19 16:34:55 +08001589 // Emit local variable declaration for strings
1590 if (stringArgs.size() > 0) {
1591 for (int i = 0; i < stringArgs.size(); i++) {
1592 int idx = stringArgs.get(i).intValue();
1593 int cIndex = jfunc.getArgCIndex(idx);
1594 String cname = cfunc.getArgName(cIndex);
1595
1596 out.println(indent + "if (_native" + cname + ") {");
1597 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1598 out.println(indent + "}");
1599 }
1600
1601 out.println();
1602 }
1603
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001604 // Copy results back to java arrays
1605 if (nonPrimitiveArgs.size() > 0) {
1606 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1607 int idx = nonPrimitiveArgs.get(i).intValue();
1608 int cIndex = jfunc.getArgCIndex(idx);
1609 String baseType = cfunc.getArgType(cIndex).getBaseType().toLowerCase();
1610 if (jfunc.getArgType(idx).isArray() && jfunc.getArgType(idx).isClass()) {
1611 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
1612 "_" + cfunc.getArgName(cIndex) + "Remaining";
1613 offset = numArrays <= 1 ? "offset" : cfunc.getArgName(cIndex) + "Offset";
1614 out.println(indent +
1615 "if (" + jfunc.getArgName(idx) + ") {");
1616 out.println(indent + indent +
1617 "for (int i = 0; i < " + remaining + "; i++) {");
1618 out.println(indent + indent + indent +
1619 "jobject " + cfunc.getArgName(cIndex) +
1620 "_new = toEGLHandle(_env, " + baseType +
1621 "Class, " + baseType + "Constructor, " +
1622 cfunc.getArgName(cIndex) + "[i]);");
1623 out.println(indent + indent + indent +
1624 (mUseCPlusPlus ? "_env" : "(*_env)") +
1625 "->SetObjectArrayElement(" +
1626 (mUseCPlusPlus ? "" : "_env, ") +
1627 cfunc.getArgName(cIndex) +
1628 "_ref, i + " + offset + ", " +
1629 cfunc.getArgName(cIndex) + "_new);");
1630 out.println(indent + indent + "}");
1631 out.println(indent + indent +
1632 "delete[] " + jfunc.getArgName(idx) + ";");
1633 out.println(indent + "}");
1634 }
1635 }
1636 }
1637
1638
1639 // Throw exception if there is one
1640 if (emitExceptionCheck) {
1641 out.println(indent + "if (_exception) {");
1642 out.println(indent + indent +
1643 "jniThrowException(_env, _exceptionType, _exceptionMessage);");
Orion Hodson91f564d2019-02-26 16:57:18 +00001644 if (!isVoid) {
1645 if (cfunc.getType().isEGLHandle()) {
1646 String baseType = cfunc.getType().getBaseType().toLowerCase();
1647 out.println(indent + indent + "return nullptr;");
1648 } else {
1649 out.println(indent + indent + "return " +
1650 getJniDefaultReturn(jfunc.getType()) + ";");
1651 }
1652 }
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001653
Orion Hodson91f564d2019-02-26 16:57:18 +00001654 out.println(indent + "}");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001655 }
1656
Jack Palevich50d0b142009-11-19 16:34:55 +08001657
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001658 if (!isVoid) {
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001659 if (cfunc.getType().isEGLHandle()) {
1660 String baseType = cfunc.getType().getBaseType().toLowerCase();
1661 out.println(indent +
1662 "return toEGLHandle(_env, " + baseType + "Class, " +
1663 baseType + "Constructor, _returnValue);");
1664 } else {
Jesse Hall68fc8bb2013-04-10 01:01:00 -07001665 out.println(indent + "return (" +
1666 getJniType(jfunc.getType()) + ")_returnValue;");
Thomas Tafertshofer66a42db2012-06-15 16:22:43 -07001667 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001668 }
1669
1670 out.println("}");
1671 out.println();
1672 }
1673
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001674}