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