blob: dcad7873c2cda15c84cf0ed977de0fa6282bfd0c [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/**
11 @hide Pending Android public API approval.
12 */
13/**
14
15******************************
16You have tried to change the API from what has been previously approved.
17
18To 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
25To submit the revised current.txt to the main Android repository,
26you will need approval.
27******************************
28
29 @hide Pending Android public API approval.
30 */
31public 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}