| Yang Ni | 281c325 | 2014-10-24 08:52:24 -0700 | [diff] [blame] | 1 | package android.renderscript; |
| 2 | |
| 3 | import android.util.Log; |
| 4 | import android.util.Pair; |
| 5 | import java.util.ArrayList; |
| 6 | import java.util.HashMap; |
| 7 | import java.util.List; |
| 8 | import java.util.Map; |
| 9 | |
| 10 | /** |
| 11 | @hide Pending Android public API approval. |
| 12 | */ |
| 13 | /** |
| 14 | |
| 15 | ****************************** |
| 16 | You have tried to change the API from what has been previously approved. |
| 17 | |
| 18 | To make these errors go away, you have two choices: |
| 19 | 1) You can add "@hide" javadoc comments to the methods, etc. listed in the |
| 20 | errors above. |
| 21 | |
| 22 | 2) You can update current.txt by executing the following command: |
| 23 | make update-api |
| 24 | |
| 25 | To submit the revised current.txt to the main Android repository, |
| 26 | you will need approval. |
| 27 | ****************************** |
| 28 | |
| 29 | @hide Pending Android public API approval. |
| 30 | */ |
| 31 | public class ScriptGroup2 extends BaseObj { |
| 32 | |
| 33 | public static class Closure extends BaseObj { |
| 34 | private Allocation mReturnValue; |
| 35 | private Map<Script.FieldID, Object> mBindings; |
| 36 | |
| 37 | private Future mReturnFuture; |
| 38 | private Map<Script.FieldID, Future> mGlobalFuture; |
| 39 | |
| 40 | private static final String TAG = "Closure"; |
| 41 | |
| 42 | public Closure(long id, RenderScript rs) { |
| 43 | super(id, rs); |
| 44 | } |
| 45 | |
| 46 | public Closure(RenderScript rs, Script.KernelID kernelID, Type returnType, |
| 47 | Object[] args, Map<Script.FieldID, Object> globals) { |
| 48 | super(0, rs); |
| 49 | |
| 50 | mReturnValue = Allocation.createTyped(rs, returnType); |
| 51 | mBindings = new HashMap<Script.FieldID, Object>(); |
| 52 | mGlobalFuture = new HashMap<Script.FieldID, Future>(); |
| 53 | |
| 54 | int numValues = args.length + globals.size(); |
| 55 | |
| 56 | long[] fieldIDs = new long[numValues]; |
| 57 | long[] values = new long[numValues]; |
| 58 | int[] sizes = new int[numValues]; |
| 59 | long[] depClosures = new long[numValues]; |
| 60 | long[] depFieldIDs = new long[numValues]; |
| 61 | |
| 62 | int i; |
| 63 | for (i = 0; i < args.length; i++) { |
| 64 | Object obj = args[i]; |
| 65 | fieldIDs[i] = 0; |
| 66 | if (obj instanceof UnboundValue) { |
| 67 | UnboundValue unbound = (UnboundValue)obj; |
| 68 | unbound.addReference(this, i); |
| 69 | } else { |
| 70 | retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes, |
| 71 | depClosures, depFieldIDs); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) { |
| 76 | Object obj = entry.getValue(); |
| 77 | Script.FieldID fieldID = entry.getKey(); |
| 78 | fieldIDs[i] = fieldID.getID(rs); |
| 79 | if (obj instanceof UnboundValue) { |
| 80 | UnboundValue unbound = (UnboundValue)obj; |
| 81 | unbound.addReference(this, fieldID); |
| 82 | } else { |
| 83 | retrieveValueAndDependenceInfo(rs, i, obj, values, |
| 84 | sizes, depClosures, depFieldIDs); |
| 85 | } |
| 86 | i++; |
| 87 | } |
| 88 | |
| 89 | long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs), |
| 90 | fieldIDs, values, sizes, depClosures, depFieldIDs); |
| 91 | |
| 92 | setID(id); |
| 93 | } |
| 94 | |
| 95 | private static void retrieveValueAndDependenceInfo(RenderScript rs, |
| 96 | int index, Object obj, long[] values, int[] sizes, long[] depClosures, |
| 97 | long[] depFieldIDs) { |
| 98 | |
| 99 | if (obj instanceof Future) { |
| 100 | Future f = (Future)obj; |
| 101 | obj = f.getValue(); |
| 102 | depClosures[index] = f.getClosure().getID(rs); |
| 103 | Script.FieldID fieldID = f.getFieldID(); |
| 104 | depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0; |
| 105 | } else { |
| 106 | depClosures[index] = 0; |
| 107 | depFieldIDs[index] = 0; |
| 108 | } |
| 109 | |
| 110 | ValueAndSize vs = new ValueAndSize(rs, obj); |
| 111 | values[index] = vs.value; |
| 112 | sizes[index] = vs.size; |
| 113 | } |
| 114 | |
| 115 | public Future getReturn() { |
| 116 | if (mReturnFuture == null) { |
| 117 | mReturnFuture = new Future(this, null, mReturnValue); |
| 118 | } |
| 119 | |
| 120 | return mReturnFuture; |
| 121 | } |
| 122 | |
| 123 | public Future getGlobal(Script.FieldID field) { |
| 124 | Future f = mGlobalFuture.get(field); |
| 125 | |
| 126 | if (f == null) { |
| 127 | f = new Future(this, field, mBindings.get(field)); |
| 128 | mGlobalFuture.put(field, f); |
| 129 | } |
| 130 | |
| 131 | return f; |
| 132 | } |
| 133 | |
| 134 | void setArg(int index, Object obj) { |
| 135 | ValueAndSize vs = new ValueAndSize(mRS, obj); |
| 136 | mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size); |
| 137 | } |
| 138 | |
| 139 | void setGlobal(Script.FieldID fieldID, Object obj) { |
| 140 | ValueAndSize vs = new ValueAndSize(mRS, obj); |
| 141 | mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size); |
| 142 | } |
| 143 | |
| 144 | private static final class ValueAndSize { |
| 145 | public ValueAndSize(RenderScript rs, Object obj) { |
| 146 | if (obj instanceof Allocation) { |
| 147 | value = ((Allocation)obj).getID(rs); |
| 148 | size = -1; |
| 149 | } else if (obj instanceof Boolean) { |
| 150 | value = ((Boolean)obj).booleanValue() ? 1 : 0; |
| 151 | size = 4; |
| 152 | } else if (obj instanceof Integer) { |
| 153 | value = ((Integer)obj).longValue(); |
| 154 | size = 4; |
| 155 | } else if (obj instanceof Long) { |
| 156 | value = ((Long)obj).longValue(); |
| 157 | size = 8; |
| 158 | } else if (obj instanceof Float) { |
| 159 | value = ((Float)obj).longValue(); |
| 160 | size = 4; |
| 161 | } else if (obj instanceof Double) { |
| 162 | value = ((Double)obj).longValue(); |
| 163 | size = 8; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | public long value; |
| 168 | public int size; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | public static class Future { |
| 173 | Closure mClosure; |
| 174 | Script.FieldID mFieldID; |
| 175 | Object mValue; |
| 176 | |
| 177 | Future(Closure closure, Script.FieldID fieldID, Object value) { |
| 178 | mClosure = closure; |
| 179 | mFieldID = fieldID; |
| 180 | mValue = value; |
| 181 | } |
| 182 | |
| 183 | Closure getClosure() { return mClosure; } |
| 184 | Script.FieldID getFieldID() { return mFieldID; } |
| 185 | Object getValue() { return mValue; } |
| 186 | } |
| 187 | |
| 188 | public static class UnboundValue { |
| 189 | // Either mFieldID or mArgIndex should be set but not both. |
| 190 | List<Pair<Closure, Script.FieldID>> mFieldID; |
| 191 | // -1 means unset. Legal values are 0 .. n-1, where n is the number of |
| 192 | // arguments for the referencing closure. |
| 193 | List<Pair<Closure, Integer>> mArgIndex; |
| 194 | |
| 195 | UnboundValue() { |
| 196 | mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>(); |
| 197 | mArgIndex = new ArrayList<Pair<Closure, Integer>>(); |
| 198 | } |
| 199 | |
| 200 | void addReference(Closure closure, int index) { |
| 201 | mArgIndex.add(Pair.create(closure, Integer.valueOf(index))); |
| 202 | } |
| 203 | |
| 204 | void addReference(Closure closure, Script.FieldID fieldID) { |
| 205 | mFieldID.add(Pair.create(closure, fieldID)); |
| 206 | } |
| 207 | |
| 208 | void set(Object value) { |
| 209 | for (Pair<Closure, Integer> p : mArgIndex) { |
| 210 | Closure closure = p.first; |
| 211 | int index = p.second.intValue(); |
| 212 | closure.setArg(index, value); |
| 213 | } |
| 214 | for (Pair<Closure, Script.FieldID> p : mFieldID) { |
| 215 | Closure closure = p.first; |
| 216 | Script.FieldID fieldID = p.second; |
| 217 | closure.setGlobal(fieldID, value); |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | List<Closure> mClosures; |
| 223 | List<UnboundValue> mInputs; |
| 224 | Future[] mOutputs; |
| 225 | |
| 226 | private static final String TAG = "ScriptGroup2"; |
| 227 | |
| 228 | public ScriptGroup2(long id, RenderScript rs) { |
| 229 | super(id, rs); |
| 230 | } |
| 231 | |
| 232 | ScriptGroup2(RenderScript rs, List<Closure> closures, |
| 233 | List<UnboundValue> inputs, Future[] outputs) { |
| 234 | super(0, rs); |
| 235 | mClosures = closures; |
| 236 | mInputs = inputs; |
| 237 | mOutputs = outputs; |
| 238 | |
| 239 | long[] closureIDs = new long[closures.size()]; |
| 240 | for (int i = 0; i < closureIDs.length; i++) { |
| 241 | closureIDs[i] = closures.get(i).getID(rs); |
| 242 | } |
| 243 | long id = rs.nScriptGroup2Create(closureIDs); |
| 244 | setID(id); |
| 245 | } |
| 246 | |
| 247 | // TODO: If this was reflected method, we could enforce the number of |
| 248 | // arguments. |
| 249 | public Object[] execute(Object... inputs) { |
| 250 | if (inputs.length < mInputs.size()) { |
| 251 | Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " + |
| 252 | "less than expected " + mInputs.size()); |
| 253 | return null; |
| 254 | } |
| 255 | |
| 256 | if (inputs.length > mInputs.size()) { |
| 257 | Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " + |
| 258 | "more than expected " + mInputs.size()); |
| 259 | } |
| 260 | |
| 261 | for (int i = 0; i < mInputs.size(); i++) { |
| 262 | Object obj = inputs[i]; |
| 263 | if (obj instanceof Future || obj instanceof UnboundValue) { |
| 264 | Log.e(TAG, this.toString() + ": input " + i + |
| 265 | " is a future or unbound value"); |
| 266 | return null; |
| 267 | } |
| 268 | UnboundValue unbound = mInputs.get(i); |
| 269 | unbound.set(obj); |
| 270 | } |
| 271 | |
| 272 | mRS.nScriptGroup2Execute(getID(mRS)); |
| 273 | |
| 274 | Object[] outputObjs = new Object[mOutputs.length]; |
| 275 | int i = 0; |
| 276 | for (Future f : mOutputs) { |
| 277 | outputObjs[i++] = f.getValue(); |
| 278 | } |
| 279 | return outputObjs; |
| 280 | } |
| 281 | |
| 282 | /** |
| 283 | @hide Pending Android public API approval. |
| 284 | */ |
| 285 | public static final class Builder { |
| 286 | RenderScript mRS; |
| 287 | List<Closure> mClosures; |
| 288 | List<UnboundValue> mInputs; |
| 289 | |
| 290 | private static final String TAG = "ScriptGroup2.Builder"; |
| 291 | |
| 292 | public Builder(RenderScript rs) { |
| 293 | mRS = rs; |
| 294 | mClosures = new ArrayList<Closure>(); |
| 295 | mInputs = new ArrayList<UnboundValue>(); |
| 296 | } |
| 297 | |
| 298 | public Closure addKernel(Script.KernelID k, Type returnType, Object[] args, |
| 299 | Map<Script.FieldID, Object> globalBindings) { |
| 300 | Closure c = new Closure(mRS, k, returnType, args, globalBindings); |
| 301 | mClosures.add(c); |
| 302 | return c; |
| 303 | } |
| 304 | |
| 305 | public UnboundValue addInput() { |
| 306 | UnboundValue unbound = new UnboundValue(); |
| 307 | mInputs.add(unbound); |
| 308 | return unbound; |
| 309 | } |
| 310 | |
| 311 | public ScriptGroup2 create(Future... outputs) { |
| 312 | // TODO: Save all script groups that have been created and return one that was |
| 313 | // saved and matches the outputs. |
| 314 | ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs); |
| 315 | return ret; |
| 316 | } |
| 317 | |
| 318 | } |
| 319 | } |