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