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