diff options
Diffstat (limited to 'rs/java/android/renderscript/ScriptGroup2.java')
-rw-r--r-- | rs/java/android/renderscript/ScriptGroup2.java | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/rs/java/android/renderscript/ScriptGroup2.java b/rs/java/android/renderscript/ScriptGroup2.java new file mode 100644 index 0000000..857e9fb --- /dev/null +++ b/rs/java/android/renderscript/ScriptGroup2.java @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2015 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 android.util.Log; +import android.util.Pair; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + +****************************** +You have tried to change the API from what has been previously approved. + +To make these errors go away, you have two choices: +1) You can add "@hide" javadoc comments to the methods, etc. listed in the +errors above. + +2) You can update current.txt by executing the following command: +make update-api + +To submit the revised current.txt to the main Android repository, +you will need approval. +****************************** + +@hide Pending Android public API approval. +*/ +public class ScriptGroup2 extends BaseObj { + + public static class Closure extends BaseObj { + private Object[] mArgs; + private Allocation mReturnValue; + private Map<Script.FieldID, Object> mBindings; + + private Future mReturnFuture; + private Map<Script.FieldID, Future> mGlobalFuture; + + private FieldPacker mFP; + + private static final String TAG = "Closure"; + + public Closure(long id, RenderScript rs) { + super(id, rs); + } + + public Closure(RenderScript rs, Script.KernelID kernelID, Type returnType, + Object[] args, Map<Script.FieldID, Object> globals) { + super(0, rs); + + mArgs = args; + mReturnValue = Allocation.createTyped(rs, returnType); + mBindings = globals; + mGlobalFuture = new HashMap<Script.FieldID, Future>(); + + int numValues = args.length + globals.size(); + + long[] fieldIDs = new long[numValues]; + long[] values = new long[numValues]; + int[] sizes = new int[numValues]; + long[] depClosures = new long[numValues]; + long[] depFieldIDs = new long[numValues]; + + int i; + for (i = 0; i < args.length; i++) { + Object obj = args[i]; + fieldIDs[i] = 0; + if (obj instanceof UnboundValue) { + UnboundValue unbound = (UnboundValue)obj; + unbound.addReference(this, i); + } else { + retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes, + depClosures, depFieldIDs); + } + } + + for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) { + Object obj = entry.getValue(); + Script.FieldID fieldID = entry.getKey(); + fieldIDs[i] = fieldID.getID(rs); + if (obj instanceof UnboundValue) { + UnboundValue unbound = (UnboundValue)obj; + unbound.addReference(this, fieldID); + } else { + retrieveValueAndDependenceInfo(rs, i, obj, values, + sizes, depClosures, depFieldIDs); + } + i++; + } + + long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs), + fieldIDs, values, sizes, depClosures, depFieldIDs); + + setID(id); + } + + public Closure(RenderScript rs, Script.InvokeID invokeID, + Object[] args, Map<Script.FieldID, Object> globals) { + super(0, rs); + mFP = FieldPacker.createFromArray(args); + + mArgs = args; + mBindings = globals; + mGlobalFuture = new HashMap<Script.FieldID, Future>(); + + int numValues = globals.size(); + + long[] fieldIDs = new long[numValues]; + long[] values = new long[numValues]; + int[] sizes = new int[numValues]; + long[] depClosures = new long[numValues]; + long[] depFieldIDs = new long[numValues]; + + int i = 0; + for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) { + Object obj = entry.getValue(); + Script.FieldID fieldID = entry.getKey(); + fieldIDs[i] = fieldID.getID(rs); + if (obj instanceof UnboundValue) { + UnboundValue unbound = (UnboundValue)obj; + unbound.addReference(this, fieldID); + } else { + // TODO(yangni): Verify obj not a future. + retrieveValueAndDependenceInfo(rs, i, obj, values, + sizes, depClosures, depFieldIDs); + } + i++; + } + + long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs, + values, sizes); + + setID(id); + } + + private static + void retrieveValueAndDependenceInfo(RenderScript rs, + int index, Object obj, + long[] values, int[] sizes, + long[] depClosures, + long[] depFieldIDs) { + + if (obj instanceof Future) { + Future f = (Future)obj; + obj = f.getValue(); + depClosures[index] = f.getClosure().getID(rs); + Script.FieldID fieldID = f.getFieldID(); + depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0; + if (obj == null) { + // Value is originally created by the owner closure + values[index] = 0; + sizes[index] = 0; + return; + } + } else { + depClosures[index] = 0; + depFieldIDs[index] = 0; + } + + ValueAndSize vs = new ValueAndSize(rs, obj); + values[index] = vs.value; + sizes[index] = vs.size; + } + + public Future getReturn() { + if (mReturnFuture == null) { + mReturnFuture = new Future(this, null, mReturnValue); + } + + return mReturnFuture; + } + + public Future getGlobal(Script.FieldID field) { + Future f = mGlobalFuture.get(field); + + if (f == null) { + // If the field is not bound to this closure, this will return a future + // without an associated value (reference). So this is not working for + // cross-module (cross-script) linking in this case where a field not + // explicitly bound. + f = new Future(this, field, mBindings.get(field)); + mGlobalFuture.put(field, f); + } + + return f; + } + + void setArg(int index, Object obj) { + mArgs[index] = obj; + ValueAndSize vs = new ValueAndSize(mRS, obj); + mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size); + } + + void setGlobal(Script.FieldID fieldID, Object obj) { + mBindings.put(fieldID, obj); + ValueAndSize vs = new ValueAndSize(mRS, obj); + mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size); + } + + private static final class ValueAndSize { + public ValueAndSize(RenderScript rs, Object obj) { + if (obj instanceof Allocation) { + value = ((Allocation)obj).getID(rs); + size = -1; + } else if (obj instanceof Boolean) { + value = ((Boolean)obj).booleanValue() ? 1 : 0; + size = 4; + } else if (obj instanceof Integer) { + value = ((Integer)obj).longValue(); + size = 4; + } else if (obj instanceof Long) { + value = ((Long)obj).longValue(); + size = 8; + } else if (obj instanceof Float) { + value = ((Float)obj).longValue(); + size = 4; + } else if (obj instanceof Double) { + value = ((Double)obj).longValue(); + size = 8; + } + } + public long value; + public int size; + } + } + + public static class Future { + Closure mClosure; + Script.FieldID mFieldID; + Object mValue; + + Future(Closure closure, Script.FieldID fieldID, Object value) { + mClosure = closure; + mFieldID = fieldID; + mValue = value; + } + + Closure getClosure() { return mClosure; } + Script.FieldID getFieldID() { return mFieldID; } + Object getValue() { return mValue; } + } + + public static class UnboundValue { + // Either mFieldID or mArgIndex should be set but not both. + List<Pair<Closure, Script.FieldID>> mFieldID; + // -1 means unset. Legal values are 0 .. n-1, where n is the number of + // arguments for the referencing closure. + List<Pair<Closure, Integer>> mArgIndex; + + UnboundValue() { + mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>(); + mArgIndex = new ArrayList<Pair<Closure, Integer>>(); + } + + void addReference(Closure closure, int index) { + mArgIndex.add(Pair.create(closure, Integer.valueOf(index))); + } + + void addReference(Closure closure, Script.FieldID fieldID) { + mFieldID.add(Pair.create(closure, fieldID)); + } + + void set(Object value) { + for (Pair<Closure, Integer> p : mArgIndex) { + Closure closure = p.first; + int index = p.second.intValue(); + closure.setArg(index, value); + } + for (Pair<Closure, Script.FieldID> p : mFieldID) { + Closure closure = p.first; + Script.FieldID fieldID = p.second; + closure.setGlobal(fieldID, value); + } + } + } + + List<Closure> mClosures; + List<UnboundValue> mInputs; + Future[] mOutputs; + + private static final String TAG = "ScriptGroup2"; + + public ScriptGroup2(long id, RenderScript rs) { + super(id, rs); + } + + ScriptGroup2(RenderScript rs, List<Closure> closures, + List<UnboundValue> inputs, Future[] outputs) { + super(0, rs); + mClosures = closures; + mInputs = inputs; + mOutputs = outputs; + + long[] closureIDs = new long[closures.size()]; + for (int i = 0; i < closureIDs.length; i++) { + closureIDs[i] = closures.get(i).getID(rs); + } + long id = rs.nScriptGroup2Create(ScriptC.mCachePath, closureIDs); + setID(id); + } + + public Object[] execute(Object... inputs) { + if (inputs.length < mInputs.size()) { + Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " + + "less than expected " + mInputs.size()); + return null; + } + + if (inputs.length > mInputs.size()) { + Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " + + "more than expected " + mInputs.size()); + } + + for (int i = 0; i < mInputs.size(); i++) { + Object obj = inputs[i]; + if (obj instanceof Future || obj instanceof UnboundValue) { + Log.e(TAG, this.toString() + ": input " + i + + " is a future or unbound value"); + return null; + } + UnboundValue unbound = mInputs.get(i); + unbound.set(obj); + } + + mRS.nScriptGroup2Execute(getID(mRS)); + + Object[] outputObjs = new Object[mOutputs.length]; + int i = 0; + for (Future f : mOutputs) { + outputObjs[i++] = f.getValue(); + } + return outputObjs; + } + + /** + @hide Pending Android public API approval. + */ + public static final class Binding { + public Script.FieldID mField; + public Object mValue; + public Binding(Script.FieldID field, Object value) { + mField = field; + mValue = value; + } + } + + /** + @hide Pending Android public API approval. + */ + public static final class Builder { + RenderScript mRS; + List<Closure> mClosures; + List<UnboundValue> mInputs; + private static final String TAG = "ScriptGroup2.Builder"; + + public Builder(RenderScript rs) { + mRS = rs; + mClosures = new ArrayList<Closure>(); + mInputs = new ArrayList<UnboundValue>(); + } + + public Closure addKernel(Script.KernelID k, Type returnType, Object[] args, + Map<Script.FieldID, Object> globalBindings) { + Closure c = new Closure(mRS, k, returnType, args, globalBindings); + mClosures.add(c); + return c; + } + + public Closure addInvoke(Script.InvokeID invoke, Object[] args, + Map<Script.FieldID, Object> globalBindings) { + Closure c = new Closure(mRS, invoke, args, globalBindings); + mClosures.add(c); + return c; + } + + public UnboundValue addInput() { + UnboundValue unbound = new UnboundValue(); + mInputs.add(unbound); + return unbound; + } + + public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) { + ArrayList<Object> args = new ArrayList<Object>(); + Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>(); + if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) { + return null; + } + return addKernel(k, returnType, args.toArray(), bindingMap); + } + + public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) { + ArrayList<Object> args = new ArrayList<Object>(); + Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>(); + if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) { + return null; + } + return addInvoke(invoke, args.toArray(), bindingMap); + } + + public ScriptGroup2 create(Future... outputs) { + ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs); + return ret; + } + + private boolean seperateArgsAndBindings(Object[] argsAndBindings, + ArrayList<Object> args, + Map<Script.FieldID, Object> bindingMap) { + int i; + for (i = 0; i < argsAndBindings.length; i++) { + if (argsAndBindings[i] instanceof Binding) { + break; + } + args.add(argsAndBindings[i]); + } + + for (; i < argsAndBindings.length; i++) { + if (!(argsAndBindings[i] instanceof Binding)) { + return false; + } + Binding b = (Binding)argsAndBindings[i]; + bindingMap.put(b.mField, b.mValue); + } + + return true; + } + + } +} |