Help adapting to JSR-231?

Hi,
I know people said this is really straightforward but for the slow ones like myself:

  1. OpenGL doesn’t run. Code that was working fine before the transition, now, whenever i try to initialize openGL, says:

java.lang.UnsatisfiedLinkError: JAWT_GetAWT0
at com.sun.opengl.impl.JAWTFactory.JAWT_GetAWT0(Native Method)
at com.sun.opengl.impl.JAWTFactory.JAWT_GetAWT(JAWTFactory.java:37)
at com.sun.opengl.impl.NativeLibLoader$1.run(NativeLibLoader.java:83)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.opengl.impl.NativeLibLoader.load(NativeLibLoader.java:59)
at com.sun.opengl.impl.windows.WindowsGLDrawableFactory.(WindowsGLDrawableFactory.java:64)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at javax.media.opengl.GLDrawableFactory.getFactory(GLDrawableFactory.java:92)
at GLRenderer.(GLRenderer.java:109)

where the line in question is
canvas = GLDrawableFactory.getFactory().createGLCanvas(glCaps);

This is on JDK 1.5.0_05 on WinXP.

  1. I had to comment out the following essential(?) calls because I don’t know what the analogue is:

2.1. canvas.setNoAutoRedrawMode(false); //doesn’t know of setNoAuto… method

2.2. GLU glu = drawable.getGLU(); //doesn’t know of getGLU() method inside drawable (which, incidentally, I changed from GLDrawable to GLAutoDrawable). Similarly I now can’t do canvas.getGLU()

2.3. In my run() method I had to comment out
canvas.setRenderingThread(Thread.currentThread()); //doesn’t know of the setRendering…() method.

  1. In my initTexture method, I had the following code:
    int[] texArr = {0};
    if(gl.glIsTexture(1))
    gl.glDeleteTextures(1, texArr);
    gl.glGenTextures(1, texArr);
    int texID = texArr[0];

I changed it to:
IntBuffer texArr = IntBuffer.allocate(1);
if(gl.glIsTexture(1))
gl.glDeleteTextures(1, texArr);
gl.glGenTextures(1, texArr);
int texID = texArr.get();

Is that the correct change?

Now, a couple of more general questions:
4. Do I still need the System.setProperty(“jogl.1thread”, “false”) at the program’s start for it to run using multithreading?

  1. Converting to use of GLJPanel: do I need JDK6 for doing proper display of Swing components on top of OpenGL or can I do it with JDK 1.5?

Thanks so much for answering these… I know these are silly questions but I am not an openGL expert yet I’d love to get the new Swing/OpenGL capabilities to work in our program…

You probably have a stale jogl.jar and/or jogl.dll on your system.

This call is no longer needed. The threading model of the implementation has been changed to perform all OpenGL work on a single thread so repaints by the AWT look the same as manual repaints from something like the Animator.

You can now do “new GLU()” anywhere in your program. However, any method calls on this object which perform OpenGL work must be made while an OpenGL context is current, e.g., while your GLEventListener’s callback methods are active on the stack.

This call is again no longer needed. We no longer perform the optimization of making a context current to a given thread indefinitely. Given all of the problems attempts at this kind of optimization caused, we decided to eliminate it from the default heavyweight widget (GLCanvas).

It looks to me like the original code is wrong. The call to glIsTexture and glDeleteTextures have meaningless values being passed to them. Depending on how your code is structured I think deleting the lines containing glIsTexture and glDeleteTextures should be correct and anyway more correct than the current code. The transformation you made from int[] to IntBuffer is correct.

I strongly recommend you remove this call. We have not been able to measure any significant performance impact on real applications from JOGL’s serializing all OpenGL work on a single thread, and we have seen enough multithreading-related bugs in OpenGL drivers on all platforms that the only reasonable way to write a portable OpenGL application at this point seems to be to keep all of the OpenGL work on a single thread, which is now done automatically by the JOGL implementation (if you restrict yourself to using the GLAutoDrawable/GLEventListener programming model).

You can do it with 1.5 but the performance will not be good if the GLJPanel is large. With Java SE 6 we think we’ve made good progress in making this almost as fast as the GLCanvas case while maintaining correctness.

Not silly questions at all. Please post if you have more problems or questions about the new build.

Hi, i have a little problem with glDrawArrays (not using VBOs for old Sun video card concerns)…

In the previuous build the following was good :


        vertexArrayBuffer = BufferUtils.newFloatBuffer ( 4 *2 * count );
        vertexArrayCoordBuffer = BufferUtils.newFloatBuffer ( 4 * 2 * count );

        // Fill these to buffers with a 'chessboard' of quads using 
                vertexArrayCoordBuffer.put ( 0.0f + xoffset);
                vertexArrayCoordBuffer.put ( 0.50f + yoffset );
                vertexArrayBuffer.put ( 0.0f + i * 33.0f );
                vertexArrayBuffer.put ( 0.0f + j * 33.0f );

        gl.glEnableClientState ( GL_VERTEX_ARRAY );
        gl.glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
        
        gl.glVertexPointer ( 2, GL_FLOAT, 0, vertexArrayBuffer );
        gl.glTexCoordPointer ( 2, GL_FLOAT, 0, vertexArrayCoordBuffer );
        
        gl.glDrawArrays ( GL_QUADS, 0, 4 * count );
        
        gl.glDisableClientState ( GL_VERTEX_ARRAY );
        gl.glDisableClientState ( GL_TEXTURE_COORD_ARRAY );

With the new build I only added a rewind on each FloatBuffer but the screen kept as black as possible…
I certainly miss a little thing…

Can a guru give me some help…
Thanks in advance.

PS : The texture loading is correct since basic quad drawings works…

Ken,
Thanks a million for your patient and clear answer - the result: it works! And it shows Swing elements on top of the video. This is truly awesome. Thank you very much.

Now a couple of followup things in case you don’t mind answering…

  1. With both 1.5.0_05 and 1.6, the following occurs:

1.1. If i put, at the start of my program
System.setProperty(“sun.java2d.opengl”, “True”);

it has zero effect. do you know why it doesn’t work unless in the command line?

1.2. If i put that same line in the command line, the effect is: blank (black) screen. As in, my program shows its UI (no exceptions thrown), but the openGL window is just black and shows nothing. When i remove the -Dsun.java2d.opengl switch, everything shows up fine.

This seems to affect not only the openGL window however… If I click a button that is supposed to bring up a popup menu (with some text in it), the CPU goes to 100%. Are the two things related? Obviously, if I don’t have the opengl switch active, the popup menus display just fine.

1.3. I tried putting
-Dsun.java2d.opengl=True -Djogl.debug.Java2D -Djogl.debug.GLJPanel
in the command line, to see what the problem is (as well as a few other debugging statements). I get:

OpenGL pipeline enabled for config on screen 0

display change supported = false
full screen supported = true
accelerated memory = -1
mainWindow’s buffer strategy: null
New Acceleration Threshold: 0

JOGL version jsr231-1.0-beta1-b01
Checking for Java2D/OpenGL support
Java2D support: default GraphicsConfiguration = sun.java2d.opengl.WGLGraphicsConfig
JOGL/Java2D integration enabled
GLJPanel.addNotify()
GLJPanel.handleReshape: (w,h) = (256,256)
Sending reshape because viewport changed
viewportX (0) ?= oglViewport.x (2)
viewportY (0) ?= oglViewport.y (438)

OpenGL Renderer: GeForce Go 6600/PCI/SSE2
OpenGL Vendor: NVIDIA Corporation
OpenGL Version: 2.0.1
Supported OpenGL Extensions: GL_ARB_color_buffer_float GL_ARB_depth_texture GL_ARB_draw_buffers GL_ARB_fragment_program GL_ARB_fragment_program_shadow GL_ARB_fragment_shader GL_ARB_half_float_pixel GL_ARB_imaging GL_ARB_multisample GL_ARB_multitexture GL_ARB_occlusion_query GL_ARB_pixel_buffer_object GL_ARB_point_parameters GL_ARB_point_sprite GL_ARB_shadow GL_ARB_shader_objects GL_ARB_shading_language_100 GL_ARB_texture_border_clamp GL_ARB_texture_compression GL_ARB_texture_cube_map GL_ARB_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_env_dot3 GL_ARB_texture_float GL_ARB_texture_mirrored_repeat GL_ARB_texture_non_power_of_two GL_ARB_texture_rectangle GL_ARB_transpose_matrix GL_ARB_vertex_buffer_object GL_ARB_vertex_program GL_ARB_vertex_shader GL_ARB_window_pos GL_ATI_draw_buffers GL_ATI_texture_float GL_ATI_texture_mirror_once GL_S3_s3tc GL_EXT_texture_env_add GL_EXT_abgr GL_EXT_bgra GL_EXT_blend_color GL_EXT_blend_equation_separate GL_EXT_blend_func_separate GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_compiled_vertex_array GL_EXT_Cg_shader GL_EXT_depth_bounds_test GL_EXT_draw_range_elements GL_EXT_fog_coord GL_EXT_framebuffer_object GL_EXT_multi_draw_arrays GL_EXT_packed_depth_stencil GL_EXT_packed_pixels GL_EXT_pixel_buffer_object GL_EXT_point_parameters GL_EXT_rescale_normal GL_EXT_secondary_color GL_EXT_separate_specular_color GL_EXT_shadow_funcs GL_EXT_stencil_two_side GL_EXT_stencil_wrap GL_EXT_texture3D GL_EXT_texture_compression_s3tc GL_EXT_texture_cube_map GL_EXT_texture_edge_clamp GL_EXT_texture_env_combine GL_EXT_texture_env_dot3 GL_EXT_texture_filter_anisotropic GL_EXT_texture_lod GL_EXT_texture_lod_bias GL_EXT_texture_mirror_clamp GL_EXT_texture_object GL_EXT_texture_sRGB GL_EXT_timer_query GL_EXT_vertex_array GL_HP_occlusion_test GL_IBM_rasterpos_clip GL_IBM_texture_mirrored_repeat GL_KTX_buffer_region GL_NV_blend_square GL_NV_copy_depth_to_color GL_NV_depth_clamp GL_NV_fence GL_NV_float_buffer GL_NV_fog_distance GL_NV_fragment_program GL_NV_fragment_program_option GL_NV_fragment_program2 GL_NV_half_float GL_NV_light_max_exponent GL_NV_multisample_filter_hint GL_NV_occlusion_query GL_NV_packed_depth_stencil GL_NV_pixel_data_range GL_NV_point_sprite GL_NV_primitive_restart GL_NV_register_combiners GL_NV_register_combiners2 GL_NV_texgen_reflection GL_NV_texture_compression_vtc GL_NV_texture_env_combine4 GL_NV_texture_expand_normal GL_NV_texture_rectangle GL_NV_texture_shader GL_NV_texture_shader2 GL_NV_texture_shader3 GL_NV_vertex_array_range GL_NV_vertex_array_range2 GL_NV_vertex_program GL_NV_vertex_program1_1 GL_NV_vertex_program2 GL_NV_vertex_program2_option GL_NV_vertex_program3 GL_NVX_conditional_render GL_SGIS_generate_mipmap GL_SGIS_texture_lod GL_SGIX_depth_texture GL_SGIX_shadow GL_SUN_slice_accum GL_WIN_swap_hint WGL_EXT_swap_control

glViewport(2, 438, 256, 256)

Does this tell you anything helpful? By the way, I updated my NVidia drivers to the very latest just now. Should I change some of the settings? They are now at the defaults…

  1. When i drag the window, it drags very slow as GLJPanel, both on jdk1.5 and jdk1.6 - is it because I’m not using the openGL switch (the one from question #1)?

  2. If i resize the size of the GLJPanel, it flashes to white (and then draws properly) for every resize. This happens with both JDK 5 and 6.

  3. I know this is unrelated to JSR development, but you said my deleteTexture code was wrong… I suspected as much. But my problem is, I’m not really sure what the best strategy is for what i’m trying to do. What I’m trying to do is to receive frames from QuickTime video, manipulate each frame (twist / turn / etc) and display it. So, each texture for me is just a frame of video that is only displayed once (i.e., i’m not building, say, a game where you’d reuse the same texture over and over), and i need to display them quickly. Given that problem, what would you advice to be the most computationally-efficient strategy? Now for each frame I do:

gl.glBindTexture(GL.GL_TEXTURE_2D, tex.getTextureID());
gl.glPushMatrix();
gl.glColor4f(…) //or some other manipulation
gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(tex2DQuad[0], tex2DQuad[1]);
gl.glVertex3f(tex3DQuad[0], tex3DQuad[1], 0.0f);
gl.glTexCoord2f(tex2DQuad[2], tex2DQuad[3]);
gl.glVertex3f(tex3DQuad[2], tex3DQuad[3], 0.0f);
gl.glTexCoord2f(tex2DQuad[4], tex2DQuad[5]);
gl.glVertex3f(tex3DQuad[4], tex3DQuad[5], 0.0f);
gl.glTexCoord2f(tex2DQuad[6], tex2DQuad[7]);
gl.glVertex3f(tex3DQuad[6], tex3DQuad[7], 0.0f);
gl.glEnd();

gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);

gl.glTexImage2D(GL.GL_TEXTURE_2D,0, 4, texWidth, texHeight, 0, srcPixelFormat, GL.GL_UNSIGNED_BYTE, currByteBuffer);
currByteBuffer.rewind();
//currByteBuffer is a ByteBuffer into which, at each frame I put the new QuickTime frame…
gl.glPopMatrix();

Now, in here I just reuse the same texture (i think??). Is it better if I delete and generate texture each time? Is there some automatic way to purge textures that are not being used?

Thanks a lot!
-LJ

Oh, and one more thing:

It seems that when I use GLJPanel, every time i try to change the size of the GLJPanel:
lw_canvas.setSize(new Dimension(width, height));

it calls init() ! - thus reinitialising the renderer etc. which of course leads the program to die.
when i use the heavyweight GLCanvas, it doesn’t call init after each resize.

the only thing different apart from that between the heavy/lowweight canvases in my code is the following:
if (USE_LIGHTWEIGHT_CANVAS) {
lw_canvas = GLDrawableFactory.getFactory().createGLJPanel(glCaps);
lw_canvas.setVisible(false);
lw_canvas.setSize(new Dimension(width, height));
lw_canvas.setLocation(frameLocation.x, frameLocation.y);
lw_canvas.addGLEventListener(this);
currGLCanvas = lw_canvas;
} else {
canvas = GLDrawableFactory.getFactory().createGLCanvas(glCaps);
canvas.setVisible(false);
canvas.setSize(new Dimension(width, height));
canvas.setLocation(frameLocation.x, frameLocation.y);
canvas.addGLEventListener(this);
currGLCanvas = canvas;
}

and then, in my animator’s run() method:
if(USE_LIGHTWEIGHT_CANVAS)
lw_canvas.display();
else
canvas.display();

What am I doing wrong? This prevents resizing completely - after a couple of calls like that to init() the program goes to 100% cpu and becomes unresponsive.

Thanks!
-LJ

That should work if it is executed before any AWT-related code is touched or initialized, including superclasses of your main class. If you’re instantiating widgets using assignment expressions to data members then those are going to be automatically inserted by javac before the code in your constructor.

Are you running the latest Mustang build? Interoperability between Java2D’s OpenGL pipeline and JOGL should work pretty well in 1.6, though I wouldn’t recommend trying it with 1.5. Does the JRefract demo (with the Java2D/OpenGL pipeline enabled) work on your machine? What about the XTrans demo?

If those demos work then I would think it should be possible to get your application to work. Do you have any other native code in your app aside from JOGL?

Do these problems happen even if you haven’t created any JOGL widgets? If so then that would point to a deeper problem.

It looks like the Java2D/JOGL integration is working and on NVidia hardware I would expect everything to work fine, especially if you’re running the latest drivers.

This is due to an NVidia driver bug affecting Java2D which is supposed to be fixed in a later driver release from NVidia. There is at least one workaround for this which I’m aware of but which I don’t think the Swing team wants advertised publicly. Feel free to send me email or a PM about this.

Do you have a test case for this? Does the same thing happen with the demos in the JRefract harness, in particular when the Java2D/OpenGL pipeline is enabled? I haven’t seen this behavior though something similar does happen for the GLCanvas in Mustang; a workaround for this problem is in progress.

You should use glTexSubImage2D which is much more efficient when updating a texture’s content. The only restriction is that you can’t resize the texture object using that call. You should definitely not delete and recreate the texture object each frame, so your current code is correct.

This is happening because the GLJPanel is usually implemented behind-the-scenes using a pbuffer and each time it is resized beyond the pbuffer’s current size the pbuffer is destroyed and re-created. Thus the application needs to re-initialize any persistent OpenGL state. Your init() method should be written in a way that it supports being called more than once. One-time application initialization should be handled in another way; you can still invoke it from init(), but keep track of whether it has run already.

With the Java2D/JOGL integration this no longer happens, btw. You may still see multiple calls to init() but they don’t occur on resizing of the GLJPanel.

Yes I am running the latest built of Mustang.
Yes, the demos work. The only problem with them is that when I close either of them, I get:

An unexpected error has been detected by Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x7c9105f8, pid=4072, tid=3692

Java VM: Java HotSpot™ Client VM (1.6.0-ea-b58 mixed mode, sharing)

Problematic frame:

C [ntdll.dll+0x105f8]

An error report file with more information is saved as hs_err_pid4072.log

but, as i said, they do run (with JDK 6. It was flashing like crazy with JDK 5 and cpu was 100%).

If you mean to ask whether I myself make JNI calls, then no.
If you mean, do i use any library that uses some DLL, I do. One for audio manipulation, as well as CommAPI. But they weren’t a problem ever before…

In fact the problem with the popup menus doesn’t seem be happening anymore. The only thing I changed is playing with the NVidia driver’s settings… setting it to be performance-optimized and enabling all the different optimizations. Perhaps it solved that problem. In any case, the GLJPanel is still black as long as sun.java2d.opengl is set to true.

[quote] [quote]
It seems that when I use GLJPanel, every time i try to change the size of the GLJPanel:
lw_canvas.setSize(new Dimension(width, height));

it calls init() ! - thus reinitialising the renderer etc. which of course leads the program to die.
when i use the heavyweight GLCanvas, it doesn’t call init after each resize.
[/quote]
This is happening because the GLJPanel is usually implemented behind-the-scenes using a pbuffer and each time it is resized beyond the pbuffer’s current size the pbuffer is destroyed and re-created. Thus the application needs to re-initialize any persistent OpenGL state. Your init() method should be written in a way that it supports being called more than once. One-time application initialization should be handled in another way; you can still invoke it from init(), but keep track of whether it has run already.

With the Java2D/JOGL integration this no longer happens, btw. You may still see multiple calls to init() but they don’t occur on resizing of the GLJPanel.
[/quote]
hmmm. I’m not sure I understand. Are you saying I should implement my GLJPanel drawing using pBuffers? If yes, what would I need to change compared to what I have now?

In any case: I added a check to init() to only run once, but it didn’t solve the problem because it turns out that the GL context now changes each time the size changes! And another piece of code (the one that generates new textures) runs whenever it discovers a new GL context. It obviously used to only change when you would for example add an additional video source which needed to be mixed in (so you needed an additional texture), but now it seems that there is a new GL every time the size changes… So is there a way to keep the GL constant? Or should I do it somehow differently (my decision when to generate a new texture)?
A related question: is it no longer necessary to do
GL gl = drawable.getGL() within each display() call? Should I just make gl a class variable given it seems it now changes at will?
I think I’m getting confused. Sorry about all these questions… just trying to make sense of what’s going on.

Thank you,
-LJ

I heard from a co-worker that this bug has already been filed with NVidia and will be fixed in their next driver release.

Do any of your libraries use DirectDraw internally? There are driver-level incompatibilities between DirectDraw and OpenGL which is the only real reason I can think of that you would see strange problems like the ones you described.

For what it’s worth, I’ve never tried tweaking any of the driver settings except occasionally vsync and have never seen the kind of problem you described with pop-up menus. It’s hard to tell what’s going wrong with the GLJPanel in your application when the OpenGL pipeline is enabled; we made every effort to make it a seamless transition to tne new code path but I guess there are some issues with it. Is it possible for you to construct a self-contained test case for this and file a bug?

[quote]hmmm. I’m not sure I understand. Are you saying I should implement my GLJPanel drawing using pBuffers? If yes, what would I need to change compared to what I have now?
[/quote]
No, I’m just mentioning what is going on inside the GLJPanel and why you’re seeing the behavior upon resize.

You should probably create a new texture object in your init() method, unless you have shared textures and display lists between your GLJPanel and some other GLDrawable. (In this case your texture would still be “kept alive” by the other GLDrawable due to the semantics of texture and display list sharing.) That’s the only place you should need to create a new texture object. You should also initialize it to the appropriate width and height once using glTexImage2D. After that you can repeatedly update the texture’s contents in your display method using glTexSubImage2D.

[quote]A related question: is it no longer necessary to do
GL gl = drawable.getGL() within each display() call? Should I just make gl a class variable given it seems it now changes at will?
[/quote]
You should re-fetch it every frame since that is the best way to make sure you haven’t kept a reference to a stale GL object. The old GL objects are effectively made obsolete every time the context changes.

i’ve been reworking my architecture so that the texture is only generated in the init(), per your suggestion. and, i’m getting confused.

here’s what i’m trying to do:
i want to have an unlimited number of video output ‘screens’ and an unlimited number of video ‘sources’.
i want to be able to put any source to one or MORE screens at the same time, adding and removing as desired (then obviously i want to apply manipulations to each source separately and have them all layer in the output screen).

each screen is a GLCanvas (or a GLJPanel now).
each source is a quicktime video read into a bytebuffer frame by frame.

all this used to work, before i tried to use GLJPanel (the thing with running init() on each resize messed it up and so i have to adapt it per your suggestions).

the way it used to work was: one texture generated per source, which then would be bindTexture() to whatever output screens that were registered as displays for this particular source.

however, this doesn’t work now, because i used to presume i had a continuous GL context to work with and that is no longer the case.

since you said i should only generate textures in the init() method, i now initialize texture just there.

so, with the new structure (where there’s only one texture per screen, not per source), there are two problems:

  1. With GLCanvas, the source shows up on one screen, but if i add another source to that screen, the first source becomes skewed / invisible / etc. Resizing the output windows works.
  2. If however, I try to use GLJPanel, in addition to problems in #1, the second i try to setSize() of the GLJPanel, JVM crashes.

====

An unexpected error has been detected by HotSpot Virtual Machine:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x696737b4, pid=2396, tid=3020

Java VM: Java HotSpot™ Client VM (1.5.0_05-b05 mixed mode)

Problematic frame:

C [nvoglnt.dll+0x1737b4]

An error report file with more information is saved as hs_err_pid2396.log

[error occurred during error reporting, step 270, id 0xc0000005]

what am i doing wrong?
If you’d like I can send you the .log…

thanks a lot,
-LJ

It’s difficult to guess what is happening here. If you share textures and display lists among all of your ‘screens’ then unless all of their OpenGL contexts are destroyed simultaneously then your texture objects will live beyond the destruction and re-creation of your GLJPanel’s pbuffer. You can ensure that this is the case by making a tiny (1x1 or 2x2) pbuffer which shares textures and display lists with the on-screen GLJPanels and which is kept alive for the duration of the application.

I don’t have any guesses about the behavior with the GLCanvas.

I don’t know what your application’s structure is but you may want to consider having only one OpenGL widget and drawing your video on multiple textured quads within that window, which will be much more efficient than switching among multiple OpenGL contexts on the same screen.