blob: 2e171b66c09068ec8a479c273a0a9d44d469ba73 [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 {
47 private Allocation mReturnValue;
48 private Map<Script.FieldID, Object> mBindings;
Yang Ni281c3252014-10-24 08:52:24 -070049
Yang Nicc1ca482015-03-16 15:53:18 -070050 private Future mReturnFuture;
51 private Map<Script.FieldID, Future> mGlobalFuture;
Yang Ni281c3252014-10-24 08:52:24 -070052
Yang Nicc1ca482015-03-16 15:53:18 -070053 private FieldPacker mFP;
Yang Nibe392ad2015-01-23 17:16:02 -080054
Yang Nicc1ca482015-03-16 15:53:18 -070055 private static final String TAG = "Closure";
Yang Ni281c3252014-10-24 08:52:24 -070056
Yang Nicc1ca482015-03-16 15:53:18 -070057 public Closure(long id, RenderScript rs) {
58 super(id, rs);
Yang Ni281c3252014-10-24 08:52:24 -070059 }
Yang Ni281c3252014-10-24 08:52:24 -070060
Yang Nicc1ca482015-03-16 15:53:18 -070061 public Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
62 Object[] args, Map<Script.FieldID, Object> globals) {
63 super(0, rs);
64
65 mReturnValue = Allocation.createTyped(rs, returnType);
66 mBindings = new HashMap<Script.FieldID, Object>();
67 mGlobalFuture = new HashMap<Script.FieldID, Future>();
68
69 int numValues = args.length + globals.size();
70
71 long[] fieldIDs = new long[numValues];
72 long[] values = new long[numValues];
73 int[] sizes = new int[numValues];
74 long[] depClosures = new long[numValues];
75 long[] depFieldIDs = new long[numValues];
76
77 int i;
78 for (i = 0; i < args.length; i++) {
79 Object obj = args[i];
80 fieldIDs[i] = 0;
81 if (obj instanceof UnboundValue) {
82 UnboundValue unbound = (UnboundValue)obj;
83 unbound.addReference(this, i);
84 } else {
85 retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes,
86 depClosures, depFieldIDs);
87 }
88 }
89
90 for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
91 Object obj = entry.getValue();
92 Script.FieldID fieldID = entry.getKey();
93 fieldIDs[i] = fieldID.getID(rs);
94 if (obj instanceof UnboundValue) {
95 UnboundValue unbound = (UnboundValue)obj;
96 unbound.addReference(this, fieldID);
97 } else {
98 retrieveValueAndDependenceInfo(rs, i, obj, values,
99 sizes, depClosures, depFieldIDs);
100 }
101 i++;
102 }
103
104 long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
105 fieldIDs, values, sizes, depClosures, depFieldIDs);
106
107 setID(id);
Yang Ni281c3252014-10-24 08:52:24 -0700108 }
Yang Ni281c3252014-10-24 08:52:24 -0700109
Yang Nicc1ca482015-03-16 15:53:18 -0700110 public Closure(RenderScript rs, Script.InvokeID invokeID,
111 Object[] args, Map<Script.FieldID, Object> globals) {
112 super(0, rs);
113 mFP = FieldPacker.createFieldPack(args);
Yang Ni281c3252014-10-24 08:52:24 -0700114
Yang Nicc1ca482015-03-16 15:53:18 -0700115 mBindings = new HashMap<Script.FieldID, Object>();
116 mGlobalFuture = new HashMap<Script.FieldID, Future>();
Yang Ni281c3252014-10-24 08:52:24 -0700117
Yang Nicc1ca482015-03-16 15:53:18 -0700118 int numValues = globals.size();
Yang Nibe392ad2015-01-23 17:16:02 -0800119
Yang Nicc1ca482015-03-16 15:53:18 -0700120 long[] fieldIDs = new long[numValues];
121 long[] values = new long[numValues];
122 int[] sizes = new int[numValues];
123 long[] depClosures = new long[numValues];
124 long[] depFieldIDs = new long[numValues];
Yang Nibe392ad2015-01-23 17:16:02 -0800125
Yang Nicc1ca482015-03-16 15:53:18 -0700126 int i = 0;
127 for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
128 Object obj = entry.getValue();
129 Script.FieldID fieldID = entry.getKey();
130 fieldIDs[i] = fieldID.getID(rs);
131 if (obj instanceof UnboundValue) {
132 UnboundValue unbound = (UnboundValue)obj;
133 unbound.addReference(this, fieldID);
134 } else {
135 // TODO(yangni): Verify obj not a future.
136 retrieveValueAndDependenceInfo(rs, i, obj, values,
137 sizes, depClosures, depFieldIDs);
138 }
139 i++;
140 }
Yang Nibe392ad2015-01-23 17:16:02 -0800141
Yang Nicc1ca482015-03-16 15:53:18 -0700142 long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
143 values, sizes);
Yang Nibe392ad2015-01-23 17:16:02 -0800144
Yang Nicc1ca482015-03-16 15:53:18 -0700145 setID(id);
Yang Nibe392ad2015-01-23 17:16:02 -0800146 }
Yang Nibe392ad2015-01-23 17:16:02 -0800147
Yang Nicc1ca482015-03-16 15:53:18 -0700148 private static
149 void retrieveValueAndDependenceInfo(RenderScript rs,
150 int index, Object obj,
151 long[] values, int[] sizes,
152 long[] depClosures,
153 long[] depFieldIDs) {
Yang Nibe392ad2015-01-23 17:16:02 -0800154
Yang Nicc1ca482015-03-16 15:53:18 -0700155 if (obj instanceof Future) {
156 Future f = (Future)obj;
157 obj = f.getValue();
158 depClosures[index] = f.getClosure().getID(rs);
159 Script.FieldID fieldID = f.getFieldID();
160 depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
161 if (obj == null) {
162 // Value is originally created by the owner closure
163 values[index] = 0;
164 sizes[index] = 0;
165 return;
166 }
167 } else {
168 depClosures[index] = 0;
169 depFieldIDs[index] = 0;
170 }
Yang Nibe392ad2015-01-23 17:16:02 -0800171
Yang Nicc1ca482015-03-16 15:53:18 -0700172 ValueAndSize vs = new ValueAndSize(rs, obj);
173 values[index] = vs.value;
174 sizes[index] = vs.size;
Yang Nibe392ad2015-01-23 17:16:02 -0800175 }
Yang Ni281c3252014-10-24 08:52:24 -0700176
Yang Nicc1ca482015-03-16 15:53:18 -0700177 public Future getReturn() {
178 if (mReturnFuture == null) {
179 mReturnFuture = new Future(this, null, mReturnValue);
180 }
Yang Ni281c3252014-10-24 08:52:24 -0700181
Yang Nicc1ca482015-03-16 15:53:18 -0700182 return mReturnFuture;
Yang Ni281c3252014-10-24 08:52:24 -0700183 }
Yang Ni281c3252014-10-24 08:52:24 -0700184
Yang Nicc1ca482015-03-16 15:53:18 -0700185 public Future getGlobal(Script.FieldID field) {
186 Future f = mGlobalFuture.get(field);
Yang Ni281c3252014-10-24 08:52:24 -0700187
Yang Nicc1ca482015-03-16 15:53:18 -0700188 if (f == null) {
189 // If the field is not bound to this closure, this will return a future
190 // without an associated value (reference). So this is not working for
191 // cross-module (cross-script) linking in this case where a field not
192 // explicitly bound.
193 f = new Future(this, field, mBindings.get(field));
194 mGlobalFuture.put(field, f);
195 }
196
197 return f;
198 }
199
200 void setArg(int index, Object obj) {
201 ValueAndSize vs = new ValueAndSize(mRS, obj);
202 mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
203 }
204
205 void setGlobal(Script.FieldID fieldID, Object obj) {
206 ValueAndSize vs = new ValueAndSize(mRS, obj);
207 mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
208 }
209
210 private static final class ValueAndSize {
211 public ValueAndSize(RenderScript rs, Object obj) {
212 if (obj instanceof Allocation) {
213 value = ((Allocation)obj).getID(rs);
214 size = -1;
215 } else if (obj instanceof Boolean) {
216 value = ((Boolean)obj).booleanValue() ? 1 : 0;
217 size = 4;
218 } else if (obj instanceof Integer) {
219 value = ((Integer)obj).longValue();
220 size = 4;
221 } else if (obj instanceof Long) {
222 value = ((Long)obj).longValue();
223 size = 8;
224 } else if (obj instanceof Float) {
225 value = ((Float)obj).longValue();
226 size = 4;
227 } else if (obj instanceof Double) {
228 value = ((Double)obj).longValue();
229 size = 8;
230 }
231 }
232 public long value;
233 public int size;
234 }
Yang Ni281c3252014-10-24 08:52:24 -0700235 }
236
Yang Nicc1ca482015-03-16 15:53:18 -0700237 public static class Future {
238 Closure mClosure;
239 Script.FieldID mFieldID;
240 Object mValue;
Yang Ni281c3252014-10-24 08:52:24 -0700241
Yang Nicc1ca482015-03-16 15:53:18 -0700242 Future(Closure closure, Script.FieldID fieldID, Object value) {
243 mClosure = closure;
244 mFieldID = fieldID;
245 mValue = value;
246 }
Yang Ni281c3252014-10-24 08:52:24 -0700247
Yang Nicc1ca482015-03-16 15:53:18 -0700248 Closure getClosure() { return mClosure; }
249 Script.FieldID getFieldID() { return mFieldID; }
250 Object getValue() { return mValue; }
Yang Ni281c3252014-10-24 08:52:24 -0700251 }
252
Yang Nicc1ca482015-03-16 15:53:18 -0700253 public static class UnboundValue {
254 // Either mFieldID or mArgIndex should be set but not both.
255 List<Pair<Closure, Script.FieldID>> mFieldID;
256 // -1 means unset. Legal values are 0 .. n-1, where n is the number of
257 // arguments for the referencing closure.
258 List<Pair<Closure, Integer>> mArgIndex;
259
260 UnboundValue() {
261 mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
262 mArgIndex = new ArrayList<Pair<Closure, Integer>>();
263 }
264
265 void addReference(Closure closure, int index) {
266 mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
267 }
268
269 void addReference(Closure closure, Script.FieldID fieldID) {
270 mFieldID.add(Pair.create(closure, fieldID));
271 }
272
273 void set(Object value) {
274 for (Pair<Closure, Integer> p : mArgIndex) {
275 Closure closure = p.first;
276 int index = p.second.intValue();
277 closure.setArg(index, value);
278 }
279 for (Pair<Closure, Script.FieldID> p : mFieldID) {
280 Closure closure = p.first;
281 Script.FieldID fieldID = p.second;
282 closure.setGlobal(fieldID, value);
283 }
284 }
Yang Ni281c3252014-10-24 08:52:24 -0700285 }
286
Yang Ni281c3252014-10-24 08:52:24 -0700287 List<Closure> mClosures;
288 List<UnboundValue> mInputs;
Yang Nicc1ca482015-03-16 15:53:18 -0700289 Future[] mOutputs;
Yang Ni281c3252014-10-24 08:52:24 -0700290
Yang Nicc1ca482015-03-16 15:53:18 -0700291 private static final String TAG = "ScriptGroup2";
Yang Ni281c3252014-10-24 08:52:24 -0700292
Yang Nicc1ca482015-03-16 15:53:18 -0700293 public ScriptGroup2(long id, RenderScript rs) {
294 super(id, rs);
Yang Ni281c3252014-10-24 08:52:24 -0700295 }
296
Yang Nicc1ca482015-03-16 15:53:18 -0700297 ScriptGroup2(RenderScript rs, List<Closure> closures,
298 List<UnboundValue> inputs, Future[] outputs) {
299 super(0, rs);
300 mClosures = closures;
301 mInputs = inputs;
302 mOutputs = outputs;
303
304 long[] closureIDs = new long[closures.size()];
305 for (int i = 0; i < closureIDs.length; i++) {
306 closureIDs[i] = closures.get(i).getID(rs);
307 }
308 long id = rs.nScriptGroup2Create(ScriptC.mCachePath, closureIDs);
309 setID(id);
Yang Ni281c3252014-10-24 08:52:24 -0700310 }
311
Yang Nicc1ca482015-03-16 15:53:18 -0700312 public Object[] execute(Object... inputs) {
313 if (inputs.length < mInputs.size()) {
314 Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
315 "less than expected " + mInputs.size());
316 return null;
317 }
318
319 if (inputs.length > mInputs.size()) {
320 Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
321 "more than expected " + mInputs.size());
322 }
323
324 for (int i = 0; i < mInputs.size(); i++) {
325 Object obj = inputs[i];
326 if (obj instanceof Future || obj instanceof UnboundValue) {
327 Log.e(TAG, this.toString() + ": input " + i +
328 " is a future or unbound value");
329 return null;
330 }
331 UnboundValue unbound = mInputs.get(i);
332 unbound.set(obj);
333 }
334
335 mRS.nScriptGroup2Execute(getID(mRS));
336
337 Object[] outputObjs = new Object[mOutputs.length];
338 int i = 0;
339 for (Future f : mOutputs) {
340 outputObjs[i++] = f.getValue();
341 }
342 return outputObjs;
Yang Nibe392ad2015-01-23 17:16:02 -0800343 }
344
Yang Nicc1ca482015-03-16 15:53:18 -0700345 /**
346 @hide Pending Android public API approval.
347 */
348 public static final class Builder {
349 RenderScript mRS;
350 List<Closure> mClosures;
351 List<UnboundValue> mInputs;
Yang Ni281c3252014-10-24 08:52:24 -0700352
Yang Nicc1ca482015-03-16 15:53:18 -0700353 private static final String TAG = "ScriptGroup2.Builder";
Yang Ni281c3252014-10-24 08:52:24 -0700354
Yang Nicc1ca482015-03-16 15:53:18 -0700355 public Builder(RenderScript rs) {
356 mRS = rs;
357 mClosures = new ArrayList<Closure>();
358 mInputs = new ArrayList<UnboundValue>();
359 }
360
361 public Closure addKernel(Script.KernelID k, Type returnType, Object[] args,
362 Map<Script.FieldID, Object> globalBindings) {
363 Closure c = new Closure(mRS, k, returnType, args, globalBindings);
364 mClosures.add(c);
365 return c;
366 }
367
368 public Closure addInvoke(Script.InvokeID invoke, Object[] args,
369 Map<Script.FieldID, Object> globalBindings) {
370 Closure c = new Closure(mRS, invoke, args, globalBindings);
371 mClosures.add(c);
372 return c;
373 }
374
375 public UnboundValue addInput() {
376 UnboundValue unbound = new UnboundValue();
377 mInputs.add(unbound);
378 return unbound;
379 }
380
381 public ScriptGroup2 create(Future... outputs) {
382 ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs);
383 return ret;
384 }
385
386 }
Yang Ni281c3252014-10-24 08:52:24 -0700387}