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