replicant-frameworks_native/opengl/tools/glgen/src/JniCodeEmitter.java

1181 lines
45 KiB
Java
Raw Normal View History

Add correct copyright headers to multiple files Format for the list of changes shows the origin commit reference followed by the file name. 33931-p9 awt/org/apache/harmony/awt/gl/font/AndroidGlyphVector.java 33931-p9 awt/org/apache/harmony/awt/gl/image/PngDecoderJava.java 133776-p9 core/java/android/app/IntentService.java 127013-p9 core/java/android/appwidget/AppWidgetHost.java 27863-p9 core/java/android/bluetooth/BluetoothAudioGateway.java 60765-p9 core/java/android/content/SyncResult.java 43920-p9 core/java/android/content/pm/ActivityInfo.java 43920-p9 core/java/android/content/pm/ApplicationInfo.java 43920-p9 core/java/android/content/pm/InstrumentationInfo.java 43920-p9 core/java/android/content/pm/PackageInfo.java 44103-p9 core/java/android/content/pm/PackageItemInfo.java 68960-p9 core/java/android/content/pm/PackageStats.java 43920-p9 core/java/android/content/pm/ResolveInfo.java 43920-p9 core/java/android/content/pm/ServiceInfo.java 60641-p9 core/java/android/content/res/Configuration.java 60734-p9 core/java/android/content/res/TypedArray.java 137672-p9 core/java/android/inputmethodservice/ExtractButton.java 123112-p9 core/java/android/inputmethodservice/ExtractEditText.java 119291-p9 core/java/android/inputmethodservice/IInputMethodSessionWrapper.java 112946-p9 core/java/android/inputmethodservice/IInputMethodWrapper.java 115078-p9 core/java/android/os/BatteryStats.java 124790-p9 core/java/android/text/style/UpdateAppearance.java 45083-p9 core/java/android/view/RawInputEvent.java 101491-p9 core/java/android/view/inputmethod/EditorInfo.java 114701-p9 core/java/android/view/inputmethod/ExtractedText.java 123112-p9 core/java/android/view/inputmethod/ExtractedTextRequest.java 119291-p9 core/java/com/android/internal/os/HandlerCaller.java 129279-p9 core/java/com/android/internal/os/PkgUsageStats.java 114701-p9 core/java/com/android/internal/view/IInputConnectionWrapper.java 114701-p9 core/java/com/android/internal/view/InputConnectionWrapper.java 84364-p9 opengl/java/android/opengl/EGLLogWrapper.java 11355-p9 opengl/tools/glgen/src/CFunc.java 11355-p9 opengl/tools/glgen/src/CType.java 11355-p9 opengl/tools/glgen/src/CodeEmitter.java 11355-p9 opengl/tools/glgen/src/GenerateGL.java 11355-p9 opengl/tools/glgen/src/JFunc.java 11355-p9 opengl/tools/glgen/src/JType.java 11355-p9 opengl/tools/glgen/src/JniCodeEmitter.java 11355-p9 opengl/tools/glgen/src/ParameterChecker.java 57236-p9 services/java/com/android/server/status/AnimatedImageView.java 66754-p9 services/java/com/android/server/status/CloseDragHandle.java 57188-p9 services/java/com/android/server/status/DateView.java 46928-p9 services/java/com/android/server/status/ExpandedView.java 70590-p9 services/java/com/android/server/status/FixedSizeDrawable.java 45968-p9 services/java/com/android/server/status/IconData.java 57470-p9 services/java/com/android/server/status/IconMerger.java 82719-p9 services/java/com/android/server/status/LatestItemView.java 45968-p9 services/java/com/android/server/status/NotificationData.java 66754-p9 services/java/com/android/server/status/NotificationLinearLayout.java 57458-p9 services/java/com/android/server/status/NotificationViewList.java 45968-p9 services/java/com/android/server/status/StatusBarException.java 45968-p9 services/java/com/android/server/status/StatusBarIcon.java 46130-p9 services/java/com/android/server/status/StatusBarNotification.java 45968-p9 services/java/com/android/server/status/StatusBarView.java 46199-p9 services/java/com/android/server/status/Ticker.java 62286-p9 services/java/com/android/server/status/TickerView.java 57188-p9 services/java/com/android/server/status/TrackingView.java 86041-p9 telephony/java/android/telephony/PhoneStateListener.java 87020-p9 telephony/java/com/android/internal/telephony/TelephonyIntents.java 136269-p9 telephony/java/com/android/internal/telephony/gsm/SpnOverride.java 34409-p9 tests/FrameworkTest/src/com/android/frameworktest/FrameworkTestApplication.java 55717-p9 tests/FrameworkTest/src/com/android/frameworktest/performance/InvalidateCycle.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java 129372-p9 tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScan.java 129372-p9 tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResize.java 129372-p9 tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScan.java 129372-p9 tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollableResize.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityPanScan.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityResize.java 127341-p9 tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java 129347-p9 tests/ImfTest/src/com/android/imftest/samples/DialogActivity.java 129372-p9 tests/ImfTest/src/com/android/imftest/samples/EditTextActivityDialog.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScan.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScan.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollResize.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivityNotSelected.java 128994-p9 tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivitySelected.java 25959-p9 tests/framework-tests/src/android/test/FrameworkTests.java 46162-p9 tests/framework-tests/src/com/android/internal/http/multipart/MultipartTest.java 77101-p9 tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java 9788976b1465ce982b5ae7c741345edd0ecd9322 core/java/android/accounts/AuthenticatorDescription.java 53332883543868fb83e111a07306368b7772b340 core/java/android/app/UiModeManager.java 93e7e22ec91dbc641d10ca6d70423e1357a95bba core/java/android/app/FullBackupAgent.java 328c0e7986aa6bb7752ec6de3da9c999920bb55f core/java/android/content/CursorEntityIterator.java 307da1a46b4c9b711bafe8fbaaa6b98e8868c18e core/java/android/content/SyncQueue.java 307da1a46b4c9b711bafe8fbaaa6b98e8868c18e core/java/android/content/SyncOperation.java eb034652c2037a47ebfd99779e8383bb8bb528af core/java/android/content/pm/LabeledIntent.java 49237345d83e62fdb9eb8d50b13ad086636a04fa core/java/android/content/pm/FeatureInfo.java a2b6c3775ed6b8924232d6a01bae4a19740a15f8 core/java/android/content/pm/PackageInfoLite.java 3ecd5f437580e49d80beecd29489d5fb1f7a7db0 core/java/android/content/pm/RegisteredServicesCacheListener.java 5ebbb4a6b3e16f711735ae0615b9a9ea64faad38 core/java/android/content/pm/XmlSerializerAndParser.java c4516a7b62de525e3d6d5e76851bdfaf12c11f05 core/java/android/database/sqlite/SQLiteTransactionListener.java 9bbc21a773cbdfbef2876a75c32bda5839647751 core/java/com/android/internal/backup/LocalTransport.java 21f1bd17b2dfe361acbb28453b3f3b1a110932fa core/java/com/android/internal/content/PackageMonitor.java 4c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3 core/java/com/android/internal/view/BaseSurfaceHolder.java 4c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3 core/java/com/android/internal/view/BaseIWindow.java e540833fdff4d58e37c9ba859388e24e2945ed45 core/java/com/android/internal/os/SamplingProfilerIntegration.java 192ab903887bbb8e7c7b6da5c581573850e30f46 core/tests/coretests/src/android/widget/expandablelistview/PositionTesterContextMenuListener.java 1619367ab823150fa8856d419abe02ceb75886f1 media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java 27f8002e591b5c579f75b2580183b5d1c4219cd4 opengl/tools/glgen/stubs/gles11/glGetString.java 560814f6b11abe83ff0c4ed18cac015c276b3181 opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.java 560814f6b11abe83ff0c4ed18cac015c276b3181 opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.java 560814f6b11abe83ff0c4ed18cac015c276b3181 opengl/tools/glgen/stubs/gles11/glShaderSource.java 1c4907ee77392afb768c2f088e0dedbe4239f6fb opengl/tools/glgen/src/GenerateGLES.java 1c4907ee77392afb768c2f088e0dedbe4239f6fb opengl/tools/glgen/src/Jsr239CodeEmitter.java 1c4907ee77392afb768c2f088e0dedbe4239f6fb opengl/tools/glgen/src/GLESCodeEmitter.java 69e21f5f6e0d04539cd92848ea009dd615d88c2c opengl/tests/gldual/src/com/android/gldual/TriangleRenderer.java c028be4f3b8c7476b46859f66c3f33d528adf181 packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java 7c6efa13f129dbae5319f0981a430d4662f43354 tests/BrowserPowerTest/src/com/android/browserpowertest/PowerMeasurement.java 7c6efa13f129dbae5319f0981a430d4662f43354 tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java 7c6efa13f129dbae5319f0981a430d4662f43354 tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestRunner.java df8a3f31d871db25e952972c2eb346a71186e9e3 tests/BrowserTestPlugin/src/com/android/testplugin/TestPlugin.java cfaef699e1dfb3a75d5b51f3b15816f13670fd51 tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java cfaef699e1dfb3a75d5b51f3b15816f13670fd51 tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java cfaef699e1dfb3a75d5b51f3b15816f13670fd51 tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java Copyright header moved to top in following file: core/tests/coretests/src/android/widget/ListViewTest.java Change-Id: I3c3198be5a0ba36e18679ed834170432bf0b8418
2010-03-12 02:20:12 +00:00
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
public class JniCodeEmitter {
static final boolean mUseCPlusPlus = true;
protected boolean mUseContextPointer = true;
protected boolean mUseStaticMethods = false;
protected String mClassPathName;
protected ParameterChecker mChecker;
protected List<String> nativeRegistrations = new ArrayList<String>();
boolean needsExit;
protected static String indent = " ";
HashSet<String> mFunctionsEmitted = new HashSet<String>();
public static String getJniName(JType jType) {
String jniName = "";
if (jType.isClass()) {
return "L" + jType.getBaseType() + ";";
} else if (jType.isArray()) {
jniName = "[";
}
String baseType = jType.getBaseType();
if (baseType.equals("int")) {
jniName += "I";
} else if (baseType.equals("float")) {
jniName += "F";
} else if (baseType.equals("boolean")) {
jniName += "Z";
} else if (baseType.equals("short")) {
jniName += "S";
} else if (baseType.equals("long")) {
jniName += "L";
} else if (baseType.equals("byte")) {
jniName += "B";
} else if (baseType.equals("String")) {
jniName += "Ljava/lang/String;";
} else if (baseType.equals("void")) {
// nothing.
} else {
throw new RuntimeException("Unknown primitive basetype " + baseType);
}
return jniName;
}
public void emitCode(CFunc cfunc, String original,
PrintStream javaInterfaceStream,
PrintStream javaImplStream,
PrintStream cStream) {
JFunc jfunc;
String signature;
boolean duplicate;
if (cfunc.hasTypedPointerArg()) {
jfunc = JFunc.convert(cfunc, true);
// Don't emit duplicate functions
// These may appear because they are defined in multiple
// Java interfaces (e.g., GL11/GL11ExtensionPack)
signature = jfunc.toString();
duplicate = false;
if (mFunctionsEmitted.contains(signature)) {
duplicate = true;
} else {
mFunctionsEmitted.add(signature);
}
if (!duplicate) {
emitNativeDeclaration(jfunc, javaImplStream);
emitJavaCode(jfunc, javaImplStream);
}
if (javaInterfaceStream != null) {
emitJavaInterfaceCode(jfunc, javaInterfaceStream);
}
if (!duplicate) {
emitJniCode(jfunc, cStream);
}
}
jfunc = JFunc.convert(cfunc, false);
signature = jfunc.toString();
duplicate = false;
if (mFunctionsEmitted.contains(signature)) {
duplicate = true;
} else {
mFunctionsEmitted.add(signature);
}
if (!duplicate) {
emitNativeDeclaration(jfunc, javaImplStream);
}
if (javaInterfaceStream != null) {
emitJavaInterfaceCode(jfunc, javaInterfaceStream);
}
if (!duplicate) {
emitJavaCode(jfunc, javaImplStream);
emitJniCode(jfunc, cStream);
}
}
public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
out.println(" // C function " + jfunc.getCFunc().getOriginal());
out.println();
emitFunction(jfunc, out, true, false);
}
public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
emitFunction(jfunc, out, false, true);
}
public void emitJavaCode(JFunc jfunc, PrintStream out) {
emitFunction(jfunc, out, false, false);
}
boolean isPointerFunc(JFunc jfunc) {
String name = jfunc.getName();
return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
&& jfunc.getCFunc().hasPointerArg();
}
void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
boolean isVoid = jfunc.getType().isVoid();
boolean isPointerFunc = isPointerFunc(jfunc);
if (!isVoid) {
out.println(iii +
jfunc.getType() + " _returnValue;");
}
out.println(iii +
(isVoid ? "" : "_returnValue = ") +
jfunc.getName() +
(isPointerFunc ? "Bounds" : "" ) +
"(");
int numArgs = jfunc.getNumArgs();
for (int i = 0; i < numArgs; i++) {
String argName = jfunc.getArgName(i);
JType argType = jfunc.getArgType(i);
if (grabArray && argType.isTypedBuffer()) {
String typeName = argType.getBaseType();
typeName = typeName.substring(9, typeName.length() - 6);
out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
out.print(iii + indent + "getOffset(" + argName + ")");
} else {
out.print(iii + indent + argName);
}
if (i == numArgs - 1) {
if (isPointerFunc) {
out.println(",");
out.println(iii + indent + argName + ".remaining()");
} else {
out.println();
}
} else {
out.println(",");
}
}
out.println(iii + ");");
}
void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
String iii) {
printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
"offset", "_remaining", iii);
}
void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
String offset, String remaining, String iii) {
out.println(iii + " default:");
out.println(iii + " _needed = 0;");
out.println(iii + " break;");
out.println(iii + "}");
out.println(iii + "if (" + remaining + " < _needed) {");
if (emitExceptionCheck) {
out.println(iii + indent + "_exception = 1;");
}
out.println(iii + indent + "jniThrowException(_env, " +
"\"java/lang/IllegalArgumentException\", " +
"\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < needed\");");
out.println(iii + indent + "goto exit;");
needsExit = true;
out.println(iii + "}");
}
boolean isNullAllowed(CFunc cfunc) {
String[] checks = mChecker.getChecks(cfunc.getName());
int index = 1;
if (checks != null) {
while (index < checks.length) {
if (checks[index].equals("return")) {
index += 2;
} else if (checks[index].startsWith("check")) {
index += 3;
} else if (checks[index].equals("ifcheck")) {
index += 5;
} else if (checks[index].equals("unsupported")) {
index += 1;
2010-01-28 12:28:32 +00:00
} else if (checks[index].equals("requires")) {
index += 2;
} else if (checks[index].equals("nullAllowed")) {
return true;
} else {
System.out.println("Error: unknown keyword \"" +
checks[index] + "\"");
System.exit(0);
}
}
}
return false;
}
String getErrorReturnValue(CFunc cfunc) {
CType returnType = cfunc.getType();
boolean isVoid = returnType.isVoid();
if (isVoid) {
return null;
}
String[] checks = mChecker.getChecks(cfunc.getName());
int index = 1;
if (checks != null) {
while (index < checks.length) {
if (checks[index].equals("return")) {
return checks[index + 1];
} else if (checks[index].startsWith("check")) {
index += 3;
} else if (checks[index].equals("ifcheck")) {
index += 5;
} else if (checks[index].equals("unsupported")) {
index += 1;
2010-01-28 12:28:32 +00:00
} else if (checks[index].equals("requires")) {
index += 2;
} else if (checks[index].equals("nullAllowed")) {
index += 1;
} else {
System.out.println("Error: unknown keyword \"" +
checks[index] + "\"");
System.exit(0);
}
}
}
return null;
}
boolean isUnsupportedFunc(CFunc cfunc) {
String[] checks = mChecker.getChecks(cfunc.getName());
int index = 1;
if (checks != null) {
while (index < checks.length) {
if (checks[index].equals("unsupported")) {
return true;
2010-01-28 12:28:32 +00:00
} else if (checks[index].equals("requires")) {
index += 2;
} else if (checks[index].equals("return")) {
index += 2;
} else if (checks[index].startsWith("check")) {
index += 3;
} else if (checks[index].equals("ifcheck")) {
index += 5;
} else if (checks[index].equals("nullAllowed")) {
index += 1;
} else {
System.out.println("Error: unknown keyword \"" +
checks[index] + "\"");
System.exit(0);
}
}
}
return false;
}
2010-01-28 12:28:32 +00:00
String isRequiresFunc(CFunc cfunc) {
String[] checks = mChecker.getChecks(cfunc.getName());
int index = 1;
if (checks != null) {
while (index < checks.length) {
if (checks[index].equals("unsupported")) {
index += 1;
} else if (checks[index].equals("requires")) {
return checks[index+1];
} else if (checks[index].equals("return")) {
index += 2;
} else if (checks[index].startsWith("check")) {
index += 3;
} else if (checks[index].equals("ifcheck")) {
index += 5;
} else if (checks[index].equals("nullAllowed")) {
index += 1;
} else {
System.out.println("Error: unknown keyword \"" +
checks[index] + "\"");
System.exit(0);
}
}
}
return null;
}
void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
String[] checks = mChecker.getChecks(cfunc.getName());
boolean lastWasIfcheck = false;
int index = 1;
if (checks != null) {
while (index < checks.length) {
if (checks[index].startsWith("check")) {
if (lastWasIfcheck) {
printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
offset, remaining, iii);
}
lastWasIfcheck = false;
if (cname != null && !cname.equals(checks[index + 1])) {
index += 3;
continue;
}
out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
if (emitExceptionCheck) {
out.println(iii + indent + "_exception = 1;");
}
String exceptionClassName = "java/lang/IllegalArgumentException";
// If the "check" keyword was of the form
// "check_<class name>", use the class name in the
// exception to be thrown
int underscore = checks[index].indexOf('_');
if (underscore >= 0) {
String abbr = checks[index].substring(underscore + 1);
if (abbr.equals("AIOOBE")) {
exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
} else {
throw new RuntimeException("unknown exception abbreviation: " + abbr);
}
}
out.println(iii + indent + "jniThrowException(_env, " +
"\"" + exceptionClassName + "\", " +
"\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < " + checks[index + 2] + "\");");
out.println(iii + indent + "goto exit;");
needsExit = true;
out.println(iii + "}");
index += 3;
} else if (checks[index].equals("ifcheck")) {
String[] matches = checks[index + 4].split(",");
if (!lastWasIfcheck) {
out.println(iii + "int _needed;");
out.println(iii + "switch (" + checks[index + 3] + ") {");
}
for (int i = 0; i < matches.length; i++) {
out.println("#if defined(" + matches[i] + ")");
out.println(iii + " case " + matches[i] + ":");
out.println("#endif // defined(" + matches[i] + ")");
}
out.println(iii + " _needed = " + checks[index + 2] + ";");
out.println(iii + " break;");
lastWasIfcheck = true;
index += 5;
} else if (checks[index].equals("return")) {
// ignore
index += 2;
} else if (checks[index].equals("unsupported")) {
// ignore
index += 1;
} else if (checks[index].equals("requires")) {
// ignore
index += 2;
} else if (checks[index].equals("nullAllowed")) {
// ignore
index += 1;
} else {
System.out.println("Error: unknown keyword \"" + checks[index] + "\"");
System.exit(0);
}
}
}
if (lastWasIfcheck) {
printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
}
}
boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
if (nonPrimitiveArgs.size() > 0) {
for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
int idx = nonPrimitiveArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
if (jfunc.getArgType(idx).isArray()) {
if (!cfunc.getArgType(cIndex).isConst()) {
return true;
}
} else if (jfunc.getArgType(idx).isBuffer()) {
if (!cfunc.getArgType(cIndex).isConst()) {
return true;
}
}
}
}
return false;
}
/**
* Emit a function in several variants:
*
* if nativeDecl: public native <returntype> func(args);
*
* if !nativeDecl:
* if interfaceDecl: public <returntype> func(args);
* if !interfaceDecl: public <returntype> func(args) { body }
*/
void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
boolean isPointerFunc = isPointerFunc(jfunc);
if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
// If it's not a pointer function, we've already emitted it
// with nativeDecl == true
return;
}
String maybeStatic = mUseStaticMethods ? "static " : "";
if (isPointerFunc) {
out.println(indent +
(nativeDecl ? "private " + maybeStatic +"native " :
(interfaceDecl ? "" : "public ") + maybeStatic) +
jfunc.getType() + " " +
jfunc.getName() +
(nativeDecl ? "Bounds" : "") +
"(");
} else {
out.println(indent +
(nativeDecl ? "public " + maybeStatic +"native " :
(interfaceDecl ? "" : "public ") + maybeStatic) +
jfunc.getType() + " " +
jfunc.getName() +
"(");
}
int numArgs = jfunc.getNumArgs();
for (int i = 0; i < numArgs; i++) {
String argName = jfunc.getArgName(i);
JType argType = jfunc.getArgType(i);
out.print(indent + indent + argType + " " + argName);
if (i == numArgs - 1) {
if (isPointerFunc && nativeDecl) {
out.println(",");
out.println(indent + indent + "int remaining");
} else {
out.println();
}
} else {
out.println(",");
}
}
if (nativeDecl || interfaceDecl) {
out.println(indent + ");");
} else {
out.println(indent + ") {");
String iii = indent + indent;
// emitBoundsChecks(jfunc, out, iii);
emitFunctionCall(jfunc, out, iii, false);
// Set the pointer after we call the native code, so that if
// the native code throws an exception we don't modify the
// pointer. We assume that the native code is written so that
// if an exception is thrown, then the underlying glXXXPointer
// function will not have been called.
String fname = jfunc.getName();
if (isPointerFunc) {
// TODO - deal with VBO variants
if (fname.equals("glColorPointer")) {
out.println(iii + "if ((size == 4) &&");
out.println(iii + " ((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_colorPointer = pointer;");
out.println(iii + "}");
} else if (fname.equals("glNormalPointer")) {
out.println(iii + "if (((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_BYTE) ||");
out.println(iii + " (type == GL_SHORT) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_normalPointer = pointer;");
out.println(iii + "}");
} else if (fname.equals("glTexCoordPointer")) {
out.println(iii + "if (((size == 2) ||");
out.println(iii + " (size == 3) ||");
out.println(iii + " (size == 4)) &&");
out.println(iii + " ((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_BYTE) ||");
out.println(iii + " (type == GL_SHORT) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_texCoordPointer = pointer;");
out.println(iii + "}");
} else if (fname.equals("glVertexPointer")) {
out.println(iii + "if (((size == 2) ||");
out.println(iii + " (size == 3) ||");
out.println(iii + " (size == 4)) &&");
out.println(iii + " ((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_BYTE) ||");
out.println(iii + " (type == GL_SHORT) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_vertexPointer = pointer;");
out.println(iii + "}");
} else if (fname.equals("glPointSizePointerOES")) {
out.println(iii + "if (((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_pointSizePointerOES = pointer;");
out.println(iii + "}");
} else if (fname.equals("glMatrixIndexPointerOES")) {
out.println(iii + "if (((size == 2) ||");
out.println(iii + " (size == 3) ||");
out.println(iii + " (size == 4)) &&");
out.println(iii + " ((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_BYTE) ||");
out.println(iii + " (type == GL_SHORT) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
out.println(iii + "}");
} else if (fname.equals("glWeightPointer")) {
out.println(iii + "if (((size == 2) ||");
out.println(iii + " (size == 3) ||");
out.println(iii + " (size == 4)) &&");
out.println(iii + " ((type == GL_FLOAT) ||");
out.println(iii + " (type == GL_BYTE) ||");
out.println(iii + " (type == GL_SHORT) ||");
out.println(iii + " (type == GL_FIXED)) &&");
out.println(iii + " (stride >= 0)) {");
out.println(iii + indent + "_weightPointerOES = pointer;");
out.println(iii + "}");
}
}
boolean isVoid = jfunc.getType().isVoid();
if (!isVoid) {
out.println(indent + indent + "return _returnValue;");
}
out.println(indent + "}");
}
out.println();
}
public void addNativeRegistration(String s) {
nativeRegistrations.add(s);
}
public void emitNativeRegistration(String registrationFunctionName,
PrintStream cStream) {
cStream.println("static const char *classPathName = \"" +
mClassPathName +
"\";");
cStream.println();
cStream.println("static JNINativeMethod methods[] = {");
cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
Iterator<String> i = nativeRegistrations.iterator();
while (i.hasNext()) {
cStream.println(i.next());
}
cStream.println("};");
cStream.println();
cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
cStream.println("{");
cStream.println(indent +
"int err;");
cStream.println(indent +
"err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
cStream.println(indent + "return err;");
cStream.println("}");
}
public JniCodeEmitter() {
super();
}
String getJniType(JType jType) {
if (jType.isVoid()) {
return "void";
}
String baseType = jType.getBaseType();
if (jType.isPrimitive()) {
if (baseType.equals("String")) {
return "jstring";
} else {
return "j" + baseType;
}
} else if (jType.isArray()) {
return "j" + baseType + "Array";
} else {
return "jobject";
}
}
String getJniMangledName(String name) {
name = name.replaceAll("_", "_1");
name = name.replaceAll(";", "_2");
name = name.replaceAll("\\[", "_3");
return name;
}
public void emitJniCode(JFunc jfunc, PrintStream out) {
CFunc cfunc = jfunc.getCFunc();
// Emit comment identifying original C function
//
// Example:
//
// /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
//
out.println("/* " + cfunc.getOriginal() + " */");
// Emit JNI signature (name)
//
// Example:
//
// void
// android_glClipPlanef__I_3FI
//
String outName = "android_" + jfunc.getName();
boolean isPointerFunc = isPointerFunc(jfunc);
boolean isVBOPointerFunc = (outName.endsWith("Pointer") ||
outName.endsWith("PointerOES") ||
outName.endsWith("DrawElements") || outName.endsWith("VertexAttribPointer")) &&
!jfunc.getCFunc().hasPointerArg();
if (isPointerFunc) {
outName += "Bounds";
}
out.print("static ");
out.println(getJniType(jfunc.getType()));
out.print(outName);
String rsignature = getJniName(jfunc.getType());
String signature = "";
int numArgs = jfunc.getNumArgs();
for (int i = 0; i < numArgs; i++) {
JType argType = jfunc.getArgType(i);
signature += getJniName(argType);
}
if (isPointerFunc) {
signature += "I";
}
// Append signature to function name
String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
out.print("__" + sig);
outName += "__" + sig;
signature = signature.replace('.', '/');
rsignature = rsignature.replace('.', '/');
out.println();
if (rsignature.length() == 0) {
rsignature = "V";
}
String s = "{\"" +
jfunc.getName() +
(isPointerFunc ? "Bounds" : "") +
"\", \"(" + signature +")" +
rsignature +
"\", (void *) " +
outName +
" },";
nativeRegistrations.add(s);
List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
List<Integer> stringArgs = new ArrayList<Integer>();
int numBufferArgs = 0;
List<String> bufferArgNames = new ArrayList<String>();
// Emit JNI signature (arguments)
//
// Example:
//
// (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
//
out.print(" (JNIEnv *_env, jobject _this");
for (int i = 0; i < numArgs; i++) {
out.print(", ");
JType argType = jfunc.getArgType(i);
String suffix;
if (!argType.isPrimitive()) {
if (argType.isArray()) {
suffix = "_ref";
} else {
suffix = "_buf";
}
nonPrimitiveArgs.add(new Integer(i));
if (jfunc.getArgType(i).isBuffer()) {
int cIndex = jfunc.getArgCIndex(i);
String cname = cfunc.getArgName(cIndex);
bufferArgNames.add(cname);
numBufferArgs++;
}
} else {
suffix = "";
}
if (argType.isString()) {
stringArgs.add(new Integer(i));
}
out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
}
if (isPointerFunc) {
out.print(", jint remaining");
}
out.println(") {");
int numArrays = 0;
int numBuffers = 0;
int numStrings = 0;
for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
int idx = nonPrimitiveArgs.get(i).intValue();
JType argType = jfunc.getArgType(idx);
if (argType.isArray()) {
++numArrays;
}
if (argType.isBuffer()) {
++numBuffers;
}
if (argType.isString()) {
++numStrings;
}
}
// Emit method body
// Emit local variable declarations for _exception and _returnValue
//
// Example:
//
// android::gl::ogles_context_t *ctx;
//
// jint _exception;
// GLenum _returnValue;
//
CType returnType = cfunc.getType();
boolean isVoid = returnType.isVoid();
boolean isUnsupported = isUnsupportedFunc(cfunc);
if (isUnsupported) {
out.println(indent +
"jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
out.println(indent +
" \"" + cfunc.getName() + "\");");
if (!isVoid) {
String retval = getErrorReturnValue(cfunc);
out.println(indent + "return " + retval + ";");
}
out.println("}");
out.println();
return;
}
2010-01-28 12:28:32 +00:00
String requiresExtension = isRequiresFunc(cfunc);
if (requiresExtension != null) {
out.println(indent +
"if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
out.println(indent + indent +
"jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
2010-01-28 12:28:32 +00:00
out.println(indent + indent +
" \"" + cfunc.getName() + "\");");
if (isVoid) {
out.println(indent + indent + " return;");
} else {
String retval = getErrorReturnValue(cfunc);
out.println(indent + indent + " return " + retval + ";");
}
out.println(indent + "}");
}
if (mUseContextPointer) {
out.println(indent +
"android::gl::ogles_context_t *ctx = getContext(_env, _this);");
}
boolean initializeReturnValue = stringArgs.size() > 0;
boolean emitExceptionCheck = (numArrays > 0 || numBuffers > 0 || numStrings > 0) &&
hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs);
// mChecker.getChecks(cfunc.getName()) != null
// Emit an _exeption variable if there will be error checks
if (emitExceptionCheck) {
out.println(indent + "jint _exception = 0;");
}
// Emit a single _array or multiple _XXXArray variables
if (numBufferArgs == 1) {
out.println(indent + "jarray _array = (jarray) 0;");
} else {
for (int i = 0; i < numBufferArgs; i++) {
out.println(indent + "jarray _" + bufferArgNames.get(i) +
"Array = (jarray) 0;");
}
}
if (!isVoid) {
String retval = getErrorReturnValue(cfunc);
if (retval != null) {
out.println(indent + returnType.getDeclaration() +
" _returnValue = " + retval + ";");
} else if (initializeReturnValue) {
out.println(indent + returnType.getDeclaration() +
" _returnValue = 0;");
} else {
out.println(indent + returnType.getDeclaration() +
" _returnValue;");
}
}
// Emit local variable declarations for pointer arguments
//
// Example:
//
// GLfixed *eqn_base;
// GLfixed *eqn;
//
String offset = "offset";
String remaining = "_remaining";
if (nonPrimitiveArgs.size() > 0) {
for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
int idx = nonPrimitiveArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
String cname = cfunc.getArgName(cIndex);
CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
String decl = type.getDeclaration();
if (jfunc.getArgType(idx).isArray()) {
out.println(indent +
decl +
(decl.endsWith("*") ? "" : " ") +
jfunc.getArgName(idx) +
"_base = (" + decl + ") 0;");
}
remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
"_" + cname + "Remaining";
out.println(indent +
"jint " + remaining + ";");
out.println(indent +
decl +
(decl.endsWith("*") ? "" : " ") +
jfunc.getArgName(idx) +
" = (" + decl + ") 0;");
}
out.println();
}
// Emit local variable declaration for strings
if (stringArgs.size() > 0) {
for (int i = 0; i < stringArgs.size(); i++) {
int idx = stringArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
String cname = cfunc.getArgName(cIndex);
out.println(indent + "const char* _native" + cname + " = 0;");
}
out.println();
}
// Null pointer checks and GetStringUTFChars
if (stringArgs.size() > 0) {
for (int i = 0; i < stringArgs.size(); i++) {
int idx = stringArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
String cname = cfunc.getArgName(cIndex);
CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
String decl = type.getDeclaration();
out.println(indent + "if (!" + cname + ") {");
out.println(indent + " jniThrowException(_env, " +
"\"java/lang/IllegalArgumentException\", \"" + cname + " == null\");");
out.println(indent + " goto exit;");
needsExit = true;
out.println(indent + "}");
out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
}
out.println();
}
// Emit 'GetPrimitiveArrayCritical' for arrays
// Emit 'GetPointer' calls for Buffer pointers
int bufArgIdx = 0;
if (nonPrimitiveArgs.size() > 0) {
for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
int idx = nonPrimitiveArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
String cname = cfunc.getArgName(cIndex);
offset = numArrays <= 1 ? "offset" :
cname + "Offset";
remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
"_" + cname + "Remaining";
if (jfunc.getArgType(idx).isArray()) {
out.println(indent +
"if (!" +
cname +
"_ref) {");
if (emitExceptionCheck) {
out.println(indent + indent + "_exception = 1;");
}
out.println(indent + " jniThrowException(_env, " +
"\"java/lang/IllegalArgumentException\", " +
"\"" + cname + " == null\");");
out.println(indent + " goto exit;");
needsExit = true;
out.println(indent + "}");
out.println(indent + "if (" + offset + " < 0) {");
if (emitExceptionCheck) {
out.println(indent + indent + "_exception = 1;");
}
out.println(indent + " jniThrowException(_env, " +
"\"java/lang/IllegalArgumentException\", \"" + offset + " < 0\");");
out.println(indent + " goto exit;");
needsExit = true;
out.println(indent + "}");
out.println(indent + remaining + " = " +
(mUseCPlusPlus ? "_env" : "(*_env)") +
"->GetArrayLength(" +
(mUseCPlusPlus ? "" : "_env, ") +
cname + "_ref) - " + offset + ";");
emitNativeBoundsChecks(cfunc, cname, out, false,
emitExceptionCheck,
offset, remaining, " ");
out.println(indent +
cname +
"_base = (" +
cfunc.getArgType(cIndex).getDeclaration() +
")");
out.println(indent + " " +
(mUseCPlusPlus ? "_env" : "(*_env)") +
"->GetPrimitiveArrayCritical(" +
(mUseCPlusPlus ? "" : "_env, ") +
jfunc.getArgName(idx) +
"_ref, (jboolean *)0);");
out.println(indent +
cname + " = " + cname + "_base + " + offset +
";");
out.println();
} else {
String array = numBufferArgs <= 1 ? "_array" :
"_" + bufferArgNames.get(bufArgIdx++) + "Array";
boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
if (nullAllowed) {
out.println(indent + "if (" + cname + "_buf) {");
out.print(indent);
}
if (isPointerFunc) {
out.println(indent +
cname +
" = (" +
cfunc.getArgType(cIndex).getDeclaration() +
") getDirectBufferPointer(_env, " +
cname + "_buf);");
String iii = " ";
out.println(iii + indent + "if ( ! " + cname + " ) {");
out.println(iii + iii + indent + "return;");
out.println(iii + indent + "}");
} else {
out.println(indent +
cname +
" = (" +
cfunc.getArgType(cIndex).getDeclaration() +
")getPointer(_env, " +
cname +
"_buf, &" + array + ", &" + remaining +
");");
}
emitNativeBoundsChecks(cfunc, cname, out, true,
emitExceptionCheck,
offset, remaining, nullAllowed ? " " : " ");
if (nullAllowed) {
out.println(indent + "}");
}
}
}
}
if (!isVoid) {
out.print(indent + "_returnValue = ");
} else {
out.print(indent);
}
String name = cfunc.getName();
if (mUseContextPointer) {
name = name.substring(2, name.length()); // Strip off 'gl' prefix
name = name.substring(0, 1).toLowerCase() +
name.substring(1, name.length());
out.print("ctx->procs.");
}
out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
numArgs = cfunc.getNumArgs();
if (numArgs == 0) {
if (mUseContextPointer) {
out.println("ctx);");
} else {
out.println(");");
}
} else {
if (mUseContextPointer) {
out.println("ctx,");
} else {
out.println();
}
for (int i = 0; i < numArgs; i++) {
String typecast;
if (i == numArgs - 1 && isVBOPointerFunc) {
typecast = "const GLvoid *";
} else {
typecast = cfunc.getArgType(i).getDeclaration();
}
out.print(indent + indent +
"(" +
typecast +
")");
if (cfunc.getArgType(i).isConstCharPointer()) {
out.print("_native");
}
out.print(cfunc.getArgName(i));
if (i == numArgs - 1) {
if (isPointerFunc) {
out.println(",");
out.println(indent + indent + "(GLsizei)remaining");
} else {
out.println();
}
} else {
out.println(",");
}
}
out.println(indent + ");");
}
if (needsExit) {
out.println();
out.println("exit:");
needsExit = false;
}
bufArgIdx = 0;
if (nonPrimitiveArgs.size() > 0) {
for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
int idx = nonPrimitiveArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
if (jfunc.getArgType(idx).isArray()) {
// If the argument is 'const', GL will not write to it.
// In this case, we can use the 'JNI_ABORT' flag to avoid
// the need to write back to the Java array
out.println(indent +
"if (" + jfunc.getArgName(idx) + "_base) {");
out.println(indent + indent +
(mUseCPlusPlus ? "_env" : "(*_env)") +
"->ReleasePrimitiveArrayCritical(" +
(mUseCPlusPlus ? "" : "_env, ") +
jfunc.getArgName(idx) + "_ref, " +
cfunc.getArgName(cIndex) +
"_base,");
out.println(indent + indent + indent +
(cfunc.getArgType(cIndex).isConst() ?
"JNI_ABORT" :
"_exception ? JNI_ABORT: 0") +
");");
out.println(indent + "}");
} else if (jfunc.getArgType(idx).isBuffer()) {
if (! isPointerFunc) {
String array = numBufferArgs <= 1 ? "_array" :
"_" + bufferArgNames.get(bufArgIdx++) + "Array";
out.println(indent + "if (" + array + ") {");
out.println(indent + indent +
"releasePointer(_env, " + array + ", " +
cfunc.getArgName(cIndex) +
", " +
(cfunc.getArgType(cIndex).isConst() ?
"JNI_FALSE" : "_exception ? JNI_FALSE :" +
" JNI_TRUE") +
");");
out.println(indent + "}");
}
}
}
}
// Emit local variable declaration for strings
if (stringArgs.size() > 0) {
for (int i = 0; i < stringArgs.size(); i++) {
int idx = stringArgs.get(i).intValue();
int cIndex = jfunc.getArgCIndex(idx);
String cname = cfunc.getArgName(cIndex);
out.println(indent + "if (_native" + cname + ") {");
out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
out.println(indent + "}");
}
out.println();
}
if (!isVoid) {
out.println(indent + "return _returnValue;");
}
out.println("}");
out.println();
}
}