Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae0278e9 authored by Yang Ni's avatar Yang Ni Committed by Android Git Automerger
Browse files

am cc9efb78: am 21454aa2: Merge "New Script Group API."

* commit 'cc9efb78':
  New Script Group API.
parents 2168062b cc9efb78
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -302,6 +302,46 @@ public class RenderScript {
        rsnContextResume(mContext);
    }

    native long rsnClosureCreate(long con, long kernelID, long returnValue,
        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
        long[] depFieldIDs);
    synchronized long nClosureCreate(long kernelID, long returnValue,
        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
        long[] depFieldIDs) {
      validate();
      return rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
          sizes, depClosures, depFieldIDs);
    }

    native void rsnClosureSetArg(long con, long closureID, int index,
      long value, int size);
    synchronized void nClosureSetArg(long closureID, int index, long value,
        int size) {
      validate();
      rsnClosureSetArg(mContext, closureID, index, value, size);
    }

    native void rsnClosureSetGlobal(long con, long closureID, long fieldID,
        long value, int size);
    // Does this have to be synchronized?
    synchronized void nClosureSetGlobal(long closureID, long fieldID,
        long value, int size) {
      validate(); // TODO: is this necessary?
      rsnClosureSetGlobal(mContext, closureID, fieldID, value, size);
    }

    native long rsnScriptGroup2Create(long con, long[] closures);
    synchronized long nScriptGroup2Create(long[] closures) {
      validate();
      return rsnScriptGroup2Create(mContext, closures);
    }

    native void rsnScriptGroup2Execute(long con, long groupID);
    synchronized void nScriptGroup2Execute(long groupID) {
      validate();
      rsnScriptGroup2Execute(mContext, groupID);
    }

    native void rsnAssignName(long con, long obj, byte[] name);
    synchronized void nAssignName(long obj, byte[] name) {
        validate();
+319 −0
Original line number Diff line number Diff line
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;

/**
   @hide Pending Android public API approval.
 */
/**

******************************
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 Allocation mReturnValue;
    private Map<Script.FieldID, Object> mBindings;

    private Future mReturnFuture;
    private Map<Script.FieldID, Future> mGlobalFuture;

    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);

      mReturnValue = Allocation.createTyped(rs, returnType);
      mBindings = new HashMap<Script.FieldID, Object>();
      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);
    }

    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;
      } 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) {
        f = new Future(this, field, mBindings.get(field));
        mGlobalFuture.put(field, f);
      }

      return f;
    }

    void setArg(int index, Object obj) {
      ValueAndSize vs = new ValueAndSize(mRS, obj);
      mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
    }

    void setGlobal(Script.FieldID fieldID, Object 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(closureIDs);
    setID(id);
  }

  // TODO: If this was reflected method, we could enforce the number of
  // arguments.
  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 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 UnboundValue addInput() {
      UnboundValue unbound = new UnboundValue();
      mInputs.add(unbound);
      return unbound;
    }

    public ScriptGroup2 create(Future... outputs) {
      // TODO: Save all script groups that have been created and return one that was
      // saved and matches the outputs.
      ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs);
      return ret;
    }

  }
}
+87 −0
Original line number Diff line number Diff line
@@ -193,6 +193,88 @@ nContextFinish(JNIEnv *_env, jobject _this, jlong con)
    rsContextFinish((RsContext)con);
}

static jlong
nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID,
               jlong returnValue, jlongArray fieldIDArray,
               jlongArray valueArray, jintArray sizeArray,
               jlongArray depClosureArray, jlongArray depFieldIDArray) {
  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
  RsScriptFieldID* fieldIDs =
      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
  for (int i = 0; i< fieldIDs_length; i++) {
    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
  }

  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
  jsize values_length = _env->GetArrayLength(valueArray);
  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
  for (int i = 0; i < values_length; i++) {
    values[i] = (uintptr_t)jValues[i];
  }

  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
  jsize sizes_length = _env->GetArrayLength(sizeArray);

  jlong* jDepClosures =
      _env->GetLongArrayElements(depClosureArray, nullptr);
  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
  RsClosure* depClosures =
      (RsClosure*)alloca(sizeof(RsClosure) * depClosures_length);
  for (int i = 0; i < depClosures_length; i++) {
    depClosures[i] = (RsClosure)jDepClosures[i];
  }

  jlong* jDepFieldIDs =
      _env->GetLongArrayElements(depFieldIDArray, nullptr);
  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
  RsScriptFieldID* depFieldIDs =
      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * depFieldIDs_length);
  for (int i = 0; i < depClosures_length; i++) {
    depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
  }

  return (jlong)(uintptr_t)rsClosureCreate(
      (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
      (size_t*)sizes, (size_t)sizes_length,
      depClosures, (size_t)depClosures_length,
      depFieldIDs, (size_t)depFieldIDs_length);
}

static void
nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
               jint index, jlong value, jint size) {
  rsClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index,
                  (uintptr_t)value, (size_t)size);
}

static void
nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
                  jlong fieldID, jlong value, jint size) {
  rsClosureSetGlobal((RsContext)con, (RsClosure)closureID,
                     (RsScriptFieldID)fieldID, (uintptr_t)value, (size_t)size);
}

static long
nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con,
                    jlongArray closureArray) {
  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
  jsize numClosures = _env->GetArrayLength(closureArray);
  RsClosure* closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
  for (int i = 0; i < numClosures; i++) {
    closures[i] = (RsClosure)jClosures[i];
  }

  return (jlong)(uintptr_t)rsScriptGroup2Create((RsContext)con, closures,
                                                numClosures);
}

static void
nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) {
  rsScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID);
}

static void
nAssignName(JNIEnv *_env, jobject _this, jlong con, jlong obj, jbyteArray str)
{
@@ -1841,6 +1923,9 @@ static JNINativeMethod methods[] = {
{"rsnContextPause",                  "(J)V",                                  (void*)nContextPause },
{"rsnContextResume",                 "(J)V",                                  (void*)nContextResume },
{"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
{"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
{"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
{"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
{"rsnAssignName",                    "(JJ[B)V",                               (void*)nAssignName },
{"rsnGetName",                       "(JJ)Ljava/lang/String;",                (void*)nGetName },
{"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
@@ -1915,9 +2000,11 @@ static JNINativeMethod methods[] = {
{"rsnScriptKernelIDCreate",          "(JJII)J",                               (void*)nScriptKernelIDCreate },
{"rsnScriptFieldIDCreate",           "(JJI)J",                                (void*)nScriptFieldIDCreate },
{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
{"rsnScriptGroup2Create",            "(J[J)J",                                (void*)nScriptGroup2Create },
{"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
{"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
{"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
{"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },

{"rsnProgramStoreCreate",            "(JZZZZZZIII)J",                         (void*)nProgramStoreCreate },