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) {
310ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    value = ((Float)obj).longValue();
311ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    size = 4;
312ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                } else if (obj instanceof Double) {
313ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    value = ((Double)obj).longValue();
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     */
479ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public void setInput(Script.KernelID s, Allocation a) {
48098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        for (int ct=0; ct < mInputs.length; ct++) {
481ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mInputs[ct].mKID == s) {
48298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                mInputs[ct].mAllocation = a;
483059fede7f200350b6131fc131f76248085485722Miao Wang                if (!mUseIncSupp) {
484059fede7f200350b6131fc131f76248085485722Miao Wang                    mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
485059fede7f200350b6131fc131f76248085485722Miao Wang                }
48698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                return;
48798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
48898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
48998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        throw new RSIllegalArgumentException("Script not found");
49098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
49198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
492ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
493ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Sets an output of the ScriptGroup. This specifies an
4947d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Allocation to be used for the kernels that require an output
4957d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Allocation visible after the ScriptGroup is executed.
496ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
497ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Use return value of {@link #execute(Object...)} instead.
498ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
499ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param s The ID of the kernel where the allocation should be
500ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *          connected.
501ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param a The allocation to connect.
502ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
503ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public void setOutput(Script.KernelID s, Allocation a) {
50498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        for (int ct=0; ct < mOutputs.length; ct++) {
505ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mOutputs[ct].mKID == s) {
50698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                mOutputs[ct].mAllocation = a;
507059fede7f200350b6131fc131f76248085485722Miao Wang                if (!mUseIncSupp) {
508059fede7f200350b6131fc131f76248085485722Miao Wang                    mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
509059fede7f200350b6131fc131f76248085485722Miao Wang                }
51098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                return;
51198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
51298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
51398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        throw new RSIllegalArgumentException("Script not found");
51498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
51598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
516ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
517ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Execute the ScriptGroup.  This will run all the kernels in
5187d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * the ScriptGroup.  No internal connection results will be visible
5197d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * after execution of the ScriptGroup.
520059fede7f200350b6131fc131f76248085485722Miao Wang     *
521059fede7f200350b6131fc131f76248085485722Miao Wang     * If Incremental Support for intrinsics is needed, the execution
522059fede7f200350b6131fc131f76248085485722Miao Wang     * will take the naive path: execute kernels one by one in the
523059fede7f200350b6131fc131f76248085485722Miao Wang     * correct order.
524ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
525ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Use {@link #execute} instead.
526ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
52798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    public void execute() {
528059fede7f200350b6131fc131f76248085485722Miao Wang        if (!mUseIncSupp) {
529059fede7f200350b6131fc131f76248085485722Miao Wang            mRS.nScriptGroupExecute(getID(mRS));
530059fede7f200350b6131fc131f76248085485722Miao Wang        } else {
531059fede7f200350b6131fc131f76248085485722Miao Wang            // setup the allocations.
532059fede7f200350b6131fc131f76248085485722Miao Wang            for (int ct=0; ct < mNodes.size(); ct++) {
533059fede7f200350b6131fc131f76248085485722Miao Wang                Node n = mNodes.get(ct);
534059fede7f200350b6131fc131f76248085485722Miao Wang                for (int ct2=0; ct2 < n.mOutputs.size(); ct2++) {
535059fede7f200350b6131fc131f76248085485722Miao Wang                    ConnectLine l = n.mOutputs.get(ct2);
536059fede7f200350b6131fc131f76248085485722Miao Wang                    if (l.mAllocation !=null) {
537059fede7f200350b6131fc131f76248085485722Miao Wang                        continue;
538059fede7f200350b6131fc131f76248085485722Miao Wang                    }
539059fede7f200350b6131fc131f76248085485722Miao Wang
540059fede7f200350b6131fc131f76248085485722Miao Wang                    //create allocation here
541059fede7f200350b6131fc131f76248085485722Miao Wang                    Allocation alloc = Allocation.createTyped(mRS, l.mAllocationType,
542059fede7f200350b6131fc131f76248085485722Miao Wang                                                              Allocation.MipmapControl.MIPMAP_NONE,
543059fede7f200350b6131fc131f76248085485722Miao Wang                                                              Allocation.USAGE_SCRIPT);
544059fede7f200350b6131fc131f76248085485722Miao Wang
545059fede7f200350b6131fc131f76248085485722Miao Wang                    l.mAllocation = alloc;
546059fede7f200350b6131fc131f76248085485722Miao Wang                    for (int ct3=ct2+1; ct3 < n.mOutputs.size(); ct3++) {
547059fede7f200350b6131fc131f76248085485722Miao Wang                        if (n.mOutputs.get(ct3).mFrom == l.mFrom) {
548059fede7f200350b6131fc131f76248085485722Miao Wang                            n.mOutputs.get(ct3).mAllocation = alloc;
549059fede7f200350b6131fc131f76248085485722Miao Wang                        }
550059fede7f200350b6131fc131f76248085485722Miao Wang                    }
551059fede7f200350b6131fc131f76248085485722Miao Wang                }
552059fede7f200350b6131fc131f76248085485722Miao Wang            }
553059fede7f200350b6131fc131f76248085485722Miao Wang            for (Node node : mNodes) {
554059fede7f200350b6131fc131f76248085485722Miao Wang                for (Script.KernelID kernel : node.mKernels) {
555059fede7f200350b6131fc131f76248085485722Miao Wang                    Allocation ain  = null;
556059fede7f200350b6131fc131f76248085485722Miao Wang                    Allocation aout = null;
557059fede7f200350b6131fc131f76248085485722Miao Wang
558059fede7f200350b6131fc131f76248085485722Miao Wang                    for (ConnectLine nodeInput : node.mInputs) {
559059fede7f200350b6131fc131f76248085485722Miao Wang                        if (nodeInput.mToK == kernel) {
560059fede7f200350b6131fc131f76248085485722Miao Wang                            ain = nodeInput.mAllocation;
561059fede7f200350b6131fc131f76248085485722Miao Wang                        }
562059fede7f200350b6131fc131f76248085485722Miao Wang                    }
563059fede7f200350b6131fc131f76248085485722Miao Wang
564059fede7f200350b6131fc131f76248085485722Miao Wang                    for (IO sgInput : mInputs) {
565059fede7f200350b6131fc131f76248085485722Miao Wang                        if (sgInput.mKID == kernel) {
566059fede7f200350b6131fc131f76248085485722Miao Wang                            ain = sgInput.mAllocation;
567059fede7f200350b6131fc131f76248085485722Miao Wang                        }
568059fede7f200350b6131fc131f76248085485722Miao Wang                    }
569059fede7f200350b6131fc131f76248085485722Miao Wang
570059fede7f200350b6131fc131f76248085485722Miao Wang                    for (ConnectLine nodeOutput : node.mOutputs) {
571059fede7f200350b6131fc131f76248085485722Miao Wang                        if (nodeOutput.mFrom == kernel) {
572059fede7f200350b6131fc131f76248085485722Miao Wang                            aout = nodeOutput.mAllocation;
573059fede7f200350b6131fc131f76248085485722Miao Wang                        }
574059fede7f200350b6131fc131f76248085485722Miao Wang                    }
575059fede7f200350b6131fc131f76248085485722Miao Wang
576059fede7f200350b6131fc131f76248085485722Miao Wang                    for (IO sgOutput : mOutputs) {
577059fede7f200350b6131fc131f76248085485722Miao Wang                        if (sgOutput.mKID == kernel) {
578059fede7f200350b6131fc131f76248085485722Miao Wang                            aout = sgOutput.mAllocation;
579059fede7f200350b6131fc131f76248085485722Miao Wang                        }
580059fede7f200350b6131fc131f76248085485722Miao Wang                    }
581059fede7f200350b6131fc131f76248085485722Miao Wang
582059fede7f200350b6131fc131f76248085485722Miao Wang                    kernel.mScript.forEach(kernel.mSlot, ain, aout, null);
583059fede7f200350b6131fc131f76248085485722Miao Wang                }
584059fede7f200350b6131fc131f76248085485722Miao Wang            }
585059fede7f200350b6131fc131f76248085485722Miao Wang        }
58698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
58798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
58898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
589ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
5907d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Helper class to build a ScriptGroup. A ScriptGroup is
5917d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * created in two steps.
5927d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * <p>
5937d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * First, all kernels to be used by the ScriptGroup should be added.
594ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
5957d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Second, add connections between kernels. There are two types
5967d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * of connections: kernel to kernel and kernel to field.
5977d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Kernel to kernel allows a kernel's output to be passed to
5987d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * another kernel as input. Kernel to field allows the output of
5997d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * one kernel to be bound as a script global. Kernel to kernel is
6007d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * higher performance and should be used where possible.
601ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
6027d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * A ScriptGroup must contain a single directed acyclic graph (DAG); it
6037d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * cannot contain cycles. Currently, all kernels used in a ScriptGroup
6047d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * must come from different Script objects. Additionally, all kernels
6057d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * in a ScriptGroup must have at least one input, output, or internal
6067d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * connection.
607ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
6087d435ae5ba100be5710b685653cc351cab159c11Stephen Hines     * Once all connections are made, a call to {@link #create} will
609ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * return the ScriptGroup object.
610ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
611ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * @deprecated Use {@link Builder2} instead.
612ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     *
613ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
614ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public static final class Builder {
615ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private RenderScript mRS;
616ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private ArrayList<Node> mNodes = new ArrayList<Node>();
617ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
618ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private int mKernelCount;
619059fede7f200350b6131fc131f76248085485722Miao Wang        private boolean mUseIncSupp = false;
620ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
621ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
6227d435ae5ba100be5710b685653cc351cab159c11Stephen Hines         * Create a Builder for generating a ScriptGroup.
623ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
624ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
6257d435ae5ba100be5710b685653cc351cab159c11Stephen Hines         * @param rs The RenderScript context.
626ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
62798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        public Builder(RenderScript rs) {
62898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mRS = rs;
62998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
63098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
6311b370e358d16cc3b50b169511d6b387db09f972dJason Sams        // do a DFS from original node, looking for original node
6321b370e358d16cc3b50b169511d6b387db09f972dJason Sams        // any cycle that could be created must contain original node
6331b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void validateCycle(Node target, Node original) {
6341b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct = 0; ct < target.mOutputs.size(); ct++) {
6351b370e358d16cc3b50b169511d6b387db09f972dJason Sams                final ConnectLine cl = target.mOutputs.get(ct);
636ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToK != null) {
637ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    Node tn = findNode(cl.mToK.mScript);
6381b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    if (tn.equals(original)) {
639ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
640ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
6411b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateCycle(tn, original);
642ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
643ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToF != null) {
644ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    Node tn = findNode(cl.mToF.mScript);
6451b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    if (tn.equals(original)) {
64698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
64798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    }
6481b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateCycle(tn, original);
64998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
65098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
65198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
65298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
6531b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void mergeDAGs(int valueUsed, int valueKilled) {
654ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
6551b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (mNodes.get(ct).dagNumber == valueKilled)
6561b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    mNodes.get(ct).dagNumber = valueUsed;
6571b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6581b370e358d16cc3b50b169511d6b387db09f972dJason Sams        }
6591b370e358d16cc3b50b169511d6b387db09f972dJason Sams
6601b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void validateDAGRecurse(Node n, int dagNumber) {
6611b370e358d16cc3b50b169511d6b387db09f972dJason Sams            // combine DAGs if this node has been seen already
6621b370e358d16cc3b50b169511d6b387db09f972dJason Sams            if (n.dagNumber != 0 && n.dagNumber != dagNumber) {
6631b370e358d16cc3b50b169511d6b387db09f972dJason Sams                mergeDAGs(n.dagNumber, dagNumber);
6641b370e358d16cc3b50b169511d6b387db09f972dJason Sams                return;
6651b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6661b370e358d16cc3b50b169511d6b387db09f972dJason Sams
6671b370e358d16cc3b50b169511d6b387db09f972dJason Sams            n.dagNumber = dagNumber;
6681b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < n.mOutputs.size(); ct++) {
6691b370e358d16cc3b50b169511d6b387db09f972dJason Sams                final ConnectLine cl = n.mOutputs.get(ct);
6701b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (cl.mToK != null) {
6711b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    Node tn = findNode(cl.mToK.mScript);
6721b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateDAGRecurse(tn, dagNumber);
6731b370e358d16cc3b50b169511d6b387db09f972dJason Sams                }
6741b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (cl.mToF != null) {
6751b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    Node tn = findNode(cl.mToF.mScript);
6761b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateDAGRecurse(tn, dagNumber);
677ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
6781b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6791b370e358d16cc3b50b169511d6b387db09f972dJason Sams        }
6801b370e358d16cc3b50b169511d6b387db09f972dJason Sams
6811b370e358d16cc3b50b169511d6b387db09f972dJason Sams        private void validateDAG() {
6821b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
683ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
684ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (n.mInputs.size() == 0) {
6851b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
6863b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                        String msg = "Groups cannot contain unconnected scripts";
6873b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                        throw new RSInvalidStateException(msg);
6881b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    }
6891b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    validateDAGRecurse(n, ct+1);
6901b370e358d16cc3b50b169511d6b387db09f972dJason Sams                }
6911b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
6921b370e358d16cc3b50b169511d6b387db09f972dJason Sams            int dagNumber = mNodes.get(0).dagNumber;
6931b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
6941b370e358d16cc3b50b169511d6b387db09f972dJason Sams                if (mNodes.get(ct).dagNumber != dagNumber) {
6951b370e358d16cc3b50b169511d6b387db09f972dJason Sams                    throw new RSInvalidStateException("Multiple DAGs in group not allowed.");
69698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
69798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
69898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
69998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
700ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private Node findNode(Script s) {
701ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
702ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (s == mNodes.get(ct).mScript) {
703ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    return mNodes.get(ct);
70498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
70598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
70698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return null;
70798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
70898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
709ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private Node findNode(Script.KernelID k) {
710ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
711ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
712ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
713ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (k == n.mKernels.get(ct2)) {
714ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        return n;
71598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    }
71698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
71798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
718ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return null;
719ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
720ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
721ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
722ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a Kernel to the group.
723ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
724ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
725ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param k The kernel to add.
726ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
727ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this.
728ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
729ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addKernel(Script.KernelID k) {
730ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mLines.size() != 0) {
731ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException(
732ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    "Kernels may not be added once connections exist.");
733ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
734059fede7f200350b6131fc131f76248085485722Miao Wang            if (k.mScript.isIncSupp()) {
735059fede7f200350b6131fc131f76248085485722Miao Wang                mUseIncSupp = true;
736059fede7f200350b6131fc131f76248085485722Miao Wang            }
737ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
738ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (findNode(k) != null) {
739ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                return this;
740ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
741ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addKernel 2 ");
742ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mKernelCount++;
743ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node n = findNode(k.mScript);
744ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (n == null) {
745ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                //android.util.Log.v("RSR", "addKernel 3 ");
746ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                n = new Node(k.mScript);
747ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mNodes.add(n);
748ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
749ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            n.mKernels.add(k);
750ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return this;
751ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
752ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
753ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
754ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a connection to the group.
755ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
756ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
757ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param t The type of the connection. This is used to
758ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          determine the kernel launch sizes on the source side
759ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          of this connection.
760ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param from The source for the connection.
761ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param to The destination of the connection.
762ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
763ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this
764ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
765ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
766ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
767ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nf = findNode(from);
768ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nf == null) {
7691b370e358d16cc3b50b169511d6b387db09f972dJason Sams                throw new RSInvalidStateException("From script not found.");
770ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
771ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
772ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nt = findNode(to.mScript);
773ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nt == null) {
774ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("To script not found.");
77598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
776ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
777ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ConnectLine cl = new ConnectLine(t, from, to);
778ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mLines.add(new ConnectLine(t, from, to));
779ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
780ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nf.mOutputs.add(cl);
781ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nt.mInputs.add(cl);
78298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
7831b370e358d16cc3b50b169511d6b387db09f972dJason Sams            validateCycle(nf, nf);
78498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return this;
78598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
78698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
787ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
788ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a connection to the group.
789ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
790ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
791ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param t The type of the connection. This is used to
792ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          determine the kernel launch sizes for both sides of
793ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          this connection.
794ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param from The source for the connection.
795ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param to The destination of the connection.
796ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
797ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this
798ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
799ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
800ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
801ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nf = findNode(from);
802ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nf == null) {
8031b370e358d16cc3b50b169511d6b387db09f972dJason Sams                throw new RSInvalidStateException("From script not found.");
804ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
805ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
806ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nt = findNode(to);
807ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nt == null) {
808ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("To script not found.");
809ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
810ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
811ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ConnectLine cl = new ConnectLine(t, from, to);
812ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mLines.add(new ConnectLine(t, from, to));
813ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
814ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nf.mOutputs.add(cl);
815ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nt.mInputs.add(cl);
816ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
8171b370e358d16cc3b50b169511d6b387db09f972dJason Sams            validateCycle(nf, nf);
818ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return this;
819ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
820ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
821059fede7f200350b6131fc131f76248085485722Miao Wang        /**
822059fede7f200350b6131fc131f76248085485722Miao Wang         * Calculate the order of each node.
823059fede7f200350b6131fc131f76248085485722Miao Wang         *
824059fede7f200350b6131fc131f76248085485722Miao Wang         *
825059fede7f200350b6131fc131f76248085485722Miao Wang         * @return Success or Fail
826059fede7f200350b6131fc131f76248085485722Miao Wang         */
827059fede7f200350b6131fc131f76248085485722Miao Wang        private boolean calcOrderRecurse(Node node0, int depth) {
828059fede7f200350b6131fc131f76248085485722Miao Wang            node0.mSeen = true;
829059fede7f200350b6131fc131f76248085485722Miao Wang            if (node0.mOrder < depth) {
830059fede7f200350b6131fc131f76248085485722Miao Wang                node0.mOrder = depth;
831059fede7f200350b6131fc131f76248085485722Miao Wang            }
832059fede7f200350b6131fc131f76248085485722Miao Wang            boolean ret = true;
833059fede7f200350b6131fc131f76248085485722Miao Wang
834059fede7f200350b6131fc131f76248085485722Miao Wang            for (ConnectLine link : node0.mOutputs) {
835059fede7f200350b6131fc131f76248085485722Miao Wang                Node node1 = null;
836059fede7f200350b6131fc131f76248085485722Miao Wang                if (link.mToF != null) {
837059fede7f200350b6131fc131f76248085485722Miao Wang                    node1 = findNode(link.mToF.mScript);
838059fede7f200350b6131fc131f76248085485722Miao Wang                } else {
839059fede7f200350b6131fc131f76248085485722Miao Wang                    node1 = findNode(link.mToK.mScript);
840059fede7f200350b6131fc131f76248085485722Miao Wang                }
841059fede7f200350b6131fc131f76248085485722Miao Wang                if (node1.mSeen) {
842059fede7f200350b6131fc131f76248085485722Miao Wang                    return false;
843059fede7f200350b6131fc131f76248085485722Miao Wang                }
844059fede7f200350b6131fc131f76248085485722Miao Wang                ret &= calcOrderRecurse(node1, node0.mOrder + 1);
845059fede7f200350b6131fc131f76248085485722Miao Wang            }
846059fede7f200350b6131fc131f76248085485722Miao Wang
847059fede7f200350b6131fc131f76248085485722Miao Wang            return ret;
848059fede7f200350b6131fc131f76248085485722Miao Wang        }
849059fede7f200350b6131fc131f76248085485722Miao Wang
850059fede7f200350b6131fc131f76248085485722Miao Wang        private boolean calcOrder() {
851059fede7f200350b6131fc131f76248085485722Miao Wang            boolean ret = true;
852059fede7f200350b6131fc131f76248085485722Miao Wang            for (Node n0 : mNodes) {
853059fede7f200350b6131fc131f76248085485722Miao Wang                if (n0.mInputs.size() == 0) {
854059fede7f200350b6131fc131f76248085485722Miao Wang                    for (Node n1 : mNodes) {
855059fede7f200350b6131fc131f76248085485722Miao Wang                        n1.mSeen = false;
856059fede7f200350b6131fc131f76248085485722Miao Wang                    }
857059fede7f200350b6131fc131f76248085485722Miao Wang                    ret &= calcOrderRecurse(n0, 1);
858059fede7f200350b6131fc131f76248085485722Miao Wang                }
859059fede7f200350b6131fc131f76248085485722Miao Wang            }
860059fede7f200350b6131fc131f76248085485722Miao Wang
861059fede7f200350b6131fc131f76248085485722Miao Wang            Collections.sort(mNodes, new Comparator<Node>() {
862059fede7f200350b6131fc131f76248085485722Miao Wang                public int compare(Node n1, Node n2) {
863059fede7f200350b6131fc131f76248085485722Miao Wang                    return n1.mOrder - n2.mOrder;
864059fede7f200350b6131fc131f76248085485722Miao Wang                }
865059fede7f200350b6131fc131f76248085485722Miao Wang            });
866ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
867059fede7f200350b6131fc131f76248085485722Miao Wang            return ret;
868059fede7f200350b6131fc131f76248085485722Miao Wang        }
869ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
870ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
871ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Creates the Script group.
872ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
873ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
874ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return ScriptGroup The new ScriptGroup
875ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
87698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        public ScriptGroup create() {
8773d9b60c9ae71c4c09df0b4e59c825a5d631e1254Miao Wang
8781b370e358d16cc3b50b169511d6b387db09f972dJason Sams            if (mNodes.size() == 0) {
8791b370e358d16cc3b50b169511d6b387db09f972dJason Sams                throw new RSInvalidStateException("Empty script groups are not allowed");
8801b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
8811b370e358d16cc3b50b169511d6b387db09f972dJason Sams
8821b370e358d16cc3b50b169511d6b387db09f972dJason Sams            // reset DAG numbers in case we're building a second group
8831b370e358d16cc3b50b169511d6b387db09f972dJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
8841b370e358d16cc3b50b169511d6b387db09f972dJason Sams                mNodes.get(ct).dagNumber = 0;
8851b370e358d16cc3b50b169511d6b387db09f972dJason Sams            }
8861b370e358d16cc3b50b169511d6b387db09f972dJason Sams            validateDAG();
8871b370e358d16cc3b50b169511d6b387db09f972dJason Sams
888ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ArrayList<IO> inputs = new ArrayList<IO>();
889ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ArrayList<IO> outputs = new ArrayList<IO>();
890ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
8913d9b60c9ae71c4c09df0b4e59c825a5d631e1254Miao Wang            long[] kernels = new long[mKernelCount];
892ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int idx = 0;
893ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
894ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
895ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
896ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    final Script.KernelID kid = n.mKernels.get(ct2);
897ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    kernels[idx++] = kid.getID(mRS);
898ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
899ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    boolean hasInput = false;
900ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    boolean hasOutput = false;
901ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
902ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        if (n.mInputs.get(ct3).mToK == kid) {
903ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            hasInput = true;
904ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        }
905ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
906ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
907ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        if (n.mOutputs.get(ct3).mFrom == kid) {
908ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            hasOutput = true;
909ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        }
910ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
911ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (!hasInput) {
912ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        inputs.add(new IO(kid));
913ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
914ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (!hasOutput) {
915ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        outputs.add(new IO(kid));
916ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
917ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
918ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
919ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (idx != mKernelCount) {
920ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSRuntimeException("Count mismatch, should not happen.");
921ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
922ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
923059fede7f200350b6131fc131f76248085485722Miao Wang            long id = 0;
924059fede7f200350b6131fc131f76248085485722Miao Wang            if (!mUseIncSupp) {
925059fede7f200350b6131fc131f76248085485722Miao Wang                long[] src = new long[mLines.size()];
926059fede7f200350b6131fc131f76248085485722Miao Wang                long[] dstk = new long[mLines.size()];
927059fede7f200350b6131fc131f76248085485722Miao Wang                long[] dstf = new long[mLines.size()];
928059fede7f200350b6131fc131f76248085485722Miao Wang                long[] types = new long[mLines.size()];
929059fede7f200350b6131fc131f76248085485722Miao Wang
930059fede7f200350b6131fc131f76248085485722Miao Wang                for (int ct=0; ct < mLines.size(); ct++) {
931059fede7f200350b6131fc131f76248085485722Miao Wang                    ConnectLine cl = mLines.get(ct);
932059fede7f200350b6131fc131f76248085485722Miao Wang                    src[ct] = cl.mFrom.getID(mRS);
933059fede7f200350b6131fc131f76248085485722Miao Wang                    if (cl.mToK != null) {
934059fede7f200350b6131fc131f76248085485722Miao Wang                        dstk[ct] = cl.mToK.getID(mRS);
935059fede7f200350b6131fc131f76248085485722Miao Wang                    }
936059fede7f200350b6131fc131f76248085485722Miao Wang                    if (cl.mToF != null) {
937059fede7f200350b6131fc131f76248085485722Miao Wang                        dstf[ct] = cl.mToF.getID(mRS);
938059fede7f200350b6131fc131f76248085485722Miao Wang                    }
939059fede7f200350b6131fc131f76248085485722Miao Wang                    types[ct] = cl.mAllocationType.getID(mRS);
940ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
941059fede7f200350b6131fc131f76248085485722Miao Wang                id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
942059fede7f200350b6131fc131f76248085485722Miao Wang                if (id == 0) {
943059fede7f200350b6131fc131f76248085485722Miao Wang                    throw new RSRuntimeException("Object creation error, should not happen.");
944ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
945059fede7f200350b6131fc131f76248085485722Miao Wang            } else {
946059fede7f200350b6131fc131f76248085485722Miao Wang                //Calculate the order of the DAG so that script can run one after another.
947059fede7f200350b6131fc131f76248085485722Miao Wang                calcOrder();
948ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
949ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
950ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ScriptGroup sg = new ScriptGroup(id, mRS);
951ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            sg.mOutputs = new IO[outputs.size()];
952ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < outputs.size(); ct++) {
953ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                sg.mOutputs[ct] = outputs.get(ct);
954ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
955ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
956ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            sg.mInputs = new IO[inputs.size()];
957ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < inputs.size(); ct++) {
958ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                sg.mInputs[ct] = inputs.get(ct);
959ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
960059fede7f200350b6131fc131f76248085485722Miao Wang            sg.mNodes = mNodes;
961059fede7f200350b6131fc131f76248085485722Miao Wang            sg.mUseIncSupp = mUseIncSupp;
96298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return sg;
96398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
96498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
96598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
96698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
967ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    /**
9683b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang     * Represents a binding of a value to a global variable in a
9693b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang     * kernel or invocable function. Used in closure creation.
9703b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang     */
9713b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9723b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    public static final class Binding {
9733b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private final Script.FieldID mField;
9743b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private final Object mValue;
9753b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9763b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
9773b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns a Binding object that binds value to field
9783b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
9793b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param field the Script.FieldID of the global variable
9803b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param value the value
9813b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
9823b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9833b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        public Binding(Script.FieldID field, Object value) {
9843b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            mField = field;
9853b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang            mValue = value;
9863b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        }
9873b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9883b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
9893b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns the field ID
9903b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
9913b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9923b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        public Script.FieldID getField() { return mField; }
9933b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9943b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
9953b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns the value
9963b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
9973b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
9983b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        public Object getValue() { return mValue; }
9993b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    }
10003b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
10013b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang    /**
1002ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * The builder class for creating script groups
1003ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
1004ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A script group is created using closures (see class {@link Closure}).
1005ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A closure is a function call to a kernel or
1006ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * invocable function. Each function argument or global variable accessed inside
1007ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * the function is bound to 1) a known value, 2) a script group input
1008ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * (see class {@link Input}), or 3) a
1009ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * future (see class {@link Future}).
1010ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A future is the output of a closure, either the return value of the
1011ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * function or a global variable written by that function.
1012ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
1013ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * Closures are created using the {@link #addKernel} or {@link #addInvoke}
1014ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * methods.
1015ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * When a closure is created, futures from previously created closures
1016ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * can be used as its inputs.
1017ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * External script group inputs can be used as inputs to individual closures as well.
1018ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * An external script group input is created using the {@link #addInput} method.
1019ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * A script group is created by a call to the {@link #create} method, which
1020ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * accepts an array of futures as the outputs for the script group.
1021ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * <p>
1022ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * Closures in a script group can be evaluated in any order as long as the
1023ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * following conditions are met:
1024ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * 1) a closure must be evaluated before any other closures that take its
1025ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * futures as inputs;
1026ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * 2) all closures added before an invoke closure must be evaluated
1027ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * before it;
1028ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * and 3) all closures added after an invoke closure must be evaluated after
1029ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * it.
1030ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * As a special case, the order that the closures are added is a legal
1031ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * evaluation order. However, other evaluation orders are possible, including
1032ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     * concurrently evaluating independent closures.
1033ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni     */
1034ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1035ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    public static final class Builder2 {
1036ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        RenderScript mRS;
1037ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        List<Closure> mClosures;
1038ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        List<Input> mInputs;
10393b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        private static final String TAG = "ScriptGroup.Builder2";
1040ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
10413b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
10423b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Returns a Builder object
10433b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
10443b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param rs the RenderScript context
10453b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
1046ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Builder2(RenderScript rs) {
1047ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mRS = rs;
1048ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosures = new ArrayList<Closure>();
1049ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mInputs = new ArrayList<Input>();
1050ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1051ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
10523b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
10533b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Adds a closure for a kernel
10543b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
10553b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param k Kernel ID for the kernel function
10563b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param returnType Allocation type for the return value
10573b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param args arguments to the kernel function
10583b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param globalBindings bindings for global variables
10593b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @return a closure
10603b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
10613b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
1062ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Closure addKernelInternal(Script.KernelID k, Type returnType, Object[] args,
10633b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                                          Map<Script.FieldID, Object> globalBindings) {
1064ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Closure c = new Closure(mRS, k, returnType, args, globalBindings);
1065ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosures.add(c);
1066ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return c;
1067ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1068ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
10693b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang        /**
10703b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * Adds a closure for an invocable function
10713b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         *
10723b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param invoke Invoke ID for the invocable function
10733b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param args arguments to the invocable function
10743b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @param globalBindings bindings for global variables
10753b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         * @return a closure
10763b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang         */
10773b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang
1078ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private Closure addInvokeInternal(Script.InvokeID invoke, Object[] args,
1079ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                          Map<Script.FieldID, Object> globalBindings) {
1080ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Closure c = new Closure(mRS, invoke, args, globalBindings);
1081ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mClosures.add(c);
1082ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return c;
1083ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1084ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1085ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1086ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Adds a script group input
1087ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1088ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a script group input, which can be used as an argument or a value to
1089ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *     a global variable for creating closures
1090ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1091ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1092ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Input addInput() {
1093ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Input unbound = new Input();
1094ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            mInputs.add(unbound);
1095ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return unbound;
1096ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1097ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1098ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1099ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Adds a closure for a kernel
1100ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1101ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param k Kernel ID for the kernel function
1102ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param argsAndBindings arguments followed by bindings for global variables
1103ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a closure
1104ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1105ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1106ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
1107ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ArrayList<Object> args = new ArrayList<Object>();
1108ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
1109ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
1110ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                return null;
1111ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1112ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return addKernelInternal(k, returnType, args.toArray(), bindingMap);
1113ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1114ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1115ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1116ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Adds a closure for an invocable function
1117ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1118ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param invoke Invoke ID for the invocable function
1119ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param argsAndBindings arguments followed by bindings for global variables
1120ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a closure
1121ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1122ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1123ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
1124ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ArrayList<Object> args = new ArrayList<Object>();
1125ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
1126ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
1127ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                return null;
1128ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1129ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return addInvokeInternal(invoke, args.toArray(), bindingMap);
1130ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1131ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1132ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        /**
1133ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * Creates a script group
1134ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *
1135ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param name name for the script group. Legal names can only contain letters, digits,
1136ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         *        '-', or '_'. The name can be no longer than 100 characters.
1137ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @param outputs futures intended as outputs of the script group
1138ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         * @return a script group
1139ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni         */
1140ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1141ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        public ScriptGroup create(String name, Future... outputs) {
1142ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            if (name == null || name.isEmpty() || name.length() > 100 ||
1143ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
1144ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                throw new RSIllegalArgumentException("invalid script group name");
1145ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1146ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            ScriptGroup ret = new ScriptGroup(mRS, name, mClosures, mInputs, outputs);
1147ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return ret;
1148ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1149ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1150ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        private boolean seperateArgsAndBindings(Object[] argsAndBindings,
1151ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                ArrayList<Object> args,
1152ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                                                Map<Script.FieldID, Object> bindingMap) {
1153ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            int i;
1154ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (i = 0; i < argsAndBindings.length; i++) {
1155ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                if (argsAndBindings[i] instanceof Binding) {
1156ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    break;
1157ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                }
1158ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                args.add(argsAndBindings[i]);
1159ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1160ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1161ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            for (; i < argsAndBindings.length; i++) {
1162ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                if (!(argsAndBindings[i] instanceof Binding)) {
1163ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                    return false;
1164ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                }
1165ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni                Binding b = (Binding)argsAndBindings[i];
11663b130b76bb0a170ec3e633cb227f2298d3df4352Miao Wang                bindingMap.put(b.getField(), b.getValue());
1167ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            }
1168ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1169ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni            return true;
1170ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni        }
1171ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni
1172ad3c3dc1b57435e949659adf3316413e0c6d9682Yang Ni    }
117398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
117498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams}
117598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
117698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
1177