1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.jme3.util; 34 35 import java.lang.ref.PhantomReference; 36 import java.lang.ref.ReferenceQueue; 37 import java.lang.ref.WeakReference; 38 import java.util.ArrayList; 39 import java.util.logging.Level; 40 import java.util.logging.Logger; 41 42 /** 43 * GLObjectManager tracks all GLObjects used by the Renderer. Using a 44 * <code>ReferenceQueue</code> the <code>GLObjectManager</code> can delete 45 * unused objects from GPU when their counterparts on the CPU are no longer used. 46 * 47 * On restart, the renderer may request the objects to be reset, thus allowing 48 * the GLObjects to re-initialize with the new display context. 49 */ 50 public class NativeObjectManager { 51 52 private static final Logger logger = Logger.getLogger(NativeObjectManager.class.getName()); 53 54 /** 55 * The queue will receive notifications of {@link NativeObject}s which are no longer 56 * referenced. 57 */ 58 private ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); 59 60 /** 61 * List of currently active GLObjects. 62 */ 63 private ArrayList<NativeObjectRef> refList 64 = new ArrayList<NativeObjectRef>(); 65 66 private class NativeObjectRef extends PhantomReference<Object>{ 67 68 private NativeObject objClone; 69 private WeakReference<NativeObject> realObj; 70 NativeObjectRef(NativeObject obj)71 public NativeObjectRef(NativeObject obj){ 72 super(obj.handleRef, refQueue); 73 assert obj.handleRef != null; 74 75 this.realObj = new WeakReference<NativeObject>(obj); 76 this.objClone = obj.createDestructableClone(); 77 } 78 } 79 80 /** 81 * Register a GLObject with the manager. 82 */ registerForCleanup(NativeObject obj)83 public void registerForCleanup(NativeObject obj){ 84 NativeObjectRef ref = new NativeObjectRef(obj); 85 refList.add(ref); 86 if (logger.isLoggable(Level.FINEST)) 87 logger.log(Level.FINEST, "Registered: {0}", new String[]{obj.toString()}); 88 } 89 90 /** 91 * Deletes unused GLObjects 92 */ deleteUnused(Object rendererObject)93 public void deleteUnused(Object rendererObject){ 94 while (true){ 95 NativeObjectRef ref = (NativeObjectRef) refQueue.poll(); 96 if (ref == null) 97 return; 98 99 refList.remove(ref); 100 ref.objClone.deleteObject(rendererObject); 101 if (logger.isLoggable(Level.FINEST)) 102 logger.log(Level.FINEST, "Deleted: {0}", ref.objClone); 103 } 104 } 105 106 /** 107 * Deletes all objects. Must only be called when display is destroyed. 108 */ deleteAllObjects(Object rendererObject)109 public void deleteAllObjects(Object rendererObject){ 110 deleteUnused(rendererObject); 111 for (NativeObjectRef ref : refList){ 112 ref.objClone.deleteObject(rendererObject); 113 NativeObject realObj = ref.realObj.get(); 114 if (realObj != null){ 115 // Note: make sure to reset them as well 116 // They may get used in a new renderer in the future 117 realObj.resetObject(); 118 } 119 } 120 refList.clear(); 121 } 122 123 /** 124 * Resets all {@link NativeObject}s. 125 */ resetObjects()126 public void resetObjects(){ 127 for (NativeObjectRef ref : refList){ 128 // here we use the actual obj not the clone, 129 // otherwise its useless 130 NativeObject realObj = ref.realObj.get(); 131 if (realObj == null) 132 continue; 133 134 realObj.resetObject(); 135 if (logger.isLoggable(Level.FINEST)) 136 logger.log(Level.FINEST, "Reset: {0}", realObj); 137 } 138 refList.clear(); 139 } 140 141 // public void printObjects(){ 142 // System.out.println(" ------------------- "); 143 // System.out.println(" GL Object count: "+ objectList.size()); 144 // for (GLObject obj : objectList){ 145 // System.out.println(obj); 146 // } 147 // } 148 } 149