Added generator support for null-terminated string lists.

Fixed GetUniformIndices and TransformFeedbackVaryings.
Added a ARB_uniform_buffer_object test.
This commit is contained in:
Ioannis Tsakpinis 2009-12-04 04:49:19 +00:00
parent 63ed7b268e
commit 6e5355bc83
13 changed files with 293 additions and 36 deletions

View File

@ -74,6 +74,17 @@ public class BufferChecks {
}
}
public static void checkNullTerminated(ByteBuffer buf, int count) {
int nullFound = 0;
for ( int i = buf.position(); i < buf.limit(); i++ ) {
if ( buf.get(i) == 0 )
nullFound++;
}
if ( nullFound < count )
throw new IllegalArgumentException("Missing null termination");
}
public static void checkNotNull(Object o) {
if (o == null)
throw new IllegalArgumentException("Null argument");

View File

@ -0,0 +1,129 @@
/*
* 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.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2009-12-04
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBUniformBufferObject;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
final class ShaderUNI extends Shader {
final String file;
final ByteBuffer source;
final int shaderID;
final int programID;
final int uniformA;
final int uniformB;
ShaderUNI(final String shaderFile) {
file = shaderFile;
source = getShaderText(shaderFile);
shaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(shaderID, source);
GL20.glCompileShader(shaderID);
printShaderObjectInfoLog(file, shaderID);
GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A compilation error occured in a vertex shader.");
programID = GL20.glCreateProgram();
GL20.glAttachShader(programID, shaderID);
GL20.glLinkProgram(programID);
printShaderProgramInfoLog(programID);
GL20.glGetProgram(programID, GL20.GL_LINK_STATUS, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A linking error occured in a shader program.");
uniformA = getUniformLocation(programID, "uniformA");
uniformB = getUniformLocation(programID, "uniformB");
String[] uniformNames = { "uniformA", "uniformB" };
IntBuffer tmp = BufferUtils.createIntBuffer(uniformNames.length);
ARBUniformBufferObject.glGetUniformIndices(programID, toByteBuffer(uniformNames), tmp);
System.out.println("uniformA index = " + tmp.get(0));
System.out.println("uniformB index = " + tmp.get(1));
}
private static ByteBuffer toByteBuffer(String[] strs) {
int length = 0;
for ( int i = 0; i < strs.length; i++ )
length += strs[i].length() + 1; // +1 for the NULL-character
final ByteBuffer buff = BufferUtils.createByteBuffer(length);
for ( int i = 0; i < strs.length; i++ ) {
buff.put(strs[i].getBytes());
buff.put((byte)0); // The ending NULL-character
}
buff.flip();
return buff;
}
void render() {
GL20.glUseProgram(programID);
GL20.glUniform2f(uniformA, ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f);
GL20.glUniform3f(uniformB, 0.0f, 0.7f, 0.0f);
ShadersTest.renderObject();
GL20.glUseProgram(0);
}
void cleanup() {
GL20.glDetachShader(programID, shaderID);
GL20.glDeleteShader(shaderID);
GL20.glDeleteProgram(programID);
}
}

View File

@ -1,31 +1,31 @@
/*
/*
* 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
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
*
* * 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
* * 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
* 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
* 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.
*/
@ -45,11 +45,7 @@ import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.opengl.*;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.glu.Sphere;
@ -92,7 +88,8 @@ public final class ShadersTest {
lastFrameTime = frameStart;
angle += frameTime * 90.0f;
//angle += frameTime * 90.0f;
angle += 0.1f;
sin = (float)Math.sin(Math.toRadians(angle));
handleIO();
@ -138,7 +135,7 @@ public final class ShadersTest {
System.out.println("Setting display mode to: " + displayMode);
Display.setDisplayMode(displayMode);
Display.create(new PixelFormat(8, 24, 0));
Display.create(new PixelFormat(8, 24, 0), "UNI".equalsIgnoreCase(args[0]) ? new ContextAttribs(3, 1) : null);
ShadersTest.displayMode = displayMode;
} catch (LWJGLException e) {
kill(e.getMessage());
@ -170,6 +167,11 @@ public final class ShadersTest {
kill("The ARB_fragment_shader extension is not supported.");
shader = new ShaderFSH("shaderFSH.vsh", "shaderFSH.fsh");
} else if ("UNI".equalsIgnoreCase(args[0]) ) {
if ( !GLContext.getCapabilities().OpenGL31 )
kill("OpenGL version 3.1 is not supported.");
shader = new ShaderUNI("shaderUNI.vsh");
} else {
argsError();
}

View File

@ -0,0 +1,25 @@
#version 140
uniform vec2 uniformA;
uniform vec3 uniformB;
void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec3 normal = gl_NormalMatrix * gl_Normal;
float diffuseDot = max(dot(normal, vec3(gl_LightSource[0].position)), 0.0);
float specularDot = max(dot(normal, vec3(gl_LightSource[0].halfVector)), 0.0);
specularDot = pow(specularDot, uniformA.y);
// Normalize position, to get a {-1..1} value for each vertex.
// Multiply with current sin.
vec3 color3D = normalize(vec3(gl_Vertex)) * uniformA.x;
// {-1..1} => {0..1} & Intensify colors.
color3D = (color3D * 0.5 + 0.5) * 2.0;
// Accumulate color contributions.
color3D = diffuseDot * (uniformB + color3D) + vec3(gl_LightModel.ambient);
gl_FrontColor.rgb = specularDot * vec3(gl_LightSource[0].specular) + color3D;
gl_FrontColor.a = 1.0;
}

View File

@ -41,8 +41,6 @@ package org.lwjgl.util.generator;
* $Id$
*/
import org.lwjgl.opengl.PointerWrapper;
import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*;
import com.sun.mirror.type.*;
@ -471,23 +469,23 @@ public class JavaMethodsGenerator {
check_value = check_annotation.value();
can_be_null = check_annotation.canBeNull();
}
boolean null_terminated = param.getAnnotation(NullTerminated.class) != null;
NullTerminated null_terminated = param.getAnnotation(NullTerminated.class);
if (Buffer.class.isAssignableFrom(java_type)) {
boolean indirect_buffer_allowed = param.getAnnotation(CachedReference.class) == null;
boolean out_parameter = param.getAnnotation(OutParameter.class) != null;
TypeInfo typeinfo = typeinfos.get(param);
printParameterCheck(writer, param.getSimpleName(), typeinfo.getType().getSimpleName(), check_value, can_be_null, null_terminated, indirect_buffer_allowed, out_parameter);
} else if (String.class.equals(java_type)) {
} else if ( String.class.equals(java_type)) {
if (!can_be_null)
writer.println("\t\tBufferChecks.checkNotNull(" + param.getSimpleName() + ");");
}
}
}
if (method.getAnnotation(CachedResult.class) != null)
printParameterCheck(writer, Utils.CACHED_BUFFER_NAME, null, null, true, false, false, false);
printParameterCheck(writer, Utils.CACHED_BUFFER_NAME, null, null, true, null, false, false);
}
private static void printParameterCheck(PrintWriter writer, String name, String type, String check_value, boolean can_be_null, boolean null_terminated, boolean indirect_buffer_allowed, boolean out_parameter) {
private static void printParameterCheck(PrintWriter writer, String name, String type, String check_value, boolean can_be_null, NullTerminated null_terminated, boolean indirect_buffer_allowed, boolean out_parameter) {
if (indirect_buffer_allowed && out_parameter) {
writer.println("\t\t" + type + " " + name + SAVED_PARAMETER_POSTFIX + " = " + name + ";");
}
@ -507,8 +505,15 @@ public class JavaMethodsGenerator {
writer.print("Direct(" + name);
}
writer.println(");");
if (null_terminated)
writer.println("\t\tBufferChecks.checkNullTerminated(" + name + ");");
if (null_terminated != null) {
writer.print("\t\tBufferChecks.checkNullTerminated(");
writer.print(name);
if ( null_terminated.value().length() > 0 ) {
writer.print(", ");
writer.print(null_terminated.value());
}
writer.println(");");
}
}
private static void printResultType(PrintWriter writer, MethodDeclaration method, boolean native_stub) {

View File

@ -52,6 +52,7 @@ import java.nio.*;
public class NativeMethodStubsGenerator {
private static final String BUFFER_ADDRESS_POSTFIX = "_address";
public static final String BUFFER_POSITION_POSTFIX = "_position";
private static final String STRING_LIST_POSTFIX = "_str";
public static void generateNativeMethodStubs(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration d, boolean generate_error_checks, boolean context_specific) {
for (MethodDeclaration method : d.getMethods()) {
@ -120,6 +121,7 @@ public class NativeMethodStubsGenerator {
writer.print(" = (" + typedef_name + ")((intptr_t)");
writer.println(Utils.FUNCTION_POINTER_VAR_NAME + ");");
}
generateStringListInits(writer, method.getParameters());
writer.print("\t");
if (!result_type.equals(env.getTypeUtils().getVoidType())) {
Declaration return_declaration;
@ -197,17 +199,21 @@ public class NativeMethodStubsGenerator {
writer.print(Utils.RESULT_VAR_NAME);
} else {
writer.print(param.getSimpleName());
if (Utils.isAddressableType(param.getType())) {
if ( param.getAnnotation(StringList.class) != null )
writer.print(STRING_LIST_POSTFIX);
else if (Utils.isAddressableType(param.getType()))
writer.print(BUFFER_ADDRESS_POSTFIX);
}
}
}
private static void generateStringDeallocations(PrintWriter writer, Collection<ParameterDeclaration> params) {
for (ParameterDeclaration param : params)
for (ParameterDeclaration param : params) {
if (Utils.getJavaType(param.getType()).equals(String.class) &&
param.getAnnotation(Result.class) == null)
writer.println("\tfree(" + param.getSimpleName() + BUFFER_ADDRESS_POSTFIX + ");");
else if (param.getAnnotation(StringList.class) != null ) // Free the string array mem
writer.println("\tfree(" + param.getSimpleName() + STRING_LIST_POSTFIX + ");");
}
}
private static void generateBufferParameterAddresses(TypeMap type_map, PrintWriter writer, MethodDeclaration method, Mode mode) {
@ -249,5 +255,34 @@ public class NativeMethodStubsGenerator {
throw new RuntimeException("Illegal type " + java_type);
}
writer.println(";");
if ( param.getAnnotation(StringList.class) != null ) {
if ( param.getAnnotation(GLchar.class) == null ||
param.getAnnotation(NullTerminated.class) == null ||
param.getAnnotation(NullTerminated.class).value().length() == 0
)
throw new RuntimeException("StringList annotation can only be applied on null-terminated GLchar buffers.");
// Declare string array and loop counters
writer.print("\tGLchar **" + param.getSimpleName() + STRING_LIST_POSTFIX + "; ");
writer.println("\tunsigned int " + param.getSimpleName() + "_i = 0;");
writer.println("\tGLchar *" + param.getSimpleName() + "_next = (GLchar *)" + param.getSimpleName() + BUFFER_ADDRESS_POSTFIX + ";");
}
}
private static void generateStringListInits(PrintWriter writer, Collection<ParameterDeclaration> params) {
for ( ParameterDeclaration param : params ) {
StringList stringList_annotation = param.getAnnotation(StringList.class);
if ( stringList_annotation != null ) {
// Allocate the string array
writer.println("\t" + param.getSimpleName() + STRING_LIST_POSTFIX + " = (GLchar **) malloc(" + stringList_annotation.value() + "*sizeof(GLchar*));");
// Fill string array with the string pointers
writer.println("\tdo {");
writer.println("\t\t" + param.getSimpleName() + STRING_LIST_POSTFIX + "[" + param.getSimpleName() + "_i++] = " + param.getSimpleName() + "_next;");
writer.println("\t\t" + param.getSimpleName() + "_next += strlen(" + param.getSimpleName() + "_next) + 1;");
writer.println("\t} while ( " + param.getSimpleName() + "_i < " + stringList_annotation.value() + " );");
}
}
}
}

View File

@ -46,4 +46,5 @@ import java.lang.annotation.ElementType;
@Target(ElementType.PARAMETER)
public @interface NullTerminated {
String value() default "";
}

View File

@ -0,0 +1,45 @@
/*
* 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;
/**
*
* @author spasi <spasi@users.sourceforge.net>
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER, ElementType.METHOD})
public @interface StringList {
String value();
}

View File

@ -76,7 +76,7 @@ public class TypedefsGenerator {
NativeTypeTranslator translator = new NativeTypeTranslator(type_map, param);
param.getType().accept(translator);
writer.print(translator.getSignature());
if (param.getAnnotation(Result.class) != null || param.getAnnotation(Indirect.class) != null)
if (param.getAnnotation(Result.class) != null || param.getAnnotation(Indirect.class) != null || param.getAnnotation(StringList.class) != null)
writer.print("*");
writer.print(" " + param.getSimpleName());
}

View File

@ -99,7 +99,7 @@ public interface ARB_uniform_buffer_object {
int GL_INVALID_INDEX = 0xFFFFFFFF;
void glGetUniformIndices(@GLuint int program, @AutoSize("uniformIndices") @GLsizei int uniformCount,
@Const @NullTerminated @GLchar ByteBuffer uniformNames,
@Const @NullTerminated("uniformIndices.remaining()") @GLchar @StringList("uniformCount") ByteBuffer uniformNames,
@OutParameter @GLuint IntBuffer uniformIndices);
@StripPostfix("params")

View File

@ -101,7 +101,9 @@ public interface EXT_transform_feedback {
void glEndTransformFeedbackEXT();
void glTransformFeedbackVaryingsEXT(@GLuint int program, @GLsizei int count, @Const @NullTerminated @GLchar ByteBuffer varyings, @GLenum int bufferMode);
void glTransformFeedbackVaryingsEXT(@GLuint int program, @GLsizei int count,
@Const @NullTerminated("count") @GLchar @StringList("count") ByteBuffer varyings,
@GLenum int bufferMode);
void glGetTransformFeedbackVaryingEXT(@GLuint int program, @GLuint int index,
@AutoSize("name") @GLsizei int bufSize,

View File

@ -864,7 +864,9 @@ public interface GL30 {
void glEndTransformFeedback();
void glTransformFeedbackVaryings(@GLuint int program, @GLsizei int count, @Const @NullTerminated @GLchar ByteBuffer varyings, @GLenum int bufferMode);
void glTransformFeedbackVaryings(@GLuint int program, @GLsizei int count,
@Const @NullTerminated("count") @GLchar @StringList("count") ByteBuffer varyings,
@GLenum int bufferMode);
void glGetTransformFeedbackVarying(@GLuint int program, @GLuint int index,
@AutoSize("name") @GLsizei int bufSize,

View File

@ -234,7 +234,7 @@ public interface GL31 {
int GL_INVALID_INDEX = 0xFFFFFFFF;
void glGetUniformIndices(@GLuint int program, @AutoSize("uniformIndices") @GLsizei int uniformCount,
@Const @NullTerminated @GLchar ByteBuffer uniformNames,
@Const @NullTerminated("uniformIndices.remaining()") @GLchar @StringList("uniformCount") ByteBuffer uniformNames,
@OutParameter @GLuint IntBuffer uniformIndices);
@StripPostfix("params")