GL_OUT_OF_MEMORY at random times

Hello,

I have a program which paints 2 textures (800x600) onto 2D rectangles in 3D space. Each texture is rendered with a TextureRenderer using Chris Cambell’s method from the BezierAnim3D demo. However, sometimes it crashes after using it for a few minutes (I can’t reproduce it reliably) with the following trace:

exception in QueueFlusher:
javax.media.opengl.GLException: glGetError() returned the following error codes after a call to glEnd(): GL_OUT_OF_MEMORY
at javax.media.opengl.DebugGL.checkGLGetError(DebugGL.java:12715)
at javax.media.opengl.DebugGL.glEnd(DebugGL.java:1929)
at prefuse3D.LayoutPlane.displayPrefuseRenderer(LayoutPlane.java:1349)
at prefuse3D.LayoutPlane.display(LayoutPlane.java:1510)
at prefuse3D.Display3D.render(Display3D.java:2114)
at prefuse3D.Display3D.display(Display3D.java:1832)
at com.sun.opengl.impl.GLDrawableHelper.display(GLDrawableHelper.java:78)
at javax.media.opengl.GLJPanel$Updater.display(GLJPanel.java:1046)
at javax.media.opengl.GLJPanel$DisplayAction.run(GLJPanel.java:1203)
at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
at javax.media.opengl.GLJPanel$2.run(GLJPanel.java:629)
at sun.java2d.opengl.OGLRenderQueue$QueueFlusher.run(OGLRenderQueue.java:203)

I tried to use texture.getEstimatedMemorySize() and it is 6380660 and constant throughout. The rendering code follows. Any suggestions would be appreciated!


    
private void displayPrefuseRenderer(GL gl) {
        // Draw to the animRenderer's texture using Java 2D
    	gl.glBlendFunc( GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
    	
        // Draw from the animRenderer's texture using JOGL
        if (repaint) {
        	updateAnimRenderer(); 
        	tex = prefuseRenderer.getTexture();
        	repaint = false;
        }
        
        // constant getTexture() doesn't slow it down, redraw (update) texture does
        
        TextureCoords tc = tex.getImageTexCoords();
        float tx1 = tc.left();
        float ty1 = tc.top();
        float tx2 = tc.right();
        float ty2 = tc.bottom();

        // Use the GL_MODULATE texture function to effectively multiply
        // each pixel in the texture by the current alpha value
        gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);

        double x = -bounds.getWidth()/2;
        double y = -bounds.getHeight()/2;
        double w = bounds.getWidth();
        double h = bounds.getHeight();

        tex.bind();
        tex.enable();
        
        // draw at an offset equivalent to the plane's fill offset
        gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
    	gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
    	gl.glPolygonOffset(2f, 2f);

        gl.glBegin(GL.GL_QUADS);
        // Render image 
        float a = 255;
        gl.glColor4f(a, a, a, a);
                gl.glTexCoord2f(tx1, ty1); gl.glVertex3d(x  , y+h, 0f);
        	gl.glTexCoord2f(tx2, ty1); gl.glVertex3d(x+w, y+h, 0f);
        	gl.glTexCoord2f(tx2, ty2); gl.glVertex3d(x+w, y  , 0f);
        	gl.glTexCoord2f(tx1, ty2); gl.glVertex3d(x  , y  , 0f);
        gl.glEnd(); [b]<- this is line 1349 from the stack trace[/b]
        tex.disable();
        gl.glBlendFunc( GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA );
}

private void initPrefuseRenderer() {
        // Create the BezierAnim renderer
        prefuseRenderer = new TextureRenderer((int)getWidth(),(int)getHeight(), true);
}

private void updateAnimRenderer() {
        Graphics2D g2d = prefuseRenderer.createGraphics();
        paintDisplay(g2d, getBounds().getSize());
        g2d.dispose();
        prefuseRenderer.markDirty(0, 0, (int)getWidth(), (int)getHeight());
}


Sorry, I should add that I’m using JOGL 1.1.0 and I have an NVIDIA GeForce 8800 GTX with the latest drivers, running under Vista.

Also, in subsequent rendering routines after the initial error, the following trace is generated. Actually, sometimes this is the initial error:

exception in QueueFlusher:
javax.media.opengl.GLException: glGetError() returned the following error codes after a call to glTexImage2D(): GL_OUT_OF_MEMORY
at javax.media.opengl.DebugGL.checkGLGetError(DebugGL.java:12715)
at javax.media.opengl.DebugGL.glTexImage2D(DebugGL.java:9034)
at com.sun.opengl.util.texture.Texture.updateImage(Texture.java:520)
at com.sun.opengl.util.texture.Texture.updateImage(Texture.java:358)
at com.sun.opengl.util.texture.Texture.(Texture.java:159)
at com.sun.opengl.util.texture.TextureIO.newTexture(TextureIO.java:446)
at com.sun.opengl.util.j2d.TextureRenderer.ensureTexture(TextureRenderer.java:676)
at com.sun.opengl.util.j2d.TextureRenderer.sync(TextureRenderer.java:652)
at com.sun.opengl.util.j2d.TextureRenderer.getTexture(TextureRenderer.java:293)
at prefuse3D.LayoutPlane.displayPrefuseRenderer(LayoutPlane.java:1304)
at prefuse3D.LayoutPlane.display(LayoutPlane.java:1510)
at prefuse3D.Display3D.render(Display3D.java:2114)
at prefuse3D.Display3D.display(Display3D.java:1832)
at com.sun.opengl.impl.GLDrawableHelper.display(GLDrawableHelper.java:78)
at javax.media.opengl.GLJPanel$Updater.display(GLJPanel.java:1046)
at javax.media.opengl.GLJPanel$DisplayAction.run(GLJPanel.java:1203)
at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
at javax.media.opengl.GLJPanel$2.run(GLJPanel.java:629)
at sun.java2d.opengl.OGLRenderQueue$QueueFlusher.run(OGLRenderQueue.java:203)

Chris

Looking at the TextureRenderer spec, you’re supposed to call the dispose() method of Graphics after you’re done using it. I don’t know if this created Graphics object has anything extra linked to Graphics memory, but you might try it. Also, I find it odd that the TextureRenderer is making a new Texture when ensureTexture() is called. This method isn’t in the api docs, so I’m not sure what or when it’s used.

Thanks for taking a look at this – I am calling g2d.dispose() in the texture update routine (“updateAnimRenderer”). I’m not sure about the use of ensureTexture() – this is part of the stack that is called directly by J2D/JOGL bridge code.

Chris

oops, didn’t notice that in there before :slight_smile:

Does the same problem occur if you run without -Dsun.java2d.opengl=true?

If you look at the process’s size with the Task Manager, does it grow very large up until the point where GL_OUT_OF_MEMORY is thrown?

Hi, thanks for your reply.

I was running it with the following options:

-Dsun.java2d.opengl=True
-Dsun.java2d.noddraw=true
-Djogl.debug.Java2D
-Djogl.debug.GLJPanel

I just checked it and there is no spike in memory usage – it’s constant around 188MB throughout usage and after the exception is first thrown. It’s quite large because I’m doing data visualization and I need a lot of memory for the data, but it shouldn’t be a problem because I’m using -Xmx1024m.

If I’m using the same TextureRenderer everytime, I think it tex.bind() should overwrite the texture in graphics memory, right? I shouldn’t be running out of graphics memory.

Tried it without the first two above options, framerate was 1/10 original, and it still crashed after a while, with the following trace:


java.lang.reflect.InvocationTargetException
	at java.awt.EventQueue.invokeAndWait(EventQueue.java:997)
	at javax.swing.SwingUtilities.invokeAndWait(SwingUtilities.java:1323)
	at com.sun.opengl.util.Animator.display(Animator.java:158)
	at com.sun.opengl.util.Animator$MainLoop.run(Animator.java:181)
	at java.lang.Thread.run(Thread.java:619)
Caused by: javax.media.opengl.GLException: Error making context current: 6
	at com.sun.opengl.impl.windows.WindowsGLContext.makeCurrentImpl(WindowsGLContext.java:169)
	at com.sun.opengl.impl.windows.WindowsPbufferGLContext.makeCurrentImpl(WindowsPbufferGLContext.java:102)
	at com.sun.opengl.impl.GLContextImpl.makeCurrent(GLContextImpl.java:134)
	at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:182)
	at com.sun.opengl.impl.GLPbufferImpl.maybeDoSingleThreadedWorkaround(GLPbufferImpl.java:208)
	at com.sun.opengl.impl.GLPbufferImpl.display(GLPbufferImpl.java:88)
	at javax.media.opengl.GLJPanel.paintComponent(GLJPanel.java:638)
	at prefuse3D.Display3D.paintComponent(Display3D.java:713)
	at javax.swing.JComponent.paint(JComponent.java:1027)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5122)
	at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:285)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1128)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5070)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4880)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:723)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:679)
	at com.sun.opengl.util.Animator$1.run(Animator.java:302)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

To make it crash I’ve been doing a lot of interaction to force many updates of the texture (the texture is a Java 2D graphic that is interactive). I tried running it a while just changing the camera angle but not reloading textures, and it didn’t crash.

I’ll keep looking for the problem.

Chris

Hi! I’m used to deal with OutOfMemory Error in Java for a while and your problem can be solved by using a cache/buffer Map. Because when Java2D instances your textures, new memory allocations are created each time. One more ImageObserver implies one more buffer. As you described the issue, java2D crashes in out of memory when you reload the texture. You should know that the Scaling operation makes a copy of the image to do scaling transforms. I can share you a cache/buffer Map that I use for my own programs. It’s based on an IBM dev’s research that resolves OutOfMemory Exception throughout a memoryCallback(). It can invoke such called “Memory Sensitive Methods” to resolve overflows. I have an active post with this what I named the SpritesCacheManager. Please use it ! here’s the post (I comment in English though my post is in French written). :slight_smile:

Thanks for the link to the code – I took a look at that site and code (thanks for Canadian French education!) and I’m a bit confused. It looks like your system manages regular memory – isn’t GL_OUT_OF_MEMORY an error of out of graphics memory?

As I mentioned to Ken, the actual memory usage doesn’t seem to spike before the error occurs.

Chris

it’s all about heap memory usage, indeed, not system memory. there’s a java function that can return the heap usage. :wink:

My best guess is you’re leaking OpenGL texture objects somewhere in your app, although this should show up as a steadily increasing process size. The Java 2D/JOGL bridge isn’t 100% robust so I would suggest trying to debug without it enabled.