blob: 417bbee73019ac0d826a437c0adeb223609717ac [file] [log] [blame]
Yang Nicc1ca482015-03-16 15:53:18 -07001/*
2 * Copyright (C) 2015 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
Yang Ni281c3252014-10-24 08:52:24 -070017package android.renderscript;
18
19import android.util.Log;
20import android.util.Pair;
21import java.util.ArrayList;
22import java.util.HashMap;
23import java.util.List;
24import java.util.Map;
25
26/**
Yang Ni281c3252014-10-24 08:52:24 -070027
28******************************
29You have tried to change the API from what has been previously approved.
30
31To make these errors go away, you have two choices:
Yang Nicc1ca482015-03-16 15:53:18 -0700321) You can add "@hide" javadoc comments to the methods, etc. listed in the
33errors above.
Yang Ni281c3252014-10-24 08:52:24 -070034
Yang Nicc1ca482015-03-16 15:53:18 -0700352) You can update current.txt by executing the following command:
36make update-api
Yang Ni281c3252014-10-24 08:52:24 -070037
38To submit the revised current.txt to the main Android repository,
39you will need approval.
40******************************
41
Yang Nicc1ca482015-03-16 15:53:18 -070042@hide Pending Android public API approval.
43*/
Yang Ni281c3252014-10-24 08:52:24 -070044public class ScriptGroup2 extends BaseObj {
45
Yang Nicc1ca482015-03-16 15:53:18 -070046 public static class Closure extends BaseObj {
Yang Ni4c93c8c2015-03-26 14:35:22 -070047 private Object[] mArgs;
Yang Nicc1ca482015-03-16 15:53:18 -070048 private Allocation mReturnValue;
49 private Map<Script.FieldID, Object> mBindings;
Yang Ni281c3252014-10-24 08:52:24 -070050
Yang Nicc1ca482015-03-16 15:53:18 -070051 private Future mReturnFuture;
52 private Map<Script.FieldID, Future> mGlobalFuture;
Yang Ni281c3252014-10-24 08:52:24 -070053
Yang Nicc1ca482015-03-16 15:53:18 -070054 private FieldPacker mFP;
Yang Nibe392ad2015-01-23 17:16:02 -080055
Yang Nicc1ca482015-03-16 15:53:18 -070056 private static final String TAG = "Closure";
Yang Ni281c3252014-10-24 08:52:24 -070057
Yang Nicc1ca482015-03-16 15:53:18 -070058 public Closure(long id, RenderScript rs) {
59 super(id, rs);
Yang Ni281c3252014-10-24 08:52:24 -070060 }
Yang Ni281c3252014-10-24 08:52:24 -070061
Yang Nicc1ca482015-03-16 15:53:18 -070062 public Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
63 Object[] args, Map<Script.FieldID, Object> globals) {
64 super(0, rs);
65
Yang Ni4c93c8c2015-03-26 14:35:22 -070066 mArgs = args;
Yang Nicc1ca482015-03-16 15:53:18 -070067 mReturnValue = Allocation.createTyped(rs, returnType);
Yang Ni4c93c8c2015-03-26 14:35:22 -070068 mBindings = globals;
Yang Nicc1ca482015-03-16 15:53:18 -070069 mGlobalFuture = new HashMap<Script.FieldID, Future>();
70
71 int numValues = args.length + globals.size();
72
73 long[] fieldIDs = new long[numValues];
74 long[] values = new long[numValues];
75 int[] sizes = new int[numValues];
76 long[] depClosures = new long[numValues];
77 long[] depFieldIDs = new long[numValues];
78
79 int i;
80 for (i = 0; i < args.length; i++) {
81 Object obj = args[i];
82 fieldIDs[i] = 0;
83 if (obj instanceof UnboundValue) {
84 UnboundValue unbound = (UnboundValue)obj;
85 unbound.addReference(this, i);
86 } else {
87 retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes,
88 depClosures, depFieldIDs);
89 }
90 }
91
92 for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
93 Object obj = entry.getValue();
94 Script.FieldID fieldID = entry.getKey();
95 fieldIDs[i] = fieldID.getID(rs);
96 if (obj instanceof UnboundValue) {
97 UnboundValue unbound = (UnboundValue)obj;
98 unbound.addReference(this, fieldID);
99 } else {
100 retrieveValueAndDependenceInfo(rs, i, obj, values,
101 sizes, depClosures, depFieldIDs);
102 }
103 i++;
104 }
105
106 long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
107 fieldIDs, values, sizes, depClosures, depFieldIDs);
108
109 setID(id);
Yang Ni281c3252014-10-24 08:52:24 -0700110 }
Yang Ni281c3252014-10-24 08:52:24 -0700111
Yang Nicc1ca482015-03-16 15:53:18 -0700112 public Closure(RenderScript rs, Script.InvokeID invokeID,
113 Object[] args, Map<Script.FieldID, Object> globals) {
114 super(0, rs);
Yang Ni8bcbf472015-04-01 17:29:14 -0700115 mFP = FieldPacker.createFromArray(args);
Yang Ni281c3252014-10-24 08:52:24 -0700116
Yang Ni4c93c8c2015-03-26 14:35:22 -0700117 mArgs = args;
118 mBindings = globals;
Yang Nicc1ca482015-03-16 15:53:18 -0700119 mGlobalFuture = new HashMap<Script.FieldID, Future>();
Yang Ni281c3252014-10-24 08:52:24 -0700120
Yang Nicc1ca482015-03-16 15:53:18 -0700121 int numValues = globals.size();
Yang Nibe392ad2015-01-23 17:16:02 -0800122
Yang Nicc1ca482015-03-16 15:53:18 -0700123 long[] fieldIDs = new long[numValues];
124 long[] values = new long[numValues];
125 int[] sizes = new int[numValues];
126 long[] depClosures = new long[numValues];
127 long[] depFieldIDs = new long[numValues];
Yang Nibe392ad2015-01-23 17:16:02 -0800128
Yang Nicc1ca482015-03-16 15:53:18 -0700129 int i = 0;
130 for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
131 Object obj = entry.getValue();
132 Script.FieldID fieldID = entry.getKey();
133 fieldIDs[i] = fieldID.getID(rs);
134 if (obj instanceof UnboundValue) {
135 UnboundValue unbound = (UnboundValue)obj;
136 unbound.addReference(this, fieldID);
137 } else {
138 // TODO(yangni): Verify obj not a future.
139 retrieveValueAndDependenceInfo(rs, i, obj, values,
140 sizes, depClosures, depFieldIDs);
141 }
142 i++;
143 }
Yang Nibe392ad2015-01-23 17:16:02 -0800144
Yang Nicc1ca482015-03-16 15:53:18 -0700145 long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
146 values, sizes);
Yang Nibe392ad2015-01-23 17:16:02 -0800147
Yang Nicc1ca482015-03-16 15:53:18 -0700148 setID(id);
Yang Nibe392ad2015-01-23 17:16:02 -0800149 }
Yang Nibe392ad2015-01-23 17:16:02 -0800150
Yang Nicc1ca482015-03-16 15:53:18 -0700151 private static
152 void retrieveValueAndDependenceInfo(RenderScript rs,
153 int index, Object obj,
154 long[] values, int[] sizes,
155 long[] depClosures,
156 long[] depFieldIDs) {
Yang Nibe392ad2015-01-23 17:16:02 -0800157
Yang Nicc1ca482015-03-16 15:53:18 -0700158 if (obj instanceof Future) {
159 Future f = (Future)obj;
160 obj = f.getValue();
161 depClosures[index] = f.getClosure().getID(rs);
162 Script.FieldID fieldID = f.getFieldID();
163 depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
164 if (obj == null) {
165 // Value is originally created by the owner closure
166 values[index] = 0;
167 sizes[index] = 0;
168 return;
169 }
170 } else {
171 depClosures[index] = 0;
172 depFieldIDs[index] = 0;
173 }
Yang Nibe392ad2015-01-23 17:16:02 -0800174
Yang Nicc1ca482015-03-16 15:53:18 -0700175 ValueAndSize vs = new ValueAndSize(rs, obj);
176 values[index] = vs.value;
177 sizes[index] = vs.size;
Yang Nibe392ad2015-01-23 17:16:02 -0800178 }
Yang Ni281c3252014-10-24 08:52:24 -0700179
Yang Nicc1ca482015-03-16 15:53:18 -0700180 public Future getReturn() {
181 if (mReturnFuture == null) {
182 mReturnFuture = new Future(this, null, mReturnValue);
183 }
Yang Ni281c3252014-10-24 08:52:24 -0700184
Yang Nicc1ca482015-03-16 15:53:18 -0700185 return mReturnFuture;
Yang Ni281c3252014-10-24 08:52:24 -0700186 }
Yang Ni281c3252014-10-24 08:52:24 -0700187
Yang Nicc1ca482015-03-16 15:53:18 -0700188 public Future getGlobal(Script.FieldID field) {
189 Future f = mGlobalFuture.get(field);
Yang Ni281c3252014-10-24 08:52:24 -0700190
Yang Nicc1ca482015-03-16 15:53:18 -0700191 if (f == null) {
192 // If the field is not bound to this closure, this will return a future
193 // without an associated value (reference). So this is not working for
194 // cross-module (cross-script) linking in this case where a field not
195 // explicitly bound.
196 f = new Future(this, field, mBindings.get(field));
197 mGlobalFuture.put(field, f);
198 }
199
200 return f;
201 }
202
203 void setArg(int index, Object obj) {
Yang Ni4c93c8c2015-03-26 14:35:22 -0700204 mArgs[index] = obj;
Yang Nicc1ca482015-03-16 15:53:18 -0700205 ValueAndSize vs = new ValueAndSize(mRS, obj);
206 mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
207 }
208
209 void setGlobal(Script.FieldID fieldID, Object obj) {
Yang Ni4c93c8c2015-03-26 14:35:22 -0700210 mBindings.put(fieldID, obj);
Yang Nicc1ca482015-03-16 15:53:18 -0700211 ValueAndSize vs = new ValueAndSize(mRS, obj);
212 mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
213 }
214
215 private static final class ValueAndSize {
216 public ValueAndSize(RenderScript rs, Object obj) {
217 if (obj instanceof Allocation) {
218 value = ((Allocation)obj).getID(rs);
219 size = -1;
220 } else if (obj instanceof Boolean) {
221 value = ((Boolean)obj).booleanValue() ? 1 : 0;
222 size = 4;
223 } else if (obj instanceof Integer) {
224 value = ((Integer)obj).longValue();
225 size = 4;
226 } else if (obj instanceof Long) {
227 value = ((Long)obj).longValue();
228 size = 8;
229 } else if (obj instanceof Float) {
230 value = ((Float)obj).longValue();
231 size = 4;
232 } else if (obj instanceof Double) {
233 value = ((Double)obj).longValue();
234 size = 8;
235 }
236 }
237 public long value;
238 public int size;
239 }
Yang Ni281c3252014-10-24 08:52:24 -0700240 }
241
Yang Nicc1ca482015-03-16 15:53:18 -0700242 public static class Future {
243 Closure mClosure;
244 Script.FieldID mFieldID;
245 Object mValue;
Yang Ni281c3252014-10-24 08:52:24 -0700246
Yang Nicc1ca482015-03-16 15:53:18 -0700247 Future(Closure closure, Script.FieldID fieldID, Object value) {
248 mClosure = closure;
249 mFieldID = fieldID;
250 mValue = value;
251 }
Yang Ni281c3252014-10-24 08:52:24 -0700252
Yang Nicc1ca482015-03-16 15:53:18 -0700253 Closure getClosure() { return mClosure; }
254 Script.FieldID getFieldID() { return mFieldID; }
255 Object getValue() { return mValue; }
Yang Ni281c3252014-10-24 08:52:24 -0700256 }
257
Yang Nicc1ca482015-03-16 15:53:18 -0700258 public static class UnboundValue {
259 // Either mFieldID or mArgIndex should be set but not both.
260 List<Pair<Closure, Script.FieldID>> mFieldID;
261 // -1 means unset. Legal values are 0 .. n-1, where n is the number of
262 // arguments for the referencing closure.
263 List<Pair<Closure, Integer>> mArgIndex;
264
265 UnboundValue() {
266 mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
267 mArgIndex = new ArrayList<Pair<Closure, Integer>>();
268 }
269
270 void addReference(Closure closure, int index) {
271 mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
272 }
273
274 void addReference(Closure closure, Script.FieldID fieldID) {
275 mFieldID.add(Pair.create(closure, fieldID));
276 }
277
278 void set(Object value) {
279 for (Pair<Closure, Integer> p : mArgIndex) {
280 Closure closure = p.first;
281 int index = p.second.intValue();
282 closure.setArg(index, value);
283 }
284 for (Pair<Closure, Script.FieldID> p : mFieldID) {
285 Closure closure = p.first;
286 Script.FieldID fieldID = p.second;
287 closure.setGlobal(fieldID, value);
288 }
289 }
Yang Ni281c3252014-10-24 08:52:24 -0700290 }
291
Yang Ni35be56c2015-04-02 17:47:56 -0700292 String mName;
Yang Ni281c3252014-10-24 08:52:24 -0700293 List<Closure> mClosures;
294 List<UnboundValue> mInputs;
Yang Nicc1ca482015-03-16 15:53:18 -0700295 Future[] mOutputs;
Yang Ni281c3252014-10-24 08:52:24 -0700296
Yang Nicc1ca482015-03-16 15:53:18 -0700297 private static final String TAG = "ScriptGroup2";
Yang Ni281c3252014-10-24 08:52:24 -0700298
Yang Nicc1ca482015-03-16 15:53:18 -0700299 public ScriptGroup2(long id, RenderScript rs) {
300 super(id, rs);
Yang Ni281c3252014-10-24 08:52:24 -0700301 }
302
Yang Ni35be56c2015-04-02 17:47:56 -0700303 ScriptGroup2(RenderScript rs, String name, List<Closure> closures,
Yang Nicc1ca482015-03-16 15:53:18 -0700304 List<UnboundValue> inputs, Future[] outputs) {
305 super(0, rs);
Yang Ni35be56c2015-04-02 17:47:56 -0700306 mName = name;
Yang Nicc1ca482015-03-16 15:53:18 -0700307 mClosures = closures;
308 mInputs = inputs;
309 mOutputs = outputs;
310
311 long[] closureIDs = new long[closures.size()];
312 for (int i = 0; i < closureIDs.length; i++) {
313 closureIDs[i] = closures.get(i).getID(rs);
314 }
Yang Ni35be56c2015-04-02 17:47:56 -0700315 long id = rs.nScriptGroup2Create(name, ScriptC.mCachePath, closureIDs);
Yang Nicc1ca482015-03-16 15:53:18 -0700316 setID(id);
Yang Ni281c3252014-10-24 08:52:24 -0700317 }
318
Yang Nicc1ca482015-03-16 15:53:18 -0700319 public Object[] execute(Object... inputs) {
320 if (inputs.length < mInputs.size()) {
321 Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
322 "less than expected " + mInputs.size());
323 return null;
324 }
325
326 if (inputs.length > mInputs.size()) {
327 Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
328 "more than expected " + mInputs.size());
329 }
330
331 for (int i = 0; i < mInputs.size(); i++) {
332 Object obj = inputs[i];
333 if (obj instanceof Future || obj instanceof UnboundValue) {
334 Log.e(TAG, this.toString() + ": input " + i +
335 " is a future or unbound value");
336 return null;
337 }
338 UnboundValue unbound = mInputs.get(i);
339 unbound.set(obj);
340 }
341
342 mRS.nScriptGroup2Execute(getID(mRS));
343
344 Object[] outputObjs = new Object[mOutputs.length];
345 int i = 0;
346 for (Future f : mOutputs) {
347 outputObjs[i++] = f.getValue();
348 }
349 return outputObjs;
Yang Nibe392ad2015-01-23 17:16:02 -0800350 }
351
Yang Nicc1ca482015-03-16 15:53:18 -0700352 /**
353 @hide Pending Android public API approval.
354 */
Yang Ni8ff29802015-03-11 16:25:37 -0700355 public static final class Binding {
356 public Script.FieldID mField;
357 public Object mValue;
358 public Binding(Script.FieldID field, Object value) {
359 mField = field;
360 mValue = value;
361 }
362 }
363
364 /**
365 @hide Pending Android public API approval.
366 */
Yang Nicc1ca482015-03-16 15:53:18 -0700367 public static final class Builder {
368 RenderScript mRS;
369 List<Closure> mClosures;
370 List<UnboundValue> mInputs;
Yang Nicc1ca482015-03-16 15:53:18 -0700371 private static final String TAG = "ScriptGroup2.Builder";
Yang Ni281c3252014-10-24 08:52:24 -0700372
Yang Nicc1ca482015-03-16 15:53:18 -0700373 public Builder(RenderScript rs) {
374 mRS = rs;
375 mClosures = new ArrayList<Closure>();
376 mInputs = new ArrayList<UnboundValue>();
377 }
378
379 public Closure addKernel(Script.KernelID k, Type returnType, Object[] args,
380 Map<Script.FieldID, Object> globalBindings) {
381 Closure c = new Closure(mRS, k, returnType, args, globalBindings);
382 mClosures.add(c);
383 return c;
384 }
385
386 public Closure addInvoke(Script.InvokeID invoke, Object[] args,
387 Map<Script.FieldID, Object> globalBindings) {
388 Closure c = new Closure(mRS, invoke, args, globalBindings);
389 mClosures.add(c);
390 return c;
391 }
392
393 public UnboundValue addInput() {
394 UnboundValue unbound = new UnboundValue();
395 mInputs.add(unbound);
396 return unbound;
397 }
398
Yang Ni8ff29802015-03-11 16:25:37 -0700399 public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
400 ArrayList<Object> args = new ArrayList<Object>();
401 Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
402 if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
403 return null;
404 }
405 return addKernel(k, returnType, args.toArray(), bindingMap);
406 }
407
408 public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
409 ArrayList<Object> args = new ArrayList<Object>();
410 Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
411 if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
412 return null;
413 }
414 return addInvoke(invoke, args.toArray(), bindingMap);
415 }
416
Yang Niad6b44a2015-04-06 16:58:57 -0700417 public ScriptGroup2 create(String name, Future... outputs) {
418 if (name == null || name.isEmpty() || name.length() > 100 ||
419 !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
420 throw new RSIllegalArgumentException("invalid script group name");
421 }
Yang Ni35be56c2015-04-02 17:47:56 -0700422 ScriptGroup2 ret = new ScriptGroup2(mRS, name, mClosures, mInputs, outputs);
Yang Nicc1ca482015-03-16 15:53:18 -0700423 return ret;
424 }
425
Yang Ni8ff29802015-03-11 16:25:37 -0700426 private boolean seperateArgsAndBindings(Object[] argsAndBindings,
427 ArrayList<Object> args,
428 Map<Script.FieldID, Object> bindingMap) {
429 int i;
430 for (i = 0; i < argsAndBindings.length; i++) {
431 if (argsAndBindings[i] instanceof Binding) {
432 break;
433 }
434 args.add(argsAndBindings[i]);
435 }
436
437 for (; i < argsAndBindings.length; i++) {
438 if (!(argsAndBindings[i] instanceof Binding)) {
439 return false;
440 }
441 Binding b = (Binding)argsAndBindings[i];
442 bindingMap.put(b.mField, b.mValue);
443 }
444
445 return true;
446 }
447
Yang Nicc1ca482015-03-16 15:53:18 -0700448 }
Yang Ni281c3252014-10-24 08:52:24 -0700449}