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