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