summaryrefslogtreecommitdiffstats
path: root/graphics/java/android
diff options
context:
space:
mode:
authorJason Sams <jsams@google.com>2012-08-10 15:40:53 -0700
committerJason Sams <jsams@google.com>2012-08-10 16:02:33 -0700
commit423ebcb4dc4881c3a83e8121d5212466287d0d0c (patch)
treeb8ad64ce2954386060441c9726e0d81e57b7e308 /graphics/java/android
parent6cc7a9276bdad8b230e35141204c949291350f0b (diff)
downloadframeworks_base-423ebcb4dc4881c3a83e8121d5212466287d0d0c.zip
frameworks_base-423ebcb4dc4881c3a83e8121d5212466287d0d0c.tar.gz
frameworks_base-423ebcb4dc4881c3a83e8121d5212466287d0d0c.tar.bz2
Implement ScriptGroup and add test.
Change-Id: I6ce0479c20f425d501c759c15717aa8b418c3f5f
Diffstat (limited to 'graphics/java/android')
-rw-r--r--graphics/java/android/renderscript/ScriptGroup.java391
1 files changed, 391 insertions, 0 deletions
diff --git a/graphics/java/android/renderscript/ScriptGroup.java b/graphics/java/android/renderscript/ScriptGroup.java
new file mode 100644
index 0000000..c4064b5
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptGroup.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import java.lang.reflect.Method;
+
+/**
+ * @hide
+ **/
+public class ScriptGroup extends BaseObj {
+ Node mNodes[];
+ Connection mConnections[];
+ Node mFirstNode;
+ IO mOutputs[];
+ IO mInputs[];
+
+ static class IO {
+ Script mScript;
+ Allocation mAllocation;
+ String mName;
+
+ IO(Script s) {
+ mScript = s;
+ }
+ IO(Script s, String n) {
+ mScript = s;
+ mName = n;
+ }
+ }
+
+ static class Connection {
+ Node mTo[];
+ String mToName[];
+ Node mFrom;
+ Type mAllocationType;
+ Allocation mInternalAllocation;
+
+ Connection(Node out, Type t) {
+ mFrom = out;
+ mAllocationType = t;
+ }
+
+ void addTo(Node n, String name) {
+ if (mTo == null) {
+ mTo = new Node[1];
+ mToName = new String[1];
+ } else {
+ Node nt[] = new Node[mTo.length + 1];
+ String ns[] = new String[mTo.length + 1];
+ System.arraycopy(mTo, 0, nt, 0, mTo.length);
+ System.arraycopy(mToName, 0, ns, 0, mTo.length);
+ mTo = nt;
+ mToName = ns;
+ }
+ mTo[mTo.length - 1] = n;
+ mToName[mTo.length - 1] = name;
+ }
+ }
+
+ static class Node {
+ Script mScript;
+ Connection mInput[] = new Connection[8];
+ Connection mOutput[] = new Connection[1];
+ int mInputCount;
+ int mOutputCount;
+ int mDepth;
+ boolean mSeen;
+
+ Node mNext;
+
+ Node(Script s) {
+ mScript = s;
+ }
+
+ void addInput(Connection c) {
+ if (mInput.length <= mInputCount) {
+ Connection[] nc = new Connection[mInput.length + 8];
+ System.arraycopy(mInput, 0, nc, 0, mInputCount);
+ mInput = nc;
+ }
+ mInput[mInputCount++] = c;
+ }
+
+ void addOutput(Connection c) {
+ if (mOutput.length <= mOutputCount) {
+ Connection[] nc = new Connection[mOutput.length + 8];
+ System.arraycopy(mOutput, 0, nc, 0, mOutputCount);
+ mOutput = nc;
+ }
+ mOutput[mOutputCount++] = c;
+ }
+ }
+
+
+ ScriptGroup(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ void init(int nodeCount, int connectionCount) {
+ mNodes = new Node[nodeCount];
+ mConnections = new Connection[connectionCount];
+
+ android.util.Log.v("RSR", "init" + nodeCount + ", " + connectionCount);
+
+ // Count outputs and create array.
+ Node n = mFirstNode;
+ int outputCount = 0;
+ int inputCount = 0;
+ int connectionIndex = 0;
+ int nodeNum = 0;
+ while (n != null) {
+ mNodes[nodeNum++] = n;
+
+ // Look for unattached kernel inputs
+ boolean hasInput = false;
+ for (int ct=0; ct < n.mInput.length; ct++) {
+ if (n.mInput[ct] != null) {
+ if (n.mInput[ct].mToName == null) {
+ hasInput = true;
+ }
+ }
+ }
+ if (!hasInput) {
+ if (mInputs == null) {
+ mInputs = new IO[1];
+ }
+ if (mInputs.length <= inputCount) {
+ IO t[] = new IO[mInputs.length + 1];
+ System.arraycopy(mInputs, 0, t, 0, mInputs.length);
+ mInputs = t;
+ }
+ mInputs[inputCount++] = new IO(n.mScript);
+ }
+
+ // Look for unattached kernel outputs
+ boolean hasOutput = false;
+ for (int ct=0; ct < n.mOutput.length; ct++) {
+ if (n.mOutput[ct] != null) {
+ hasOutput = true;
+ }
+ }
+ if (!hasOutput) {
+ if (mOutputs == null) {
+ mOutputs = new IO[1];
+ }
+ if (mOutputs.length <= outputCount) {
+ IO t[] = new IO[mOutputs.length + 1];
+ System.arraycopy(mOutputs, 0, t, 0, mOutputs.length);
+ mOutputs = t;
+ }
+ mOutputs[outputCount++] = new IO(n.mScript);
+ }
+
+ // Make allocations for internal connections
+ // Since script outputs are unique, use those to avoid duplicates.
+ for (int ct=0; ct < n.mOutput.length; ct++) {
+ android.util.Log.v("RSR", "init out2 " + n.mOutput[ct]);
+ if (n.mOutput[ct] != null) {
+ Connection t = n.mOutput[ct];
+ mConnections[connectionIndex++] = t;
+ t.mInternalAllocation = Allocation.createTyped(mRS, t.mAllocationType);
+ }
+ }
+
+ n = n.mNext;
+ }
+ }
+
+ public void setInput(Script s, Allocation a) {
+ for (int ct=0; ct < mInputs.length; ct++) {
+ if (mInputs[ct].mScript == s) {
+ mInputs[ct].mAllocation = a;
+ return;
+ }
+ }
+ throw new RSIllegalArgumentException("Script not found");
+ }
+
+ public void setOutput(Script s, Allocation a) {
+ for (int ct=0; ct < mOutputs.length; ct++) {
+ if (mOutputs[ct].mScript == s) {
+ mOutputs[ct].mAllocation = a;
+ return;
+ }
+ }
+ throw new RSIllegalArgumentException("Script not found");
+ }
+
+ public void execute() {
+ android.util.Log.v("RSR", "execute");
+ boolean more = true;
+ int depth = 0;
+ while (more) {
+ more = false;
+ for (int ct=0; ct < mNodes.length; ct++) {
+ if (mNodes[ct].mDepth == depth) {
+ more = true;
+
+ Allocation kernelIn = null;
+ for (int ct2=0; ct2 < mNodes[ct].mInputCount; ct2++) {
+ android.util.Log.v("RSR", " kin " + ct2 + ", to " + mNodes[ct].mInput[ct2].mTo[0] + ", name " + mNodes[ct].mInput[ct2].mToName[0]);
+ if (mNodes[ct].mInput[ct2].mToName[0] == null) {
+ kernelIn = mNodes[ct].mInput[ct2].mInternalAllocation;
+ break;
+ }
+ }
+
+ Allocation kernelOut= null;
+ for (int ct2=0; ct2 < mNodes[ct].mOutputCount; ct2++) {
+ android.util.Log.v("RSR", " kout " + ct2 + ", from " + mNodes[ct].mOutput[ct2].mFrom);
+ if (mNodes[ct].mOutput[ct2].mFrom != null) {
+ kernelOut = mNodes[ct].mOutput[ct2].mInternalAllocation;
+ break;
+ }
+ }
+ if (kernelOut == null) {
+ for (int ct2=0; ct2 < mOutputs.length; ct2++) {
+ if (mOutputs[ct2].mScript == mNodes[ct].mScript) {
+ kernelOut = mOutputs[ct2].mAllocation;
+ break;
+ }
+ }
+ }
+
+ android.util.Log.v("RSR", "execute calling " + mNodes[ct] + ", with " + kernelIn);
+ if (kernelIn != null) {
+ try {
+
+ Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
+ new Class[] { Allocation.class, Allocation.class });
+ m.invoke(mNodes[ct].mScript, new Object[] {kernelIn, kernelOut} );
+ } catch (Throwable t) {
+ android.util.Log.e("RSR", "execute error " + t);
+ }
+ } else {
+ try {
+ Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
+ new Class[] { Allocation.class });
+ m.invoke(mNodes[ct].mScript, new Object[] {kernelOut} );
+ } catch (Throwable t) {
+ android.util.Log.e("RSR", "execute error " + t);
+ }
+ }
+
+ }
+ }
+ depth ++;
+ }
+
+ }
+
+
+ public static class Builder {
+ RenderScript mRS;
+ Node mFirstNode;
+ int mConnectionCount = 0;
+ int mNodeCount = 0;
+
+ public Builder(RenderScript rs) {
+ mRS = rs;
+ }
+
+ private void validateRecurse(Node n, int depth) {
+ n.mSeen = true;
+ if (depth > n.mDepth) {
+ n.mDepth = depth;
+ }
+
+ android.util.Log.v("RSR", " validateRecurse outputCount " + n.mOutputCount);
+ for (int ct=0; ct < n.mOutputCount; ct++) {
+ for (int ct2=0; ct2 < n.mOutput[ct].mTo.length; ct2++) {
+ if (n.mOutput[ct].mTo[ct2].mSeen) {
+ throw new RSInvalidStateException("Loops in group not allowed.");
+ }
+ validateRecurse(n.mOutput[ct].mTo[ct2], depth + 1);
+ }
+ }
+ }
+
+ private void validate() {
+ android.util.Log.v("RSR", "validate");
+ Node n = mFirstNode;
+ while (n != null) {
+ n.mSeen = false;
+ n.mDepth = 0;
+ n = n.mNext;
+ }
+
+ n = mFirstNode;
+ while (n != null) {
+ android.util.Log.v("RSR", "validate n= " + n);
+ if ((n.mSeen == false) && (n.mInputCount == 0)) {
+ android.util.Log.v("RSR", " recursing " + n);
+ validateRecurse(n, 0);
+ }
+ n = n.mNext;
+ }
+ }
+
+ private Node findScript(Script s) {
+ Node n = mFirstNode;
+ while (n != null) {
+ if (n.mScript == s) {
+ return n;
+ }
+ n = n.mNext;
+ }
+ return null;
+ }
+
+ private void addNode(Node n) {
+ n.mNext = mFirstNode;
+ mFirstNode = n;
+ }
+
+ public Builder addConnection(Type t, Script output, Script input, String inputName) {
+ android.util.Log.v("RSR", "addConnection " + t +", " + output + ", " + input);
+
+ // Look for existing output
+ Node nout = findScript(output);
+ Connection c;
+ if (nout == null) {
+ // Make new node
+ android.util.Log.v("RSR", "addConnection new output node");
+ nout = new Node(output);
+ mNodeCount++;
+ c = new Connection(nout, t);
+ mConnectionCount++;
+ nout.addOutput(c);
+ addNode(nout);
+ } else {
+ // Add to existing node
+ android.util.Log.v("RSR", "addConnection reuse output node");
+ if (nout.mOutput[0] != null) {
+ if (nout.mOutput[0].mFrom.mScript != output) {
+ throw new RSInvalidStateException("Changed output of existing node");
+ }
+ if (nout.mOutput[0].mAllocationType != t) {
+ throw new RSInvalidStateException("Changed output type of existing node");
+ }
+ }
+ c = nout.mOutput[0];
+ }
+ // At this point we should have a connection attached to a script ouput.
+
+ // Find input
+ Node nin = findScript(input);
+ if (nin == null) {
+ android.util.Log.v("RSR", "addConnection new input node");
+ nin = new Node(input);
+ mNodeCount++;
+ addNode(nin);
+ }
+ c.addTo(nin, inputName);
+ nin.addInput(c);
+
+ validate();
+ return this;
+ }
+
+ public ScriptGroup create() {
+ ScriptGroup sg = new ScriptGroup(0, mRS);
+ sg.mFirstNode = mFirstNode;
+ mFirstNode = null;
+
+ android.util.Log.v("RSR", "create nodes= " + mNodeCount + ", Connections= " + mConnectionCount);
+
+ sg.init(mNodeCount, mConnectionCount);
+ return sg;
+ }
+
+ }
+
+
+}
+
+