Found a new way to use generics in Java for solving a problem with WebGL, having a function return data in different types depending on a parameter name. This is possible in JS with duck typing, but generics allowed that in Java too with Java 7.
For example: This is the code I wrote using generics for the glGetParameter() method in WebGL10 class. This does convert the objects into integers as they are represented as integers in desktop OpenGL (chosen to look like LWJGL classes since it makes it easy for me to port to WebGL in the end).
@SuppressWarnings("unchecked")
public static <T> T glGetParameter(int pname)
{
checkContextCompatibility();
T result = nglGetParameter(pname);
switch (pname)
{
case GL_ARRAY_BUFFER_BINDING:
case GL_ELEMENT_ARRAY_BUFFER_BINDING:
return (T) (Integer) WebGLObjectMap.get().createBuffer((JavaScriptObject) result);
case GL_CURRENT_PROGRAM:
return (T) (Integer) WebGLObjectMap.get().createProgram((JavaScriptObject) result);
case GL_FRAMEBUFFER_BINDING:
return (T) (Integer) WebGLObjectMap.get().createFramebuffer((JavaScriptObject) result);
case GL_RENDERBUFFER_BINDING:
return (T) (Integer) WebGLObjectMap.get().createRenderBuffer((JavaScriptObject) result);
case GL_TEXTURE_BINDING_2D:
case GL_TEXTURE_BINDING_CUBE_MAP:
return (T) (Integer) WebGLObjectMap.get().createTexture((JavaScriptObject) result);
}
return result;
}
The above allows one to use it to take multiple parameters, as like in this example.
int texture = glGetParameter(GL_TEXTURE_BINDING_2D);
boolean blending = glGetParameter(GL_BLEND);
Float32Array blendColor = glGetParameter(GL_BLEND_COLOR);
This is similar to how people use WebGL from the native JavaScript too, where the var keyword is used instead of the return types. Interested, I thought how this will be output in JS by the GWT compiler. This is the version without optimisations in SuperDev mode.
function glGetParameter_0_g$(pname_0_g$){
$clinit_WebGL10_0_g$();
var result_0_g$;
checkContextCompatibility_0_g$();
result_0_g$ = nglGetParameter_0_g$(pname_0_g$);
switch (pname_0_g$) {
case 34964:
case 34965:
return dynamicCastAllowJso_0_g$(dynamicCast_0_g$(valueOf_60_g$(get_40_g$().createBuffer_1_g$(dynamicCastJso_0_g$(result_0_g$))), 1480), 1);
case 35725:
return dynamicCastAllowJso_0_g$(dynamicCast_0_g$(valueOf_60_g$(get_40_g$().createProgram_1_g$(dynamicCastJso_0_g$(result_0_g$))), 1480), 1);
case 36006:
return dynamicCastAllowJso_0_g$(dynamicCast_0_g$(valueOf_60_g$(get_40_g$().createFramebuffer_1_g$(dynamicCastJso_0_g$(result_0_g$))), 1480), 1);
case 36007:
return dynamicCastAllowJso_0_g$(dynamicCast_0_g$(valueOf_60_g$(get_40_g$().createRenderBuffer_1_g$(dynamicCastJso_0_g$(result_0_g$))), 1480), 1);
case 32873:
case 34068:
return dynamicCastAllowJso_0_g$(dynamicCast_0_g$(valueOf_60_g$(get_40_g$().createTexture_1_g$(dynamicCastJso_0_g$(result_0_g$))), 1480), 1);
}
return result_0_g$;
}
It is almost the same, but the call to nglGetParameter, a method that is written using JSNI is still not inlined. So I thought verifying the optimised output of the method and setting the compile style to pretty for this input:
int result = glGetParameter(GL_TEXTURE_BINDING_2D);
GWT.log("" + result);
It inlined the code perfectly, even from the parameter it judged what type I was trying to create and inlined the casts as well, producing the following version:
checkContextCompatibility();
result = $wnd.gl.getParameter(32873);
valueOf($createTexture(get_2(), dynamicCastJso(result)));
The piece where $wnd.gl.getParameter is actually part of nglGetParameter method which is the JSNI method, and it got inlined into the glGetParameter method, which itself is inlined into the onModuleLoad method which is the entry point. This is extremely good, I was initially worried about the overhead my library introduces, but it turned out that there is no overhead actually!
It started with the question on how to write the Java function for the IDL [icode]any getParameter(GLenum pname)[/icode] that made me look into generics, and took me to verify the contents of the generated JS by the compiler. Learnt this today.