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