JME2: texture cache does not seem to work

I am using the code in jmetest.util.JMESWTTest.MyImplementor as my graphics model.  I load it from file and display it in an RCP editor window in my app.  The first time I open an editor the rotating monkey cube is fine.  Subsequent openings show the rotating cube, with random colors, but no textures.



After tracing through the code for a while it seems that the first instance of the model loads the monkey texture and puts it in the cache (i.e. com.jme.scene.state.lwjgl.LWJGLTextureState.load(int)).  Subsequent instances of the model recognize that the monkey texture has already been loaded and simply call a "bind" (i.e. GL11.glBindTexture(int target, int texture)).  However, this fails to make the texture appear.

If, however, I call TextureManager.clearCache() before instantiating the model then the textures always appear.  So, my conclusion is that something about the texture cache is broken.



The critical code which detects the cache hit and calls the bind is in com.jme.scene.state.lwjgl.LWJGLTextureState…



                if (texture.getTextureId() == 0) {
                    // texture not yet loaded.
                    // this will load and bind and set the records...
                    load(i);
                    if (texture.getTextureId() == 0)
                        continue;
                } else {
                    // texture already exists in OpenGL, just bind it if needed
                    if (!unitRecord.isValid()
                            || unitRecord.boundTexture != texture
                                    .getTextureId()) {
                        checkAndSetUnit(i, record);
                        GL11.glBindTexture(getGLType(type), texture
                                .getTextureId());
                        if (Debug.stats) {
                            StatCollector.addStat(StatType.STAT_TEXTURE_BINDS, 1);
                        }
                        unitRecord.boundTexture = texture.getTextureId();
                    }
                }



Note that texture.getTextureId() is always 2, unitRecord.isValid() is always false, and unitRecordBoundTexture is always -1, which means that the cache is hit (as per the code comments) and the bind -- and only the bind -- is called.

Unfortunately your conclusion is most likely wrong.  The problem is that subsequent openings of the window belong to different gl contexts and therefore do not have access to textures loaded in the first window.

This begs the question, should the cache also track the context so that "false hits" do not occur?



In any case, what is the recommended procedure for sharing the context amongst canvases and/or sharing the textures amongst contexts?

In any case, what is the recommended procedure for sharing the context amongst canvases and/or sharing the textures amongst contexts?

IMO jME should automatically share contexts when it detects another one already exists. It makes things faster too.

I agree.  Does your context system address that, and if so, can you provide a patch to the current svn?

Unfortunately my code is not even aware of the context, and I am a babe in the woods when it comes to JME.  In tracing the code there seems to be a whole lot of infrastructure (e.g. states, records, units, etc.) that I have only a vague notion of what it does much less how to modify it.



That said, if you give me some pointers I'll add it to my task list and take a stab at it.



BTW:  Do you recommend incorporating context as a secondary key for the texture cache, or trying to share contexts/textures?.

renanse: I am not sure about how it works in JOGL, but in LWJGL, there's a special constructor for each type of opengl context that takes a shared_drawable parameter.


Code:
            LWJGLContext parent = (LWJGLContext) context.getParentContext();             if (parent==null){                 Display.create(pf);             }else{                 // use the parent pixel format otherwise context creation will result in a crash                 Display.create(parent.getPixelFormat(), parent.getDrawable());             }
Code:
public LWJGLCanvas(LWJGLContext cx, PixelFormat pf, Drawable shared_drawable) throws LWJGLException {     super(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(), pf, shared_drawable);
Code:
if (parent != null){                 pb = new Pbuffer(gs.getWidth(),gs.getHeight(), parent.getPixelFormat(), parent.getDrawable());             }else{                 pf = new PixelFormat(gs.getAlphaBits(),gs.getDepthBits(),gs.getStencilBits(),gs.getSamples());                 pb = new Pbuffer(gs.getWidth(),gs.getHeight(),pf,null);             }