Using multiple canvases

Hi, just started using JOGL, and I’ve got a question to ask; apologies if it’s pretty stupid or has been previously covered.

Trying to create two windows, and at the moment each one uses its own GLCanvas and Animator; defining its own init() display() etc methods. Is that not possible, or am i just going about it wrong? Currently it crashes when i try and start the second Animator.

Thanks.

Nobody?

Ive exactly the same Problem- is it possible to have more than one canvas with jogl??

A couple of multithreading bugs (two areas where synchronization was missing) were recently fixed in JOGL; the fixes are in 1.1 b07. Have you tried running with this version?

Just as an FYI: even before upgrading to 1.1b7 I’ve had multiple (at least 4) canvases running and open in my application at the same time.

I’ve just confirmed no issues with opening two canvases in 1.1b7.

Greg.

One of these days i’ll try and re-use the same context too to save me generating display lists for my maps (with more than million + vertices) on each context. :slight_smile:

Thx for the replys- Ill try 1.1b07.

But could somebody post some code which works? Maybe im doing something wrong…

Btw- the exception i get is ‘unable to set pixel format’ or something like this.

The TestContextSharing drmo in the jogl-demos workspace has an example of creating two frames and GLCanvases, though they aren’t animated. Does that demo work on your machine?

But could somebody post some code which works?
Maybe im doing something wrong…

I’m afraid I can’t, but I can tell you that I didn’t do anything special. Just create multiple jframes, each with their own canvas and fpsanimator, and everything else as normal.
I honestly did nothing special at all. This is NOT context sharing of course.

Can you post a short example class which demonstrates the problem? Are running an ATI card by the way?

I had the same problem with Xith3D (which uses JOGL) on the Mac and in Linux. In Windows, it works fine.

My current workaround is to globally synchronize all calls to view.renderOnce() in the rendering loops.


synchronized (SomeSyncClass.class) {
   view.renderOnce();
}

[quote]>
Just create multiple jframes, each with their own canvas and fpsanimator, and everything else as normal.
I honestly did nothing special at all. This is NOT context sharing of course.
[/quote]
Funnily enough I gave this a go in a different appliction over the break, and I’m facing an interesting problem. The application doesn’t crash, however, only one (fps) animator wants to work.

I can instantiate all the JFrames, canvases etc. If I call animator.start() on either of the animators (I have separate instances obviously) then everything is drawn nicely on the associated canvas. However, if I call start() on both, only the first canvas (well, it’s GLEventListener) get’s the init()/reshape()/display() but the second doesn’t and hence doesn’t draw anything.

Quite wierd. I’m even getting errors now which I wasn’t right at the start:

Exception in thread “Thread-5” java.lang.NullPointerException
at net.java.games.jogl.impl.windows.WindowsGLContextFactory.getDummyGL(WindowsGLContextFactory.java:117)
at net.java.games.jogl.impl.windows.WindowsGLContext.choosePixelFormatAndCreateContext(WindowsGLContext.java:279)
at net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.create(WindowsOnscreenGLContext.java:211)
at net.java.games.jogl.impl.windows.WindowsGLContext.makeCurrent(WindowsGLContext.java:135)
at net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.makeCurrent(WindowsOnscreenGLContext.java:110)
at net.java.games.jogl.impl.GLContext.invokeGL(GLContext.java:250)
at net.java.games.jogl.GLCanvas.displayImpl(GLCanvas.java:208)
at net.java.games.jogl.GLCanvas.display(GLCanvas.java:75)
at net.java.games.jogl.Animator$1.run(Animator.java:107)
at java.lang.Thread.run(Thread.java:595)

I think there may be race conditions in that code, which was added relatively recently. Could you please file a bug and post a small test case? Thanks.

Here’s a simple example of the problem. I use a JSplitPane in this example. I think it’s pretty clear that the Animator threads, or maybe the GLCanvas’es, are competing for some resource. When two Animator threads are created, then either a deadlock will occur, or one of the threads starve and nothing gets rendered in that panel.

One interesting observation… If you don’t create an Animator for the GLCanvas, and then if you play around with the JSplitPane to force the two panes to repaint, then they both repaint without any trouble. I’ve tried adding a thread that continuously calls repaint() on the panels, but that doesn’t work.


import net.java.games.jogl.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;

import javax.swing.*;
import javax.swing.event.*;

public class Main extends javax.swing.JFrame {
    private JMenuBar menubar;
    private JMenu fileMenu;
    private JMenuItem fileExit;
    private JPanel leftPanel, rightPanel;
    private JSplitPane splitPane;
    private TestPanel panel1, panel2;
    
    public static void main(String args[]) {
            EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Main().setVisible(true);
            }
        });
    }
    
    public Main() {
        // This call ensures that the JMenuBar will render over the GLCanvas.
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
        
        // Create components.
        splitPane = new JSplitPane();
        leftPanel = new JPanel();
        rightPanel = new JPanel();
        menubar = new JMenuBar();
        fileMenu = new JMenu();
        fileExit = new JMenuItem();
        
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        leftPanel.setLayout(new BorderLayout());        
        leftPanel.setPreferredSize(new Dimension(400, 600));
        splitPane.setLeftComponent(leftPanel);        
        rightPanel.setLayout(new BorderLayout());        
        splitPane.setRightComponent(rightPanel);
        
        getContentPane().add(splitPane, BorderLayout.CENTER);
        
        fileMenu.setText("File");
        fileExit.setText("Exit");
        fileExit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                fileExitActionPerformed(evt);
            }
        });
        
        fileMenu.add(fileExit);        
        menubar.add(fileMenu);        
        setJMenuBar(menubar);
                
        panel1 = new TestPanel();
        panel2 = new TestPanel();
        leftPanel.add(panel1, BorderLayout.CENTER);    
        rightPanel.add(panel2, BorderLayout.CENTER);
        
        pack();
        
        setSize(800, 600);  
        
        // Start the animation on panel 1.
        panel1.start();

/******************************************************
// When we attempt to start the animation on panel 2, the
// program will either lock up or the program will run but 
// panel2 won't render.  It's clear that the two animator
// threads are competing for some resource, causing a 
// deadlock or causing the second thread to starve.
 ******************************************************/
        panel2.start();

    }
    
    private void fileExitActionPerformed(ActionEvent evt) {                                         
        System.exit(0);
    }
    
    public class TestPanel extends JPanel {
        GLCanvas canvas;
        Animator animator;
        
        public TestPanel() {
            // The JPanel must use the Border layout manager.
            setLayout(new java.awt.BorderLayout());
            
            // Create the GLCanvas.
            canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
            canvas.addGLEventListener(new TestRenderer());
            
            // Create an animator thread for the canvas.
            animator = new Animator(canvas);
            
            // Add the canvas to the center of the JPanel.
            add(canvas);
            
            // We need to create a Dimension object for the JPanel minimum size to fix a GLCanvas resize bug.
            // The GLCanvas normally won't recieve resize events that shrink a JPanel controled by a JSplitPane.  
            setMinimumSize(new Dimension());             
        }
        
        public void start(){
            animator.start();
        }
        
        public void stop(){
            animator.stop();
        }
        
        class TestRenderer implements GLEventListener {
            private GL gl;
            private GLDrawable gldrawable;
            float angle = 0;
            
            public void init(GLDrawable drawable) {        
                gl = drawable.getGL();
                this.gldrawable = drawable;
            }
            
            public void reshape(GLDrawable drawable, int x, int y, int width, int height) {
                gl. glViewport(0, 0, width, height);
            }
            
            public void display(GLDrawable drawable) {
                gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
                
                gl.glRotatef(angle, 0f, 0f, 1f);
                angle += 2;
                
                gl.glBegin(GL.GL_POLYGON);
                gl.glVertex2f(-0.5f, -0.5f);
                gl.glVertex2f(-0.5f, 0.5f);
                gl.glVertex2f(0.5f, 0.5f);
                gl.glVertex2f(0.5f, -0.5f);
                gl.glEnd();
            }
            
            public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
        }
    }
}

Could you please go to http://jogl.dev.java.net/, click on “Membership”, request Observer status (I’ll approve it right away), open a bug with the Issue Tracker, and attach this test case? These forums are transient and the Issue Tracker is the only way we can manage reports like these. Thanks.

This is a noob question, but is it possible to have two canvas’ one transparent over the other?
Then to be able to interact with each at the same time?
Or will I have to generate multiple canvas’ for each object I want to appear over the other?

You normally wouldn’t do this kind of stuff with two canvases. just render the two objects in the same canvas with alpha blending enabled.