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