Selaa lähdekoodia

* Fixed assertion error bug in NativeObjectManager.deleteAllObjects()
* Fixed ID collision bug in NativeObjectManager by introducing NativeObject.getUniqueId()

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10637 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

sha..RD 12 vuotta sitten
vanhempi
commit
dec182b13f

+ 5 - 0
engine/src/android/com/jme3/audio/android/AndroidAudioData.java

@@ -59,4 +59,9 @@ public class AndroidAudioData extends AudioData {
     public NativeObject createDestructableClone() {
         return new AndroidAudioData(id);
     }
+
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_AUDIOBUFFER << 32) | ((long)id);
+    }
 }

+ 4 - 0
engine/src/core/com/jme3/audio/AudioBuffer.java

@@ -120,4 +120,8 @@ public class AudioBuffer extends AudioData {
         return new AudioBuffer(id);
     }
 
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_AUDIOBUFFER << 32) | ((long)id);
+    }
 }

+ 4 - 1
engine/src/core/com/jme3/audio/AudioStream.java

@@ -199,5 +199,8 @@ public class AudioStream extends AudioData implements Closeable{
         }
     }
 
-    
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_AUDIOSTREAM << 32) | ((long)ids[0]);
+    }
 }

+ 4 - 0
engine/src/core/com/jme3/audio/LowPassFilter.java

@@ -96,4 +96,8 @@ public class LowPassFilter extends Filter {
         return new LowPassFilter(id);
     }
 
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_FILTER << 32) | ((long)id);
+    }
 }

+ 5 - 0
engine/src/core/com/jme3/scene/VertexBuffer.java

@@ -1004,6 +1004,11 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
         return new VertexBuffer(id);
     }
 
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_VERTEXBUFFER << 32) | ((long)id);
+    }
+    
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule oc = ex.getCapsule(this);
         oc.write(components, "components", 0);

+ 9 - 0
engine/src/core/com/jme3/shader/Shader.java

@@ -155,6 +155,11 @@ public final class Shader extends NativeObject {
             return defines;
         }
         
+        @Override
+        public long getUniqueId() {
+            return ((long)OBJTYPE_SHADERSOURCE << 32) | ((long)id);
+        }
+        
         @Override
         public String toString(){
             String nameTxt = "";
@@ -322,4 +327,8 @@ public final class Shader extends NativeObject {
         return new Shader(this);
     }
 
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_SHADER << 32) | ((long)id);
+    }
 }

+ 5 - 0
engine/src/core/com/jme3/texture/FrameBuffer.java

@@ -501,4 +501,9 @@ public class FrameBuffer extends NativeObject {
     public NativeObject createDestructableClone(){
         return new FrameBuffer(this);
     }
+    
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_FRAMEBUFFER << 32) | ((long)id);
+    }
 }

+ 5 - 0
engine/src/core/com/jme3/texture/Image.java

@@ -393,6 +393,11 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ {
         return new Image(id);
     }
 
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_TEXTURE << 32) | ((long)id);
+    }
+    
     /**
      * @return A shallow clone of this image. The data is not cloned.
      */

+ 18 - 1
engine/src/core/com/jme3/util/NativeObject.java

@@ -45,6 +45,15 @@ public abstract class NativeObject implements Cloneable {
 
     public static final int INVALID_ID = -1;
     
+    protected static final int OBJTYPE_VERTEXBUFFER = 1,
+                               OBJTYPE_TEXTURE      = 2,
+                               OBJTYPE_FRAMEBUFFER  = 3,
+                               OBJTYPE_SHADER       = 4,
+                               OBJTYPE_SHADERSOURCE = 5,
+                               OBJTYPE_AUDIOBUFFER  = 6,
+                               OBJTYPE_AUDIOSTREAM  = 7,
+                               OBJTYPE_FILTER       = 8;
+    
     /**
      * The object manager to which this NativeObject is registered to.
      */
@@ -111,7 +120,7 @@ public abstract class NativeObject implements Cloneable {
     public int getId(){
         return id;
     }
-
+    
     /**
      * Internal use only. Indicates that the object has changed
      * and its state needs to be updated.
@@ -199,6 +208,14 @@ public abstract class NativeObject implements Cloneable {
      */
     public abstract NativeObject createDestructableClone();
     
+    /**
+     * Returns a unique ID for this NativeObject. No other NativeObject shall
+     * have the same ID.
+     * 
+     * @return unique ID for this NativeObject.
+     */
+    public abstract long getUniqueId();
+    
     /**
      * Reclaims native resources used by this NativeObject.
      * It should be safe to call this method or even use the object

+ 37 - 32
engine/src/core/com/jme3/util/NativeObjectManager.java

@@ -37,7 +37,7 @@ import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Queue;
+import java.util.HashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -74,7 +74,7 @@ public class NativeObjectManager {
     /**
      * List of currently active GLObjects.
      */
-    private IntMap<NativeObjectRef> refMap = new IntMap<NativeObjectRef>();
+    private HashMap<Long, NativeObjectRef> refMap = new HashMap<Long, NativeObjectRef>();
     
     /**
      * List of real objects requested by user for deletion.
@@ -91,7 +91,8 @@ public class NativeObjectManager {
             assert obj.handleRef != null;
 
             this.realObj = new WeakReference<NativeObject>(obj);
-            this.objClone = obj.createDestructableClone();       
+            this.objClone = obj.createDestructableClone();
+            assert objClone.getId() == obj.getId();
         }
     }
 
@@ -104,7 +105,7 @@ public class NativeObjectManager {
         }
 
         NativeObjectRef ref = new NativeObjectRef(refQueue, obj);
-        refMap.put(obj.getId(), ref);
+        refMap.put(obj.getUniqueId(), ref);
         
         obj.setNativeObjectManager(this);
 
@@ -125,30 +126,34 @@ public class NativeObjectManager {
         
         assert realObj == null || obj.getId() == realObj.getId();
         
-        if (deleteGL && obj.getId() > 0) {
-            // Unregister it from cleanup list.
-            NativeObjectRef ref2 = refMap.remove(obj.getId());
-            if (ref2 == null) {
-                throw new IllegalArgumentException("This NativeObject is not " + 
-                                                   "registered in this NativeObjectManager");
-            }
-
-            assert ref == null || ref == ref2;
-
-            int id = obj.getId();
-            
-            // Delete object from the GL driver
-            obj.deleteObject(rendererObject);
-            assert obj.getId() == NativeObject.INVALID_ID;
-            
-            if (logger.isLoggable(Level.FINEST)) {
-                logger.log(Level.FINEST, "Deleted: {0}", obj.getClass().getSimpleName() + "/" + id);
-            }
-
-            if (realObj != null){
-                // Note: make sure to reset them as well
-                // They may get used in a new renderer in the future
-                realObj.resetObject();
+        if (deleteGL) {
+            if (obj.getId() <= 0) {
+                logger.log(Level.WARNING, "Object already deleted: {0}", obj.getClass().getSimpleName() + "/" + obj.getId());
+            } else {
+                // Unregister it from cleanup list.
+                NativeObjectRef ref2 = refMap.remove(obj.getUniqueId());
+                if (ref2 == null) {
+                    throw new IllegalArgumentException("This NativeObject is not " + 
+                                                       "registered in this NativeObjectManager");
+                }
+
+                assert ref == null || ref == ref2;
+
+                int id = obj.getId();
+
+                // Delete object from the GL driver
+                obj.deleteObject(rendererObject);
+                assert obj.getId() == NativeObject.INVALID_ID;
+
+                if (logger.isLoggable(Level.FINEST)) {
+                    logger.log(Level.FINEST, "Deleted: {0}", obj.getClass().getSimpleName() + "/" + id);
+                }
+
+                if (realObj != null){
+                    // Note: make sure to reset them as well
+                    // They may get used in a new renderer in the future
+                    realObj.resetObject();
+                }
             }
         }
         if (deleteBufs && UNSAFE && realObj != null) {
@@ -194,8 +199,8 @@ public class NativeObjectManager {
      */
     public void deleteAllObjects(Object rendererObject){
         deleteUnused(rendererObject);
-        for (IntMap.Entry<NativeObjectRef> entry : refMap) {
-            NativeObjectRef ref = entry.getValue();
+        ArrayList<NativeObjectRef> refMapCopy = new ArrayList<NativeObjectRef>(refMap.values());
+        for (NativeObjectRef ref : refMapCopy) {
             deleteNativeObject(rendererObject, ref.objClone, ref, true, false);
         }
         assert refMap.size() == 0;
@@ -219,9 +224,9 @@ public class NativeObjectManager {
      * This is typically called when the context is restarted.
      */
     public void resetObjects(){
-        for (IntMap.Entry<NativeObjectRef> entry : refMap) {
+        for (NativeObjectRef ref : refMap.values()) {
             // Must use the real object here, for this to be effective.
-            NativeObject realObj = entry.getValue().realObj.get();
+            NativeObject realObj = ref.realObj.get();
             if (realObj == null) {
                 continue;
             }