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
17package android.renderscript;
18
19import java.lang.reflect.Field;
20import 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 **/
44public 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