Bug 669

Summary: Recursive GLContext makeCurrent() doesn't work
Product: [JogAmp] Jogl Reporter: Sven Gothel <sgothel>
Component: coreAssignee: Sven Gothel <sgothel>
Status: RESOLVED FIXED    
Severity: enhancement CC: gouessej, sgothel, skatejoe1
Priority: ---    
Version: 2   
Hardware: All   
OS: all   
Type: --- SCM Refs:
jogl 34687193484b2404d83eebf5d008b71d54e52286
Workaround: ---

Description Sven Gothel 2013-01-18 01:36:08 CET
If issuing makeCurrent()/release() on a GLContext,
the recursive makeCurrent() fails.

The latter is the subsequent where GLContext is already current
and lock-count > 1.

Phenomenon:
  The call succeeds, however, the lock-count is decreased.

  This results in a failing final release() call, where the 
  'inner' recursive release() call already releases the context.

Observed w/:
  - com.ardor3d.example.canvas.JoglAwtExample
  - and JOGL > RC11

Test case will follow up.
Comment 1 Sven Gothel 2013-01-18 03:40:17 CET
http://jogamp.org/git/?p=jogl.git;a=commit;h=34687193484b2404d83eebf5d008b71d54e52286

    Culprit:
      GLContext's makeCurrent() didn't clear the boolean flag 'unlockContextAndSurface'
      in case the context is already current (-> recursion).
      Above case was detected within a code block tailed by a finally block,
      which acted on mentioned flag, i.e. called lock.unlock() and hence decremented the lock count
      even though the method return w/ successful state.
    
      Fixed.
    
    Added debug code:
      GLContext.release() debug code (DEBUG | TRACE_SWITCH),
      recording stack trace of last release() call, which is dumped in case no current was current.
    
    Added 2 unit tests:
      - Simple recursive GLContext makeCurrent()/release() from within GLEventListener's display().
        Test also validates lock count and lock ownership.
    
      - GLAutoDrawable display() of another GLAutoDrawable
        from within GLEventListener's display(..).
Comment 2 david w 2013-01-19 09:19:15 CET
Hi i wanted to try out your new fix, (was debugging my slow app with visualvm and noticing that makeCurrent(), release and makeCurrentWithinLock was called every frame in invokeGLImpl)

This is the output from the new "TraceSwitch" flag:
AWT-EventQueue-0: GLContext.ContextSwitch[makeCurrent.0]: obj 0x400746fe, ctx 0x7fa2140b3400, surf 0x5000012 - <1dc5ee89, 2daf73a4>[count 0, qsz 0, owner <NULL>]
AWT-EventQueue-0: GLContext.ContextSwitch: - setCurrent() - obj 0x400746fe, ctx 0x7fa2140b3400
AWT-EventQueue-0: GLContext.ContextSwitch[makeCurrent.X3]: obj 0x400746fe, ctx 0x7fa2140b3400, surf 0x5000012 - switch - CONTEXT_CURRENT - <1dc5ee89, 2daf73a4>[count 1, qsz 0, owner <AWT-EventQueue-0>]
AWT-EventQueue-0: GLContext.ContextSwitch[release.0]: obj 0x400746fe, ctx 0x7fa2140b3400, surf 0x5000012, inDestruction: false, <1dc5ee89, 2daf73a4>[count 1, qsz 0, owner <AWT-EventQueue-0>]
AWT-EventQueue-0: GLContext.ContextSwitch: - setCurrent() - NULL
AWT-EventQueue-0: GLContext.ContextSwitch[release.X]: obj 0x400746fe, ctx 0x7fa2140b3400, surf 0x5000012 - switch - <1dc5ee89, 2daf73a4>[count 0, qsz 0, owner <NULL>]

from what i understood from the patch it should go into the state
 final GLContext current = getCurrent();
                if (current != null) {
                    if (current == this) {...}

but getCurrent() is always null.

please respond if you need more details!

regards david
Comment 3 david w 2013-01-20 11:06:53 CET
this happens using GLCanvas on Ubuntu 12.10

(In reply to comment #2)
> Hi i wanted to try out your new fix, (was debugging my slow app with visualvm
> and noticing that makeCurrent(), release and makeCurrentWithinLock was called
> every frame in invokeGLImpl)
> 
> This is the output from the new "TraceSwitch" flag:
> AWT-EventQueue-0: GLContext.ContextSwitch[makeCurrent.0]: obj 0x400746fe, ctx
> 0x7fa2140b3400, surf 0x5000012 - <1dc5ee89, 2daf73a4>[count 0, qsz 0, owner
> <NULL>]
> AWT-EventQueue-0: GLContext.ContextSwitch: - setCurrent() - obj 0x400746fe, ctx
> 0x7fa2140b3400
> AWT-EventQueue-0: GLContext.ContextSwitch[makeCurrent.X3]: obj 0x400746fe, ctx
> 0x7fa2140b3400, surf 0x5000012 - switch - CONTEXT_CURRENT - <1dc5ee89,
> 2daf73a4>[count 1, qsz 0, owner <AWT-EventQueue-0>]
> AWT-EventQueue-0: GLContext.ContextSwitch[release.0]: obj 0x400746fe, ctx
> 0x7fa2140b3400, surf 0x5000012, inDestruction: false, <1dc5ee89,
> 2daf73a4>[count 1, qsz 0, owner <AWT-EventQueue-0>]
> AWT-EventQueue-0: GLContext.ContextSwitch: - setCurrent() - NULL
> AWT-EventQueue-0: GLContext.ContextSwitch[release.X]: obj 0x400746fe, ctx
> 0x7fa2140b3400, surf 0x5000012 - switch - <1dc5ee89, 2daf73a4>[count 0, qsz 0,
> owner <NULL>]
> 
> from what i understood from the patch it should go into the state
>  final GLContext current = getCurrent();
>                 if (current != null) {
>                     if (current == this) {...}
> 
> but getCurrent() is always null.
> 
> please respond if you need more details!
> 
> regards david
Comment 4 Julien Gouesse 2013-01-20 11:37:15 CET
(In reply to comment #3)
> this happens using GLCanvas on Ubuntu 12.10

Do you reproduce this bug with an existing test case? If not, please provide one. This fix works under GNU Linux. Keep in mind that makeCurrent() may fail, look at the return code. I'm not sure your problem has something to do with this fix.
Comment 5 Sven Gothel 2013-01-20 13:24:24 CET
(In reply to comment #2)
> Hi i wanted to try out your new fix, (was debugging my slow app with visualvm
> and noticing that makeCurrent(), release and makeCurrentWithinLock was called
> every frame in invokeGLImpl)
> 

Of course, thats the default behavior.

> 
> from what i understood from the patch it should go into the state
>  final GLContext current = getCurrent();
>                 if (current != null) {
>                     if (current == this) {...}
> 
> but getCurrent() is always null.

Outside of GLEventListener calls it is intended to be null,
otherwise the surface (window, ..) lock would be hold as well.

The fix does fix the use cases as described in the new unit tests
added w/ 34687193484b2404d83eebf5d008b71d54e52286 - please read!

You were probably thinking of an additional feature 
like the Exclusive Context Thread (ECT) as implemented here:
  <http://jogamp.org/git/?p=jogl.git;a=commit;h=224fab1b2c71464826594740022fdcbe278867dc>
Comment 6 Sven Gothel 2013-01-20 13:25:43 CET
(In reply to comment #4)
> (In reply to comment #3)
> > this happens using GLCanvas on Ubuntu 12.10
> 
> Do you reproduce this bug with an existing test case? If not, please provide
> one. This fix works under GNU Linux. Keep in mind that makeCurrent() may fail,
> look at the return code. I'm not sure your problem has something to do with
> this fix.

I think it's only a misunderstanding.

However ..  David, if you think of something else, please provide a full unit test - thx.