Home | History | Annotate | Download | only in renderscript
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.renderscript;
     18 
     19 import android.util.SparseArray;
     20 
     21 /**
     22  * The parent class for all executable scripts. This should not be used by
     23  * applications.
     24  **/
     25 public class Script extends BaseObj {
     26     /**
     27      * Determine if Incremental Intrinsic Support is needed
     28      *
     29      */
     30     private boolean mUseIncSupp;
     31     protected void setIncSupp(boolean useInc) {
     32         mUseIncSupp = useInc;
     33     }
     34     protected boolean isIncSupp() {
     35         return mUseIncSupp;
     36     }
     37     /**
     38      * An allocation for the compat context will be created when needed
     39      * e.g. foreach(ain, aout), setVar(ain);
     40      *
     41      */
     42     long getDummyAlloc(Allocation ain) {
     43         long dInElement = 0;
     44         long dInType = 0;
     45         long dummyAlloc = 0;
     46         if (ain != null) {
     47             Type inType = ain.getType();
     48             dInElement = inType.getElement().getDummyElement(mRS);
     49             dInType = inType.getDummyType(mRS, dInElement);
     50             int xBytesSize = inType.getX() * inType.getElement().getBytesSize();
     51             dummyAlloc = mRS.nIncAllocationCreateTyped(ain.getID(mRS), dInType, xBytesSize);
     52             ain.setIncAllocID(dummyAlloc);
     53         }
     54 
     55         return dummyAlloc;
     56     }
     57     /**
     58      * KernelID is an identifier for a Script + root function pair. It is used
     59      * as an identifier for ScriptGroup creation.
     60      *
     61      * This class should not be directly created. Instead use the method in the
     62      * reflected or intrinsic code "getKernelID_funcname()".
     63      *
     64      */
     65     public static final class KernelID extends BaseObj {
     66         android.renderscript.Script.KernelID mN;
     67         Script mScript;
     68         int mSlot;
     69         int mSig;
     70         KernelID(long id, RenderScript rs, Script s, int slot, int sig) {
     71             super(id, rs);
     72             mScript = s;
     73             mSlot = slot;
     74             mSig = sig;
     75         }
     76     }
     77 
     78     private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
     79     /**
     80      * Only to be used by generated reflected classes.
     81      *
     82      *
     83      * @param slot
     84      * @param sig
     85      * @param ein
     86      * @param eout
     87      *
     88      * @return KernelID
     89      */
     90     protected KernelID createKernelID(int slot, int sig, Element ein, Element eout) {
     91         KernelID k = mKIDs.get(slot);
     92         if (k != null) {
     93             return k;
     94         }
     95 
     96         long id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig, mUseIncSupp);
     97         if (id == 0) {
     98             throw new RSDriverException("Failed to create KernelID");
     99         }
    100 
    101         k = new KernelID(id, mRS, this, slot, sig);
    102 
    103         mKIDs.put(slot, k);
    104         return k;
    105     }
    106 
    107     /**
    108      * InvokeID is an identifier for a invoke function. It is used
    109      * as an identifier for ScriptGroup creation.
    110      *
    111      * This class should not be directly created. Instead use the method in the
    112      * reflected or intrinsic code "getInvokeID_funcname()".
    113      *
    114      */
    115     public static final class InvokeID extends BaseObj {
    116         Script mScript;
    117         int mSlot;
    118         InvokeID(long id, RenderScript rs, Script s, int slot) {
    119             super(id, rs);
    120             mScript = s;
    121             mSlot = slot;
    122         }
    123     }
    124 
    125     private final SparseArray<InvokeID> mIIDs = new SparseArray<InvokeID>();
    126     /**
    127      * Only to be used by generated reflected classes.
    128      */
    129     protected InvokeID createInvokeID(int slot) {
    130         InvokeID i = mIIDs.get(slot);
    131         if (i != null) {
    132             return i;
    133         }
    134 
    135         long id = mRS.nScriptInvokeIDCreate(getID(mRS), slot);
    136         if (id == 0) {
    137             throw new RSDriverException("Failed to create KernelID");
    138         }
    139 
    140         i = new InvokeID(id, mRS, this, slot);
    141         mIIDs.put(slot, i);
    142         return i;
    143     }
    144 
    145     /**
    146      * FieldID is an identifier for a Script + exported field pair. It is used
    147      * as an identifier for ScriptGroup creation.
    148      *
    149      * This class should not be directly created. Instead use the method in the
    150      * reflected or intrinsic code "getFieldID_funcname()".
    151      *
    152      */
    153     public static final class FieldID extends BaseObj {
    154         android.renderscript.Script.FieldID mN;
    155         Script mScript;
    156         int mSlot;
    157         FieldID(long id, RenderScript rs, Script s, int slot) {
    158             super(id, rs);
    159             mScript = s;
    160             mSlot = slot;
    161         }
    162     }
    163 
    164     private final SparseArray<FieldID> mFIDs = new SparseArray();
    165     /**
    166      * Only to be used by generated reflected classes.
    167      *
    168      * @param slot
    169      * @param e
    170      *
    171      * @return FieldID
    172      */
    173     protected FieldID createFieldID(int slot, Element e) {
    174         FieldID f = mFIDs.get(slot);
    175         if (f != null) {
    176             return f;
    177         }
    178 
    179         long id = mRS.nScriptFieldIDCreate(getID(mRS), slot, mUseIncSupp);
    180         if (id == 0) {
    181             throw new RSDriverException("Failed to create FieldID");
    182         }
    183 
    184         f = new FieldID(id, mRS, this, slot);
    185         mFIDs.put(slot, f);
    186         return f;
    187     }
    188 
    189     /**
    190      * Only intended for use by generated reflected code.
    191      *
    192      * @param slot
    193      */
    194     protected void invoke(int slot) {
    195         mRS.nScriptInvoke(getID(mRS), slot, mUseIncSupp);
    196     }
    197 
    198     /**
    199      * Only intended for use by generated reflected code.
    200      *
    201      * @param slot
    202      * @param v
    203      */
    204     protected void invoke(int slot, FieldPacker v) {
    205         if (v != null) {
    206             mRS.nScriptInvokeV(getID(mRS), slot, v.getData(), mUseIncSupp);
    207         } else {
    208             mRS.nScriptInvoke(getID(mRS), slot, mUseIncSupp);
    209         }
    210     }
    211 
    212     /**
    213      * Only intended for use by generated reflected code.
    214      *
    215      * @param va
    216      * @param slot
    217      */
    218     public void bindAllocation(Allocation va, int slot) {
    219         mRS.validate();
    220         if (va != null) {
    221             mRS.nScriptBindAllocation(getID(mRS), va.getID(mRS), slot, mUseIncSupp);
    222         } else {
    223             mRS.nScriptBindAllocation(getID(mRS), 0, slot, mUseIncSupp);
    224         }
    225     }
    226 
    227     public void setTimeZone(String timeZone) {
    228         mRS.validate();
    229         try {
    230             mRS.nScriptSetTimeZone(getID(mRS), timeZone.getBytes("UTF-8"), mUseIncSupp);
    231         } catch (java.io.UnsupportedEncodingException e) {
    232             throw new RuntimeException(e);
    233         }
    234     }
    235 
    236 
    237     /**
    238      * Only intended for use by generated reflected code.
    239      *
    240      * @param slot
    241      * @param ain
    242      * @param aout
    243      * @param v
    244      */
    245     protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
    246         if (ain == null && aout == null) {
    247             throw new RSIllegalArgumentException(
    248                 "At least one of ain or aout is required to be non-null.");
    249         }
    250         long in_id = 0;
    251         long out_id = 0;
    252         if (ain != null) {
    253             in_id = ain.getID(mRS);
    254         }
    255         if (aout != null) {
    256             out_id = aout.getID(mRS);
    257         }
    258 
    259         byte[] params = null;
    260         if (v != null) {
    261             params = v.getData();
    262         }
    263 
    264         if (mUseIncSupp) {
    265             long ainInc = getDummyAlloc(ain);
    266             long aoutInc = getDummyAlloc(aout);
    267             mRS.nScriptForEach(getID(mRS), slot, ainInc, aoutInc, params, mUseIncSupp);
    268         } else {
    269             mRS.nScriptForEach(getID(mRS), slot, in_id, out_id, params, mUseIncSupp);
    270         }
    271     }
    272 
    273     /**
    274      * Only intended for use by generated reflected code.
    275      *
    276      * @param slot
    277      * @param ain
    278      * @param aout
    279      * @param v
    280      * @param sc
    281      */
    282     protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc) {
    283         if (ain == null && aout == null) {
    284             throw new RSIllegalArgumentException(
    285                 "At least one of ain or aout is required to be non-null.");
    286         }
    287 
    288         if (sc == null) {
    289             forEach(slot, ain, aout, v);
    290             return;
    291         }
    292         long in_id = 0;
    293         long out_id = 0;
    294         if (ain != null) {
    295             in_id = ain.getID(mRS);
    296         }
    297         if (aout != null) {
    298             out_id = aout.getID(mRS);
    299         }
    300 
    301         byte[] params = null;
    302         if (v != null) {
    303             params = v.getData();
    304         }
    305         if (mUseIncSupp) {
    306             long ainInc = getDummyAlloc(ain);
    307             long aoutInc = getDummyAlloc(aout);
    308             mRS.nScriptForEachClipped(getID(mRS), slot, ainInc, aoutInc, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend, mUseIncSupp);
    309         } else {
    310             mRS.nScriptForEachClipped(getID(mRS), slot, in_id, out_id, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend, mUseIncSupp);
    311         }
    312     }
    313 
    314     Script(long id, RenderScript rs) {
    315         super(id, rs);
    316         mUseIncSupp = false;
    317     }
    318 
    319     /**
    320      * Only intended for use by generated reflected code.
    321      *
    322      * @hide
    323      */
    324     protected void forEach(int slot, Allocation[] ains, Allocation aout,
    325                            FieldPacker v) {
    326         forEach(slot, ains, aout, v, null);
    327     }
    328 
    329     /**
    330      * Only intended for use by generated reflected code.
    331      *
    332      * @hide
    333      */
    334     protected void forEach(int slot, Allocation[] ains, Allocation aout,
    335                            FieldPacker v, LaunchOptions sc) {
    336         // TODO: Is this necessary if nScriptForEach calls validate as well?
    337         mRS.validate();
    338         if (ains != null) {
    339             for (Allocation ain : ains) {
    340                 mRS.validateObject(ain);
    341             }
    342         }
    343         mRS.validateObject(aout);
    344 
    345         if (ains == null && aout == null) {
    346             throw new RSIllegalArgumentException(
    347                 "At least one of ain or aout is required to be non-null.");
    348         }
    349 
    350         long[] in_ids;
    351         if (ains != null) {
    352             in_ids = new long[ains.length];
    353             for (int index = 0; index < ains.length; ++index) {
    354                 in_ids[index] = ains[index].getID(mRS);
    355             }
    356         } else {
    357             in_ids = null;
    358         }
    359 
    360         long out_id = 0;
    361         if (aout != null) {
    362             out_id = aout.getID(mRS);
    363         }
    364 
    365         byte[] params = null;
    366         if (v != null) {
    367             params = v.getData();
    368         }
    369 
    370         int[] limits = null;
    371         if (sc != null) {
    372             limits = new int[6];
    373 
    374             limits[0] = sc.xstart;
    375             limits[1] = sc.xend;
    376             limits[2] = sc.ystart;
    377             limits[3] = sc.yend;
    378             limits[4] = sc.zstart;
    379             limits[5] = sc.zend;
    380         }
    381 
    382         mRS.nScriptForEach(getID(mRS), slot, in_ids, out_id, params, limits);
    383     }
    384 
    385     /**
    386      * Only intended for use by generated reflected code.  (General reduction)
    387      *
    388      * @hide
    389      */
    390     protected void reduce(int slot, Allocation[] ains, Allocation aout, LaunchOptions sc) {
    391         mRS.validate();
    392         if (ains == null || ains.length < 1) {
    393             throw new RSIllegalArgumentException(
    394                 "At least one input is required.");
    395         }
    396         if (aout == null) {
    397             throw new RSIllegalArgumentException(
    398                 "aout is required to be non-null.");
    399         }
    400         for (Allocation ain : ains) {
    401             mRS.validateObject(ain);
    402         }
    403 
    404         long[] in_ids = new long[ains.length];
    405         for (int index = 0; index < ains.length; ++index) {
    406             in_ids[index] = ains[index].getID(mRS);
    407         }
    408         long out_id = aout.getID(mRS);
    409 
    410         int[] limits = null;
    411         if (sc != null) {
    412             limits = new int[6];
    413 
    414             limits[0] = sc.xstart;
    415             limits[1] = sc.xend;
    416             limits[2] = sc.ystart;
    417             limits[3] = sc.yend;
    418             limits[4] = sc.zstart;
    419             limits[5] = sc.zend;
    420         }
    421 
    422         mRS.nScriptReduce(getID(mRS), slot, in_ids, out_id, limits);
    423     }
    424 
    425     /**
    426      * Only intended for use by generated reflected code.
    427      *
    428      * @param index
    429      * @param v
    430      */
    431     public void setVar(int index, float v) {
    432         mRS.nScriptSetVarF(getID(mRS), index, v, mUseIncSupp);
    433     }
    434 
    435     /**
    436      * Only intended for use by generated reflected code.
    437      *
    438      * @param index
    439      * @param v
    440      */
    441     public void setVar(int index, double v) {
    442         mRS.nScriptSetVarD(getID(mRS), index, v, mUseIncSupp);
    443     }
    444 
    445     /**
    446      * Only intended for use by generated reflected code.
    447      *
    448      * @param index
    449      * @param v
    450      */
    451     public void setVar(int index, int v) {
    452         mRS.nScriptSetVarI(getID(mRS), index, v, mUseIncSupp);
    453     }
    454 
    455     /**
    456      * Only intended for use by generated reflected code.
    457      *
    458      * @param index
    459      * @param v
    460      */
    461     public void setVar(int index, long v) {
    462         mRS.nScriptSetVarJ(getID(mRS), index, v, mUseIncSupp);
    463     }
    464 
    465     /**
    466      * Only intended for use by generated reflected code.
    467      *
    468      * @param index
    469      * @param v
    470      */
    471     public void setVar(int index, boolean v) {
    472         mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0, mUseIncSupp);
    473     }
    474 
    475     /**
    476      * Only intended for use by generated reflected code.
    477      *
    478      * @param index
    479      * @param o
    480      */
    481     public void setVar(int index, BaseObj o) {
    482         if (mUseIncSupp) {
    483             long oInc = getDummyAlloc((Allocation)o);
    484             mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : oInc, mUseIncSupp);
    485         } else {
    486             mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS), mUseIncSupp);
    487         }
    488     }
    489 
    490     /**
    491      * Only intended for use by generated reflected code.
    492      *
    493      * @param index
    494      * @param v
    495      */
    496     public void setVar(int index, FieldPacker v) {
    497         mRS.nScriptSetVarV(getID(mRS), index, v.getData(), mUseIncSupp);
    498     }
    499 
    500     /**
    501      * Only intended for use by generated reflected code.
    502      *
    503      * @param index
    504      * @param v
    505      * @param e
    506      * @param dims
    507      */
    508     public void setVar(int index, FieldPacker v, Element e, int[] dims) {
    509         if (mUseIncSupp) {
    510             long dElement = e.getDummyElement(mRS);
    511             mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), dElement, dims, mUseIncSupp);
    512         } else {
    513             mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), e.getID(mRS), dims, mUseIncSupp);
    514         }
    515     }
    516 
    517     /**
    518      * Only intended for use by generated reflected code.
    519      *
    520      */
    521     public static class Builder {
    522         RenderScript mRS;
    523 
    524         Builder(RenderScript rs) {
    525             mRS = rs;
    526         }
    527     }
    528 
    529 
    530     /**
    531      * Only intended for use by generated reflected code.
    532      *
    533      */
    534     public static class FieldBase {
    535         protected Element mElement;
    536         protected Allocation mAllocation;
    537 
    538         protected void init(RenderScript rs, int dimx) {
    539             mAllocation = Allocation.createSized(rs, mElement, dimx, Allocation.USAGE_SCRIPT);
    540         }
    541 
    542         protected void init(RenderScript rs, int dimx, int usages) {
    543             mAllocation = Allocation.createSized(rs, mElement, dimx, Allocation.USAGE_SCRIPT | usages);
    544         }
    545 
    546         protected FieldBase() {
    547         }
    548 
    549         public Element getElement() {
    550             return mElement;
    551         }
    552 
    553         public Type getType() {
    554             return mAllocation.getType();
    555         }
    556 
    557         public Allocation getAllocation() {
    558             return mAllocation;
    559         }
    560 
    561         //@Override
    562         public void updateAllocation() {
    563         }
    564     }
    565 
    566 
    567     /**
    568      * Class for specifying the specifics about how a kernel will be
    569      * launched.
    570      *
    571      * This class can specify a potential range of cells on which to
    572      * run a kernel.  If no set is called for a dimension then this
    573      * class will have no impact on that dimension when the kernel
    574      * is executed.
    575      *
    576      * The forEach kernel launch will operate over the intersection of
    577      * the dimensions.
    578      *
    579      * Example:
    580      * LaunchOptions with setX(5, 15)
    581      * Allocation with dimension X=10, Y=10
    582      * The resulting forEach run would execute over:
    583      * x = 5 to 9 (inclusive) and
    584      * y = 0 to 9 (inclusive).
    585      *
    586      */
    587     public static final class LaunchOptions {
    588         private int xstart = 0;
    589         private int ystart = 0;
    590         private int xend = 0;
    591         private int yend = 0;
    592         private int zstart = 0;
    593         private int zend = 0;
    594         private int strategy;
    595 
    596         /**
    597          * Set the X range. xstartArg is the lowest coordinate of the range,
    598          * and xendArg-1 is the highest coordinate of the range.
    599          *
    600          * @param xstartArg Must be >= 0
    601          * @param xendArg Must be > xstartArg
    602          *
    603          * @return LaunchOptions
    604          */
    605         public LaunchOptions setX(int xstartArg, int xendArg) {
    606             if (xstartArg < 0 || xendArg <= xstartArg) {
    607                 throw new RSIllegalArgumentException("Invalid dimensions");
    608             }
    609             xstart = xstartArg;
    610             xend = xendArg;
    611             return this;
    612         }
    613 
    614         /**
    615          * Set the Y range. ystartArg is the lowest coordinate of the range,
    616          * and yendArg-1 is the highest coordinate of the range.
    617          *
    618          * @param ystartArg Must be >= 0
    619          * @param yendArg Must be > ystartArg
    620          *
    621          * @return LaunchOptions
    622          */
    623         public LaunchOptions setY(int ystartArg, int yendArg) {
    624             if (ystartArg < 0 || yendArg <= ystartArg) {
    625                 throw new RSIllegalArgumentException("Invalid dimensions");
    626             }
    627             ystart = ystartArg;
    628             yend = yendArg;
    629             return this;
    630         }
    631 
    632         /**
    633          * Set the Z range. zstartArg is the lowest coordinate of the range,
    634          * and zendArg-1 is the highest coordinate of the range.
    635          *
    636          * @param zstartArg Must be >= 0
    637          * @param zendArg Must be > zstartArg
    638          *
    639          * @return LaunchOptions
    640          */
    641         public LaunchOptions setZ(int zstartArg, int zendArg) {
    642             if (zstartArg < 0 || zendArg <= zstartArg) {
    643                 throw new RSIllegalArgumentException("Invalid dimensions");
    644             }
    645             zstart = zstartArg;
    646             zend = zendArg;
    647             return this;
    648         }
    649 
    650 
    651         /**
    652          * Returns the current X start
    653          *
    654          * @return int current value
    655          */
    656         public int getXStart() {
    657             return xstart;
    658         }
    659         /**
    660          * Returns the current X end
    661          *
    662          * @return int current value
    663          */
    664         public int getXEnd() {
    665             return xend;
    666         }
    667         /**
    668          * Returns the current Y start
    669          *
    670          * @return int current value
    671          */
    672         public int getYStart() {
    673             return ystart;
    674         }
    675         /**
    676          * Returns the current Y end
    677          *
    678          * @return int current value
    679          */
    680         public int getYEnd() {
    681             return yend;
    682         }
    683         /**
    684          * Returns the current Z start
    685          *
    686          * @return int current value
    687          */
    688         public int getZStart() {
    689             return zstart;
    690         }
    691         /**
    692          * Returns the current Z end
    693          *
    694          * @return int current value
    695          */
    696         public int getZEnd() {
    697             return zend;
    698         }
    699 
    700     }
    701 }
    702