JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
NativeSignatureJavaMethodBindingEmitter.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2023 JogAmp Community. All rights reserved.
3 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * - Redistribution of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistribution in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of Sun Microsystems, Inc. or the names of
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use
34 * in the design, construction, operation or maintenance of any nuclear
35 * facility.
36 *
37 * Sun gratefully acknowledges that this software was originally authored
38 * and developed by Kenneth Bradley Russell and Christopher John Kline.
39 */
40
41package com.jogamp.gluegen.opengl.nativesig;
42
43import com.jogamp.gluegen.GlueGenException;
44import com.jogamp.gluegen.JavaMethodBindingEmitter;
45import com.jogamp.gluegen.JavaType;
46import com.jogamp.gluegen.MethodBinding;
47import com.jogamp.gluegen.cgram.types.Type;
48import com.jogamp.gluegen.opengl.GLEmitter;
49import com.jogamp.gluegen.opengl.GLJavaMethodBindingEmitter;
50import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
51
52/** Review: This Package/Class is not used and subject to be deleted. */
54
56 super(methodToWrap);
57 }
58
59 public NativeSignatureJavaMethodBindingEmitter(final ProcAddressJavaMethodBindingEmitter methodToWrap, final GLEmitter emitter, final boolean bufferObjectVariant) {
60 super(methodToWrap, emitter, bufferObjectVariant);
61 }
62
63 public NativeSignatureJavaMethodBindingEmitter(final JavaMethodBindingEmitter methodToWrap, final NativeSignatureEmitter emitter) {
64 super(methodToWrap, false, null, false, false, emitter);
65 }
66
67 @Override
68 protected StringBuilder appendSignature(final StringBuilder buf) {
69 buf.append(getBaseIndentString());
71 return super.appendSignature(buf);
72 }
73
74 protected void appendNativeSignatureAnnotation(final StringBuilder buf) {
75 if (hasModifier(JavaMethodBindingEmitter.NATIVE)) {
76 // Emit everything as a leaf for now
77 // FIXME: make this configurable
78 buf.append("@NativeSignature(\"l");
79 final MethodBinding binding = getBinding();
80 if (callThroughProcAddress) {
81 buf.append("p");
82 }
83 buf.append("(");
84 if (callThroughProcAddress) {
85 buf.append("P");
86 }
87 for (int i = 0; i < binding.getNumArguments(); i++) {
88 appendNativeSignatureElement(buf, binding.getJavaArgumentType(i), binding.getCArgumentType(i), i);
89 }
90 buf.append(")");
91 appendNativeSignatureElement(buf, binding.getJavaReturnType(), binding.getCReturnType(), -1);
92 buf.append("\")");
93 }
94 }
95
96 protected void appendNativeSignatureElement(final StringBuilder buf, final JavaType type, final Type cType, final int index) {
97 if (type.isVoid()) {
98 if (index > 0) {
99 throw new InternalError("Error parsing arguments -- void should not be seen aside from argument 0");
100 }
101 return;
102 }
103
104 if (type.isNIOBuffer()) {
105 buf.append("A");
106 } else if (type.isPrimitiveArray()) {
107 buf.append("MO");
108 } else if (type.isPrimitive()) {
109 final Class<?> clazz = type.getJavaClass();
110 if (clazz == Byte.TYPE) { buf.append("B"); }
111 else if (clazz == Character.TYPE) { buf.append("C"); }
112 else if (clazz == Double.TYPE) { buf.append("D"); }
113 else if (clazz == Float.TYPE) { buf.append("F"); }
114 else if (clazz == Integer.TYPE) { buf.append("I"); }
115 else if (clazz == Long.TYPE) {
116 // See if this is intended to be a pointer at the C level
117 if (cType.isPointer()) {
118 buf.append("A");
119 } else {
120 buf.append("J");
121 }
122 }
123 else if (clazz == Short.TYPE) { buf.append("S"); }
124 else if (clazz == Boolean.TYPE) { buf.append("Z"); }
125 else throw new InternalError("Unhandled primitive type " + clazz);
126 } else if (type.isString()) {
127 buf.append("A");
128 } else {
129 throw new RuntimeException("Type not yet handled: " + type);
130 }
131 }
132
133 @Override
134 protected String getReturnTypeString(final boolean skipArray) {
135 if (isPrivateNativeMethod()) {
136 final JavaType returnType = getBinding().getJavaReturnType();
137 if (returnType.isString() || returnType.isNIOByteBuffer()) {
138 // Treat these as addresses
139 return "long";
140 }
141 }
142 return super.getReturnTypeString(skipArray);
143 }
144
145 @Override
146 protected void emitPreCallSetup(final MethodBinding binding) {
147 super.emitPreCallSetup(binding);
148 for (int i = 0; i < binding.getNumArguments(); i++) {
149 final JavaType type = binding.getJavaArgumentType(i);
150 if (type.isNIOBuffer() && !useNIODirectOnly ) {
151 // Emit declarations for variables holding primitive arrays as type Object
152 // We don't know 100% sure we're going to use these at this point in the code, though
153 unit.emitln(" Object " + getNIOBufferArrayName(i) + " = (_direct ? null : Buffers.getArray(" +
154 getArgumentName(i) + "));");
155 } else if (type.isString()) {
156 unit.emitln(" long " + binding.getArgumentName(i) + "_c_str = BuffersInternal.newCString(" + binding.getArgumentName(i) + ");");
157 }
158 // FIXME: going to need more of these for Buffer[] and String[], at least
159 }
160 }
161
162 protected String getNIOBufferArrayName(final int argNumber) {
163 return "__buffer_array_" + argNumber;
164 }
165
166 @Override
167 protected int appendArguments(final StringBuilder buf) {
168 boolean needComma = false;
169 int numEmitted = 0;
170
171 if (callThroughProcAddress) {
172 if (changeNameAndArguments) {
173 buf.append("long procAddress");
174 ++numEmitted;
175 needComma = true;
176 }
177 }
178
179 if (isPrivateNativeMethod() && binding.hasContainingType()) {
180 if (needComma) {
181 buf.append(", ");
182 }
183
184 // Always emit outgoing "this" argument
185 buf.append("long ");
186 buf.append(javaThisArgumentName());
187 ++numEmitted;
188 needComma = true;
189 }
190
191 for (int i = 0; i < binding.getNumArguments(); i++) {
192 final JavaType type = binding.getJavaArgumentType(i);
193 if (type.isVoid()) {
194 // Make sure this is the only param to the method; if it isn't,
195 // there's something wrong with our parsing of the headers.
196 if (binding.getNumArguments() != 1) {
197 throw new InternalError(
198 "\"void\" argument type found in " +
199 "multi-argument function \"" + binding + "\"");
200 }
201 continue;
202 }
203
204 if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
205 // Don't need to expose these at the Java level
206 continue;
207 }
208
209 if (needComma) {
210 buf.append(", ");
211 }
212
213 if (isPrivateNativeMethod() &&
214 (isForDirectBufferImplementation() && type.isNIOBuffer() ||
215 type.isString())) {
216 // Direct Buffers and Strings go out as longs
217 buf.append("long");
218 // FIXME: will need more tests here to handle other constructs like String and direct Buffer arrays
219 } else {
220 buf.append(erasedTypeString(type, false));
221 }
222 buf.append(" ");
223 buf.append(getArgumentName(i));
224
225 ++numEmitted;
226 needComma = true;
227
228 // Add Buffer and array index offset arguments after each associated argument
229 if (isForIndirectBufferAndArrayImplementation()) {
230 if (type.isNIOBuffer()) {
231 buf.append(", int " + byteOffsetArgName(i));
232 } else if (type.isNIOBufferArray()) {
233 buf.append(", int[] " +
234 byteOffsetArrayArgName(i));
235 }
236 }
237
238 // Add offset argument after each primitive array
239 if (type.isPrimitiveArray()) {
240 buf.append(", int " + offsetArgName(i));
241 }
242 }
243 return numEmitted;
244 }
245
246 @Override
247 protected void emitReturnVariableSetupAndCall(final MethodBinding binding) {
248 unit.emit(" ");
249 final JavaType returnType = binding.getJavaReturnType();
250 boolean needsResultAssignment = false;
251
252 if (!returnType.isVoid()) {
253 if (returnType.isCompoundTypeWrapper() ||
254 returnType.isNIOByteBuffer()) {
255 unit.emitln("final java.nio.ByteBuffer _res;");
256 needsResultAssignment = true;
257 } else if (returnType.isArrayOfCompoundTypeWrappers()) {
258 unit.emitln("final java.nio.ByteBuffer[] _res;");
259 needsResultAssignment = true;
260 } else if (returnType.isString() || returnType.isNIOByteBuffer()) {
261 unit.emit("final ");
262 unit.emit(returnType.toString());
263 unit.emitln(" _res;");
264 needsResultAssignment = true;
265 } else {
266 // Always assign to "_res" variable so we can clean up
267 // outgoing String arguments, for example
268 unit.emit("final ");
269 emitReturnType();
270 unit.emitln(" _res;");
271 needsResultAssignment = true;
272 }
273 }
274
275 if (binding.signatureCanUseIndirectNIO() && !useNIODirectOnly) {
276 // Must generate two calls for this gated on whether the NIO
277 // buffers coming in are all direct or indirect
278 unit.emitln("if (_direct) {");
279 unit.emit (" ");
280 }
281
282 if (needsResultAssignment) {
283 unit.emit(" _res = ");
284 if (returnType.isString()) {
285 unit.emit("BuffersInternal.newJavaString(");
286 } else if (returnType.isNIOByteBuffer()) {
287 unit.emit("BuffersInternal.newDirectByteBuffer(");
288 }
289 } else {
290 unit.emit(" ");
291 if (!returnType.isVoid()) {
292 unit.emit("return ");
293 }
294 }
295
296 if (binding.signatureUsesJavaPrimitiveArrays() &&
297 !binding.signatureCanUseIndirectNIO()) {
298 // FIXME: what happens with a C function of the form
299 // void foo(int* arg0, void* arg1);
300 // ?
301
302 // Only one call being made in this body, going to indirect
303 // buffer / array entry point
304 emitCall(binding);
305 if (returnType.isString() || returnType.isNIOByteBuffer()) {
306 unit.emit(")");
307 }
308 unit.emit(";");
309 unit.emitln();
310 } else {
311 emitCall(binding);
312 if (returnType.isString() || returnType.isNIOByteBuffer()) {
313 unit.emit(")");
314 }
315 unit.emit(";");
316 }
317
318 if (binding.signatureCanUseIndirectNIO() && !useNIODirectOnly) {
319 // Must generate two calls for this gated on whether the NIO
320 // buffers coming in are all direct or indirect
321 unit.emitln();
322 unit.emitln(" } else {");
323 unit.emit (" ");
324 if (needsResultAssignment) {
325 unit.emit(" _res = ");
326 } else {
327 unit.emit(" ");
328 if (!returnType.isVoid()) {
329 unit.emit("return ");
330 }
331 }
332 emitCall(binding);
333 unit.emit(";");
334 unit.emitln();
335 unit.emitln(" }");
336 } else {
337 unit.emitln();
338 }
339 emitPrologueOrEpilogue(epilogue);
340 if (needsResultAssignment) {
341 emitCallResultReturn(binding);
342 }
343 }
344
345 protected int emitCallArguments(final MethodBinding binding, final boolean direct) {
346 // Note that we override this completely because we both need to
347 // move the potential location of the outgoing proc address as
348 // well as change the way we pass out Buffers, arrays, Strings, etc.
349
350 boolean needComma = false;
351 int numArgsEmitted = 0;
352
353 if (callThroughProcAddress) {
354 unit.emit("__addr_");
355 needComma = true;
356 ++numArgsEmitted;
357 }
358
359 if (binding.hasContainingType()) {
360 // Emit this pointer
361 assert(binding.getContainingType().isCompoundTypeWrapper());
362 unit.emit("BuffersInternal.getDirectBufferAddress(");
363 unit.emit("getBuffer()");
364 unit.emit(")");
365 needComma = true;
366 ++numArgsEmitted;
367 }
368 for (int i = 0; i < binding.getNumArguments(); i++) {
369 final JavaType type = binding.getJavaArgumentType(i);
370 if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
371 // Don't need to expose these at the Java level
372 continue;
373 }
374
375 if (type.isVoid()) {
376 // Make sure this is the only param to the method; if it isn't,
377 // there's something wrong with our parsing of the headers.
378 assert(binding.getNumArguments() == 1);
379 continue;
380 }
381
382 if (needComma) {
383 unit.emit(", ");
384 }
385
386 if (type.isCompoundTypeWrapper()) {
387 unit.emit("BuffersInternal.getDirectBufferAddress(");
388 unit.emit("((");
389 }
390
391 if (type.isNIOBuffer()) {
392 if (!direct) {
393 unit.emit(getNIOBufferArrayName(i));
394 } else {
395 unit.emit("BuffersInternal.getDirectBufferAddress(");
396 unit.emit(getArgumentName(i));
397 unit.emit(")");
398 }
399 } else {
400 unit.emit(getArgumentName(i));
401 }
402
403 if (type.isCompoundTypeWrapper()) {
404 unit.emit(" == null) ? null : ");
405 unit.emit(getArgumentName(i));
406 unit.emit(".getBuffer())");
407 unit.emit(")");
408 }
409
410 if (type.isNIOBuffer()) {
411 if (direct) {
412 unit.emit("+ Buffers.getDirectBufferByteOffset(" + getArgumentName(i) + ")");
413 } else {
414 unit.emit(", BuffersInternal.arrayBaseOffset(" +
416 ") + Buffers.getIndirectBufferByteOffset(" + getArgumentName(i) + ")");
417 }
418 } else if (type.isNIOBufferArray()) {
419 unit.emit(", " + byteOffsetArrayArgName(i));
420 }
421
422 // Add Array offset parameter for primitive arrays
423 if (type.isPrimitiveArray()) {
424 unit.emit(", ");
425 unit.emit("BuffersInternal.arrayBaseOffset(" + getArgumentName(i) + ") + ");
426 if(type.isFloatArray()) {
427 unit.emit("Buffers.SIZEOF_FLOAT * ");
428 } else if(type.isDoubleArray()) {
429 unit.emit("Buffers.SIZEOF_DOUBLE * ");
430 } else if(type.isByteArray()) {
431 unit.emit("1 * ");
432 } else if(type.isLongArray()) {
433 unit.emit("Buffers.SIZEOF_LONG * ");
434 } else if(type.isShortArray()) {
435 unit.emit("Buffers.SIZEOF_SHORT * ");
436 } else if(type.isIntArray()) {
437 unit.emit("Buffers.SIZEOF_INT * ");
438 } else {
439 throw new GlueGenException("Unsupported type for calculating array offset argument for " +
440 getArgumentName(i) +
441 "-- error occurred while processing Java glue code for " + binding.getCSymbol().getAliasedString(),
442 binding.getCSymbol().getASTLocusTag());
443 }
444 unit.emit(offsetArgName(i));
445 }
446
447 if (type.isString()) {
448 unit.emit("_c_str");
449 }
450
451 if (type.isCompoundTypeWrapper()) {
452 unit.emit(")");
453 }
454
455 needComma = true;
456 ++numArgsEmitted;
457 }
458 return numArgsEmitted;
459 }
460
461 @Override
462 protected void emitCallResultReturn(final MethodBinding binding) {
463 for (int i = 0; i < binding.getNumArguments(); i++) {
464 final JavaType type = binding.getJavaArgumentType(i);
465 if (type.isString()) {
466 unit.emitln(";");
467 unit.emitln(" BuffersInternal.freeCString(" + binding.getArgumentName(i) + "_c_str);");
468 }
469 // FIXME: will need more of these cleanups for things like Buffer[] and String[] (see above)
470 }
471
472 super.emitCallResultReturn(binding);
473 }
474
475 @Override
476 public String getNativeName() {
477 final String res = super.getNativeName();
478 if (isPrivateNativeMethod() && bufferObjectVariant) {
479 return res + "BufObj";
480 }
481 return res;
482 }
483
484 protected String getImplMethodName(final boolean direct) {
485 String name = null;
486 if (direct) {
487 name = binding.getName() + "$0";
488 } else {
489 name = binding.getName() + "$1";
490 }
492 return name + "BufObj";
493 }
494 return name;
495 }
496}
A subclass of ProcAddressEmitter with special OpenGL-specific configuration abilities.
Definition: GLEmitter.java:74
A specialization of the proc address emitter which knows how to change argument names to take into ac...
NativeSignatureJavaMethodBindingEmitter(final JavaMethodBindingEmitter methodToWrap, final NativeSignatureEmitter emitter)
NativeSignatureJavaMethodBindingEmitter(final ProcAddressJavaMethodBindingEmitter methodToWrap, final GLEmitter emitter, final boolean bufferObjectVariant)
void appendNativeSignatureElement(final StringBuilder buf, final JavaType type, final Type cType, final int index)