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