1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.renderscript; 18 19 import java.util.concurrent.locks.ReentrantReadWriteLock; 20 21 /** 22 * BaseObj is the base class for all RenderScript objects owned by a RS context. 23 * It is responsible for lifetime management and resource tracking. This class 24 * should not be used by a user application. 25 * 26 **/ 27 public class BaseObj { 28 BaseObj(int id, RenderScript rs) { 29 rs.validate(); 30 mRS = rs; 31 mID = id; 32 mDestroyed = false; 33 } 34 35 void setID(int id) { 36 if (mID != 0) { 37 throw new RSRuntimeException("Internal Error, reset of object ID."); 38 } 39 mID = id; 40 } 41 42 /** 43 * Lookup the native object ID for this object. Primarily used by the 44 * generated reflected code. 45 * 46 * @param rs Context to verify against internal context for 47 * match. 48 * 49 * @return int 50 */ 51 int getID(RenderScript rs) { 52 mRS.validate(); 53 if (mDestroyed) { 54 throw new RSInvalidStateException("using a destroyed object."); 55 } 56 if (mID == 0) { 57 throw new RSRuntimeException("Internal error: Object id 0."); 58 } 59 if ((rs != null) && (rs != mRS)) { 60 throw new RSInvalidStateException("using object with mismatched context."); 61 } 62 return mID; 63 } 64 65 void checkValid() { 66 if (mID == 0) { 67 throw new RSIllegalArgumentException("Invalid object."); 68 } 69 } 70 71 private int mID; 72 private boolean mDestroyed; 73 private String mName; 74 RenderScript mRS; 75 76 /** 77 * setName assigns a name to an object. This object can later be looked up 78 * by this name. 79 * 80 * @param name The name to assign to the object. 81 */ 82 public void setName(String name) { 83 if (name == null) { 84 throw new RSIllegalArgumentException( 85 "setName requires a string of non-zero length."); 86 } 87 if(name.length() < 1) { 88 throw new RSIllegalArgumentException( 89 "setName does not accept a zero length string."); 90 } 91 if(mName != null) { 92 throw new RSIllegalArgumentException( 93 "setName object already has a name."); 94 } 95 96 try { 97 byte[] bytes = name.getBytes("UTF-8"); 98 mRS.nAssignName(mID, bytes); 99 mName = name; 100 } catch (java.io.UnsupportedEncodingException e) { 101 throw new RuntimeException(e); 102 } 103 } 104 105 /** 106 * @return name of the renderscript object 107 */ 108 public String getName() { 109 return mName; 110 } 111 112 private void helpDestroy() { 113 boolean shouldDestroy = false; 114 synchronized(this) { 115 if (!mDestroyed) { 116 shouldDestroy = true; 117 mDestroyed = true; 118 } 119 } 120 121 if (shouldDestroy) { 122 // must include nObjDestroy in the critical section 123 ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock(); 124 rlock.lock(); 125 // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy 126 if(mRS.isAlive() && mID != 0) { 127 mRS.nObjDestroy(mID); 128 } 129 rlock.unlock(); 130 mRS = null; 131 mID = 0; 132 } 133 } 134 135 protected void finalize() throws Throwable { 136 helpDestroy(); 137 super.finalize(); 138 } 139 140 /** 141 * Frees any native resources associated with this object. The 142 * primary use is to force immediate cleanup of resources when it is 143 * believed the GC will not respond quickly enough. 144 */ 145 public void destroy() { 146 if(mDestroyed) { 147 throw new RSInvalidStateException("Object already destroyed."); 148 } 149 helpDestroy(); 150 } 151 152 /** 153 * If an object came from an a3d file, java fields need to be 154 * created with objects from the native layer 155 */ 156 void updateFromNative() { 157 mRS.validate(); 158 mName = mRS.nGetName(getID(mRS)); 159 } 160 161 /** 162 * Calculates the hash code value for a BaseObj. 163 * 164 * @return int 165 */ 166 @Override 167 public int hashCode() { 168 return mID; 169 } 170 171 /** 172 * Compare the current BaseObj with another BaseObj for equality. 173 * 174 * @param obj The object to check equality with. 175 * 176 * @return boolean 177 */ 178 @Override 179 public boolean equals(Object obj) { 180 // Early-out check to see if both BaseObjs are actually the same 181 if (this == obj) 182 return true; 183 184 if (getClass() != obj.getClass()) { 185 return false; 186 } 187 188 BaseObj b = (BaseObj) obj; 189 return mID == b.mID; 190 } 191 } 192 193