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