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