blob: 9b926115f29e940df82c242e1835287a18250077 [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 Ni281c3252014-10-24 08:52:24 -0700292 List<Closure> mClosures;
293 List<UnboundValue> mInputs;
Yang Nicc1ca482015-03-16 15:53:18 -0700294 Future[] mOutputs;
Yang Ni281c3252014-10-24 08:52:24 -0700295
Yang Nicc1ca482015-03-16 15:53:18 -0700296 private static final String TAG = "ScriptGroup2";
Yang Ni281c3252014-10-24 08:52:24 -0700297
Yang Nicc1ca482015-03-16 15:53:18 -0700298 public ScriptGroup2(long id, RenderScript rs) {
299 super(id, rs);
Yang Ni281c3252014-10-24 08:52:24 -0700300 }
301
Yang Nicc1ca482015-03-16 15:53:18 -0700302 ScriptGroup2(RenderScript rs, List<Closure> closures,
303 List<UnboundValue> inputs, Future[] outputs) {
304 super(0, rs);
305 mClosures = closures;
306 mInputs = inputs;
307 mOutputs = outputs;
308
309 long[] closureIDs = new long[closures.size()];
310 for (int i = 0; i < closureIDs.length; i++) {
311 closureIDs[i] = closures.get(i).getID(rs);
312 }
313 long id = rs.nScriptGroup2Create(ScriptC.mCachePath, closureIDs);
314 setID(id);
Yang Ni281c3252014-10-24 08:52:24 -0700315 }
316
Yang Nicc1ca482015-03-16 15:53:18 -0700317 public Object[] execute(Object... inputs) {
318 if (inputs.length < mInputs.size()) {
319 Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
320 "less than expected " + mInputs.size());
321 return null;
322 }
323
324 if (inputs.length > mInputs.size()) {
325 Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
326 "more than expected " + mInputs.size());
327 }
328
329 for (int i = 0; i < mInputs.size(); i++) {
330 Object obj = inputs[i];
331 if (obj instanceof Future || obj instanceof UnboundValue) {
332 Log.e(TAG, this.toString() + ": input " + i +
333 " is a future or unbound value");
334 return null;
335 }
336 UnboundValue unbound = mInputs.get(i);
337 unbound.set(obj);
338 }
339
340 mRS.nScriptGroup2Execute(getID(mRS));
341
342 Object[] outputObjs = new Object[mOutputs.length];
343 int i = 0;
344 for (Future f : mOutputs) {
345 outputObjs[i++] = f.getValue();
346 }
347 return outputObjs;
Yang Nibe392ad2015-01-23 17:16:02 -0800348 }
349
Yang Nicc1ca482015-03-16 15:53:18 -0700350 /**
351 @hide Pending Android public API approval.
352 */
Yang Ni8ff29802015-03-11 16:25:37 -0700353 public static final class Binding {
354 public Script.FieldID mField;
355 public Object mValue;
356 public Binding(Script.FieldID field, Object value) {
357 mField = field;
358 mValue = value;
359 }
360 }
361
362 /**
363 @hide Pending Android public API approval.
364 */
Yang Nicc1ca482015-03-16 15:53:18 -0700365 public static final class Builder {
366 RenderScript mRS;
367 List<Closure> mClosures;
368 List<UnboundValue> mInputs;
Yang Nicc1ca482015-03-16 15:53:18 -0700369 private static final String TAG = "ScriptGroup2.Builder";
Yang Ni281c3252014-10-24 08:52:24 -0700370
Yang Nicc1ca482015-03-16 15:53:18 -0700371 public Builder(RenderScript rs) {
372 mRS = rs;
373 mClosures = new ArrayList<Closure>();
374 mInputs = new ArrayList<UnboundValue>();
375 }
376
377 public Closure addKernel(Script.KernelID k, Type returnType, Object[] args,
378 Map<Script.FieldID, Object> globalBindings) {
379 Closure c = new Closure(mRS, k, returnType, args, globalBindings);
380 mClosures.add(c);
381 return c;
382 }
383
384 public Closure addInvoke(Script.InvokeID invoke, Object[] args,
385 Map<Script.FieldID, Object> globalBindings) {
386 Closure c = new Closure(mRS, invoke, args, globalBindings);
387 mClosures.add(c);
388 return c;
389 }
390
391 public UnboundValue addInput() {
392 UnboundValue unbound = new UnboundValue();
393 mInputs.add(unbound);
394 return unbound;
395 }
396
Yang Ni8ff29802015-03-11 16:25:37 -0700397 public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
398 ArrayList<Object> args = new ArrayList<Object>();
399 Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
400 if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
401 return null;
402 }
403 return addKernel(k, returnType, args.toArray(), bindingMap);
404 }
405
406 public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
407 ArrayList<Object> args = new ArrayList<Object>();
408 Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
409 if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
410 return null;
411 }
412 return addInvoke(invoke, args.toArray(), bindingMap);
413 }
414
Yang Niad6b44a2015-04-06 16:58:57 -0700415 public ScriptGroup2 create(String name, Future... outputs) {
416 if (name == null || name.isEmpty() || name.length() > 100 ||
417 !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
418 throw new RSIllegalArgumentException("invalid script group name");
419 }
Yang Nicc1ca482015-03-16 15:53:18 -0700420 ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs);
421 return ret;
422 }
423
Yang Ni8ff29802015-03-11 16:25:37 -0700424 private boolean seperateArgsAndBindings(Object[] argsAndBindings,
425 ArrayList<Object> args,
426 Map<Script.FieldID, Object> bindingMap) {
427 int i;
428 for (i = 0; i < argsAndBindings.length; i++) {
429 if (argsAndBindings[i] instanceof Binding) {
430 break;
431 }
432 args.add(argsAndBindings[i]);
433 }
434
435 for (; i < argsAndBindings.length; i++) {
436 if (!(argsAndBindings[i] instanceof Binding)) {
437 return false;
438 }
439 Binding b = (Binding)argsAndBindings[i];
440 bindingMap.put(b.mField, b.mValue);
441 }
442
443 return true;
444 }
445
Yang Nicc1ca482015-03-16 15:53:18 -0700446 }
Yang Ni281c3252014-10-24 08:52:24 -0700447}