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

Commit 21454aa2 authored by Yang Ni's avatar Yang Ni Committed by Gerrit Code Review
Browse files

Merge "New Script Group API."

parents 837261cc 281c3252
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 },