1423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams/*
2423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * Copyright (C) 2012 The Android Open Source Project
3423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams *
4423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * you may not use this file except in compliance with the License.
6423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * You may obtain a copy of the License at
7423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams *
8423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams *
10423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * Unless required by applicable law or agreed to in writing, software
11423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * See the License for the specific language governing permissions and
14423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams * limitations under the License.
15423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams */
16423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
17423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Samspackage android.renderscript;
18423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
1918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Niimport android.util.Log;
2018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Niimport android.util.Pair;
2108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Samsimport java.util.ArrayList;
2218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Niimport java.util.HashMap;
2318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Niimport java.util.List;
2418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Niimport java.util.Map;
25423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
26423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams/**
2718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * A group of kernels that are executed
2818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * together with one execution call as if they were a single kernel
2908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams * <p>
3018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * In addition to kernels, a script group may contain invocable functions as well.
3118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * A script group may take inputs and generate outputs, which are consumed and
3218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * produced by its member kernels.
3318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * Inside a script group, outputs from one kernel can be passed to another kernel as inputs.
3418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * The API disallows cyclic dependencies among kernels in a script group,
3518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * effectively making it a directed acyclic graph (DAG) of kernels.
362a603897c6fdeba553051eedb911ec3b0b794530Tim Murray * <p>
3718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * Grouping kernels together allows for more efficient execution. For example,
3818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * runtime and compiler optimization can be applied to reduce computation and
3918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni * communication overhead, and to make better use of the CPU and the GPU.
40423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams **/
4108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Samspublic final class ScriptGroup extends BaseObj {
4218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    private static final String TAG = "ScriptGroup";
43423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    IO mOutputs[];
44423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    IO mInputs[];
45423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
46423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    static class IO {
4708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        Script.KernelID mKID;
48423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        Allocation mAllocation;
49423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
5008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        IO(Script.KernelID s) {
5108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mKID = s;
52423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
53423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
54423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
5508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    static class ConnectLine {
5608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
5708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mFrom = from;
5808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mToK = to;
59423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            mAllocationType = t;
60423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
61423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
6208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
6308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mFrom = from;
6408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mToF = to;
6508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mAllocationType = t;
66423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
6708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
6808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        Script.FieldID mToF;
6908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        Script.KernelID mToK;
7008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        Script.KernelID mFrom;
7108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        Type mAllocationType;
72423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
73423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
74423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    static class Node {
75423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        Script mScript;
7608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
7708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
7808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
792a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        int dagNumber;
80423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
81423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        Node mNext;
82423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
83423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        Node(Script s) {
84423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            mScript = s;
85423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
86423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
87423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
88423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
8918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    /**
9018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * An opaque class for closures
9118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * <p>
9218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A closure represents a function call to a kernel or invocable function,
9318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * combined with arguments and values for global variables. A closure is
9418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * created using the {@link android.renderscript.ScriptGroup.Builder2#addKernel} or
9518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * {@link android.renderscript.ScriptGroup.Builder2#addInvoke}
9618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * method.
9718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     */
9818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
9918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    public static final class Closure extends BaseObj {
10018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Object[] mArgs;
10118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Allocation mReturnValue;
10218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Map<Script.FieldID, Object> mBindings;
10318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
10418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Future mReturnFuture;
10518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Map<Script.FieldID, Future> mGlobalFuture;
10618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
10718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private FieldPacker mFP;
10818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
10918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private static final String TAG = "Closure";
11018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
11118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Closure(long id, RenderScript rs) {
11218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            super(id, rs);
11318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
11418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
11518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
11618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                       Object[] args, Map<Script.FieldID, Object> globals) {
11718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            super(0, rs);
11818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
11918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mArgs = args;
12018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mReturnValue = Allocation.createTyped(rs, returnType);
12118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mBindings = globals;
12218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mGlobalFuture = new HashMap<Script.FieldID, Future>();
12318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
12418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int numValues = args.length + globals.size();
12518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
12618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] fieldIDs = new long[numValues];
12718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] values = new long[numValues];
12818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int[] sizes = new int[numValues];
12918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] depClosures = new long[numValues];
13018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] depFieldIDs = new long[numValues];
13118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
13218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int i;
13318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (i = 0; i < args.length; i++) {
13418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                fieldIDs[i] = 0;
135870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                retrieveValueAndDependenceInfo(rs, i, null, args[i],
136870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                                               values, sizes, depClosures, depFieldIDs);
13718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
13818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
13918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Object obj = entry.getValue();
14018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Script.FieldID fieldID = entry.getKey();
14118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                fieldIDs[i] = fieldID.getID(rs);
142870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                retrieveValueAndDependenceInfo(rs, i, fieldID, obj,
143870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                                               values, sizes, depClosures, depFieldIDs);
14418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                i++;
14518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
14618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
14718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
14818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                        fieldIDs, values, sizes, depClosures, depFieldIDs);
14918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
15018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            setID(id);
15118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
15218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
15318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Closure(RenderScript rs, Script.InvokeID invokeID,
15418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                       Object[] args, Map<Script.FieldID, Object> globals) {
15518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            super(0, rs);
15618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mFP = FieldPacker.createFromArray(args);
15718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
15818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mArgs = args;
15918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mBindings = globals;
16018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mGlobalFuture = new HashMap<Script.FieldID, Future>();
16118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
16218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int numValues = globals.size();
16318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
16418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] fieldIDs = new long[numValues];
16518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] values = new long[numValues];
16618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int[] sizes = new int[numValues];
16718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] depClosures = new long[numValues];
16818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long[] depFieldIDs = new long[numValues];
16918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
17018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int i = 0;
17118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
17218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Object obj = entry.getValue();
17318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Script.FieldID fieldID = entry.getKey();
17418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                fieldIDs[i] = fieldID.getID(rs);
175870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                retrieveValueAndDependenceInfo(rs, i, fieldID, obj, values,
176870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                                               sizes, depClosures, depFieldIDs);
17718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                i++;
17818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
17918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
18018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
18118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                              values, sizes);
18218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
18318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            setID(id);
18418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
18518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
186870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni        private void retrieveValueAndDependenceInfo(RenderScript rs,
187870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                                                    int index, Script.FieldID fid, Object obj,
18818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                                    long[] values, int[] sizes,
18918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                                    long[] depClosures,
19018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                                    long[] depFieldIDs) {
19118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
19218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (obj instanceof Future) {
19318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Future f = (Future)obj;
19418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                obj = f.getValue();
19518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                depClosures[index] = f.getClosure().getID(rs);
19618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Script.FieldID fieldID = f.getFieldID();
19718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
19818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            } else {
19918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                depClosures[index] = 0;
20018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                depFieldIDs[index] = 0;
20118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
20218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
203870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            if (obj instanceof Input) {
204870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                Input unbound = (Input)obj;
205870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                if (index < mArgs.length) {
206870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                    unbound.addReference(this, index);
207870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                } else {
208870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                    unbound.addReference(this, fid);
209870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                }
210870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                values[index] = 0;
211870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                sizes[index] = 0;
212870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            } else {
213870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                ValueAndSize vs = new ValueAndSize(rs, obj);
214870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                values[index] = vs.value;
215870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                sizes[index] = vs.size;
216870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            }
21718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
21818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
21918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
22018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Returns the future for the return value
22118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
22218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a future
22318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
22418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
22518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Future getReturn() {
22618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (mReturnFuture == null) {
22718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                mReturnFuture = new Future(this, null, mReturnValue);
22818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
22918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
23018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return mReturnFuture;
23118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
23218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
23318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
23418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Returns the future for a global variable
23518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
23618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param field the field ID for the global variable
23718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a future
23818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
23918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
24018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Future getGlobal(Script.FieldID field) {
24118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Future f = mGlobalFuture.get(field);
24218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
24318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (f == null) {
24418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                // If the field is not bound to this closure, this will return a future
24518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                // without an associated value (reference). So this is not working for
24618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                // cross-module (cross-script) linking in this case where a field not
24718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                // explicitly bound.
248870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                Object obj = mBindings.get(field);
249870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                if (obj instanceof Future) {
250870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                    obj = ((Future)obj).getValue();
251870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                }
252870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                f = new Future(this, field, obj);
25318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                mGlobalFuture.put(field, f);
25418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
25518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
25618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return f;
25718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
25818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
25918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        void setArg(int index, Object obj) {
260870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            if (obj instanceof Future) {
261870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                obj = ((Future)obj).getValue();
262870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            }
26318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mArgs[index] = obj;
26418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            ValueAndSize vs = new ValueAndSize(mRS, obj);
26518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
26618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
26718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
26818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        void setGlobal(Script.FieldID fieldID, Object obj) {
269870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            if (obj instanceof Future) {
270870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                obj = ((Future)obj).getValue();
271870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            }
27218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mBindings.put(fieldID, obj);
27318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            ValueAndSize vs = new ValueAndSize(mRS, obj);
27418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
27518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
27618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
27718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private static final class ValueAndSize {
27818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            public ValueAndSize(RenderScript rs, Object obj) {
27918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                if (obj instanceof Allocation) {
28018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    value = ((Allocation)obj).getID(rs);
28118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    size = -1;
28218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                } else if (obj instanceof Boolean) {
28318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    value = ((Boolean)obj).booleanValue() ? 1 : 0;
28418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    size = 4;
28518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                } else if (obj instanceof Integer) {
28618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    value = ((Integer)obj).longValue();
28718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    size = 4;
28818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                } else if (obj instanceof Long) {
28918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    value = ((Long)obj).longValue();
29018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    size = 8;
29118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                } else if (obj instanceof Float) {
29218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    value = ((Float)obj).longValue();
29318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    size = 4;
29418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                } else if (obj instanceof Double) {
29518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    value = ((Double)obj).longValue();
29618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    size = 8;
29718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                }
29818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
29918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            public long value;
30018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            public int size;
30118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
30218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
30318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
30418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    /**
30518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * An opaque class for futures
30618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * <p>
30718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A future represents an output of a closure, either the return value of
30818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * the function, or the value of a global variable written by the function.
30918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A future is created by calling the {@link Closure#getReturn}  or
31018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * {@link Closure#getGlobal} method.
31118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     */
31218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
31318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    public static final class Future {
31418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Closure mClosure;
31518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Script.FieldID mFieldID;
31618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Object mValue;
31718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
31818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Future(Closure closure, Script.FieldID fieldID, Object value) {
31918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mClosure = closure;
32018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mFieldID = fieldID;
32118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mValue = value;
32218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
32318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
32418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Closure getClosure() { return mClosure; }
32518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Script.FieldID getFieldID() { return mFieldID; }
32618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Object getValue() { return mValue; }
32718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
32818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
32918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    /**
33018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * An opaque class for script group inputs
33118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * <p>
33218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * Created by calling the {@link Builder2#addInput} method. The value
33318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * is assigned in {@link ScriptGroup#execute(Object...)} method as
33418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * one of its arguments. Arguments to the execute method should be in
33518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * the same order as intputs are added using the addInput method.
33618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     */
33718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
33818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    public static final class Input {
33918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        // Either mFieldID or mArgIndex should be set but not both.
34018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        List<Pair<Closure, Script.FieldID>> mFieldID;
34118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        // -1 means unset. Legal values are 0 .. n-1, where n is the number of
34218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        // arguments for the referencing closure.
34318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        List<Pair<Closure, Integer>> mArgIndex;
344870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni        Object mValue;
34518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
34618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Input() {
34718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
34818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mArgIndex = new ArrayList<Pair<Closure, Integer>>();
34918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
35018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
35118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        void addReference(Closure closure, int index) {
35218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
35318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
35418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
35518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        void addReference(Closure closure, Script.FieldID fieldID) {
35618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mFieldID.add(Pair.create(closure, fieldID));
35718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
35818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
35918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        void set(Object value) {
360870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            mValue = value;
36118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (Pair<Closure, Integer> p : mArgIndex) {
36218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Closure closure = p.first;
36318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                int index = p.second.intValue();
36418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                closure.setArg(index, value);
36518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
36618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (Pair<Closure, Script.FieldID> p : mFieldID) {
36718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Closure closure = p.first;
36818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Script.FieldID fieldID = p.second;
36918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                closure.setGlobal(fieldID, value);
37018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
37118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
372870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni
373870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni        Object get() { return mValue; }
37418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
37518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
37618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    private String mName;
37718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    private List<Closure> mClosures;
37818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    private List<Input> mInputs2;
37918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    private Future[] mOutputs2;
38018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
381460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray    ScriptGroup(long id, RenderScript rs) {
382423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        super(id, rs);
383423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
384423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
38518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    ScriptGroup(RenderScript rs, String name, List<Closure> closures,
38618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                 List<Input> inputs, Future[] outputs) {
38718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        super(0, rs);
38818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        mName = name;
38918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        mClosures = closures;
39018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        mInputs2 = inputs;
39118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        mOutputs2 = outputs;
39218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
39318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        long[] closureIDs = new long[closures.size()];
39418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        for (int i = 0; i < closureIDs.length; i++) {
39518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            closureIDs[i] = closures.get(i).getID(rs);
39618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
39718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        long id = rs.nScriptGroup2Create(name, ScriptC.mCachePath, closureIDs);
39818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        setID(id);
39918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
40018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
40118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    /**
40218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * Executes a script group
40318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     *
40443563896061bd70f83b10325c2642d1b97b26df5Yang Ni     * @param inputs Values for inputs to the script group, in the order as the
40543563896061bd70f83b10325c2642d1b97b26df5Yang Ni     *        inputs are added via {@link Builder2#addInput}.
40643563896061bd70f83b10325c2642d1b97b26df5Yang Ni     * @return Outputs of the script group as an array of objects, in the order
40743563896061bd70f83b10325c2642d1b97b26df5Yang Ni     *         as futures are passed to {@link Builder2#create}.
40818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     */
40918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
41018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    public Object[] execute(Object... inputs) {
41118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        if (inputs.length < mInputs2.size()) {
41218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
41318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                  "less than expected " + mInputs2.size());
41418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return null;
41518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
41618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
41718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        if (inputs.length > mInputs2.size()) {
41818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
41918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                  "more than expected " + mInputs2.size());
42018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
42118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
42218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        for (int i = 0; i < mInputs2.size(); i++) {
42318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Object obj = inputs[i];
42418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (obj instanceof Future || obj instanceof Input) {
42518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Log.e(TAG, this.toString() + ": input " + i +
42618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                      " is a future or unbound value");
42718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                return null;
42818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
42918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Input unbound = mInputs2.get(i);
43018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            unbound.set(obj);
43118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
43218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
43318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        mRS.nScriptGroup2Execute(getID(mRS));
43418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
43518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        Object[] outputObjs = new Object[mOutputs2.length];
43618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        int i = 0;
43718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        for (Future f : mOutputs2) {
438870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            Object output = f.getValue();
439870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            if (output instanceof Input) {
440870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                output = ((Input)output).get();
441870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            }
442870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni            outputObjs[i++] = output;
44318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
44418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        return outputObjs;
44518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
44618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
44708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    /**
44808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * Sets an input of the ScriptGroup. This specifies an
449c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Allocation to be used for kernels that require an input
450c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Allocation provided from outside of the ScriptGroup.
45108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     *
45218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * @deprecated Set arguments to {@link #execute(Object...)} instead.
45318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     *
45408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * @param s The ID of the kernel where the allocation should be
45508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     *          connected.
45608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * @param a The allocation to connect.
45708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     */
45808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    public void setInput(Script.KernelID s, Allocation a) {
459423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        for (int ct=0; ct < mInputs.length; ct++) {
46008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (mInputs[ct].mKID == s) {
461423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                mInputs[ct].mAllocation = a;
46208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
463423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                return;
464423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            }
465423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
466423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        throw new RSIllegalArgumentException("Script not found");
467423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
468423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
46908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    /**
47008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * Sets an output of the ScriptGroup. This specifies an
471c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Allocation to be used for the kernels that require an output
472c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Allocation visible after the ScriptGroup is executed.
47308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     *
47418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * @deprecated Use return value of {@link #execute(Object...)} instead.
47518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     *
47608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * @param s The ID of the kernel where the allocation should be
47708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     *          connected.
47808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * @param a The allocation to connect.
47908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     */
48008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    public void setOutput(Script.KernelID s, Allocation a) {
481423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        for (int ct=0; ct < mOutputs.length; ct++) {
48208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (mOutputs[ct].mKID == s) {
483423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                mOutputs[ct].mAllocation = a;
48408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
485423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                return;
486423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            }
487423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
488423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        throw new RSIllegalArgumentException("Script not found");
489423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
490423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
49108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    /**
49208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * Execute the ScriptGroup.  This will run all the kernels in
493c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * the ScriptGroup.  No internal connection results will be visible
494c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * after execution of the ScriptGroup.
49518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     *
49618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * @deprecated Use {@link #execute} instead.
49718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     *
49808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     */
499423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    public void execute() {
50008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        mRS.nScriptGroupExecute(getID(mRS));
501423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
502423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
503423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
50408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    /**
505c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Helper class to build a ScriptGroup. A ScriptGroup is
506c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * created in two steps.
507c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * <p>
508c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * First, all kernels to be used by the ScriptGroup should be added.
50908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * <p>
510c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Second, add connections between kernels. There are two types
511c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * of connections: kernel to kernel and kernel to field.
512c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Kernel to kernel allows a kernel's output to be passed to
513c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * another kernel as input. Kernel to field allows the output of
514c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * one kernel to be bound as a script global. Kernel to kernel is
515c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * higher performance and should be used where possible.
51608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * <p>
517c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * A ScriptGroup must contain a single directed acyclic graph (DAG); it
518c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * cannot contain cycles. Currently, all kernels used in a ScriptGroup
519c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * must come from different Script objects. Additionally, all kernels
520c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * in a ScriptGroup must have at least one input, output, or internal
521c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * connection.
52208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * <p>
523c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Once all connections are made, a call to {@link #create} will
52408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     * return the ScriptGroup object.
52508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     *
52618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * @deprecated Use {@link Builder2} instead.
52718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     *
52808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams     */
52908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams    public static final class Builder {
53008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        private RenderScript mRS;
53108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        private ArrayList<Node> mNodes = new ArrayList<Node>();
53208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
53308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        private int mKernelCount;
53408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
53508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        /**
536c11e25c4e653124def1fb18e203b894f42106cbeTim Murray         * Create a Builder for generating a ScriptGroup.
53708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
53808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
539c11e25c4e653124def1fb18e203b894f42106cbeTim Murray         * @param rs The RenderScript context.
54008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         */
541423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        public Builder(RenderScript rs) {
542423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            mRS = rs;
543423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
544423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
545091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray        // do a DFS from original node, looking for original node
546091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray        // any cycle that could be created must contain original node
547091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray        private void validateCycle(Node target, Node original) {
548091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray            for (int ct = 0; ct < target.mOutputs.size(); ct++) {
549091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                final ConnectLine cl = target.mOutputs.get(ct);
55008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                if (cl.mToK != null) {
55108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    Node tn = findNode(cl.mToK.mScript);
552091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                    if (tn.equals(original)) {
553423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
554423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                    }
555091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                    validateCycle(tn, original);
55608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                }
55708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                if (cl.mToF != null) {
55808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    Node tn = findNode(cl.mToF.mScript);
559091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                    if (tn.equals(original)) {
56008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
56108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    }
562091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                    validateCycle(tn, original);
5632a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                }
5642a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
5652a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        }
5662a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
5672a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        private void mergeDAGs(int valueUsed, int valueKilled) {
5682a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            for (int ct=0; ct < mNodes.size(); ct++) {
5692a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                if (mNodes.get(ct).dagNumber == valueKilled)
5702a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    mNodes.get(ct).dagNumber = valueUsed;
5712a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
5722a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        }
5732a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
5742a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        private void validateDAGRecurse(Node n, int dagNumber) {
5752a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            // combine DAGs if this node has been seen already
5762a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            if (n.dagNumber != 0 && n.dagNumber != dagNumber) {
5772a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                mergeDAGs(n.dagNumber, dagNumber);
5782a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                return;
5792a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
5802a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
5812a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            n.dagNumber = dagNumber;
5822a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            for (int ct=0; ct < n.mOutputs.size(); ct++) {
5832a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                final ConnectLine cl = n.mOutputs.get(ct);
5842a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                if (cl.mToK != null) {
5852a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    Node tn = findNode(cl.mToK.mScript);
5862a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    validateDAGRecurse(tn, dagNumber);
5872a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                }
5882a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                if (cl.mToF != null) {
5892a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    Node tn = findNode(cl.mToF.mScript);
5902a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    validateDAGRecurse(tn, dagNumber);
5912a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                }
5922a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
5932a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        }
5942a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
5952a603897c6fdeba553051eedb911ec3b0b794530Tim Murray        private void validateDAG() {
5962a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            for (int ct=0; ct < mNodes.size(); ct++) {
5972a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                Node n = mNodes.get(ct);
5982a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                if (n.mInputs.size() == 0) {
5992a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
600870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                        String msg = "Groups cannot contain unconnected scripts";
601870767eb95a05d50c67db4a1a46ce73ada94bd59Yang Ni                        throw new RSInvalidStateException(msg);
6022a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    }
6032a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    validateDAGRecurse(n, ct+1);
6042a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                }
6052a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
6062a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            int dagNumber = mNodes.get(0).dagNumber;
6072a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            for (int ct=0; ct < mNodes.size(); ct++) {
6082a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                if (mNodes.get(ct).dagNumber != dagNumber) {
6092a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                    throw new RSInvalidStateException("Multiple DAGs in group not allowed.");
610423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                }
611423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            }
612423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
613423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
61408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        private Node findNode(Script s) {
61508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
61608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                if (s == mNodes.get(ct).mScript) {
61708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    return mNodes.get(ct);
618423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                }
619423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            }
620423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            return null;
621423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
622423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
62308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        private Node findNode(Script.KernelID k) {
62408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
62508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                Node n = mNodes.get(ct);
62608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
62708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    if (k == n.mKernels.get(ct2)) {
62808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        return n;
629423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                    }
630423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams                }
631423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            }
63208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            return null;
63308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        }
63408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
63508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        /**
63608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * Adds a Kernel to the group.
63708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
63808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
63908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param k The kernel to add.
64008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
64108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @return Builder Returns this.
64208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         */
64308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        public Builder addKernel(Script.KernelID k) {
64408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (mLines.size() != 0) {
64508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                throw new RSInvalidStateException(
64608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    "Kernels may not be added once connections exist.");
64708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
64808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
64908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
65008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (findNode(k) != null) {
65108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                return this;
65208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
65308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            //android.util.Log.v("RSR", "addKernel 2 ");
65408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mKernelCount++;
65508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            Node n = findNode(k.mScript);
65608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (n == null) {
65708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                //android.util.Log.v("RSR", "addKernel 3 ");
65808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                n = new Node(k.mScript);
65908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                mNodes.add(n);
66008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
66108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            n.mKernels.add(k);
66208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            return this;
66308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        }
66408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
66508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        /**
66608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * Adds a connection to the group.
66708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
66808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
66908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param t The type of the connection. This is used to
67008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *          determine the kernel launch sizes on the source side
67108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *          of this connection.
67208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param from The source for the connection.
67308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param to The destination of the connection.
67408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
67508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @return Builder Returns this
67608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         */
67708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
67808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
67908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
68008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            Node nf = findNode(from);
68108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (nf == null) {
682091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                throw new RSInvalidStateException("From script not found.");
68308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
68408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
68508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            Node nt = findNode(to.mScript);
68608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (nt == null) {
68708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                throw new RSInvalidStateException("To script not found.");
68808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
68908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
69008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            ConnectLine cl = new ConnectLine(t, from, to);
69108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mLines.add(new ConnectLine(t, from, to));
69208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
69308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            nf.mOutputs.add(cl);
69408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            nt.mInputs.add(cl);
69508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
696091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray            validateCycle(nf, nf);
69708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            return this;
69808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        }
69908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
70008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        /**
70108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * Adds a connection to the group.
70208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
70308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
70408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param t The type of the connection. This is used to
70508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *          determine the kernel launch sizes for both sides of
70608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *          this connection.
70708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param from The source for the connection.
70808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @param to The destination of the connection.
70908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
71008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @return Builder Returns this
71108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         */
71208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
71308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
71408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
71508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            Node nf = findNode(from);
71608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (nf == null) {
717091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray                throw new RSInvalidStateException("From script not found.");
71808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
71908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
72008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            Node nt = findNode(to);
72108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (nt == null) {
72208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                throw new RSInvalidStateException("To script not found.");
723423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            }
72408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
72508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            ConnectLine cl = new ConnectLine(t, from, to);
72608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            mLines.add(new ConnectLine(t, from, to));
72708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
72808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            nf.mOutputs.add(cl);
72908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            nt.mInputs.add(cl);
730423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
731091f7ccf9a97aed94383370666b592a57a1b9400Tim Murray            validateCycle(nf, nf);
732423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            return this;
733423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
734423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
73508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
73608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
73708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams        /**
73808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * Creates the Script group.
73908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
74008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         *
74108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         * @return ScriptGroup The new ScriptGroup
74208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams         */
743423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        public ScriptGroup create() {
7442a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
7452a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            if (mNodes.size() == 0) {
7462a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                throw new RSInvalidStateException("Empty script groups are not allowed");
7472a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
7482a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
7492a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            // reset DAG numbers in case we're building a second group
7502a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            for (int ct=0; ct < mNodes.size(); ct++) {
7512a603897c6fdeba553051eedb911ec3b0b794530Tim Murray                mNodes.get(ct).dagNumber = 0;
7522a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            }
7532a603897c6fdeba553051eedb911ec3b0b794530Tim Murray            validateDAG();
7542a603897c6fdeba553051eedb911ec3b0b794530Tim Murray
75508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            ArrayList<IO> inputs = new ArrayList<IO>();
75608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            ArrayList<IO> outputs = new ArrayList<IO>();
75708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
7589807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat            long[] kernels = new long[mKernelCount];
75908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            int idx = 0;
76008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
76108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                Node n = mNodes.get(ct);
76208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
76308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    final Script.KernelID kid = n.mKernels.get(ct2);
7649807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat                    kernels[idx++] = kid.getID(mRS);
76508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
76608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    boolean hasInput = false;
76708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    boolean hasOutput = false;
76808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
76908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        if (n.mInputs.get(ct3).mToK == kid) {
77008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                            hasInput = true;
77108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        }
77208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    }
77308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
77408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        if (n.mOutputs.get(ct3).mFrom == kid) {
77508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                            hasOutput = true;
77608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        }
77708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    }
77808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    if (!hasInput) {
77908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        inputs.add(new IO(kid));
78008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    }
78108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    if (!hasOutput) {
78208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                        outputs.add(new IO(kid));
78308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                    }
784423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
78508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                }
78608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
78708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (idx != mKernelCount) {
78808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                throw new RSRuntimeException("Count mismatch, should not happen.");
78908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
79008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
7919807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat            long[] src = new long[mLines.size()];
7929807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat            long[] dstk = new long[mLines.size()];
7939807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat            long[] dstf = new long[mLines.size()];
7949807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat            long[] types = new long[mLines.size()];
79508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
79608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            for (int ct=0; ct < mLines.size(); ct++) {
79708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                ConnectLine cl = mLines.get(ct);
7989807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat                src[ct] = cl.mFrom.getID(mRS);
79908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                if (cl.mToK != null) {
8009807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat                    dstk[ct] = cl.mToK.getID(mRS);
80108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                }
80208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                if (cl.mToF != null) {
8039807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat                    dstf[ct] = cl.mToF.getID(mRS);
80408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                }
8059807155b11a25fb6068edc9b1cd82928ac2f05deAshok Bhat                types[ct] = cl.mAllocationType.getID(mRS);
80608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
80708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
808460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray            long id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
80908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            if (id == 0) {
81008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                throw new RSRuntimeException("Object creation error, should not happen.");
81108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
81208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
81308a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            ScriptGroup sg = new ScriptGroup(id, mRS);
81408a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            sg.mOutputs = new IO[outputs.size()];
81508a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            for (int ct=0; ct < outputs.size(); ct++) {
81608a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                sg.mOutputs[ct] = outputs.get(ct);
81708a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
81808a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams
81908a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            sg.mInputs = new IO[inputs.size()];
82008a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            for (int ct=0; ct < inputs.size(); ct++) {
82108a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams                sg.mInputs[ct] = inputs.get(ct);
82208a81583c18a849e442ceeb8d7baeca743fb3be8Jason Sams            }
823423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
824423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams            return sg;
825423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams        }
826423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
827423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams    }
828423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
82918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    /**
83018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * Represents a binding of a value to a global variable in a
83118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * kernel or invocable function. Used in closure creation.
83218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     */
833423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
83418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    public static final class Binding {
83518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private final Script.FieldID mField;
83618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private final Object mValue;
83718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
83818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
83918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Returns a Binding object that binds value to field
84018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
84118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param field the Script.FieldID of the global variable
84218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param value the value
84318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
84418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
84518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Binding(Script.FieldID field, Object value) {
84618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mField = field;
84718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mValue = value;
84818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
84918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
85018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
85118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Returns the field ID
85218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
85318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
85477eba488894494e739c47723cd46b7652d5cc6deYang Ni        Script.FieldID getField() { return mField; }
85518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
85618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
85718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Returns the value
85818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
85918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
86077eba488894494e739c47723cd46b7652d5cc6deYang Ni        Object getValue() { return mValue; }
86118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
86218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
86318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    /**
86418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * The builder class for creating script groups
86518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * <p>
86618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A script group is created using closures (see class {@link Closure}).
86718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A closure is a function call to a kernel or
86818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * invocable function. Each function argument or global variable accessed inside
86918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * the function is bound to 1) a known value, 2) a script group input
87018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * (see class {@link Input}), or 3) a
87118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * future (see class {@link Future}).
87218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A future is the output of a closure, either the return value of the
87318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * function or a global variable written by that function.
87418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * <p>
87518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * Closures are created using the {@link #addKernel} or {@link #addInvoke}
87618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * methods.
87718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * When a closure is created, futures from previously created closures
87818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * can be used as its inputs.
87918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * External script group inputs can be used as inputs to individual closures as well.
88018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * An external script group input is created using the {@link #addInput} method.
88118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * A script group is created by a call to the {@link #create} method, which
88218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * accepts an array of futures as the outputs for the script group.
88318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * <p>
88418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * Closures in a script group can be evaluated in any order as long as the
88518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * following conditions are met:
88618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * 1) a closure must be evaluated before any other closures that take its
88718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * futures as inputs;
88818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * 2) all closures added before an invoke closure must be evaluated
88918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * before it;
89018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * and 3) all closures added after an invoke closure must be evaluated after
89118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * it.
89218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * As a special case, the order that the closures are added is a legal
89318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * evaluation order. However, other evaluation orders are possible, including
89418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     * concurrently evaluating independent closures.
89518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni     */
89618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
89718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    public static final class Builder2 {
89818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        RenderScript mRS;
89918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        List<Closure> mClosures;
90018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        List<Input> mInputs;
90118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private static final String TAG = "ScriptGroup.Builder2";
90218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
90318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
90418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Returns a Builder object
90518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
90618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param rs the RenderScript context
90718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
90818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Builder2(RenderScript rs) {
90918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mRS = rs;
91018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mClosures = new ArrayList<Closure>();
91118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mInputs = new ArrayList<Input>();
91218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
913423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
91418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
91518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Adds a closure for a kernel
91618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
91718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param k Kernel ID for the kernel function
91818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param returnType Allocation type for the return value
91918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param args arguments to the kernel function
92018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param globalBindings bindings for global variables
92118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a closure
92218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
923423ebcb4dc4881c3a83e8121d5212466287d0d0cJason Sams
92418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Closure addKernelInternal(Script.KernelID k, Type returnType, Object[] args,
92518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                          Map<Script.FieldID, Object> globalBindings) {
92618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Closure c = new Closure(mRS, k, returnType, args, globalBindings);
92718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mClosures.add(c);
92818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return c;
92918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
93018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
93118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
93218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Adds a closure for an invocable function
93318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
93418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param invoke Invoke ID for the invocable function
93518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param args arguments to the invocable function
93618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param globalBindings bindings for global variables
93718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a closure
93818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
93918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
94018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private Closure addInvokeInternal(Script.InvokeID invoke, Object[] args,
94118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                          Map<Script.FieldID, Object> globalBindings) {
94218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Closure c = new Closure(mRS, invoke, args, globalBindings);
94318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mClosures.add(c);
94418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return c;
94518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
94618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
94718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
94818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Adds a script group input
94918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
95018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a script group input, which can be used as an argument or a value to
95118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *     a global variable for creating closures
95218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
95318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Input addInput() {
95418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Input unbound = new Input();
95518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            mInputs.add(unbound);
95618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return unbound;
95718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
95818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
95918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
96018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Adds a closure for a kernel
96118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
96218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param k Kernel ID for the kernel function
96318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param argsAndBindings arguments followed by bindings for global variables
96418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a closure
96518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
96618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
96718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
96818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            ArrayList<Object> args = new ArrayList<Object>();
96918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
97018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
97118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                return null;
97218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
97318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return addKernelInternal(k, returnType, args.toArray(), bindingMap);
97418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
97518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
97618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
97718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Adds a closure for an invocable function
97818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
97918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param invoke Invoke ID for the invocable function
98018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param argsAndBindings arguments followed by bindings for global variables
98118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a closure
98218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
98318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
98418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
98518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            ArrayList<Object> args = new ArrayList<Object>();
98618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
98718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
98818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                return null;
98918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
99018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return addInvokeInternal(invoke, args.toArray(), bindingMap);
99118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
99218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
99318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        /**
99418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * Creates a script group
99518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *
99618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param name name for the script group. Legal names can only contain letters, digits,
99718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         *        '-', or '_'. The name can be no longer than 100 characters.
998dbb6fd58a4b113f8761ce825ad5b91e50c170971Yang Ni         *        Try to use unique names, to avoid name conflicts and reduce
999dbb6fd58a4b113f8761ce825ad5b91e50c170971Yang Ni         *        the cost of group creation.
100018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @param outputs futures intended as outputs of the script group
100118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         * @return a script group
100218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni         */
100318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
100418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        public ScriptGroup create(String name, Future... outputs) {
100518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            if (name == null || name.isEmpty() || name.length() > 100 ||
100618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
100718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                throw new RSIllegalArgumentException("invalid script group name");
100818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
100918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            ScriptGroup ret = new ScriptGroup(mRS, name, mClosures, mInputs, outputs);
101018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return ret;
101118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
101218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
101318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        private boolean seperateArgsAndBindings(Object[] argsAndBindings,
101418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                                ArrayList<Object> args,
101518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                                                Map<Script.FieldID, Object> bindingMap) {
101618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            int i;
101718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (i = 0; i < argsAndBindings.length; i++) {
101818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                if (argsAndBindings[i] instanceof Binding) {
101918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    break;
102018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                }
102118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                args.add(argsAndBindings[i]);
102218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
102318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
102418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            for (; i < argsAndBindings.length; i++) {
102518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                if (!(argsAndBindings[i] instanceof Binding)) {
102618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                    return false;
102718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                }
102818314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                Binding b = (Binding)argsAndBindings[i];
102918314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni                bindingMap.put(b.getField(), b.getValue());
103018314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            }
103118314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
103218314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni            return true;
103318314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni        }
103418314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
103518314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni    }
103618314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni
103718314caccd4e4b7cf59f2a18a38181f8e3d88634Yang Ni}
1038