AWTGLCanvas with Linux paint loop leak

Started by broumbroum, January 16, 2009, 15:25:33

Previous topic - Next topic

broumbroum

HI ! This is the first time I try porting my code to Linux and it is worth to say that LWJGL is a good lib. However, I'm not able to init the LWJGL screen with my AWTGLCanvas extension, which has worked on Windows and Mac.
I'm wondering if the Thread context handler is much eager on Linux. I think if my code is well designed, especially with the context switch. Could someone check upon this sample ? :
if ((mode & options.MODE_RENDER_GL.bit()) != 0) {
  889                     if (initGL) {/*getContext() == null) {*/
  890                         /** initGL context with a call to super.paint()*/
  891                         try {
  892                             SwingUtilities.invokeAndWait(new Runnable() {
  893 
  894                                 public void run() {
  895                                     try {
  896                                         final CoalescedThreadsMonitor monitor0 = bufferSynch;
  897                                         synchronized (monitor0.getMonitor()) {
  898                                             if (buffering) {
  899                                                 System.err.println("RenderingScene screen task is waitin' for buffering...");
  900                                             }
  901                                             while (buffering) {
  902                                                 System.err.print(".");
  903                                                 monitor0.waitOnMonitor();
  904                                             }
  905                                             rendering = true;
  906                                             Graphics g = getGraphics();
  907                                             update(g);
  908                                             g.dispose();
  909                                             monitor0.notifyOnMonitor();
  910                                         }
  911                                     } catch (Exception e) {
  912                                         e.printStackTrace(System.out);
  913                                     } finally {
  914                                         try {
  915                                             releaseContext();
  916                                             initGL = false;
  917                                             final CoalescedThreadsMonitor monitor1 = vSynch;
  918                                             synchronized (monitor1.getMonitor()) {
  919                                                 rendering = false;
  920                                                 monitor1.notifyAllOnMonitor();
  921                                             }
  922                                             System.out.println("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\screen flushed - " + System.currentTimeMillis());
  923                                         } catch (LWJGLException ex) {
  924                                             ex.printStackTrace();
  925                                         }
  926                                     }
  927                                 }
  928                             });
  929                         } catch (Exception ex) {
  930                             ex.printStackTrace();
  931                         }
  932                     } 

I've initialized the Canvas over Swing-EDT--initially with the AWTGLCanvas new instance creation--and yet the SwingEDT has just released the LWJGL Thread above. Now rendering is done on a dedicated Timer until the user stops it manually :
else {
  933                         try {
  934                             final CoalescedThreadsMonitor monitor0 = bufferSynch;
  935                             synchronized (monitor0.getMonitor()) {
  936                                 if (buffering) {
  937                                     System.err.println("RenderingScene screen task is waitin' for buffering...");
  938                                 }
  939                                 while (buffering) {
  940                                     System.err.print(".");
  941                                     monitor0.waitOnMonitor();
  942                                 }
  943                                 rendering = true;
  944                                 paintGL();
  945                                 swapBuffers();
  946                                 markFPS();
  947                                 monitor0.notifyOnMonitor();
  948                             }
  949                         } catch (Exception e) {
  950                             e.printStackTrace(System.out);
  951                         } finally {
  952                             try {
  953                                 releaseContext();
  954                                 initGL = false;
  955                                 final CoalescedThreadsMonitor monitor1 = vSynch;
  956                                 synchronized (monitor1.getMonitor()) {
  957                                     rendering = false;
  958                                     monitor1.notifyAllOnMonitor();
  959                                 }
  960                                 System.out.println("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\screen flushed - " + System.currentTimeMillis());
  961                             } catch (LWJGLException ex) {
  962                                 ex.printStackTrace();
  963                             }
  964                         }
  965                     }
  966                 }

This is all part of one TimerTask run() method.
Issue is with Linux, where I received a XLib : async error and the jvm crashes , which turns out to be a Thread context error. Think about that the LWJGL demos run well (except for the openAL ALC sound)... ::)

broumbroum


broumbroum

I found out how to correct my code. I'll post the solution further... :D thanks to you who read my posts !

broumbroum

SO to correct the bug above, it's quite simple : we use SwingEDT to render and a Timer to send an update event as if you were rendering softly.
               
/** within any external Timer/Thread loop */
     try {
                            SwingUtilities.invokeAndWait(LWJGLrender);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        } finally {
                            System.out.println("XXXX GL CONTEXT SHOULD BE INITIED XXXX");
                        }
   

the LWJGLrender Swing Runnable looks like the Swing soft update call, adding releaseContext() in the case you want to render else where too (which is thoroughly NOT recommended) :
        public void run() {
            try {
                final CoalescedThreadsMonitor monitor0 = bufferSynch;
                synchronized (monitor0.getMonitor()) {
                    if (buffering) {
                        System.err.println("RenderingScene screen task is waitin' for buffering...");
                    }
                    while (buffering) {
                        System.err.print(".");
                        monitor0.waitOnMonitor();
                    }
                    rendering = true;
                    Graphics g = getGraphics();
                    update(g);
                    g.dispose();
                    monitor0.notifyOnMonitor();
                }
            } catch (Exception e) {
                e.printStackTrace(System.out);
            } finally {
                try {
                    releaseContext();
                    final CoalescedThreadsMonitor monitor1 = vSynch;
                    synchronized (monitor1.getMonitor()) {
                        rendering = false;
                        monitor1.notifyAllOnMonitor();
                    }
                    System.out.println("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\screen flushed - " + System.currentTimeMillis());
                } catch (LWJGLException ex) {
                    ex.printStackTrace();
                }
            }
        }
   

the most IMPORTANT is paintGL() which HAS TO INCLUDE SWAPBUFFERS() :
protected void paintGL() {
        try {
            if ((mode & options.MODE_RENDER_GL.bit()) == 0) {
                return;
            }
            makeCurrent(); // not used
            super.paintGL();
            /*GLContext.useContext(getContext());*/
            _GL_reshape(this);
            /* clear screen*/
            GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
// RENDERING IS DONE HERE
            GL11.glFlush();
            swapBuffers();
            markFPS();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
   

Think about that this uses the AWTGLCanvas and not Display !!! ;D

Matzon