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