Renderer.updateTexture2DSubImage...

classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Renderer.updateTexture2DSubImage...

ThomasR
Hi,

How to use this? I'm trying to update a texture in place (ie, w/o modifying the scene graph) but I get this exception:

com.jogamp.opengl.GLException: pool-1-thread-9: No OpenGL context current on this thread
        at com.jogamp.opengl.GLContext.getCurrentGL(GLContext.java:510)
        at com.ardor3d.renderer.jogl.JoglRenderer.updateTexSubImage(JoglRenderer.java:547)
        at com.ardor3d.renderer.jogl.JoglRenderer.updateTexture2DSubImage(JoglRenderer.java:521)

First of all, is this the proper use of this method? I want to rapidly update the byte values of a texture.
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
Hey

The error message is crystal clear, you must do it when the OpenGL context is current on the thread. You have to use com.ardor3d.util.GameTaskQueueManager.getManager() when the RenderContext is not null (after initialization), then call getQueue(), and finally enqueue(Callable).

You mustn't try to make the OpenGL context current on several threads at the same time. I think that you try to implement multi-threading at the wrong place.

I do the same in my game, I have to update a texture that I render in real time on a cube. The web project space is still down on Sourceforge :s
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
Hi,

So FrameHandler.updateFrame(), which can be called from any thread I think, internally ensures that the subsequent Scene.draw() is called on the OpenGL rendering thread (the one that has the Context)?

Will something like this work:

      com.ardor3d.renderer.Renderer renderer;
     ByteBuffer bf;

       Callable updateCallable = new Callable() {
          public Object call() {
             renderer.updateTexture2DSubImage(texture2D, 0, 0, texW, texH, bf, 0, 0, texW);            
             return null;
          }
       };
       GameTaskQueue uQueue = myQueueManager.getQueue(GameTaskQueue.UPDATE); // Or RENDER or BOTH???
       uQueue.enqueue(updateCallable);
       uQueue.execute();

Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
The canvas or window uses GLAutoDrawable.invoke(true, GLRunnable) in its method draw(CountDownLatch) to ensure that the drawing occurs on the thread on which the OpenGL context is current.

You don't need to put your callable into both queues. The stuffs of the update queue are treated before those of the render queue.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
I receive the same exception as above, but from my Callable's call method? This must not be the correct queue?
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
I use a flag to prevent the engine from making the context and releasing it, that's why it works in my case but not in yours. I have to find where I do this...
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
okay, thanks for the help. At your convenience.
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
You have to set contextDropAndReclaimOnDrawEnabled to false when you create your JoglCanvasRenderer or to call Renderer.makeContextCurrent() and releaseCurrentContext() in your callable.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
Hi there,

Callable() {
   JoglCanvasRenderer.makeContextCurrent()
     updateTexture
  JoglCanvasRenderer.releaseCurrrentContext()
}

Works! Thank you for the tip!  I need to work with this for a more general approach in our system.

However, contextDropAndReclaimOnDrawEnabled=false does NOT work. Looking at the code a bit, I think this boolean is not checked in time, ie. updateTexture wants to know the context is current before the draw() method is called. Not sure.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
How do you build your canvas renderer? It doesn't work in your case but it works in mine because this is what I have done for years in my game. As the context is made current once and released only at the end of the execution, when I'm on the correct thread, the renderer succeeds in retrieving the context. When contextDropAndReclaimOnDrawEnabled is set to true, it's up to the programmer to ensure that the OpenGL context is current before using OpenGL calls in enqueued callables because you could wish to perform some non OpenGL related operations before rendering.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
        canvasRenderer = new JoglCanvasRenderer(dspRenderer, false, null, false);
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
Do you override Scene.renderUnto(Renderer)?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
MyScene extends Scene {
   Node root; // the top level node for this display

   @Override
   public boolean renderUnto(Renderer renderer) {
      root.onDraw(renderer);
      return true;
   }
}

myCanvasRenderer = new JoglCanvasRenderer(myScene, false, null, false);
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
    @Override
    public final boolean renderUnto(final Renderer renderer) {
        final boolean isOpen = !canvas.isClosing();
        if (isOpen) {// draws the root and all its children
            renderer.draw(root);
            // executes all update tasks queued by the controllers
            GameTaskQueueManager.getManager(canvas.getCanvasRenderer().getRenderContext())
                    .getQueue(GameTaskQueue.UPDATE).execute(renderer);
            // executes all rendering tasks queued by the controllers
            GameTaskQueueManager.getManager(canvas.getCanvasRenderer().getRenderContext())
                    .getQueue(GameTaskQueue.RENDER).execute(renderer);
        }
        return (isOpen);
    }
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
Hi,

Thanks, I will study this. But looking at this makes me consider a few things. I've been having an issue trying to make sure that the Transform and changes to the Scene can appear to happen atomically to the user. Is it okay to modify the Scene (detach/attach, etc) attached to a CanvasRender from an application thread (user thread, not the EDT or any Ardor or JOGL threads) separate from the thread calling renderUnto? When I experiment and move the modification to the the latter, it's much better.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
Rather use the source code above and push your modifications as Callable instances into the update queue. The engine allows to implement more or less the traditional approach:
while (!canvas.isClosing()) {
    update();
    render();
}
If you modify something in another thread while the one on which the OpenGL context is current, bad things might happen and it's not specific to JogAmp's Ardor3D Continuation. It's possible to add some proper synchronization to prevent those bad things from happening but it's not worth it.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
Hi,

Okay, I will work on this. I'll be on travel for little while, so you get a much deserved vacation from me! Thanks for your prompt and helpful conversations!

Tom
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

gouessej
Administrator
Lol. You're welcome. I'm here even during my holidays ;)
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
Hi,

The OpenGL context is current on the thread calling Scene.renderUnto when contextDropAndReclaimOnDrawEnabled=false?
If contextDropAndReclaimOnDrawEnabled=true then the OpenGL context could be made current (via Renderer.makeContextCurrent()) on a thread other than this one?

Some thread calling Queue.execute runs the code in the Callable (another thread is not spawned)?
Reply | Threaded
Open this post in threaded view
|

Re: Renderer.updateTexture2DSubImage...

ThomasR
these were just questions posed to summarize this thread a bit. Answers: True, True, True (I think, based on some experimentation)
12