Home | History | Annotate | Download | only in renderscript
      1 /*
      2  * Copyright (C) 2013 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 /**
     20  * <p>An Element represents one item within an {@link
     21  * android.renderscript.Allocation}.  An Element is roughly equivalent to a C
     22  * type in a RenderScript kernel. Elements may be basic or complex. Some basic
     23  * elements are</p> <ul> <li>A single float value (equivalent to a float in a
     24  * kernel)</li> <li>A four-element float vector (equivalent to a float4 in a
     25  * kernel)</li> <li>An unsigned 32-bit integer (equivalent to an unsigned int in
     26  * a kernel)</li> <li>A single signed 8-bit integer (equivalent to a char in a
     27  * kernel)</li> </ul> <p>A complex element is roughly equivalent to a C struct
     28  * and contains a number of basic or complex Elements. From Java code, a complex
     29  * element contains a list of sub-elements and names that represents a
     30  * particular data structure. Structs used in RS scripts are available to Java
     31  * code by using the {@code ScriptField_structname} class that is reflected from
     32  * a particular script.</p>
     33  *
     34  * <p>Basic Elements are comprised of a {@link
     35  * android.renderscript.Element.DataType} and a {@link
     36  * android.renderscript.Element.DataKind}. The DataType encodes C type
     37  * information of an Element, while the DataKind encodes how that Element should
     38  * be interpreted by a {@link android.renderscript.Sampler}. Note that {@link
     39  * android.renderscript.Allocation} objects with DataKind {@link
     40  * android.renderscript.Element.DataKind#USER} cannot be used as input for a
     41  * {@link android.renderscript.Sampler}. In general, {@link
     42  * android.renderscript.Allocation} objects that are intended for use with a
     43  * {@link android.renderscript.Sampler} should use bitmap-derived Elements such
     44  * as {@link android.renderscript.Element#RGBA_8888} or {@link
     45  * android.renderscript#Element.A_8}.</p>
     46  *
     47  * <div class="special reference">
     48  * <h3>Developer Guides</h3>
     49  * <p>For more information about creating an application that uses RenderScript, read the
     50  * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
     51  * </div>
     52  **/
     53 public class Element extends BaseObj {
     54     int mSize;
     55     Element[] mElements;
     56     String[] mElementNames;
     57     int[] mArraySizes;
     58     int[] mOffsetInBytes;
     59 
     60     int[] mVisibleElementMap;
     61 
     62     DataType mType;
     63     DataKind mKind;
     64     boolean mNormalized;
     65     int mVectorSize;
     66 
     67     private void updateVisibleSubElements() {
     68         if (mElements == null) {
     69             return;
     70         }
     71 
     72         int noPaddingFieldCount = 0;
     73         int fieldCount = mElementNames.length;
     74         // Find out how many elements are not padding
     75         for (int ct = 0; ct < fieldCount; ct ++) {
     76             if (mElementNames[ct].charAt(0) != '#') {
     77                 noPaddingFieldCount ++;
     78             }
     79         }
     80         mVisibleElementMap = new int[noPaddingFieldCount];
     81 
     82         // Make a map that points us at non-padding elements
     83         for (int ct = 0, ctNoPadding = 0; ct < fieldCount; ct ++) {
     84             if (mElementNames[ct].charAt(0) != '#') {
     85                 mVisibleElementMap[ctNoPadding ++] = ct;
     86             }
     87         }
     88     }
     89 
     90     /**
     91     * @return element size in bytes
     92     */
     93     public int getBytesSize() {return mSize;}
     94 
     95     /**
     96     * Returns the number of vector components. 2 for float2, 4 for
     97     * float4, etc.
     98     * @return element vector size
     99     */
    100     public int getVectorSize() {return mVectorSize;}
    101 
    102 
    103     /**
    104      * DataType represents the basic type information for a basic element.  The
    105      * naming convention follows.  For numeric types it is FLOAT,
    106      * SIGNED, or UNSIGNED followed by the _BITS where BITS is the
    107      * size of the data.  BOOLEAN is a true / false (1,0)
    108      * represented in an 8 bit container.  The UNSIGNED variants
    109      * with multiple bit definitions are for packed graphical data
    110      * formats and represent vectors with per vector member sizes
    111      * which are treated as a single unit for packing and alignment
    112      * purposes.
    113      *
    114      * MATRIX the three matrix types contain FLOAT_32 elements and are treated
    115      * as 32 bits for alignment purposes.
    116      *
    117      * RS_* objects:  opaque handles with implementation dependent
    118      * sizes.
    119      */
    120     public enum DataType {
    121         NONE (0, 0),
    122         FLOAT_16 (1, 2),
    123         FLOAT_32 (2, 4),
    124         FLOAT_64 (3, 8),
    125         SIGNED_8 (4, 1),
    126         SIGNED_16 (5, 2),
    127         SIGNED_32 (6, 4),
    128         SIGNED_64 (7, 8),
    129         UNSIGNED_8 (8, 1),
    130         UNSIGNED_16 (9, 2),
    131         UNSIGNED_32 (10, 4),
    132         UNSIGNED_64 (11, 8),
    133 
    134         BOOLEAN(12, 1),
    135 
    136         UNSIGNED_5_6_5 (13, 2),
    137         UNSIGNED_5_5_5_1 (14, 2),
    138         UNSIGNED_4_4_4_4 (15, 2),
    139 
    140         MATRIX_4X4 (16, 64),
    141         MATRIX_3X3 (17, 36),
    142         MATRIX_2X2 (18, 16),
    143 
    144         RS_ELEMENT (1000),
    145         RS_TYPE (1001),
    146         RS_ALLOCATION (1002),
    147         RS_SAMPLER (1003),
    148         RS_SCRIPT (1004),
    149         RS_MESH (1005),
    150         RS_PROGRAM_FRAGMENT (1006),
    151         RS_PROGRAM_VERTEX (1007),
    152         RS_PROGRAM_RASTER (1008),
    153         RS_PROGRAM_STORE (1009),
    154         RS_FONT (1010);
    155 
    156         int mID;
    157         int mSize;
    158         DataType(int id, int size) {
    159             mID = id;
    160             mSize = size;
    161         }
    162 
    163         DataType(int id) {
    164             mID = id;
    165             mSize = 4;
    166             if (RenderScript.sPointerSize == 8) {
    167                 mSize = 32;
    168             }
    169         }
    170     }
    171 
    172     /**
    173      * The special interpretation of the data if required.  This is primarly
    174      * useful for graphical data.  USER indicates no special interpretation is
    175      * expected.  PIXEL is used in conjunction with the standard data types for
    176      * representing texture formats.
    177      */
    178     public enum DataKind {
    179         USER (0),
    180 
    181         PIXEL_L (7),
    182         PIXEL_A (8),
    183         PIXEL_LA (9),
    184         PIXEL_RGB (10),
    185         PIXEL_RGBA (11),
    186         PIXEL_DEPTH (12),
    187         PIXEL_YUV(13);
    188 
    189         int mID;
    190         DataKind(int id) {
    191             mID = id;
    192         }
    193     }
    194 
    195     /**
    196      * Return if a element is too complex for use as a data source for a Mesh or
    197      * a Program.
    198      *
    199      * @return boolean
    200      */
    201     public boolean isComplex() {
    202         if (mElements == null) {
    203             return false;
    204         }
    205         for (int ct=0; ct < mElements.length; ct++) {
    206             if (mElements[ct].mElements != null) {
    207                 return true;
    208             }
    209         }
    210         return false;
    211     }
    212 
    213     /**
    214     * Elements could be simple, such as an int or a float, or a
    215     * structure with multiple sub elements, such as a collection of
    216     * floats, float2, float4. This function returns zero for simple
    217     * elements or the number of sub-elements otherwise.
    218     * @return number of sub-elements in this element
    219     */
    220     public int getSubElementCount() {
    221         if (mVisibleElementMap == null) {
    222             return 0;
    223         }
    224         return mVisibleElementMap.length;
    225     }
    226 
    227     /**
    228     * For complex elements, this function will return the
    229     * sub-element at index
    230     * @param index index of the sub-element to return
    231     * @return sub-element in this element at given index
    232     */
    233     public Element getSubElement(int index) {
    234         if (mVisibleElementMap == null) {
    235             throw new RSIllegalArgumentException("Element contains no sub-elements");
    236         }
    237         if (index < 0 || index >= mVisibleElementMap.length) {
    238             throw new RSIllegalArgumentException("Illegal sub-element index");
    239         }
    240         return mElements[mVisibleElementMap[index]];
    241     }
    242 
    243     /**
    244     * For complex elements, this function will return the
    245     * sub-element name at index
    246     * @param index index of the sub-element
    247     * @return sub-element in this element at given index
    248     */
    249     public String getSubElementName(int index) {
    250         if (mVisibleElementMap == null) {
    251             throw new RSIllegalArgumentException("Element contains no sub-elements");
    252         }
    253         if (index < 0 || index >= mVisibleElementMap.length) {
    254             throw new RSIllegalArgumentException("Illegal sub-element index");
    255         }
    256         return mElementNames[mVisibleElementMap[index]];
    257     }
    258 
    259     /**
    260     * For complex elements, some sub-elements could be statically
    261     * sized arrays. This function will return the array size for
    262     * sub-element at index
    263     * @param index index of the sub-element
    264     * @return array size of sub-element in this element at given index
    265     */
    266     public int getSubElementArraySize(int index) {
    267         if (mVisibleElementMap == null) {
    268             throw new RSIllegalArgumentException("Element contains no sub-elements");
    269         }
    270         if (index < 0 || index >= mVisibleElementMap.length) {
    271             throw new RSIllegalArgumentException("Illegal sub-element index");
    272         }
    273         return mArraySizes[mVisibleElementMap[index]];
    274     }
    275 
    276     /**
    277     * This function specifies the location of a sub-element within
    278     * the element
    279     * @param index index of the sub-element
    280     * @return offset in bytes of sub-element in this element at given index
    281     */
    282     public int getSubElementOffsetBytes(int index) {
    283         if (mVisibleElementMap == null) {
    284             throw new RSIllegalArgumentException("Element contains no sub-elements");
    285         }
    286         if (index < 0 || index >= mVisibleElementMap.length) {
    287             throw new RSIllegalArgumentException("Illegal sub-element index");
    288         }
    289         return mOffsetInBytes[mVisibleElementMap[index]];
    290     }
    291 
    292     /**
    293     * @return element data type
    294     */
    295     public DataType getDataType() {
    296         return mType;
    297     }
    298 
    299     /**
    300     * @return element data kind
    301     */
    302     public DataKind getDataKind() {
    303         return mKind;
    304     }
    305 
    306     /**
    307      * Utility function for returning an Element containing a single Boolean.
    308      *
    309      * @param rs Context to which the element will belong.
    310      *
    311      * @return Element
    312      */
    313     public static Element BOOLEAN(RenderScript rs) {
    314         if(rs.mElement_BOOLEAN == null) {
    315             rs.mElement_BOOLEAN = createUser(rs, DataType.BOOLEAN);
    316         }
    317         return rs.mElement_BOOLEAN;
    318     }
    319 
    320     /**
    321      * Utility function for returning an Element containing a single UNSIGNED_8.
    322      *
    323      * @param rs Context to which the element will belong.
    324      *
    325      * @return Element
    326      */
    327     public static Element U8(RenderScript rs) {
    328         if(rs.mElement_U8 == null) {
    329             rs.mElement_U8 = createUser(rs, DataType.UNSIGNED_8);
    330         }
    331         return rs.mElement_U8;
    332     }
    333 
    334     /**
    335      * Utility function for returning an Element containing a single SIGNED_8.
    336      *
    337      * @param rs Context to which the element will belong.
    338      *
    339      * @return Element
    340      */
    341     public static Element I8(RenderScript rs) {
    342         if(rs.mElement_I8 == null) {
    343             rs.mElement_I8 = createUser(rs, DataType.SIGNED_8);
    344         }
    345         return rs.mElement_I8;
    346     }
    347 
    348     public static Element U16(RenderScript rs) {
    349         if(rs.mElement_U16 == null) {
    350             rs.mElement_U16 = createUser(rs, DataType.UNSIGNED_16);
    351         }
    352         return rs.mElement_U16;
    353     }
    354 
    355     public static Element I16(RenderScript rs) {
    356         if(rs.mElement_I16 == null) {
    357             rs.mElement_I16 = createUser(rs, DataType.SIGNED_16);
    358         }
    359         return rs.mElement_I16;
    360     }
    361 
    362     public static Element U32(RenderScript rs) {
    363         if(rs.mElement_U32 == null) {
    364             rs.mElement_U32 = createUser(rs, DataType.UNSIGNED_32);
    365         }
    366         return rs.mElement_U32;
    367     }
    368 
    369     public static Element I32(RenderScript rs) {
    370         if(rs.mElement_I32 == null) {
    371             rs.mElement_I32 = createUser(rs, DataType.SIGNED_32);
    372         }
    373         return rs.mElement_I32;
    374     }
    375 
    376     public static Element U64(RenderScript rs) {
    377         if(rs.mElement_U64 == null) {
    378             rs.mElement_U64 = createUser(rs, DataType.UNSIGNED_64);
    379         }
    380         return rs.mElement_U64;
    381     }
    382 
    383     public static Element I64(RenderScript rs) {
    384         if(rs.mElement_I64 == null) {
    385             rs.mElement_I64 = createUser(rs, DataType.SIGNED_64);
    386         }
    387         return rs.mElement_I64;
    388     }
    389 
    390     public static Element F16(RenderScript rs) {
    391         if(rs.mElement_F16 == null) {
    392             rs.mElement_F16 = createUser(rs, DataType.FLOAT_16);
    393         }
    394         return rs.mElement_F16;
    395     }
    396 
    397     public static Element F32(RenderScript rs) {
    398         if(rs.mElement_F32 == null) {
    399             rs.mElement_F32 = createUser(rs, DataType.FLOAT_32);
    400         }
    401         return rs.mElement_F32;
    402     }
    403 
    404     public static Element F64(RenderScript rs) {
    405         if(rs.mElement_F64 == null) {
    406             rs.mElement_F64 = createUser(rs, DataType.FLOAT_64);
    407         }
    408         return rs.mElement_F64;
    409     }
    410 
    411     public static Element ELEMENT(RenderScript rs) {
    412         if(rs.mElement_ELEMENT == null) {
    413             rs.mElement_ELEMENT = createUser(rs, DataType.RS_ELEMENT);
    414         }
    415         return rs.mElement_ELEMENT;
    416     }
    417 
    418     public static Element TYPE(RenderScript rs) {
    419         if(rs.mElement_TYPE == null) {
    420             rs.mElement_TYPE = createUser(rs, DataType.RS_TYPE);
    421         }
    422         return rs.mElement_TYPE;
    423     }
    424 
    425     public static Element ALLOCATION(RenderScript rs) {
    426         if(rs.mElement_ALLOCATION == null) {
    427             rs.mElement_ALLOCATION = createUser(rs, DataType.RS_ALLOCATION);
    428         }
    429         return rs.mElement_ALLOCATION;
    430     }
    431 
    432     public static Element SAMPLER(RenderScript rs) {
    433         if(rs.mElement_SAMPLER == null) {
    434             rs.mElement_SAMPLER = createUser(rs, DataType.RS_SAMPLER);
    435         }
    436         return rs.mElement_SAMPLER;
    437     }
    438 
    439     public static Element SCRIPT(RenderScript rs) {
    440         if(rs.mElement_SCRIPT == null) {
    441             rs.mElement_SCRIPT = createUser(rs, DataType.RS_SCRIPT);
    442         }
    443         return rs.mElement_SCRIPT;
    444     }
    445 
    446     public static Element MESH(RenderScript rs) {
    447         if(rs.mElement_MESH == null) {
    448             rs.mElement_MESH = createUser(rs, DataType.RS_MESH);
    449         }
    450         return rs.mElement_MESH;
    451     }
    452 
    453     public static Element PROGRAM_FRAGMENT(RenderScript rs) {
    454         if(rs.mElement_PROGRAM_FRAGMENT == null) {
    455             rs.mElement_PROGRAM_FRAGMENT = createUser(rs, DataType.RS_PROGRAM_FRAGMENT);
    456         }
    457         return rs.mElement_PROGRAM_FRAGMENT;
    458     }
    459 
    460     public static Element PROGRAM_VERTEX(RenderScript rs) {
    461         if(rs.mElement_PROGRAM_VERTEX == null) {
    462             rs.mElement_PROGRAM_VERTEX = createUser(rs, DataType.RS_PROGRAM_VERTEX);
    463         }
    464         return rs.mElement_PROGRAM_VERTEX;
    465     }
    466 
    467     public static Element PROGRAM_RASTER(RenderScript rs) {
    468         if(rs.mElement_PROGRAM_RASTER == null) {
    469             rs.mElement_PROGRAM_RASTER = createUser(rs, DataType.RS_PROGRAM_RASTER);
    470         }
    471         return rs.mElement_PROGRAM_RASTER;
    472     }
    473 
    474     public static Element PROGRAM_STORE(RenderScript rs) {
    475         if(rs.mElement_PROGRAM_STORE == null) {
    476             rs.mElement_PROGRAM_STORE = createUser(rs, DataType.RS_PROGRAM_STORE);
    477         }
    478         return rs.mElement_PROGRAM_STORE;
    479     }
    480 
    481     public static Element FONT(RenderScript rs) {
    482         if(rs.mElement_FONT == null) {
    483             rs.mElement_FONT = createUser(rs, DataType.RS_FONT);
    484         }
    485         return rs.mElement_FONT;
    486     }
    487 
    488 
    489     public static Element A_8(RenderScript rs) {
    490         if(rs.mElement_A_8 == null) {
    491             rs.mElement_A_8 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_A);
    492         }
    493         return rs.mElement_A_8;
    494     }
    495 
    496     public static Element RGB_565(RenderScript rs) {
    497         if(rs.mElement_RGB_565 == null) {
    498             rs.mElement_RGB_565 = createPixel(rs, DataType.UNSIGNED_5_6_5, DataKind.PIXEL_RGB);
    499         }
    500         return rs.mElement_RGB_565;
    501     }
    502 
    503     public static Element RGB_888(RenderScript rs) {
    504         if(rs.mElement_RGB_888 == null) {
    505             rs.mElement_RGB_888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGB);
    506         }
    507         return rs.mElement_RGB_888;
    508     }
    509 
    510     public static Element RGBA_5551(RenderScript rs) {
    511         if(rs.mElement_RGBA_5551 == null) {
    512             rs.mElement_RGBA_5551 = createPixel(rs, DataType.UNSIGNED_5_5_5_1, DataKind.PIXEL_RGBA);
    513         }
    514         return rs.mElement_RGBA_5551;
    515     }
    516 
    517     public static Element RGBA_4444(RenderScript rs) {
    518         if(rs.mElement_RGBA_4444 == null) {
    519             rs.mElement_RGBA_4444 = createPixel(rs, DataType.UNSIGNED_4_4_4_4, DataKind.PIXEL_RGBA);
    520         }
    521         return rs.mElement_RGBA_4444;
    522     }
    523 
    524     public static Element RGBA_8888(RenderScript rs) {
    525         if(rs.mElement_RGBA_8888 == null) {
    526             rs.mElement_RGBA_8888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGBA);
    527         }
    528         return rs.mElement_RGBA_8888;
    529     }
    530 
    531     public static Element F16_2(RenderScript rs) {
    532         if(rs.mElement_HALF_2 == null) {
    533             rs.mElement_HALF_2 = createVector(rs, DataType.FLOAT_16, 2);
    534         }
    535         return rs.mElement_HALF_2;
    536     }
    537 
    538     public static Element F16_3(RenderScript rs) {
    539         if(rs.mElement_HALF_3 == null) {
    540             rs.mElement_HALF_3 = createVector(rs, DataType.FLOAT_16, 3);
    541         }
    542         return rs.mElement_HALF_3;
    543     }
    544 
    545     public static Element F16_4(RenderScript rs) {
    546         if(rs.mElement_HALF_4 == null) {
    547             rs.mElement_HALF_4 = createVector(rs, DataType.FLOAT_16, 4);
    548         }
    549         return rs.mElement_HALF_4;
    550     }
    551 
    552     public static Element F32_2(RenderScript rs) {
    553         if(rs.mElement_FLOAT_2 == null) {
    554             rs.mElement_FLOAT_2 = createVector(rs, DataType.FLOAT_32, 2);
    555         }
    556         return rs.mElement_FLOAT_2;
    557     }
    558 
    559     public static Element F32_3(RenderScript rs) {
    560         if(rs.mElement_FLOAT_3 == null) {
    561             rs.mElement_FLOAT_3 = createVector(rs, DataType.FLOAT_32, 3);
    562         }
    563         return rs.mElement_FLOAT_3;
    564     }
    565 
    566     public static Element F32_4(RenderScript rs) {
    567         if(rs.mElement_FLOAT_4 == null) {
    568             rs.mElement_FLOAT_4 = createVector(rs, DataType.FLOAT_32, 4);
    569         }
    570         return rs.mElement_FLOAT_4;
    571     }
    572 
    573     public static Element F64_2(RenderScript rs) {
    574         if(rs.mElement_DOUBLE_2 == null) {
    575             rs.mElement_DOUBLE_2 = createVector(rs, DataType.FLOAT_64, 2);
    576         }
    577         return rs.mElement_DOUBLE_2;
    578     }
    579 
    580     public static Element F64_3(RenderScript rs) {
    581         if(rs.mElement_DOUBLE_3 == null) {
    582             rs.mElement_DOUBLE_3 = createVector(rs, DataType.FLOAT_64, 3);
    583         }
    584         return rs.mElement_DOUBLE_3;
    585     }
    586 
    587     public static Element F64_4(RenderScript rs) {
    588         if(rs.mElement_DOUBLE_4 == null) {
    589             rs.mElement_DOUBLE_4 = createVector(rs, DataType.FLOAT_64, 4);
    590         }
    591         return rs.mElement_DOUBLE_4;
    592     }
    593 
    594     public static Element U8_2(RenderScript rs) {
    595         if(rs.mElement_UCHAR_2 == null) {
    596             rs.mElement_UCHAR_2 = createVector(rs, DataType.UNSIGNED_8, 2);
    597         }
    598         return rs.mElement_UCHAR_2;
    599     }
    600 
    601     public static Element U8_3(RenderScript rs) {
    602         if(rs.mElement_UCHAR_3 == null) {
    603             rs.mElement_UCHAR_3 = createVector(rs, DataType.UNSIGNED_8, 3);
    604         }
    605         return rs.mElement_UCHAR_3;
    606     }
    607 
    608     public static Element U8_4(RenderScript rs) {
    609         if(rs.mElement_UCHAR_4 == null) {
    610             rs.mElement_UCHAR_4 = createVector(rs, DataType.UNSIGNED_8, 4);
    611         }
    612         return rs.mElement_UCHAR_4;
    613     }
    614 
    615     public static Element I8_2(RenderScript rs) {
    616         if(rs.mElement_CHAR_2 == null) {
    617             rs.mElement_CHAR_2 = createVector(rs, DataType.SIGNED_8, 2);
    618         }
    619         return rs.mElement_CHAR_2;
    620     }
    621 
    622     public static Element I8_3(RenderScript rs) {
    623         if(rs.mElement_CHAR_3 == null) {
    624             rs.mElement_CHAR_3 = createVector(rs, DataType.SIGNED_8, 3);
    625         }
    626         return rs.mElement_CHAR_3;
    627     }
    628 
    629     public static Element I8_4(RenderScript rs) {
    630         if(rs.mElement_CHAR_4 == null) {
    631             rs.mElement_CHAR_4 = createVector(rs, DataType.SIGNED_8, 4);
    632         }
    633         return rs.mElement_CHAR_4;
    634     }
    635 
    636     public static Element U16_2(RenderScript rs) {
    637         if(rs.mElement_USHORT_2 == null) {
    638             rs.mElement_USHORT_2 = createVector(rs, DataType.UNSIGNED_16, 2);
    639         }
    640         return rs.mElement_USHORT_2;
    641     }
    642 
    643     public static Element U16_3(RenderScript rs) {
    644         if(rs.mElement_USHORT_3 == null) {
    645             rs.mElement_USHORT_3 = createVector(rs, DataType.UNSIGNED_16, 3);
    646         }
    647         return rs.mElement_USHORT_3;
    648     }
    649 
    650     public static Element U16_4(RenderScript rs) {
    651         if(rs.mElement_USHORT_4 == null) {
    652             rs.mElement_USHORT_4 = createVector(rs, DataType.UNSIGNED_16, 4);
    653         }
    654         return rs.mElement_USHORT_4;
    655     }
    656 
    657     public static Element I16_2(RenderScript rs) {
    658         if(rs.mElement_SHORT_2 == null) {
    659             rs.mElement_SHORT_2 = createVector(rs, DataType.SIGNED_16, 2);
    660         }
    661         return rs.mElement_SHORT_2;
    662     }
    663 
    664     public static Element I16_3(RenderScript rs) {
    665         if(rs.mElement_SHORT_3 == null) {
    666             rs.mElement_SHORT_3 = createVector(rs, DataType.SIGNED_16, 3);
    667         }
    668         return rs.mElement_SHORT_3;
    669     }
    670 
    671     public static Element I16_4(RenderScript rs) {
    672         if(rs.mElement_SHORT_4 == null) {
    673             rs.mElement_SHORT_4 = createVector(rs, DataType.SIGNED_16, 4);
    674         }
    675         return rs.mElement_SHORT_4;
    676     }
    677 
    678     public static Element U32_2(RenderScript rs) {
    679         if(rs.mElement_UINT_2 == null) {
    680             rs.mElement_UINT_2 = createVector(rs, DataType.UNSIGNED_32, 2);
    681         }
    682         return rs.mElement_UINT_2;
    683     }
    684 
    685     public static Element U32_3(RenderScript rs) {
    686         if(rs.mElement_UINT_3 == null) {
    687             rs.mElement_UINT_3 = createVector(rs, DataType.UNSIGNED_32, 3);
    688         }
    689         return rs.mElement_UINT_3;
    690     }
    691 
    692     public static Element U32_4(RenderScript rs) {
    693         if(rs.mElement_UINT_4 == null) {
    694             rs.mElement_UINT_4 = createVector(rs, DataType.UNSIGNED_32, 4);
    695         }
    696         return rs.mElement_UINT_4;
    697     }
    698 
    699     public static Element I32_2(RenderScript rs) {
    700         if(rs.mElement_INT_2 == null) {
    701             rs.mElement_INT_2 = createVector(rs, DataType.SIGNED_32, 2);
    702         }
    703         return rs.mElement_INT_2;
    704     }
    705 
    706     public static Element I32_3(RenderScript rs) {
    707         if(rs.mElement_INT_3 == null) {
    708             rs.mElement_INT_3 = createVector(rs, DataType.SIGNED_32, 3);
    709         }
    710         return rs.mElement_INT_3;
    711     }
    712 
    713     public static Element I32_4(RenderScript rs) {
    714         if(rs.mElement_INT_4 == null) {
    715             rs.mElement_INT_4 = createVector(rs, DataType.SIGNED_32, 4);
    716         }
    717         return rs.mElement_INT_4;
    718     }
    719 
    720     public static Element U64_2(RenderScript rs) {
    721         if(rs.mElement_ULONG_2 == null) {
    722             rs.mElement_ULONG_2 = createVector(rs, DataType.UNSIGNED_64, 2);
    723         }
    724         return rs.mElement_ULONG_2;
    725     }
    726 
    727     public static Element U64_3(RenderScript rs) {
    728         if(rs.mElement_ULONG_3 == null) {
    729             rs.mElement_ULONG_3 = createVector(rs, DataType.UNSIGNED_64, 3);
    730         }
    731         return rs.mElement_ULONG_3;
    732     }
    733 
    734     public static Element U64_4(RenderScript rs) {
    735         if(rs.mElement_ULONG_4 == null) {
    736             rs.mElement_ULONG_4 = createVector(rs, DataType.UNSIGNED_64, 4);
    737         }
    738         return rs.mElement_ULONG_4;
    739     }
    740 
    741     public static Element I64_2(RenderScript rs) {
    742         if(rs.mElement_LONG_2 == null) {
    743             rs.mElement_LONG_2 = createVector(rs, DataType.SIGNED_64, 2);
    744         }
    745         return rs.mElement_LONG_2;
    746     }
    747 
    748     public static Element I64_3(RenderScript rs) {
    749         if(rs.mElement_LONG_3 == null) {
    750             rs.mElement_LONG_3 = createVector(rs, DataType.SIGNED_64, 3);
    751         }
    752         return rs.mElement_LONG_3;
    753     }
    754 
    755     public static Element I64_4(RenderScript rs) {
    756         if(rs.mElement_LONG_4 == null) {
    757             rs.mElement_LONG_4 = createVector(rs, DataType.SIGNED_64, 4);
    758         }
    759         return rs.mElement_LONG_4;
    760     }
    761 
    762     public static Element YUV(RenderScript rs) {
    763         if (rs.mElement_YUV == null) {
    764             rs.mElement_YUV = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_YUV);
    765         }
    766         return rs.mElement_YUV;
    767     }
    768 
    769     public static Element MATRIX_4X4(RenderScript rs) {
    770         if(rs.mElement_MATRIX_4X4 == null) {
    771             rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
    772         }
    773         return rs.mElement_MATRIX_4X4;
    774     }
    775 
    776     /** @deprecated use MATRIX_4X4
    777     */
    778     public static Element MATRIX4X4(RenderScript rs) {
    779         return MATRIX_4X4(rs);
    780     }
    781 
    782     public static Element MATRIX_3X3(RenderScript rs) {
    783         if(rs.mElement_MATRIX_3X3 == null) {
    784             rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3);
    785         }
    786         return rs.mElement_MATRIX_3X3;
    787     }
    788 
    789     public static Element MATRIX_2X2(RenderScript rs) {
    790         if(rs.mElement_MATRIX_2X2 == null) {
    791             rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2);
    792         }
    793         return rs.mElement_MATRIX_2X2;
    794     }
    795 
    796     Element(long id, RenderScript rs, Element[] e, String[] n, int[] as) {
    797         super(id, rs);
    798         mSize = 0;
    799         mVectorSize = 1;
    800         mElements = e;
    801         mElementNames = n;
    802         mArraySizes = as;
    803         mType = DataType.NONE;
    804         mKind = DataKind.USER;
    805         mOffsetInBytes = new int[mElements.length];
    806         for (int ct = 0; ct < mElements.length; ct++ ) {
    807             mOffsetInBytes[ct] = mSize;
    808             mSize += mElements[ct].mSize * mArraySizes[ct];
    809         }
    810         updateVisibleSubElements();
    811     }
    812 
    813     Element(long id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
    814         super(id, rs);
    815         if ((dt != DataType.UNSIGNED_5_6_5) &&
    816             (dt != DataType.UNSIGNED_4_4_4_4) &&
    817             (dt != DataType.UNSIGNED_5_5_5_1)) {
    818             if (size == 3) {
    819                 mSize = dt.mSize * 4;
    820             } else {
    821                 mSize = dt.mSize * size;
    822             }
    823         } else {
    824             mSize = dt.mSize;
    825         }
    826         mType = dt;
    827         mKind = dk;
    828         mNormalized = norm;
    829         mVectorSize = size;
    830     }
    831 
    832     Element(long id, RenderScript rs) {
    833         super(id, rs);
    834     }
    835 
    836     @Override
    837     void updateFromNative() {
    838         super.updateFromNative();
    839 
    840         // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
    841         int[] dataBuffer = new int[5];
    842         mRS.nElementGetNativeData(getID(mRS), dataBuffer);
    843 
    844         mNormalized = dataBuffer[2] == 1 ? true : false;
    845         mVectorSize = dataBuffer[3];
    846         mSize = 0;
    847         for (DataType dt: DataType.values()) {
    848             if(dt.mID == dataBuffer[0]){
    849                 mType = dt;
    850                 mSize = mType.mSize * mVectorSize;
    851             }
    852         }
    853         for (DataKind dk: DataKind.values()) {
    854             if(dk.mID == dataBuffer[1]){
    855                 mKind = dk;
    856             }
    857         }
    858 
    859         int numSubElements = dataBuffer[4];
    860         if(numSubElements > 0) {
    861             mElements = new Element[numSubElements];
    862             mElementNames = new String[numSubElements];
    863             mArraySizes = new int[numSubElements];
    864             mOffsetInBytes = new int[numSubElements];
    865 
    866             long[] subElementIds = new long[numSubElements];
    867             mRS.nElementGetSubElements(getID(mRS), subElementIds, mElementNames, mArraySizes);
    868             for(int i = 0; i < numSubElements; i ++) {
    869                 mElements[i] = new Element(subElementIds[i], mRS);
    870                 mElements[i].updateFromNative();
    871                 mOffsetInBytes[i] = mSize;
    872                 mSize += mElements[i].mSize * mArraySizes[i];
    873             }
    874         }
    875         updateVisibleSubElements();
    876     }
    877 
    878     /**
    879      * Create a custom Element of the specified DataType.  The DataKind will be
    880      * set to USER and the vector size to 1 indicating non-vector.
    881      *
    882      * @param rs The context associated with the new Element.
    883      * @param dt The DataType for the new element.
    884      * @return Element
    885      */
    886     static Element createUser(RenderScript rs, DataType dt) {
    887         DataKind dk = DataKind.USER;
    888         boolean norm = false;
    889         int vecSize = 1;
    890         long id = rs.nElementCreate(dt.mID, dk.mID, norm, vecSize);
    891         return new Element(id, rs, dt, dk, norm, vecSize);
    892     }
    893 
    894     /**
    895      * Create a custom vector element of the specified DataType and vector size.
    896      * DataKind will be set to USER. Only primitive types (FLOAT_32, FLOAT_64,
    897      * SIGNED_8, SIGNED_16, SIGNED_32, SIGNED_64, UNSIGNED_8, UNSIGNED_16,
    898      * UNSIGNED_32, UNSIGNED_64, BOOLEAN) are supported.
    899      *
    900      * @param rs The context associated with the new Element.
    901      * @param dt The DataType for the new Element.
    902      * @param size Vector size for the new Element.  Range 2-4 inclusive
    903      *             supported.
    904      *
    905      * @return Element
    906      */
    907     public static Element createVector(RenderScript rs, DataType dt, int size) {
    908         if (size < 2 || size > 4) {
    909             throw new RSIllegalArgumentException("Vector size out of range 2-4.");
    910         }
    911 
    912         switch (dt) {
    913         // Support only primitive integer/float/boolean types as vectors.
    914         case FLOAT_16:
    915         case FLOAT_32:
    916         case FLOAT_64:
    917         case SIGNED_8:
    918         case SIGNED_16:
    919         case SIGNED_32:
    920         case SIGNED_64:
    921         case UNSIGNED_8:
    922         case UNSIGNED_16:
    923         case UNSIGNED_32:
    924         case UNSIGNED_64:
    925         case BOOLEAN: {
    926             DataKind dk = DataKind.USER;
    927             boolean norm = false;
    928             long id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
    929             return new Element(id, rs, dt, dk, norm, size);
    930         }
    931 
    932         default: {
    933             throw new RSIllegalArgumentException("Cannot create vector of " +
    934                 "non-primitive type.");
    935         }
    936         }
    937     }
    938 
    939     /**
    940      * Create a new pixel Element type.  A matching DataType and DataKind must
    941      * be provided.  The DataType and DataKind must contain the same number of
    942      * components.  Vector size will be set to 1.
    943      *
    944      * @param rs The context associated with the new Element.
    945      * @param dt The DataType for the new element.
    946      * @param dk The DataKind to specify the mapping of each component in the
    947      *           DataType.
    948      *
    949      * @return Element
    950      */
    951     public static Element createPixel(RenderScript rs, DataType dt, DataKind dk) {
    952         if (!(dk == DataKind.PIXEL_L ||
    953               dk == DataKind.PIXEL_A ||
    954               dk == DataKind.PIXEL_LA ||
    955               dk == DataKind.PIXEL_RGB ||
    956               dk == DataKind.PIXEL_RGBA ||
    957               dk == DataKind.PIXEL_DEPTH ||
    958               dk == DataKind.PIXEL_YUV)) {
    959             throw new RSIllegalArgumentException("Unsupported DataKind");
    960         }
    961         if (!(dt == DataType.UNSIGNED_8 ||
    962               dt == DataType.UNSIGNED_16 ||
    963               dt == DataType.UNSIGNED_5_6_5 ||
    964               dt == DataType.UNSIGNED_4_4_4_4 ||
    965               dt == DataType.UNSIGNED_5_5_5_1)) {
    966             throw new RSIllegalArgumentException("Unsupported DataType");
    967         }
    968         if (dt == DataType.UNSIGNED_5_6_5 && dk != DataKind.PIXEL_RGB) {
    969             throw new RSIllegalArgumentException("Bad kind and type combo");
    970         }
    971         if (dt == DataType.UNSIGNED_5_5_5_1 && dk != DataKind.PIXEL_RGBA) {
    972             throw new RSIllegalArgumentException("Bad kind and type combo");
    973         }
    974         if (dt == DataType.UNSIGNED_4_4_4_4 && dk != DataKind.PIXEL_RGBA) {
    975             throw new RSIllegalArgumentException("Bad kind and type combo");
    976         }
    977         if (dt == DataType.UNSIGNED_16 &&
    978             dk != DataKind.PIXEL_DEPTH) {
    979             throw new RSIllegalArgumentException("Bad kind and type combo");
    980         }
    981 
    982         int size = 1;
    983         switch (dk) {
    984         case PIXEL_LA:
    985             size = 2;
    986             break;
    987         case PIXEL_RGB:
    988             size = 3;
    989             break;
    990         case PIXEL_RGBA:
    991             size = 4;
    992             break;
    993         case PIXEL_DEPTH:
    994             size = 2;
    995             break;
    996         }
    997 
    998         boolean norm = true;
    999         long id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
   1000         return new Element(id, rs, dt, dk, norm, size);
   1001     }
   1002 
   1003     /**
   1004      * Check if the current Element is compatible with another Element.
   1005      * Primitive Elements are compatible if they share the same underlying
   1006      * size and type (i.e. U8 is compatible with A_8). User-defined Elements
   1007      * must be equal in order to be compatible. This requires strict name
   1008      * equivalence for all sub-Elements (in addition to structural equivalence).
   1009      *
   1010      * @param e The Element to check compatibility with.
   1011      *
   1012      * @return boolean true if the Elements are compatible, otherwise false.
   1013      */
   1014     public boolean isCompatible(Element e) {
   1015         // Try strict BaseObj equality to start with.
   1016         if (this.equals(e)) {
   1017             return true;
   1018         }
   1019 
   1020         // Ignore mKind because it is allowed to be different (user vs. pixel).
   1021         // We also ignore mNormalized because it can be different. The mType
   1022         // field must not be NONE since we require name equivalence for
   1023         // all user-created Elements.
   1024         return ((mSize == e.mSize) &&
   1025                 (mType != DataType.NONE) &&
   1026                 (mType == e.mType) &&
   1027                 (mVectorSize == e.mVectorSize));
   1028     }
   1029 
   1030     /**
   1031      * Builder class for producing complex elements with matching field and name
   1032      * pairs.  The builder starts empty.  The order in which elements are added
   1033      * is retained for the layout in memory.
   1034      *
   1035      */
   1036     public static class Builder {
   1037         RenderScript mRS;
   1038         Element[] mElements;
   1039         String[] mElementNames;
   1040         int[] mArraySizes;
   1041         int mCount;
   1042         int mSkipPadding;
   1043 
   1044         /**
   1045          * Create a builder object.
   1046          *
   1047          * @param rs
   1048          */
   1049         public Builder(RenderScript rs) {
   1050             mRS = rs;
   1051             mCount = 0;
   1052             mElements = new Element[8];
   1053             mElementNames = new String[8];
   1054             mArraySizes = new int[8];
   1055         }
   1056 
   1057         /**
   1058          * Add an array of elements to this element.
   1059          *
   1060          * @param element
   1061          * @param name
   1062          * @param arraySize
   1063          */
   1064         public Builder add(Element element, String name, int arraySize) {
   1065             if (arraySize < 1) {
   1066                 throw new RSIllegalArgumentException("Array size cannot be less than 1.");
   1067             }
   1068 
   1069             // Skip padding fields after a vector 3 type.
   1070             if (mSkipPadding != 0) {
   1071                 if (name.startsWith("#padding_")) {
   1072                     mSkipPadding = 0;
   1073                     return this;
   1074                 }
   1075             }
   1076 
   1077             if (element.mVectorSize == 3) {
   1078                 mSkipPadding = 1;
   1079             } else {
   1080                 mSkipPadding = 0;
   1081             }
   1082 
   1083             if(mCount == mElements.length) {
   1084                 Element[] e = new Element[mCount + 8];
   1085                 String[] s = new String[mCount + 8];
   1086                 int[] as = new int[mCount + 8];
   1087                 System.arraycopy(mElements, 0, e, 0, mCount);
   1088                 System.arraycopy(mElementNames, 0, s, 0, mCount);
   1089                 System.arraycopy(mArraySizes, 0, as, 0, mCount);
   1090                 mElements = e;
   1091                 mElementNames = s;
   1092                 mArraySizes = as;
   1093             }
   1094             mElements[mCount] = element;
   1095             mElementNames[mCount] = name;
   1096             mArraySizes[mCount] = arraySize;
   1097             mCount++;
   1098             return this;
   1099         }
   1100 
   1101         /**
   1102          * Add a single element to this Element.
   1103          *
   1104          * @param element
   1105          * @param name
   1106          */
   1107         public Builder add(Element element, String name) {
   1108             return add(element, name, 1);
   1109         }
   1110 
   1111         /**
   1112          * Create the element from this builder.
   1113          *
   1114          *
   1115          * @return Element
   1116          */
   1117         public Element create() {
   1118             mRS.validate();
   1119             Element[] ein = new Element[mCount];
   1120             String[] sin = new String[mCount];
   1121             int[] asin = new int[mCount];
   1122             java.lang.System.arraycopy(mElements, 0, ein, 0, mCount);
   1123             java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount);
   1124             java.lang.System.arraycopy(mArraySizes, 0, asin, 0, mCount);
   1125 
   1126             long[] ids = new long[ein.length];
   1127             for (int ct = 0; ct < ein.length; ct++ ) {
   1128                 ids[ct] = ein[ct].getID(mRS);
   1129             }
   1130             long id = mRS.nElementCreate2(ids, sin, asin);
   1131             return new Element(id, mRS, ein, sin, asin);
   1132         }
   1133     }
   1134 }
   1135 
   1136