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
1998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Samsimport java.lang.reflect.Method;
20ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsimport java.util.ArrayList;
2198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
2298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams/**
23ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * ScriptGroup creates a groups of scripts which are executed
24ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * together based upon upon one execution call as if they were
25ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * all part of a single script.  The scripts may be connected
26ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * internally or to an external allocation. For the internal
27ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * connections the intermediate results are not observable after
28ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * the execution of the script.
29ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * <p>
30ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * The external connections are grouped into inputs and outputs.
31ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * All outputs are produced by a script kernel and placed into a
32ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * user supplied allocation. Inputs are similar but supply the
33ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * input of a kernal. Inputs bounds to a script are set directly
34ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * upon the script.
35ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams *
3698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams **/
37ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samspublic final class ScriptGroup extends BaseObj {
3898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    IO mOutputs[];
3998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    IO mInputs[];
4098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
4198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    static class IO {
42ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.KernelID mKID;
4398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Allocation mAllocation;
4498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
45ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        IO(Script.KernelID s) {
46ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mKID = s;
4798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
4898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
4998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
50ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    static class ConnectLine {
51ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
52ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mFrom = from;
53ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mToK = to;
5498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mAllocationType = t;
5598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
5698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
57ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
58ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mFrom = from;
59ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mToF = to;
60ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mAllocationType = t;
6198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
62ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
63ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.FieldID mToF;
64ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.KernelID mToK;
65ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Script.KernelID mFrom;
66ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        Type mAllocationType;
6798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
6898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
6998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    static class Node {
7098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Script mScript;
71ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
72ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
73ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
7498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        boolean mSeen;
7598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
7698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Node mNext;
7798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
7898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        Node(Script s) {
7998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mScript = s;
8098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
8198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
8298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
8398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
8498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    ScriptGroup(int id, RenderScript rs) {
8598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        super(id, rs);
8698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
8798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
88ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
89ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Sets an input of the ScriptGroup. This specifies an
90ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Allocation to be used for the kernels which require a kernel
91ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * input and that input is provided external to the group.
92ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
93ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param s The ID of the kernel where the allocation should be
94ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *          connected.
95ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param a The allocation to connect.
96ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
97ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public void setInput(Script.KernelID s, Allocation a) {
9898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        for (int ct=0; ct < mInputs.length; ct++) {
99ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mInputs[ct].mKID == s) {
10098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                mInputs[ct].mAllocation = a;
101ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
10298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                return;
10398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
10498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
10598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        throw new RSIllegalArgumentException("Script not found");
10698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
10798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
108ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
109ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Sets an output of the ScriptGroup. This specifies an
110ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Allocation to be used for the kernels which require a kernel
111ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * output and that output is provided external to the group.
112ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
113ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param s The ID of the kernel where the allocation should be
114ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *          connected.
115ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * @param a The allocation to connect.
116ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
117ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public void setOutput(Script.KernelID s, Allocation a) {
11898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        for (int ct=0; ct < mOutputs.length; ct++) {
119ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mOutputs[ct].mKID == s) {
12098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                mOutputs[ct].mAllocation = a;
121ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
12298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                return;
12398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
12498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
12598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        throw new RSIllegalArgumentException("Script not found");
12698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
12798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
128ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
129ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Execute the ScriptGroup.  This will run all the kernels in
130ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * the script.  The state of the connecting lines will not be
131ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * observable after this operation.
132ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
13398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    public void execute() {
134ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mRS.nScriptGroupExecute(getID(mRS));
13598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
13698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
13798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
138ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    /**
139ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Create a ScriptGroup. There are two steps to creating a
140ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * ScriptGoup.
141ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
142ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * First all the Kernels to be used by the group should be
143ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * added.  Once this is done the kernels should be connected.
144ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Kernels cannot be added once a connection has been made.
145ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
146ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Second, add connections. There are two forms of connections.
147ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Kernel to Kernel and Kernel to Field. Kernel to Kernel is
148ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * higher performance and should be used where possible. The
149ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * line of connections cannot form a loop. If a loop is detected
150ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * an exception is thrown.
151ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * <p>
152ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * Once all the connections are made a call to create will
153ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     * return the ScriptGroup object.
154ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     *
155ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams     */
156ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    public static final class Builder {
157ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private RenderScript mRS;
158ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private ArrayList<Node> mNodes = new ArrayList<Node>();
159ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
160ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private int mKernelCount;
161ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
162ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
163ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Create a builder for generating a ScriptGroup.
164ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
165ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
166ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param rs The Renderscript context.
167ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
16898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        public Builder(RenderScript rs) {
16998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            mRS = rs;
17098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
17198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
17298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        private void validateRecurse(Node n, int depth) {
17398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            n.mSeen = true;
17498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
175ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", " validateRecurse outputCount " + n.mOutputs.size());
176ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < n.mOutputs.size(); ct++) {
177ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                final ConnectLine cl = n.mOutputs.get(ct);
178ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToK != null) {
179ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    Node tn = findNode(cl.mToK.mScript);
180ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (tn.mSeen) {
181ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
182ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
183ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    validateRecurse(tn, depth + 1);
184ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
185ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToF != null) {
186ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    Node tn = findNode(cl.mToF.mScript);
187ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (tn.mSeen) {
18898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                        throw new RSInvalidStateException("Loops in group not allowed.");
18998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    }
190ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    validateRecurse(tn, depth + 1);
19198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
19298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
19398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
19498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
19598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        private void validate() {
196ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "validate");
19798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
198ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
199ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < mNodes.size(); ct2++) {
200ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    mNodes.get(ct2).mSeen = false;
201ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
202ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
203ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (n.mInputs.size() == 0) {
20498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    validateRecurse(n, 0);
20598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
20698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
20798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
20898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
209ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private Node findNode(Script s) {
210ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
211ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (s == mNodes.get(ct).mScript) {
212ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    return mNodes.get(ct);
21398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
21498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
21598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return null;
21698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
21798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
218ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        private Node findNode(Script.KernelID k) {
219ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
220ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
221ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
222ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (k == n.mKernels.get(ct2)) {
223ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        return n;
22498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                    }
22598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams                }
22698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
227ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return null;
228ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
229ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
230ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
231ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a Kernel to the group.
232ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
233ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
234ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param k The kernel to add.
235ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
236ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this.
237ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
238ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addKernel(Script.KernelID k) {
239ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (mLines.size() != 0) {
240ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException(
241ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    "Kernels may not be added once connections exist.");
242ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
243ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
244ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
245ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (findNode(k) != null) {
246ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                return this;
247ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
248ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addKernel 2 ");
249ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mKernelCount++;
250ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node n = findNode(k.mScript);
251ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (n == null) {
252ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                //android.util.Log.v("RSR", "addKernel 3 ");
253ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                n = new Node(k.mScript);
254ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mNodes.add(n);
255ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
256ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            n.mKernels.add(k);
257ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return this;
258ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
259ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
260ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
261ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a connection to the group.
262ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
263ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
264ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param t The type of the connection. This is used to
265ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          determine the kernel launch sizes on the source side
266ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          of this connection.
267ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param from The source for the connection.
268ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param to The destination of the connection.
269ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
270ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this
271ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
272ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
273ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
274ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
275ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nf = findNode(from);
276ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nf == null) {
277ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("From kernel not found.");
278ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
279ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
280ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nt = findNode(to.mScript);
281ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nt == null) {
282ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("To script not found.");
28398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            }
284ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
285ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ConnectLine cl = new ConnectLine(t, from, to);
286ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mLines.add(new ConnectLine(t, from, to));
287ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
288ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nf.mOutputs.add(cl);
289ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nt.mInputs.add(cl);
29098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
29198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            validate();
29298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return this;
29398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
29498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
295ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
296ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Adds a connection to the group.
297ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
298ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
299ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param t The type of the connection. This is used to
300ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          determine the kernel launch sizes for both sides of
301ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *          this connection.
302ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param from The source for the connection.
303ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @param to The destination of the connection.
304ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
305ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return Builder Returns this
306ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
307ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
308ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
309ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
310ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nf = findNode(from);
311ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nf == null) {
312ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("From kernel not found.");
313ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
314ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
315ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            Node nt = findNode(to);
316ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (nt == null) {
317ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSInvalidStateException("To script not found.");
318ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
319ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
320ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ConnectLine cl = new ConnectLine(t, from, to);
321ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mLines.add(new ConnectLine(t, from, to));
322ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
323ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nf.mOutputs.add(cl);
324ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            nt.mInputs.add(cl);
325ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
326ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            validate();
327ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            return this;
328ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
329ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
330ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
331ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
332ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        /**
333ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * Creates the Script group.
334ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
335ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         *
336ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         * @return ScriptGroup The new ScriptGroup
337ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams         */
33898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        public ScriptGroup create() {
339ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ArrayList<IO> inputs = new ArrayList<IO>();
340ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ArrayList<IO> outputs = new ArrayList<IO>();
341ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
342ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int[] kernels = new int[mKernelCount];
343ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int idx = 0;
344ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mNodes.size(); ct++) {
345ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                Node n = mNodes.get(ct);
346ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
347ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    final Script.KernelID kid = n.mKernels.get(ct2);
348ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    kernels[idx++] = kid.getID(mRS);
349ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
350ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    boolean hasInput = false;
351ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    boolean hasOutput = false;
352ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
353ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        if (n.mInputs.get(ct3).mToK == kid) {
354ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            hasInput = true;
355ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        }
356ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
357ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
358ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        if (n.mOutputs.get(ct3).mFrom == kid) {
359ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            hasOutput = true;
360ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        }
361ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
362ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (!hasInput) {
363ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        inputs.add(new IO(kid));
364ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
365ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    if (!hasOutput) {
366ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                        outputs.add(new IO(kid));
367ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    }
36898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
369ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
370ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
371ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (idx != mKernelCount) {
372ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSRuntimeException("Count mismatch, should not happen.");
373ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
374ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
375ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int[] src = new int[mLines.size()];
376ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int[] dstk = new int[mLines.size()];
377ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int[] dstf = new int[mLines.size()];
378ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int[] types = new int[mLines.size()];
379ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
380ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < mLines.size(); ct++) {
381ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                ConnectLine cl = mLines.get(ct);
382ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                src[ct] = cl.mFrom.getID(mRS);
383ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToK != null) {
384ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    dstk[ct] = cl.mToK.getID(mRS);
385ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
386ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                if (cl.mToF != null) {
387ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    dstf[ct] = cl.mToF.getID(mRS);
388ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                }
389ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                types[ct] = cl.mAllocationType.getID(mRS);
390ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
391ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
392ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            int id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
393ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if (id == 0) {
394ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                throw new RSRuntimeException("Object creation error, should not happen.");
395ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
396ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
397ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            ScriptGroup sg = new ScriptGroup(id, mRS);
398ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            sg.mOutputs = new IO[outputs.size()];
399ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < outputs.size(); ct++) {
400ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                sg.mOutputs[ct] = outputs.get(ct);
401ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
402ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
403ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            sg.mInputs = new IO[inputs.size()];
404ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (int ct=0; ct < inputs.size(); ct++) {
405ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                sg.mInputs[ct] = inputs.get(ct);
406ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            }
40798a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
40898a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams            return sg;
40998a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams        }
41098a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
41198a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams    }
41298a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
41398a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
41498a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams}
41598a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
41698a281354fe06d1f970d0521c9a08d9eb0aa1a45Jason Sams
417