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