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