341 lines
15 KiB
Java
341 lines
15 KiB
Java
/*
|
|
* Copyright (c) 2002-2008 LWJGL Project
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'LWJGL' nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
package org.lwjgl.util.generator.opengl;
|
|
|
|
import org.lwjgl.util.generator.*;
|
|
|
|
import java.io.PrintWriter;
|
|
import java.util.Arrays;
|
|
import java.util.EnumSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import javax.annotation.processing.*;
|
|
import javax.lang.model.element.ExecutableElement;
|
|
import javax.lang.model.element.TypeElement;
|
|
import javax.lang.model.type.TypeMirror;
|
|
|
|
/**
|
|
* Generator visitor for the context capabilities generator tool
|
|
*
|
|
* @author elias_naur <elias_naur@users.sourceforge.net>
|
|
* @version $Revision: 3355 $
|
|
* $Id: ContextCapabilitiesGenerator.java 3355 2010-05-27 22:56:29Z spasi $
|
|
*/
|
|
public final class GLCapabilitiesGenerator {
|
|
|
|
private static final String STUBS_LOADED_NAME = "loaded_stubs";
|
|
private static final String ALL_INIT_METHOD_NAME = "initAllStubs";
|
|
private static final String POINTER_INITIALIZER_POSTFIX = "_initNativeFunctionAddresses";
|
|
private static final String CACHED_EXTS_VAR_NAME = "supported_extensions";
|
|
private static final String PROFILE_MASK_VAR_NAME = "profileMask";
|
|
private static final String EXTENSION_PREFIX = "GL_";
|
|
private static final String CORE_PREFIX = "Open";
|
|
|
|
public static void generateClassPrologue(PrintWriter writer, boolean context_specific, boolean generate_error_checks) {
|
|
writer.append("public final class " + Utils.CONTEXT_CAPS_CLASS_NAME + " {\n");
|
|
writer.append("\tstatic final boolean DEBUG = ").append(Boolean.toString(generate_error_checks)).append(";\n");
|
|
writer.append("\tfinal APIUtil util = new APIUtil();\n");
|
|
writer.append("\tfinal StateTracker tracker = new StateTracker();\n\n");
|
|
if ( !context_specific ) {
|
|
writer.append("\tprivate static boolean " + STUBS_LOADED_NAME + " = false;\n");
|
|
}
|
|
}
|
|
|
|
public static void generateInitializerPrologue(PrintWriter writer) {
|
|
writer.append("\t" + Utils.CONTEXT_CAPS_CLASS_NAME + "(boolean forwardCompatible) throws LWJGLException {\n");
|
|
writer.append("\t\tSet<String> " + CACHED_EXTS_VAR_NAME + " = " + ALL_INIT_METHOD_NAME + "(forwardCompatible);\n");
|
|
}
|
|
|
|
private static PrintWriter translateFieldName(PrintWriter writer, String interface_name) {
|
|
return writer.append(interface_name.startsWith("GL") ? CORE_PREFIX : EXTENSION_PREFIX)
|
|
.append(interface_name);
|
|
}
|
|
|
|
public static void generateSuperClassAdds(PrintWriter writer, TypeElement d, ProcessingEnvironment env) {
|
|
List<? extends TypeMirror> super_interfaces = d.getInterfaces();
|
|
if ( super_interfaces.size() > 1 )
|
|
throw new RuntimeException(d + " extends more than one other interface");
|
|
if ( super_interfaces.size() == 1 ) {
|
|
TypeMirror super_interface = super_interfaces.iterator().next();
|
|
writer.append("\t\tif (" + CACHED_EXTS_VAR_NAME + ".contains(\"");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append("\"))\n" + "\t\t\t");
|
|
generateAddExtension(writer, env.getElementUtils().getTypeElement(super_interface.toString()));
|
|
}
|
|
}
|
|
|
|
public static void generateInitializer(PrintWriter writer, TypeElement d, ProcessingEnvironment env) {
|
|
String non_translated_field_name = d.getSimpleName().toString();
|
|
translateFieldName(writer.append("\t\tthis."), non_translated_field_name).append(" = ");
|
|
writer.append(CACHED_EXTS_VAR_NAME + ".contains(\"");
|
|
translateFieldName(writer, non_translated_field_name).append("\")");
|
|
List<? extends TypeMirror> super_interfaces = d.getInterfaces();
|
|
if ( super_interfaces.size() > 1 )
|
|
throw new RuntimeException(d + " extends more than one other interface");
|
|
if ( super_interfaces.size() == 1 ) {
|
|
TypeMirror super_interface = super_interfaces.iterator().next();
|
|
writer.append("\n\t\t\t&& " + CACHED_EXTS_VAR_NAME + ".contains(\"");
|
|
translateFieldName(writer, env.getElementUtils().getTypeElement(super_interface.toString()).getSimpleName().toString()).append("\")");
|
|
}
|
|
Alias alias_annotation = d.getAnnotation(Alias.class);
|
|
if ( alias_annotation != null ) {
|
|
writer.append("\n\t\t\t|| " + CACHED_EXTS_VAR_NAME + ".contains(\"");
|
|
translateFieldName(writer, alias_annotation.value()).append("\")");
|
|
}
|
|
writer.append(";\n");
|
|
}
|
|
|
|
private static PrintWriter getAddressesInitializerName(PrintWriter writer, String class_name) {
|
|
return writer.append(class_name).append(POINTER_INITIALIZER_POSTFIX);
|
|
}
|
|
|
|
public static void generateInitStubsPrologue(PrintWriter writer, boolean context_specific) {
|
|
writer.append("\tprivate Set<String> " + ALL_INIT_METHOD_NAME + "(boolean forwardCompatible) throws LWJGLException {\n");
|
|
|
|
// Load the basic pointers we need to detect OpenGL version and supported extensions.
|
|
writer.append("\t\tglGetError = GLContext.getFunctionAddress(\"glGetError\");\n");
|
|
writer.append("\t\tglGetString = GLContext.getFunctionAddress(\"glGetString\");\n");
|
|
|
|
// Initialize GL11.glGetIntegerv and GL30.glGetStringi here, in case we have created an OpenGL 3.0 context.
|
|
// (they will be used in GLContext.getSupportedExtensions)
|
|
writer.append("\t\tglGetIntegerv = GLContext.getFunctionAddress(\"glGetIntegerv\");\n");
|
|
writer.append("\t\tglGetStringi = GLContext.getFunctionAddress(\"glGetStringi\");\n");
|
|
|
|
// Get the supported extensions set.
|
|
writer.append("\t\tGLContext.setCapabilities(this);\n");
|
|
writer.append("\t\tSet<String> " + CACHED_EXTS_VAR_NAME + " = new HashSet<String>(256);\n");
|
|
writer.append("\t\tint " + PROFILE_MASK_VAR_NAME + " = GLContext.getSupportedExtensions(" + CACHED_EXTS_VAR_NAME + ");\n");
|
|
|
|
// Force forward compatible mode when OpenGL version is 3.1 or higher and ARB_compatibility is not available.
|
|
writer.append("\t\tif (" + CACHED_EXTS_VAR_NAME + ".contains(\"OpenGL31\") && !(" + CACHED_EXTS_VAR_NAME + ".contains(\"GL_ARB_compatibility\") || (" + PROFILE_MASK_VAR_NAME + " & GL32.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0)) {\n");
|
|
writer.append("\t\t\tforwardCompatible = true;\n");
|
|
writer.append("\t\t\tLWJGLUtil.logger().log(() -> \"Forcing forwardCompatible=true because OpenGL version is 3.1 or higher AND ARB_compatibility is not available OR " + PROFILE_MASK_VAR_NAME + " has GL32.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT set.\");\n");
|
|
writer.append("\t\t}\n");
|
|
|
|
if ( !context_specific ) {
|
|
writer.append("\t\tif (" + STUBS_LOADED_NAME + ")\n");
|
|
writer.append("\t\t\treturn GLContext.getSupportedExtensions();\n");
|
|
writer.append("\t\torg.lwjgl.opengl.GL11." + Utils.STUB_INITIALIZER_NAME + "();\n");
|
|
} else {
|
|
writer.append("\t\tif (!");
|
|
getAddressesInitializerName(writer, "GL11").append("(forwardCompatible))\n" + "\t\t\tthrow new LWJGLException(\"GL11 not supported\");\n");
|
|
}
|
|
}
|
|
|
|
public static void generateInitStubsEpilogue(PrintWriter writer, boolean context_specific) {
|
|
if ( !context_specific ) {
|
|
writer.append("\t\t" + STUBS_LOADED_NAME + " = true;\n");
|
|
}
|
|
writer.append("\t\treturn " + CACHED_EXTS_VAR_NAME + ";\n");
|
|
writer.append("\t}\n");
|
|
}
|
|
|
|
public static void generateUnloadStubs(ProcessingEnvironment env, PrintWriter writer, TypeElement d) {
|
|
if ( Utils.getMethods(d).size() > 0 ) {
|
|
writer.append("\t\tGLContext.resetNativeStubs(").append(Utils.getSimpleClassName(d)).append(".class);\n");
|
|
}
|
|
}
|
|
|
|
public static void generateInitStubs(ProcessingEnvironment env, PrintWriter writer, TypeElement d, boolean context_specific) {
|
|
if ( Utils.getMethods(d).size() > 0 ) {
|
|
if ( context_specific ) {
|
|
final Alias alias_annotation = d.getAnnotation(Alias.class);
|
|
|
|
if ( d.getAnnotation(ForceInit.class) != null ) {
|
|
writer.append("\t\t" + CACHED_EXTS_VAR_NAME + ".add(\"");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append("\");\n");
|
|
}
|
|
writer.append("\t\tif (");
|
|
if ( alias_annotation != null ) {
|
|
writer.append('(');
|
|
}
|
|
writer.append(CACHED_EXTS_VAR_NAME + ".contains(\"");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append("\")");
|
|
if ( alias_annotation != null ) {
|
|
writer.append(" || " + CACHED_EXTS_VAR_NAME + ".contains(\"");
|
|
translateFieldName(writer, alias_annotation.value()).append("\"))");
|
|
}
|
|
writer.append(" && !");
|
|
getAddressesInitializerName(writer, d.getSimpleName().toString()).append('(');
|
|
if ( d.getAnnotation(DeprecatedGL.class) != null ) {
|
|
writer.append("forwardCompatible");
|
|
}
|
|
if ( d.getAnnotation(Dependent.class) != null ) {
|
|
if ( d.getAnnotation(DeprecatedGL.class) != null ) {
|
|
writer.append(",");
|
|
}
|
|
writer.append(CACHED_EXTS_VAR_NAME);
|
|
}
|
|
if ( alias_annotation != null ) {
|
|
writer.append(")) {\n" + "\t\t\tremove(" + CACHED_EXTS_VAR_NAME + ", \"");
|
|
translateFieldName(writer, alias_annotation.value()).append("\");\n");
|
|
} else {
|
|
writer.append("))\n");
|
|
}
|
|
writer.append("\t\t\tremove(" + CACHED_EXTS_VAR_NAME + ", \"");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append("\");\n");
|
|
if ( alias_annotation != null ) {
|
|
writer.append("\t\t}\n");
|
|
}
|
|
} else {
|
|
writer.append("\t\tGLContext." + Utils.STUB_INITIALIZER_NAME + '(').append(Utils.getSimpleClassName(d));
|
|
writer.append(".class, " + CACHED_EXTS_VAR_NAME + ", \"");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append("\");\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void generateAddExtension(PrintWriter writer, TypeElement d) {
|
|
writer.append(CACHED_EXTS_VAR_NAME + ".add(\"");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append("\");\n");
|
|
}
|
|
|
|
public static void generateAddressesInitializers(ProcessingEnvironment env, PrintWriter writer, TypeElement d) {
|
|
Iterator<? extends ExecutableElement> methods = Utils.getMethods(d).iterator();
|
|
if (!methods.hasNext()) return;
|
|
|
|
writer.append("\tprivate boolean ");
|
|
getAddressesInitializerName(writer, d.getSimpleName().toString()).append('(');
|
|
|
|
boolean optional;
|
|
boolean deprecated = d.getAnnotation(DeprecatedGL.class) != null;
|
|
Dependent dependent = d.getAnnotation(Dependent.class);
|
|
if (deprecated) {
|
|
writer.append("boolean forwardCompatible");
|
|
}
|
|
if (dependent != null) {
|
|
if (deprecated) {
|
|
writer.append(',');
|
|
}
|
|
writer.append("Set<String> " + CACHED_EXTS_VAR_NAME);
|
|
}
|
|
|
|
Alias alias_annotation = d.getAnnotation(Alias.class);
|
|
boolean aliased = alias_annotation != null && alias_annotation.postfix().length() > 0;
|
|
|
|
writer.append(") {\n" + "\t\treturn \n");
|
|
|
|
boolean first = true;
|
|
while ( methods.hasNext() ) {
|
|
ExecutableElement method = methods.next();
|
|
if ( method.getAnnotation(Alternate.class) != null )
|
|
continue;
|
|
|
|
if (!first) {
|
|
writer.append(" &\n");
|
|
} else {
|
|
first = false;
|
|
}
|
|
|
|
optional = method.getAnnotation(Optional.class) != null;
|
|
deprecated = method.getAnnotation(DeprecatedGL.class) != null;
|
|
dependent = method.getAnnotation(Dependent.class);
|
|
|
|
writer.append("\t\t\t(");
|
|
if (optional) {
|
|
writer.append('(');
|
|
}
|
|
if (deprecated) {
|
|
writer.append("forwardCompatible || ");
|
|
}
|
|
if (dependent != null) {
|
|
if (dependent.value().indexOf(',') == -1)
|
|
writer.append("!" + CACHED_EXTS_VAR_NAME + ".contains(\"").append(dependent.value()).append("\") || ");
|
|
else {
|
|
writer.append("!(false");
|
|
for (String extension : dependent.value().split(",")) {
|
|
writer.append(" || " + CACHED_EXTS_VAR_NAME + ".contains(\"").append(extension).append("\")");
|
|
}
|
|
writer.append(") || ");
|
|
}
|
|
}
|
|
if (deprecated || dependent != null) {
|
|
writer.append('(');
|
|
}
|
|
writer.append(Utils.getFunctionAddressName(d, method)).append(" = ");
|
|
PlatformDependent platform_dependent = method.getAnnotation(PlatformDependent.class);
|
|
if (platform_dependent != null) {
|
|
EnumSet<Platform> platform_set = EnumSet.copyOf(Arrays.asList(platform_dependent.value()));
|
|
writer.append("GLContext.getPlatformSpecificFunctionAddress(\"").append(Platform.ALL.getPrefix()).append("\", " + "new String[]{");
|
|
Iterator<Platform> platforms = platform_set.iterator();
|
|
while ( platforms.hasNext() ) {
|
|
writer.append("\"").append(platforms.next().getOSPrefix()).append("\"");
|
|
if (platforms.hasNext()) {
|
|
writer.append(", ");
|
|
}
|
|
}
|
|
writer.append("}, new String[]{");
|
|
platforms = platform_set.iterator();
|
|
while (platforms.hasNext()) {
|
|
writer.append("\"").append(platforms.next().getPrefix()).append("\"");
|
|
if (platforms.hasNext()) {
|
|
writer.append(", ");
|
|
}
|
|
}
|
|
writer.append("}, ");
|
|
} else if (aliased) {
|
|
writer.append("GLContext.getFunctionAddress(new String[] {\"").append(method.getSimpleName()).append("\",\"").append(method.getSimpleName()).append(alias_annotation.postfix()).append("\"})) != 0");
|
|
} else {
|
|
writer.append("GLContext.getFunctionAddress(");
|
|
}
|
|
if (!aliased) {
|
|
writer.append("\"").append(method.getSimpleName()).append("\")) != 0");
|
|
}
|
|
if (deprecated || dependent != null) {
|
|
writer.append(')');
|
|
}
|
|
if (optional) {
|
|
writer.append(" || true)");
|
|
}
|
|
}
|
|
writer.append(";\n" + "\t}\n");
|
|
}
|
|
|
|
public static void generateSymbolAddresses(ProcessingEnvironment env, PrintWriter writer, TypeElement d) {
|
|
boolean first = true;
|
|
for (final ExecutableElement method : Utils.getMethods(d)) {
|
|
if (method.getAnnotation(Alternate.class) != null || method.getAnnotation(Reuse.class) != null) continue;
|
|
|
|
if (first) {
|
|
writer.append("\t// ").append(d.getSimpleName()).append('\n');
|
|
first = false;
|
|
}
|
|
writer.append("\tlong ").append(Utils.getFunctionAddressName(d, method)).append(";\n");
|
|
}
|
|
}
|
|
|
|
public static void generateField(PrintWriter writer, TypeElement d) {
|
|
writer.append("\tpublic final boolean ");
|
|
translateFieldName(writer, d.getSimpleName().toString()).append(";\n");
|
|
}
|
|
}
|