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