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