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