198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams/*
298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * Copyright (C) 2012 The Android Open Source Project
398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams *
498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * you may not use this file except in compliance with the License.
698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * You may obtain a copy of the License at
798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams *
898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams *
1098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * Unless required by applicable law or agreed to in writing, software
1198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
1298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * See the License for the specific language governing permissions and
1498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams * limitations under the License.
1598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams */
1698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
1798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Samspackage android.support.v8.renderscript;
1898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
19ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Niimport android.util.Log;
20ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Niimport android.util.Pair;
2198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Samsimport java.lang.reflect.Method;
22ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsimport java.util.ArrayList;
23059fede7f200350b6131fc131f76248085485722Miao Wangimport java.util.Collections;
24059fede7f200350b6131fc131f76248085485722Miao Wangimport java.util.Comparator;
25ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Niimport java.util.HashMap;
26ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Niimport java.util.List;
27ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Niimport java.util.Map;
2898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
2998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams/**
30ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * A group of kernels that are executed
31ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * together with one execution call as if they were a single kernel
32ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * <p>
33ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * In addition to kernels, a script group may contain invocable functions as well.
34ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * A script group may take inputs and generate outputs, which are consumed and
35ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * produced by its member kernels.
36ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * Inside a script group, outputs from one kernel can be passed to another kernel as inputs.
37ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * The API disallows cyclic dependencies among kernels in a script group,
38ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * effectively making it a directed acyclic graph (DAG) of kernels.
391b370e358d16cc3b50b169511d6b387db09f972dJason Sams * <p>
40ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * Grouping kernels together allows for more efficient execution. For example,
41ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * runtime and compiler optimization can be applied to reduce computation and
42ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni * communication overhead, and to make better use of the CPU and the GPU.
4398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams **/
443b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wangpublic final class ScriptGroup extends BaseObj {
45ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    //FIXME: Change 23 to the codename when that is decided.
46ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    private static final int MIN_API_VERSION = 23;
473b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    private static final String TAG = "ScriptGroup";
4898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    IO mOutputs[];
4998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    IO mInputs[];
50059fede7f200350b6131fc131f76248085485722Miao Wang    private boolean mUseIncSupp = false;
51059fede7f200350b6131fc131f76248085485722Miao Wang    private ArrayList<Node> mNodes = new ArrayList<Node>();
5298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
5398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    static class IO {
54ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.KernelID mKID;
5598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Allocation mAllocation;
5698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
57ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        IO(Script.KernelID s) {
58ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mKID = s;
5998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
6098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
6198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
62ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    static class ConnectLine {
63ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
64ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mFrom = from;
65ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mToK = to;
6698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mAllocationType = t;
6798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
6898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
69ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
70ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mFrom = from;
71ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mToF = to;
72ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mAllocationType = t;
7398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
74ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
75ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.FieldID mToF;
76ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.KernelID mToK;
77ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.KernelID mFrom;
78ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Type mAllocationType;
79059fede7f200350b6131fc131f76248085485722Miao Wang        Allocation mAllocation;
8098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
8198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
8298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    static class Node {
8398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Script mScript;
84ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
85ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
86ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
871b370e358d16cc3b50b169511d6b387db09f972dJason Sams        int dagNumber;
88059fede7f200350b6131fc131f76248085485722Miao Wang        boolean mSeen;
89059fede7f200350b6131fc131f76248085485722Miao Wang        int mOrder;
9098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
9198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Node mNext;
9298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
9398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Node(Script s) {
9498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mScript = s;
9598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
9698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
9798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
98ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
99ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * An opaque class for closures
100ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
101ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A closure represents a function call to a kernel or invocable function,
102ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * combined with arguments and values for global variables. A closure is
1039c53b57a26392971b94693d15669599583b250b1Yang Ni     * created using the {@link Builder2#addKernel} or
1049c53b57a26392971b94693d15669599583b250b1Yang Ni     * {@link Builder2#addInvoke}
105ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * method.
106ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     */
107ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
108ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    public static final class Closure extends BaseObj {
109ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Object[] mArgs;
110ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Allocation mReturnValue;
111ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Map<Script.FieldID, Object> mBindings;
112ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
113ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Future mReturnFuture;
114ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Map<Script.FieldID, Future> mGlobalFuture;
115ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
116ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private FieldPacker mFP;
117ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
118ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private static final String TAG = "Closure";
119ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1203b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        Closure(long id, RenderScript rs) {
121ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            super(id, rs);
122ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
123ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1243b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
125ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                       Object[] args, Map<Script.FieldID, Object> globals) {
126ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            super(0, rs);
127ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
128ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (android.os.Build.VERSION.SDK_INT < MIN_API_VERSION && rs.isUseNative()) {
129ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                throw new RSRuntimeException("ScriptGroup2 not supported in this API level");
130ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
131ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
132ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mArgs = args;
133ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mReturnValue = Allocation.createTyped(rs, returnType);
134ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mBindings = globals;
135ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mGlobalFuture = new HashMap<Script.FieldID, Future>();
136ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
137ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int numValues = args.length + globals.size();
138ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
139ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] fieldIDs = new long[numValues];
140ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] values = new long[numValues];
141ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int[] sizes = new int[numValues];
142ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] depClosures = new long[numValues];
143ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] depFieldIDs = new long[numValues];
144ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
145ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int i;
146ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (i = 0; i < args.length; i++) {
147ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                fieldIDs[i] = 0;
1483b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                retrieveValueAndDependenceInfo(rs, i, null, args[i],
1493b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                                               values, sizes, depClosures, depFieldIDs);
150ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
151ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
152ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Object obj = entry.getValue();
153ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Script.FieldID fieldID = entry.getKey();
154ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                fieldIDs[i] = fieldID.getID(rs);
1553b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                retrieveValueAndDependenceInfo(rs, i, fieldID, obj,
1563b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                                               values, sizes, depClosures, depFieldIDs);
157ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                i++;
158ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
159ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
160ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
161ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                        fieldIDs, values, sizes, depClosures, depFieldIDs);
162ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
163ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            setID(id);
164ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
165ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1663b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        Closure(RenderScript rs, Script.InvokeID invokeID,
1673b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                Object[] args, Map<Script.FieldID, Object> globals) {
168ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            super(0, rs);
169ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
170ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (android.os.Build.VERSION.SDK_INT < MIN_API_VERSION && rs.isUseNative()) {
171ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                throw new RSRuntimeException("ScriptGroup2 not supported in this API level");
172ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
173ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
174ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mFP = FieldPacker.createFromArray(args);
175ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
176ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mArgs = args;
177ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mBindings = globals;
178ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mGlobalFuture = new HashMap<Script.FieldID, Future>();
179ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
180ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int numValues = globals.size();
181ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
182ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] fieldIDs = new long[numValues];
183ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] values = new long[numValues];
184ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int[] sizes = new int[numValues];
185ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] depClosures = new long[numValues];
186ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long[] depFieldIDs = new long[numValues];
187ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
188ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int i = 0;
189ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
190ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Object obj = entry.getValue();
191ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Script.FieldID fieldID = entry.getKey();
192ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                fieldIDs[i] = fieldID.getID(rs);
1933b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                retrieveValueAndDependenceInfo(rs, i, fieldID, obj, values,
1943b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                                               sizes, depClosures, depFieldIDs);
195ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                i++;
196ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
197ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
198ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
199ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                              values, sizes);
200ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
201ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            setID(id);
202ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
203ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
2043b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private void retrieveValueAndDependenceInfo(RenderScript rs,
2053b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                                                    int index, Script.FieldID fid, Object obj,
206ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                    long[] values, int[] sizes,
207ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                    long[] depClosures,
208ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                    long[] depFieldIDs) {
209ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
210ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (obj instanceof Future) {
211ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Future f = (Future)obj;
212ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                obj = f.getValue();
213ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                depClosures[index] = f.getClosure().getID(rs);
214ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Script.FieldID fieldID = f.getFieldID();
215ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
216ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            } else {
217ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                depClosures[index] = 0;
218ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                depFieldIDs[index] = 0;
219ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
220ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
2213b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            if (obj instanceof Input) {
2223b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                Input unbound = (Input)obj;
2233b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                if (index < mArgs.length) {
2243b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                    unbound.addReference(this, index);
2253b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                } else {
2263b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                    unbound.addReference(this, fid);
2273b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                }
2283b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                values[index] = 0;
2293b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                sizes[index] = 0;
2303b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            } else {
2313b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                ValueAndSize vs = new ValueAndSize(rs, obj);
2323b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                values[index] = vs.value;
2333b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                sizes[index] = vs.size;
2343b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            }
235ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
236ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
237ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
238ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Returns the future for the return value
239ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
240ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a future
241ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
242ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
243ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Future getReturn() {
244ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (mReturnFuture == null) {
245ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                mReturnFuture = new Future(this, null, mReturnValue);
246ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
247ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
248ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return mReturnFuture;
249ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
250ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
251ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
252ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Returns the future for a global variable
253ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
254ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param field the field ID for the global variable
255ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a future
256ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
257ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
258ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Future getGlobal(Script.FieldID field) {
259ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Future f = mGlobalFuture.get(field);
260ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
261ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (f == null) {
262ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                // If the field is not bound to this closure, this will return a future
263ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                // without an associated value (reference). So this is not working for
264ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                // cross-module (cross-script) linking in this case where a field not
265ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                // explicitly bound.
2663b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                Object obj = mBindings.get(field);
2673b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                if (obj instanceof Future) {
2683b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                    obj = ((Future)obj).getValue();
2693b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                }
2703b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                f = new Future(this, field, obj);
271ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                mGlobalFuture.put(field, f);
272ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
273ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
274ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return f;
275ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
276ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
277ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        void setArg(int index, Object obj) {
2783b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            if (obj instanceof Future) {
2793b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                obj = ((Future)obj).getValue();
2803b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            }
281ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mArgs[index] = obj;
282ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ValueAndSize vs = new ValueAndSize(mRS, obj);
283ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
284ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
285ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
286ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        void setGlobal(Script.FieldID fieldID, Object obj) {
2873b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            if (obj instanceof Future) {
2883b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                obj = ((Future)obj).getValue();
2893b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            }
290ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mBindings.put(fieldID, obj);
291ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ValueAndSize vs = new ValueAndSize(mRS, obj);
292ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
293ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
294ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
295ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private static final class ValueAndSize {
296ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            public ValueAndSize(RenderScript rs, Object obj) {
297ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                if (obj instanceof Allocation) {
298ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    value = ((Allocation)obj).getID(rs);
299ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = -1;
300ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                } else if (obj instanceof Boolean) {
301ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    value = ((Boolean)obj).booleanValue() ? 1 : 0;
302ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = 4;
303ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                } else if (obj instanceof Integer) {
304ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    value = ((Integer)obj).longValue();
305ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = 4;
306ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                } else if (obj instanceof Long) {
307ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    value = ((Long)obj).longValue();
308ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = 8;
309ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                } else if (obj instanceof Float) {
3106d056f6d36b9016574c94ec903e873feb2ad31b1Yang Ni                    value = Float.floatToRawIntBits(((Float)obj).floatValue());
311ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = 4;
312ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                } else if (obj instanceof Double) {
3136d056f6d36b9016574c94ec903e873feb2ad31b1Yang Ni                    value = Double.doubleToRawLongBits(((Double)obj).doubleValue());
314ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = 8;
315ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                }
316ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
317ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            public long value;
318ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            public int size;
319ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
320ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    }
321ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
322ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
323ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * An opaque class for futures
324ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
325ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A future represents an output of a closure, either the return value of
326ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * the function, or the value of a global variable written by the function.
327ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A future is created by calling the {@link Closure#getReturn}  or
328ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * {@link Closure#getGlobal} method.
329ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     */
330ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
331ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    public static final class Future {
332ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Closure mClosure;
333ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Script.FieldID mFieldID;
334ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Object mValue;
335ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
336ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Future(Closure closure, Script.FieldID fieldID, Object value) {
337ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosure = closure;
338ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mFieldID = fieldID;
339ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mValue = value;
340ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
341ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
342ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Closure getClosure() { return mClosure; }
343ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Script.FieldID getFieldID() { return mFieldID; }
344ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Object getValue() { return mValue; }
345ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    }
346ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
347ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
348ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * An opaque class for unbound values (used for script group inputs)
349ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
350ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * Created by calling the {@link Builder2#addInput} method. The value
351ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * is assigned in {@link ScriptGroup#execute(Object...)} method as
352ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * one of its arguments. Arguments to the execute method should be in
353ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * the same order as intputs are added using the addInput method.
354ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     */
355ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
356ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    public static final class Input {
357ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        // Either mFieldID or mArgIndex should be set but not both.
358ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        List<Pair<Closure, Script.FieldID>> mFieldID;
359ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        // -1 means unset. Legal values are 0 .. n-1, where n is the number of
360ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        // arguments for the referencing closure.
361ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        List<Pair<Closure, Integer>> mArgIndex;
3623b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        Object mValue;
363ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
364ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Input() {
365ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
366ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mArgIndex = new ArrayList<Pair<Closure, Integer>>();
367ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
368ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
369ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        void addReference(Closure closure, int index) {
370ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
371ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
372ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
373ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        void addReference(Closure closure, Script.FieldID fieldID) {
374ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mFieldID.add(Pair.create(closure, fieldID));
375ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
376ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
377ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        void set(Object value) {
3783b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            mValue = value;
379ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (Pair<Closure, Integer> p : mArgIndex) {
380ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Closure closure = p.first;
381ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                int index = p.second.intValue();
382ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                closure.setArg(index, value);
383ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
384ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (Pair<Closure, Script.FieldID> p : mFieldID) {
385ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Closure closure = p.first;
386ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Script.FieldID fieldID = p.second;
387ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                closure.setGlobal(fieldID, value);
388ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
389ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
390ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
3913b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        Object get() { return mValue; }
3923b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    }
393ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
3943b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    private String mName;
3953b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    private List<Closure> mClosures;
3963b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    private List<Input> mInputs2;
3973b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    private Future[] mOutputs2;
39898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
3993d9b60c9ae71c4c09df0b4e59c825a5d631e1254Miao Wang    ScriptGroup(long id, RenderScript rs) {
40098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        super(id, rs);
40198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
40298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
403ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    ScriptGroup(RenderScript rs, String name, List<Closure> closures,
404ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                List<Input> inputs, Future[] outputs) {
405ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        super(0, rs);
406ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
407ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        if (android.os.Build.VERSION.SDK_INT < MIN_API_VERSION && rs.isUseNative()) {
408ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            throw new RSRuntimeException("ScriptGroup2 not supported in this API level");
409ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
410ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        mName = name;
411ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        mClosures = closures;
412ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        mInputs2 = inputs;
413ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        mOutputs2 = outputs;
414ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
415ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        long[] closureIDs = new long[closures.size()];
416ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        for (int i = 0; i < closureIDs.length; i++) {
417ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            closureIDs[i] = closures.get(i).getID(rs);
418ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
419ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        String cachePath = rs.getApplicationContext().getCacheDir().toString();
420ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        long id = rs.nScriptGroup2Create(name, cachePath, closureIDs);
421ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        setID(id);
422ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    }
423ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
424ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
425ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * Executes a script group
426ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
427ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @param inputs inputs to the script group
428ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @return outputs of the script group as an array of objects
429ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     */
430ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
431ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    public Object[] execute(Object... inputs) {
432ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        if (inputs.length < mInputs2.size()) {
433ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
434ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                  "less than expected " + mInputs2.size());
435ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return null;
436ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
437ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
438ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        if (inputs.length > mInputs2.size()) {
439ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
440ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                  "more than expected " + mInputs2.size());
441ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
442ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
443ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        for (int i = 0; i < mInputs2.size(); i++) {
444ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Object obj = inputs[i];
445ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (obj instanceof Future || obj instanceof Input) {
446ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Log.e(TAG, this.toString() + ": input " + i +
447ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                      " is a future or unbound value");
448ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                return null;
449ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
450ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Input unbound = mInputs2.get(i);
451ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            unbound.set(obj);
452ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
453ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
454ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        mRS.nScriptGroup2Execute(getID(mRS));
455ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
456ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        Object[] outputObjs = new Object[mOutputs2.length];
457ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        int i = 0;
458ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        for (Future f : mOutputs2) {
4593b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            Object output = f.getValue();
4603b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            if (output instanceof Input) {
4613b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                output = ((Input)output).get();
4623b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            }
4633b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            outputObjs[i++] = output;
464ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
465ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        return outputObjs;
466ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    }
467ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
468ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
469ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Sets an input of the ScriptGroup. This specifies an
4707d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Allocation to be used for kernels that require an input
4717d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Allocation provided from outside of the ScriptGroup.
472ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
473ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Set arguments to {@link #execute(Object...)} instead.
474ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
475ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param s The ID of the kernel where the allocation should be
476ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *          connected.
477ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param a The allocation to connect.
478ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
479d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette    @Deprecated
480ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public void setInput(Script.KernelID s, Allocation a) {
48198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        for (int ct=0; ct < mInputs.length; ct++) {
482ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mInputs[ct].mKID == s) {
48398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                mInputs[ct].mAllocation = a;
484059fede7f200350b6131fc131f76248085485722Miao Wang                if (!mUseIncSupp) {
485059fede7f200350b6131fc131f76248085485722Miao Wang                    mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
486059fede7f200350b6131fc131f76248085485722Miao Wang                }
48798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                return;
48898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
48998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
49098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        throw new RSIllegalArgumentException("Script not found");
49198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
49298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
493ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
494ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Sets an output of the ScriptGroup. This specifies an
4957d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Allocation to be used for the kernels that require an output
4967d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Allocation visible after the ScriptGroup is executed.
497ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
498ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Use return value of {@link #execute(Object...)} instead.
499ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
500ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param s The ID of the kernel where the allocation should be
501ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *          connected.
502ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param a The allocation to connect.
503ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
504d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette    @Deprecated
505ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public void setOutput(Script.KernelID s, Allocation a) {
50698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        for (int ct=0; ct < mOutputs.length; ct++) {
507ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mOutputs[ct].mKID == s) {
50898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                mOutputs[ct].mAllocation = a;
509059fede7f200350b6131fc131f76248085485722Miao Wang                if (!mUseIncSupp) {
510059fede7f200350b6131fc131f76248085485722Miao Wang                    mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
511059fede7f200350b6131fc131f76248085485722Miao Wang                }
51298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                return;
51398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
51498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
51598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        throw new RSIllegalArgumentException("Script not found");
51698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
51798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
518ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
519ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Execute the ScriptGroup.  This will run all the kernels in
5207d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * the ScriptGroup.  No internal connection results will be visible
5217d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * after execution of the ScriptGroup.
522059fede7f200350b6131fc131f76248085485722Miao Wang     *
523059fede7f200350b6131fc131f76248085485722Miao Wang     * If Incremental Support for intrinsics is needed, the execution
524059fede7f200350b6131fc131f76248085485722Miao Wang     * will take the naive path: execute kernels one by one in the
525059fede7f200350b6131fc131f76248085485722Miao Wang     * correct order.
526ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
527ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Use {@link #execute} instead.
528ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
529d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette    @Deprecated
53098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    public void execute() {
531059fede7f200350b6131fc131f76248085485722Miao Wang        if (!mUseIncSupp) {
532059fede7f200350b6131fc131f76248085485722Miao Wang            mRS.nScriptGroupExecute(getID(mRS));
533059fede7f200350b6131fc131f76248085485722Miao Wang        } else {
534059fede7f200350b6131fc131f76248085485722Miao Wang            // setup the allocations.
535059fede7f200350b6131fc131f76248085485722Miao Wang            for (int ct=0; ct < mNodes.size(); ct++) {
536059fede7f200350b6131fc131f76248085485722Miao Wang                Node n = mNodes.get(ct);
537059fede7f200350b6131fc131f76248085485722Miao Wang                for (int ct2=0; ct2 < n.mOutputs.size(); ct2++) {
538059fede7f200350b6131fc131f76248085485722Miao Wang                    ConnectLine l = n.mOutputs.get(ct2);
539059fede7f200350b6131fc131f76248085485722Miao Wang                    if (l.mAllocation !=null) {
540059fede7f200350b6131fc131f76248085485722Miao Wang                        continue;
541059fede7f200350b6131fc131f76248085485722Miao Wang                    }
542059fede7f200350b6131fc131f76248085485722Miao Wang
543059fede7f200350b6131fc131f76248085485722Miao Wang                    //create allocation here
544059fede7f200350b6131fc131f76248085485722Miao Wang                    Allocation alloc = Allocation.createTyped(mRS, l.mAllocationType,
545059fede7f200350b6131fc131f76248085485722Miao Wang                                                              Allocation.MipmapControl.MIPMAP_NONE,
546059fede7f200350b6131fc131f76248085485722Miao Wang                                                              Allocation.USAGE_SCRIPT);
547059fede7f200350b6131fc131f76248085485722Miao Wang
548059fede7f200350b6131fc131f76248085485722Miao Wang                    l.mAllocation = alloc;
549059fede7f200350b6131fc131f76248085485722Miao Wang                    for (int ct3=ct2+1; ct3 < n.mOutputs.size(); ct3++) {
550059fede7f200350b6131fc131f76248085485722Miao Wang                        if (n.mOutputs.get(ct3).mFrom == l.mFrom) {
551059fede7f200350b6131fc131f76248085485722Miao Wang                            n.mOutputs.get(ct3).mAllocation = alloc;
552059fede7f200350b6131fc131f76248085485722Miao Wang                        }
553059fede7f200350b6131fc131f76248085485722Miao Wang                    }
554059fede7f200350b6131fc131f76248085485722Miao Wang                }
555059fede7f200350b6131fc131f76248085485722Miao Wang            }
556059fede7f200350b6131fc131f76248085485722Miao Wang            for (Node node : mNodes) {
557059fede7f200350b6131fc131f76248085485722Miao Wang                for (Script.KernelID kernel : node.mKernels) {
558059fede7f200350b6131fc131f76248085485722Miao Wang                    Allocation ain  = null;
559059fede7f200350b6131fc131f76248085485722Miao Wang                    Allocation aout = null;
560059fede7f200350b6131fc131f76248085485722Miao Wang
561059fede7f200350b6131fc131f76248085485722Miao Wang                    for (ConnectLine nodeInput : node.mInputs) {
562059fede7f200350b6131fc131f76248085485722Miao Wang                        if (nodeInput.mToK == kernel) {
563059fede7f200350b6131fc131f76248085485722Miao Wang                            ain = nodeInput.mAllocation;
564059fede7f200350b6131fc131f76248085485722Miao Wang                        }
565059fede7f200350b6131fc131f76248085485722Miao Wang                    }
566059fede7f200350b6131fc131f76248085485722Miao Wang
567059fede7f200350b6131fc131f76248085485722Miao Wang                    for (IO sgInput : mInputs) {
568059fede7f200350b6131fc131f76248085485722Miao Wang                        if (sgInput.mKID == kernel) {
569059fede7f200350b6131fc131f76248085485722Miao Wang                            ain = sgInput.mAllocation;
570059fede7f200350b6131fc131f76248085485722Miao Wang                        }
571059fede7f200350b6131fc131f76248085485722Miao Wang                    }
572059fede7f200350b6131fc131f76248085485722Miao Wang
573059fede7f200350b6131fc131f76248085485722Miao Wang                    for (ConnectLine nodeOutput : node.mOutputs) {
574059fede7f200350b6131fc131f76248085485722Miao Wang                        if (nodeOutput.mFrom == kernel) {
575059fede7f200350b6131fc131f76248085485722Miao Wang                            aout = nodeOutput.mAllocation;
576059fede7f200350b6131fc131f76248085485722Miao Wang                        }
577059fede7f200350b6131fc131f76248085485722Miao Wang                    }
578059fede7f200350b6131fc131f76248085485722Miao Wang
579059fede7f200350b6131fc131f76248085485722Miao Wang                    for (IO sgOutput : mOutputs) {
580059fede7f200350b6131fc131f76248085485722Miao Wang                        if (sgOutput.mKID == kernel) {
581059fede7f200350b6131fc131f76248085485722Miao Wang                            aout = sgOutput.mAllocation;
582059fede7f200350b6131fc131f76248085485722Miao Wang                        }
583059fede7f200350b6131fc131f76248085485722Miao Wang                    }
584059fede7f200350b6131fc131f76248085485722Miao Wang
585059fede7f200350b6131fc131f76248085485722Miao Wang                    kernel.mScript.forEach(kernel.mSlot, ain, aout, null);
586059fede7f200350b6131fc131f76248085485722Miao Wang                }
587059fede7f200350b6131fc131f76248085485722Miao Wang            }
588059fede7f200350b6131fc131f76248085485722Miao Wang        }
58998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
59098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
59198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
592ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
5937d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Helper class to build a ScriptGroup. A ScriptGroup is
5947d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * created in two steps.
5957d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * <p>
5967d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * First, all kernels to be used by the ScriptGroup should be added.
597ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
5987d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Second, add connections between kernels. There are two types
5997d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * of connections: kernel to kernel and kernel to field.
6007d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Kernel to kernel allows a kernel's output to be passed to
6017d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * another kernel as input. Kernel to field allows the output of
6027d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * one kernel to be bound as a script global. Kernel to kernel is
6037d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * higher performance and should be used where possible.
604ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
6057d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * A ScriptGroup must contain a single directed acyclic graph (DAG); it
6067d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * cannot contain cycles. Currently, all kernels used in a ScriptGroup
6077d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * must come from different Script objects. Additionally, all kernels
6087d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * in a ScriptGroup must have at least one input, output, or internal
6097d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * connection.
610ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
6117d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Once all connections are made, a call to {@link #create} will
612ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * return the ScriptGroup object.
613ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
614ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Use {@link Builder2} instead.
615ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
616ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
617d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette    @Deprecated
618ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public static final class Builder {
619ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private RenderScript mRS;
620ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private ArrayList<Node> mNodes = new ArrayList<Node>();
621ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
622ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private int mKernelCount;
623059fede7f200350b6131fc131f76248085485722Miao Wang        private boolean mUseIncSupp = false;
624ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
625ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
6267d435ae5ba100be5710b685653cc351cab159c11Stephen Hines         * Create a Builder for generating a ScriptGroup.
627ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
628ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
6297d435ae5ba100be5710b685653cc351cab159c11Stephen Hines         * @param rs The RenderScript context.
630ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
63198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        public Builder(RenderScript rs) {
63298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mRS = rs;
63398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
63498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
6351b370e358d16cc3b50b169511d6b387db09f972dJason Sams        // do a DFS from original node, looking for original node
6361b370e358d16cc3b50b169511d6b387db09f972dJason Sams        // any cycle that could be created must contain original node
6371b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void validateCycle(Node target, Node original) {
6381b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct = 0; ct < target.mOutputs.size(); ct++) {
6391b370e358d16cc3b50b169511d6b387db09f972dJason Sams                final ConnectLine cl = target.mOutputs.get(ct);
640ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToK != null) {
641ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    Node tn = findNode(cl.mToK.mScript);
6421b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    if (tn.equals(original)) {
643ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
644ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
6451b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateCycle(tn, original);
646ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
647ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToF != null) {
648ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    Node tn = findNode(cl.mToF.mScript);
6491b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    if (tn.equals(original)) {
65098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
65198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    }
6521b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateCycle(tn, original);
65398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
65498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
65598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
65698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
6571b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void mergeDAGs(int valueUsed, int valueKilled) {
658ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
6591b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (mNodes.get(ct).dagNumber == valueKilled)
6601b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    mNodes.get(ct).dagNumber = valueUsed;
6611b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6621b370e358d16cc3b50b169511d6b387db09f972dJason Sams        }
6631b370e358d16cc3b50b169511d6b387db09f972dJason Sams
6641b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void validateDAGRecurse(Node n, int dagNumber) {
6651b370e358d16cc3b50b169511d6b387db09f972dJason Sams            // combine DAGs if this node has been seen already
6661b370e358d16cc3b50b169511d6b387db09f972dJason Sams            if (n.dagNumber != 0 && n.dagNumber != dagNumber) {
6671b370e358d16cc3b50b169511d6b387db09f972dJason Sams                mergeDAGs(n.dagNumber, dagNumber);
6681b370e358d16cc3b50b169511d6b387db09f972dJason Sams                return;
6691b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6701b370e358d16cc3b50b169511d6b387db09f972dJason Sams
6711b370e358d16cc3b50b169511d6b387db09f972dJason Sams            n.dagNumber = dagNumber;
6721b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < n.mOutputs.size(); ct++) {
6731b370e358d16cc3b50b169511d6b387db09f972dJason Sams                final ConnectLine cl = n.mOutputs.get(ct);
6741b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (cl.mToK != null) {
6751b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    Node tn = findNode(cl.mToK.mScript);
6761b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateDAGRecurse(tn, dagNumber);
6771b370e358d16cc3b50b169511d6b387db09f972dJason Sams                }
6781b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (cl.mToF != null) {
6791b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    Node tn = findNode(cl.mToF.mScript);
6801b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateDAGRecurse(tn, dagNumber);
681ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
6821b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6831b370e358d16cc3b50b169511d6b387db09f972dJason Sams        }
6841b370e358d16cc3b50b169511d6b387db09f972dJason Sams
6851b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void validateDAG() {
6861b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
687ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
688ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (n.mInputs.size() == 0) {
6891b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
6903b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                        String msg = "Groups cannot contain unconnected scripts";
6913b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                        throw new RSInvalidStateException(msg);
6921b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    }
6931b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateDAGRecurse(n, ct+1);
6941b370e358d16cc3b50b169511d6b387db09f972dJason Sams                }
6951b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6961b370e358d16cc3b50b169511d6b387db09f972dJason Sams            int dagNumber = mNodes.get(0).dagNumber;
6971b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
6981b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (mNodes.get(ct).dagNumber != dagNumber) {
6991b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    throw new RSInvalidStateException("Multiple DAGs in group not allowed.");
70098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
70198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
70298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
70398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
704ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private Node findNode(Script s) {
705ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
706ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (s == mNodes.get(ct).mScript) {
707ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    return mNodes.get(ct);
70898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
70998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
71098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return null;
71198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
71298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
713ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private Node findNode(Script.KernelID k) {
714ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
715ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
716ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
717ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (k == n.mKernels.get(ct2)) {
718ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        return n;
71998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    }
72098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
72198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
722ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return null;
723ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
724ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
725ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
726ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a Kernel to the group.
727ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
728ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
729ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param k The kernel to add.
730ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
731ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this.
732ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
733ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addKernel(Script.KernelID k) {
734ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mLines.size() != 0) {
735ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException(
736ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    "Kernels may not be added once connections exist.");
737ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
738059fede7f200350b6131fc131f76248085485722Miao Wang            if (k.mScript.isIncSupp()) {
739059fede7f200350b6131fc131f76248085485722Miao Wang                mUseIncSupp = true;
740059fede7f200350b6131fc131f76248085485722Miao Wang            }
741ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
742ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (findNode(k) != null) {
743ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                return this;
744ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
745ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addKernel 2 ");
746ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mKernelCount++;
747ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node n = findNode(k.mScript);
748ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (n == null) {
749ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                //android.util.Log.v("RSR", "addKernel 3 ");
750ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                n = new Node(k.mScript);
751ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mNodes.add(n);
752ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
753ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            n.mKernels.add(k);
754ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return this;
755ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
756ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
757ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
758ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a connection to the group.
759ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
760ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
761ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param t The type of the connection. This is used to
762ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          determine the kernel launch sizes on the source side
763ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          of this connection.
764ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param from The source for the connection.
765ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param to The destination of the connection.
766ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
767ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this
768ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
769ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
770ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
771ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nf = findNode(from);
772ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nf == null) {
7731b370e358d16cc3b50b169511d6b387db09f972dJason Sams                throw new RSInvalidStateException("From script not found.");
774ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
775ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
776ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nt = findNode(to.mScript);
777ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nt == null) {
778ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("To script not found.");
77998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
780ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
781ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ConnectLine cl = new ConnectLine(t, from, to);
782ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mLines.add(new ConnectLine(t, from, to));
783ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
784ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nf.mOutputs.add(cl);
785ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nt.mInputs.add(cl);
78698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
7871b370e358d16cc3b50b169511d6b387db09f972dJason Sams            validateCycle(nf, nf);
78898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return this;
78998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
79098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
791ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
792ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a connection to the group.
793ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
794ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
795ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param t The type of the connection. This is used to
796ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          determine the kernel launch sizes for both sides of
797ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          this connection.
798ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param from The source for the connection.
799ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param to The destination of the connection.
800ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
801ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this
802ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
803ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
804ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
805ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nf = findNode(from);
806ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nf == null) {
8071b370e358d16cc3b50b169511d6b387db09f972dJason Sams                throw new RSInvalidStateException("From script not found.");
808ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
809ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
810ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nt = findNode(to);
811ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nt == null) {
812ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("To script not found.");
813ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
814ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
815ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ConnectLine cl = new ConnectLine(t, from, to);
816ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mLines.add(new ConnectLine(t, from, to));
817ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
818ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nf.mOutputs.add(cl);
819ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nt.mInputs.add(cl);
820ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
8211b370e358d16cc3b50b169511d6b387db09f972dJason Sams            validateCycle(nf, nf);
822ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return this;
823ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
824ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
825059fede7f200350b6131fc131f76248085485722Miao Wang        /**
826059fede7f200350b6131fc131f76248085485722Miao Wang         * Calculate the order of each node.
827059fede7f200350b6131fc131f76248085485722Miao Wang         *
828059fede7f200350b6131fc131f76248085485722Miao Wang         *
829059fede7f200350b6131fc131f76248085485722Miao Wang         * @return Success or Fail
830059fede7f200350b6131fc131f76248085485722Miao Wang         */
831059fede7f200350b6131fc131f76248085485722Miao Wang        private boolean calcOrderRecurse(Node node0, int depth) {
832059fede7f200350b6131fc131f76248085485722Miao Wang            node0.mSeen = true;
833059fede7f200350b6131fc131f76248085485722Miao Wang            if (node0.mOrder < depth) {
834059fede7f200350b6131fc131f76248085485722Miao Wang                node0.mOrder = depth;
835059fede7f200350b6131fc131f76248085485722Miao Wang            }
836059fede7f200350b6131fc131f76248085485722Miao Wang            boolean ret = true;
837059fede7f200350b6131fc131f76248085485722Miao Wang
838059fede7f200350b6131fc131f76248085485722Miao Wang            for (ConnectLine link : node0.mOutputs) {
839059fede7f200350b6131fc131f76248085485722Miao Wang                Node node1 = null;
840059fede7f200350b6131fc131f76248085485722Miao Wang                if (link.mToF != null) {
841059fede7f200350b6131fc131f76248085485722Miao Wang                    node1 = findNode(link.mToF.mScript);
842059fede7f200350b6131fc131f76248085485722Miao Wang                } else {
843059fede7f200350b6131fc131f76248085485722Miao Wang                    node1 = findNode(link.mToK.mScript);
844059fede7f200350b6131fc131f76248085485722Miao Wang                }
845059fede7f200350b6131fc131f76248085485722Miao Wang                if (node1.mSeen) {
846059fede7f200350b6131fc131f76248085485722Miao Wang                    return false;
847059fede7f200350b6131fc131f76248085485722Miao Wang                }
848059fede7f200350b6131fc131f76248085485722Miao Wang                ret &= calcOrderRecurse(node1, node0.mOrder + 1);
849059fede7f200350b6131fc131f76248085485722Miao Wang            }
850059fede7f200350b6131fc131f76248085485722Miao Wang
851059fede7f200350b6131fc131f76248085485722Miao Wang            return ret;
852059fede7f200350b6131fc131f76248085485722Miao Wang        }
853059fede7f200350b6131fc131f76248085485722Miao Wang
854059fede7f200350b6131fc131f76248085485722Miao Wang        private boolean calcOrder() {
855059fede7f200350b6131fc131f76248085485722Miao Wang            boolean ret = true;
856059fede7f200350b6131fc131f76248085485722Miao Wang            for (Node n0 : mNodes) {
857059fede7f200350b6131fc131f76248085485722Miao Wang                if (n0.mInputs.size() == 0) {
858059fede7f200350b6131fc131f76248085485722Miao Wang                    for (Node n1 : mNodes) {
859059fede7f200350b6131fc131f76248085485722Miao Wang                        n1.mSeen = false;
860059fede7f200350b6131fc131f76248085485722Miao Wang                    }
861059fede7f200350b6131fc131f76248085485722Miao Wang                    ret &= calcOrderRecurse(n0, 1);
862059fede7f200350b6131fc131f76248085485722Miao Wang                }
863059fede7f200350b6131fc131f76248085485722Miao Wang            }
864059fede7f200350b6131fc131f76248085485722Miao Wang
865059fede7f200350b6131fc131f76248085485722Miao Wang            Collections.sort(mNodes, new Comparator<Node>() {
866059fede7f200350b6131fc131f76248085485722Miao Wang                public int compare(Node n1, Node n2) {
867059fede7f200350b6131fc131f76248085485722Miao Wang                    return n1.mOrder - n2.mOrder;
868059fede7f200350b6131fc131f76248085485722Miao Wang                }
869059fede7f200350b6131fc131f76248085485722Miao Wang            });
870ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
871059fede7f200350b6131fc131f76248085485722Miao Wang            return ret;
872059fede7f200350b6131fc131f76248085485722Miao Wang        }
873ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
874ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
875ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Creates the Script group.
876ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
877ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
878ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return ScriptGroup The new ScriptGroup
879ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
88098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        public ScriptGroup create() {
8813d9b60c9ae71c4c09df0b4e59c825a5d631e1254Miao Wang
8821b370e358d16cc3b50b169511d6b387db09f972dJason Sams            if (mNodes.size() == 0) {
8831b370e358d16cc3b50b169511d6b387db09f972dJason Sams                throw new RSInvalidStateException("Empty script groups are not allowed");
8841b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
8851b370e358d16cc3b50b169511d6b387db09f972dJason Sams
8861b370e358d16cc3b50b169511d6b387db09f972dJason Sams            // reset DAG numbers in case we're building a second group
8871b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
8881b370e358d16cc3b50b169511d6b387db09f972dJason Sams                mNodes.get(ct).dagNumber = 0;
8891b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
8901b370e358d16cc3b50b169511d6b387db09f972dJason Sams            validateDAG();
8911b370e358d16cc3b50b169511d6b387db09f972dJason Sams
892ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ArrayList<IO> inputs = new ArrayList<IO>();
893ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ArrayList<IO> outputs = new ArrayList<IO>();
894ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
8953d9b60c9ae71c4c09df0b4e59c825a5d631e1254Miao Wang            long[] kernels = new long[mKernelCount];
896ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int idx = 0;
897ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
898ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
899ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
900ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    final Script.KernelID kid = n.mKernels.get(ct2);
901ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    kernels[idx++] = kid.getID(mRS);
902ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
903ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    boolean hasInput = false;
904ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    boolean hasOutput = false;
905ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
906ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        if (n.mInputs.get(ct3).mToK == kid) {
907ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            hasInput = true;
908ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        }
909ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
910ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
911ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        if (n.mOutputs.get(ct3).mFrom == kid) {
912ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            hasOutput = true;
913ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        }
914ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
915ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (!hasInput) {
916ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        inputs.add(new IO(kid));
917ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
918ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (!hasOutput) {
919ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        outputs.add(new IO(kid));
920ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
921ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
922ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
923ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (idx != mKernelCount) {
924ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSRuntimeException("Count mismatch, should not happen.");
925ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
926ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
927059fede7f200350b6131fc131f76248085485722Miao Wang            long id = 0;
928059fede7f200350b6131fc131f76248085485722Miao Wang            if (!mUseIncSupp) {
929059fede7f200350b6131fc131f76248085485722Miao Wang                long[] src = new long[mLines.size()];
930059fede7f200350b6131fc131f76248085485722Miao Wang                long[] dstk = new long[mLines.size()];
931059fede7f200350b6131fc131f76248085485722Miao Wang                long[] dstf = new long[mLines.size()];
932059fede7f200350b6131fc131f76248085485722Miao Wang                long[] types = new long[mLines.size()];
933059fede7f200350b6131fc131f76248085485722Miao Wang
934059fede7f200350b6131fc131f76248085485722Miao Wang                for (int ct=0; ct < mLines.size(); ct++) {
935059fede7f200350b6131fc131f76248085485722Miao Wang                    ConnectLine cl = mLines.get(ct);
936059fede7f200350b6131fc131f76248085485722Miao Wang                    src[ct] = cl.mFrom.getID(mRS);
937059fede7f200350b6131fc131f76248085485722Miao Wang                    if (cl.mToK != null) {
938059fede7f200350b6131fc131f76248085485722Miao Wang                        dstk[ct] = cl.mToK.getID(mRS);
939059fede7f200350b6131fc131f76248085485722Miao Wang                    }
940059fede7f200350b6131fc131f76248085485722Miao Wang                    if (cl.mToF != null) {
941059fede7f200350b6131fc131f76248085485722Miao Wang                        dstf[ct] = cl.mToF.getID(mRS);
942059fede7f200350b6131fc131f76248085485722Miao Wang                    }
943059fede7f200350b6131fc131f76248085485722Miao Wang                    types[ct] = cl.mAllocationType.getID(mRS);
944ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
945059fede7f200350b6131fc131f76248085485722Miao Wang                id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
946059fede7f200350b6131fc131f76248085485722Miao Wang                if (id == 0) {
947059fede7f200350b6131fc131f76248085485722Miao Wang                    throw new RSRuntimeException("Object creation error, should not happen.");
948ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
949059fede7f200350b6131fc131f76248085485722Miao Wang            } else {
950059fede7f200350b6131fc131f76248085485722Miao Wang                //Calculate the order of the DAG so that script can run one after another.
951059fede7f200350b6131fc131f76248085485722Miao Wang                calcOrder();
952ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
953ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
954ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ScriptGroup sg = new ScriptGroup(id, mRS);
955ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            sg.mOutputs = new IO[outputs.size()];
956ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < outputs.size(); ct++) {
957ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                sg.mOutputs[ct] = outputs.get(ct);
958ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
959ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
960ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            sg.mInputs = new IO[inputs.size()];
961ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < inputs.size(); ct++) {
962ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                sg.mInputs[ct] = inputs.get(ct);
963ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
964059fede7f200350b6131fc131f76248085485722Miao Wang            sg.mNodes = mNodes;
965059fede7f200350b6131fc131f76248085485722Miao Wang            sg.mUseIncSupp = mUseIncSupp;
96698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return sg;
96798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
96898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
96998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
97098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
971ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
9723b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang     * Represents a binding of a value to a global variable in a
9733b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang     * kernel or invocable function. Used in closure creation.
9743b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang     */
9753b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9763b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    public static final class Binding {
9773b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private final Script.FieldID mField;
9783b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private final Object mValue;
9793b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9803b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
9813b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns a Binding object that binds value to field
9823b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
9833b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param field the Script.FieldID of the global variable
9843b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param value the value
9853b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
9863b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9873b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        public Binding(Script.FieldID field, Object value) {
9883b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            mField = field;
9893b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            mValue = value;
9903b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        }
9913b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9923b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
9933b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns the field ID
9943b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
9953b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9963b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        public Script.FieldID getField() { return mField; }
9973b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9983b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
9993b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns the value
10003b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
10013b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
10023b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        public Object getValue() { return mValue; }
10033b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    }
10043b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
10053b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    /**
1006ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * The builder class for creating script groups
1007ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
1008ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A script group is created using closures (see class {@link Closure}).
1009ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A closure is a function call to a kernel or
1010ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * invocable function. Each function argument or global variable accessed inside
1011ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * the function is bound to 1) a known value, 2) a script group input
1012ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * (see class {@link Input}), or 3) a
1013ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * future (see class {@link Future}).
1014ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A future is the output of a closure, either the return value of the
1015ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * function or a global variable written by that function.
1016ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
1017ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * Closures are created using the {@link #addKernel} or {@link #addInvoke}
1018ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * methods.
1019ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * When a closure is created, futures from previously created closures
1020ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * can be used as its inputs.
1021ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * External script group inputs can be used as inputs to individual closures as well.
1022ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * An external script group input is created using the {@link #addInput} method.
1023ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A script group is created by a call to the {@link #create} method, which
1024ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * accepts an array of futures as the outputs for the script group.
1025ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
1026ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * Closures in a script group can be evaluated in any order as long as the
1027ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * following conditions are met:
1028ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * 1) a closure must be evaluated before any other closures that take its
1029ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * futures as inputs;
1030ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * 2) all closures added before an invoke closure must be evaluated
1031ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * before it;
1032ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * and 3) all closures added after an invoke closure must be evaluated after
1033ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * it.
1034ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * As a special case, the order that the closures are added is a legal
1035ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * evaluation order. However, other evaluation orders are possible, including
1036ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * concurrently evaluating independent closures.
1037ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     */
1038ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1039ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    public static final class Builder2 {
1040ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        RenderScript mRS;
1041ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        List<Closure> mClosures;
1042ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        List<Input> mInputs;
10433b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private static final String TAG = "ScriptGroup.Builder2";
1044ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
10453b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
10463b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns a Builder object
10473b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
10483b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param rs the RenderScript context
10493b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
1050ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Builder2(RenderScript rs) {
1051ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mRS = rs;
1052ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosures = new ArrayList<Closure>();
1053ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mInputs = new ArrayList<Input>();
1054ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1055ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
10563b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
10573b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Adds a closure for a kernel
10583b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
10593b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param k Kernel ID for the kernel function
10603b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param returnType Allocation type for the return value
10613b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param args arguments to the kernel function
10623b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param globalBindings bindings for global variables
10633b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @return a closure
10643b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
10653b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
1066ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Closure addKernelInternal(Script.KernelID k, Type returnType, Object[] args,
10673b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                                          Map<Script.FieldID, Object> globalBindings) {
1068ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Closure c = new Closure(mRS, k, returnType, args, globalBindings);
1069ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosures.add(c);
1070ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return c;
1071ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1072ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
10733b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
10743b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Adds a closure for an invocable function
10753b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
10763b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param invoke Invoke ID for the invocable function
10773b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param args arguments to the invocable function
10783b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param globalBindings bindings for global variables
10793b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @return a closure
10803b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
10813b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
1082ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Closure addInvokeInternal(Script.InvokeID invoke, Object[] args,
1083ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                          Map<Script.FieldID, Object> globalBindings) {
1084ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Closure c = new Closure(mRS, invoke, args, globalBindings);
1085ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosures.add(c);
1086ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return c;
1087ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1088ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1089ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1090ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Adds a script group input
1091ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1092ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a script group input, which can be used as an argument or a value to
1093ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *     a global variable for creating closures
1094ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1095ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1096ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Input addInput() {
1097ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Input unbound = new Input();
1098ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mInputs.add(unbound);
1099ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return unbound;
1100ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1101ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1102ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1103ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Adds a closure for a kernel
1104ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1105ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param k Kernel ID for the kernel function
1106ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param argsAndBindings arguments followed by bindings for global variables
1107ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a closure
1108ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1109ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1110ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
1111ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ArrayList<Object> args = new ArrayList<Object>();
1112ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
1113ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
1114ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                return null;
1115ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1116ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return addKernelInternal(k, returnType, args.toArray(), bindingMap);
1117ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1118ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1119ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1120ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Adds a closure for an invocable function
1121ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1122ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param invoke Invoke ID for the invocable function
1123ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param argsAndBindings arguments followed by bindings for global variables
1124ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a closure
1125ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1126ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1127ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
1128ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ArrayList<Object> args = new ArrayList<Object>();
1129ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
1130ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
1131ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                return null;
1132ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1133ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return addInvokeInternal(invoke, args.toArray(), bindingMap);
1134ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1135ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1136ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1137ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Creates a script group
1138ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1139ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param name name for the script group. Legal names can only contain letters, digits,
1140ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *        '-', or '_'. The name can be no longer than 100 characters.
1141ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param outputs futures intended as outputs of the script group
1142ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a script group
1143ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1144ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1145ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public ScriptGroup create(String name, Future... outputs) {
1146ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (name == null || name.isEmpty() || name.length() > 100 ||
1147ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
1148ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                throw new RSIllegalArgumentException("invalid script group name");
1149ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1150ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ScriptGroup ret = new ScriptGroup(mRS, name, mClosures, mInputs, outputs);
1151ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return ret;
1152ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1153ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1154ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private boolean seperateArgsAndBindings(Object[] argsAndBindings,
1155ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                ArrayList<Object> args,
1156ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                Map<Script.FieldID, Object> bindingMap) {
1157ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int i;
1158ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (i = 0; i < argsAndBindings.length; i++) {
1159ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                if (argsAndBindings[i] instanceof Binding) {
1160ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    break;
1161ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                }
1162ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                args.add(argsAndBindings[i]);
1163ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1164ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1165ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (; i < argsAndBindings.length; i++) {
1166ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                if (!(argsAndBindings[i] instanceof Binding)) {
1167ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    return false;
1168ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                }
1169ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Binding b = (Binding)argsAndBindings[i];
11703b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                bindingMap.put(b.getField(), b.getValue());
1171ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1172ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1173ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return true;
1174ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1175ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1176ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    }
117798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
117898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams}
117998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
118098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
1181