Element.cpp revision cf067b8c4d1e53bc4768fbad239851c579717f2c
1/*
2 * Copyright (C) 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
17#include <malloc.h>
18#include <string.h>
19
20#include "RenderScript.h"
21#include "rsCppInternal.h"
22
23using namespace android;
24using namespace RSC;
25
26android::RSC::sp<const Element> Element::getSubElement(uint32_t index) {
27    if (!mVisibleElementMapSize) {
28        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
29        return nullptr;
30    }
31    if (index >= mVisibleElementMapSize) {
32        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
33        return nullptr;
34    }
35    return mElements[mVisibleElementMap[index]];
36}
37
38const char * Element::getSubElementName(uint32_t index) {
39    if (!mVisibleElementMapSize) {
40        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
41        return nullptr;
42    }
43    if (index >= mVisibleElementMapSize) {
44        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
45        return nullptr;
46    }
47    return mElementNames[mVisibleElementMap[index]];
48}
49
50size_t Element::getSubElementArraySize(uint32_t index) {
51    if (!mVisibleElementMapSize) {
52        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
53        return 0;
54    }
55    if (index >= mVisibleElementMapSize) {
56        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
57        return 0;
58    }
59    return mArraySizes[mVisibleElementMap[index]];
60}
61
62uint32_t Element::getSubElementOffsetBytes(uint32_t index) {
63    if (!mVisibleElementMapSize) {
64        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
65        return 0;
66    }
67    if (index >= mVisibleElementMapSize) {
68        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
69        return 0;
70    }
71    return mOffsetInBytes[mVisibleElementMap[index]];
72}
73
74
75#define CREATE_USER(N, T) android::RSC::sp<const Element> Element::N(android::RSC::sp<RS> rs) { \
76    if (rs->mElements.N == nullptr) {                               \
77        rs->mElements.N = (createUser(rs, RS_TYPE_##T));            \
78    }                                                               \
79    return rs->mElements.N;                                         \
80    }
81
82CREATE_USER(BOOLEAN, BOOLEAN);
83CREATE_USER(U8, UNSIGNED_8);
84CREATE_USER(I8, SIGNED_8);
85CREATE_USER(U16, UNSIGNED_16);
86CREATE_USER(I16, SIGNED_16);
87CREATE_USER(U32, UNSIGNED_32);
88CREATE_USER(I32, SIGNED_32);
89CREATE_USER(U64, UNSIGNED_64);
90CREATE_USER(I64, SIGNED_64);
91CREATE_USER(F32, FLOAT_32);
92CREATE_USER(F64, FLOAT_64);
93CREATE_USER(ELEMENT, ELEMENT);
94CREATE_USER(TYPE, TYPE);
95CREATE_USER(ALLOCATION, ALLOCATION);
96CREATE_USER(SAMPLER, SAMPLER);
97CREATE_USER(SCRIPT, SCRIPT);
98CREATE_USER(MATRIX_4X4, MATRIX_4X4);
99CREATE_USER(MATRIX_3X3, MATRIX_3X3);
100CREATE_USER(MATRIX_2X2, MATRIX_2X2);
101
102#define CREATE_PIXEL(N, T, K) android::RSC::sp<const Element> Element::N(android::RSC::sp<RS> rs) { \
103    if (rs->mElements.N == nullptr) {                                \
104        rs->mElements.N = createPixel(rs, RS_TYPE_##T, RS_KIND_##K); \
105    }                                                                \
106    return rs->mElements.N;                                          \
107}
108
109CREATE_PIXEL(A_8, UNSIGNED_8, PIXEL_A);
110CREATE_PIXEL(RGB_565, UNSIGNED_5_6_5, PIXEL_RGB);
111CREATE_PIXEL(RGB_888, UNSIGNED_8, PIXEL_RGB);
112CREATE_PIXEL(RGBA_4444, UNSIGNED_4_4_4_4, PIXEL_RGBA);
113CREATE_PIXEL(RGBA_8888, UNSIGNED_8, PIXEL_RGBA);
114CREATE_PIXEL(YUV, UNSIGNED_8, PIXEL_YUV);
115CREATE_PIXEL(RGBA_5551, UNSIGNED_5_5_5_1, PIXEL_RGBA);
116
117#define CREATE_VECTOR(N, T) android::RSC::sp<const Element> Element::N##_2(android::RSC::sp<RS> rs) { \
118    if (rs->mElements.N##_2 == nullptr) {                                 \
119        rs->mElements.N##_2 = createVector(rs, RS_TYPE_##T, 2);           \
120    }                                                                     \
121    return rs->mElements.N##_2;                                           \
122}                                                                         \
123android::RSC::sp<const Element> Element::N##_3(android::RSC::sp<RS> rs) { \
124    if (rs->mElements.N##_3 == nullptr) {                                 \
125        rs->mElements.N##_3 = createVector(rs, RS_TYPE_##T, 3);           \
126    }                                                                     \
127    return rs->mElements.N##_3;                                           \
128} \
129android::RSC::sp<const Element> Element::N##_4(android::RSC::sp<RS> rs) { \
130    if (rs->mElements.N##_4 == nullptr) {                                 \
131        rs->mElements.N##_4 = createVector(rs, RS_TYPE_##T, 4);           \
132    }                                                                     \
133    return rs->mElements.N##_4;                                           \
134}
135CREATE_VECTOR(U8, UNSIGNED_8);
136CREATE_VECTOR(I8, SIGNED_8);
137CREATE_VECTOR(U16, UNSIGNED_16);
138CREATE_VECTOR(I16, SIGNED_16);
139CREATE_VECTOR(U32, UNSIGNED_32);
140CREATE_VECTOR(I32, SIGNED_32);
141CREATE_VECTOR(U64, UNSIGNED_64);
142CREATE_VECTOR(I64, SIGNED_64);
143CREATE_VECTOR(F32, FLOAT_32);
144CREATE_VECTOR(F64, FLOAT_64);
145
146
147void Element::updateVisibleSubElements() {
148    if (!mElementsCount) {
149        return;
150    }
151    if (mVisibleElementMapSize) {
152        free(mVisibleElementMap);
153        mVisibleElementMapSize = 0;
154    }
155    mVisibleElementMap = (uint32_t*)calloc(mElementsCount, sizeof(uint32_t));
156
157    int noPaddingFieldCount = 0;
158    size_t fieldCount = mElementsCount;
159    // Find out how many elements are not padding.
160    for (size_t ct = 0; ct < fieldCount; ct ++) {
161        if (mElementNames[ct][0] != '#') {
162            noPaddingFieldCount ++;
163        }
164    }
165
166    // Make a map that points us at non-padding elements.
167    size_t i = 0;
168    for (size_t ct = 0; ct < fieldCount; ct ++) {
169        if (mElementNames[ct][0] != '#') {
170            mVisibleElementMap[i++] = (uint32_t)ct;
171        }
172    }
173    mVisibleElementMapSize = i;
174}
175
176Element::Element(void *id, android::RSC::sp<RS> rs,
177                 android::RSC::sp<const Element> * elements,
178                 size_t elementCount,
179                 const char ** elementNames,
180                 size_t * elementNameLengths,
181                 uint32_t * arraySizes) : BaseObj(id, rs) {
182    mSizeBytes = 0;
183    mVectorSize = 1;
184    mElementsCount = elementCount;
185    mVisibleElementMap = nullptr;
186    mVisibleElementMapSize = 0;
187
188    mElements = (android::RSC::sp<const Element> *)calloc(mElementsCount, sizeof(android::RSC::sp<Element>));
189    mElementNames = (char **)calloc(mElementsCount, sizeof(char *));
190    mElementNameLengths = (size_t*)calloc(mElementsCount, sizeof(size_t));
191    mArraySizes = (uint32_t*)calloc(mElementsCount, sizeof(uint32_t));
192    mOffsetInBytes = (uint32_t*)calloc(mElementsCount, sizeof(uint32_t));
193
194    memcpy(mElements, elements, mElementsCount * sizeof(android::RSC::sp<Element>));
195    memcpy(mArraySizes, arraySizes, mElementsCount * sizeof(uint32_t));
196
197    // Copy strings (char array).
198    memcpy(mElementNameLengths, elementNameLengths, mElementsCount * sizeof(size_t));
199    for (size_t ct = 0; ct < mElementsCount; ct++ ) {
200        size_t elemNameLen = mElementNameLengths[ct];
201        mElementNames[ct] = (char *)calloc(elemNameLen, sizeof(char));
202        memcpy(mElementNames[ct], elementNames[ct], elemNameLen);
203    }
204
205    mType = RS_TYPE_NONE;
206    mKind = RS_KIND_USER;
207
208    for (size_t ct = 0; ct < mElementsCount; ct++ ) {
209        mOffsetInBytes[ct] = mSizeBytes;
210        mSizeBytes += mElements[ct]->mSizeBytes * mArraySizes[ct];
211    }
212    updateVisibleSubElements();
213}
214
215Element::Element(void *id, android::RSC::sp<RS> rs) :
216    BaseObj(id, rs) {
217}
218
219static uint32_t GetSizeInBytesForType(RsDataType dt) {
220    switch(dt) {
221    case RS_TYPE_NONE:
222        return 0;
223    case RS_TYPE_SIGNED_8:
224    case RS_TYPE_UNSIGNED_8:
225    case RS_TYPE_BOOLEAN:
226        return 1;
227
228    case RS_TYPE_FLOAT_16:
229    case RS_TYPE_SIGNED_16:
230    case RS_TYPE_UNSIGNED_16:
231    case RS_TYPE_UNSIGNED_5_6_5:
232    case RS_TYPE_UNSIGNED_5_5_5_1:
233    case RS_TYPE_UNSIGNED_4_4_4_4:
234        return 2;
235
236    case RS_TYPE_FLOAT_32:
237    case RS_TYPE_SIGNED_32:
238    case RS_TYPE_UNSIGNED_32:
239        return 4;
240
241    case RS_TYPE_FLOAT_64:
242    case RS_TYPE_SIGNED_64:
243    case RS_TYPE_UNSIGNED_64:
244        return 8;
245
246    case RS_TYPE_MATRIX_4X4:
247        return 16 * 4;
248    case RS_TYPE_MATRIX_3X3:
249        return 9 * 4;
250    case RS_TYPE_MATRIX_2X2:
251        return 4 * 4;
252
253    case RS_TYPE_TYPE:
254    case RS_TYPE_ALLOCATION:
255    case RS_TYPE_SAMPLER:
256    case RS_TYPE_SCRIPT:
257    case RS_TYPE_MESH:
258    case RS_TYPE_PROGRAM_FRAGMENT:
259    case RS_TYPE_PROGRAM_VERTEX:
260    case RS_TYPE_PROGRAM_RASTER:
261    case RS_TYPE_PROGRAM_STORE:
262        return 4;
263
264    default:
265        break;
266    }
267
268    ALOGE("Missing type %i", dt);
269    return 0;
270}
271
272Element::Element(void *id, android::RSC::sp<RS> rs,
273                 RsDataType dt, RsDataKind dk, bool norm, uint32_t size) :
274    BaseObj(id, rs)
275{
276    uint32_t tsize = GetSizeInBytesForType(dt);
277    if ((dt != RS_TYPE_UNSIGNED_5_6_5) &&
278        (dt != RS_TYPE_UNSIGNED_4_4_4_4) &&
279        (dt != RS_TYPE_UNSIGNED_5_5_5_1)) {
280        if (size == 3) {
281            mSizeBytes = tsize * 4;
282        } else {
283            mSizeBytes = tsize * size;
284        }
285    } else {
286        mSizeBytes = tsize;
287    }
288    mType = dt;
289    mKind = dk;
290    mNormalized = norm;
291    mVectorSize = size;
292    mElementsCount = 0;
293    mVisibleElementMap = 0;
294}
295
296Element::~Element() {
297    if (mElementsCount) {
298        free(mElements);
299        for (size_t ct = 0; ct < mElementsCount; ct++ ) {
300            free(mElementNames[ct]);
301        }
302        free(mElementNames);
303        free(mElementNameLengths);
304        free(mArraySizes);
305        free(mOffsetInBytes);
306    }
307    if (mVisibleElementMapSize) {
308        free(mVisibleElementMap);
309    }
310}
311
312void Element::updateFromNative() {
313    BaseObj::updateFromNative();
314    updateVisibleSubElements();
315}
316
317android::RSC::sp<const Element> Element::createUser(android::RSC::sp<RS> rs, RsDataType dt) {
318    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, 1);
319    return new Element(id, rs, dt, RS_KIND_USER, false, 1);
320}
321
322android::RSC::sp<const Element> Element::createVector(android::RSC::sp<RS> rs, RsDataType dt, uint32_t size) {
323    if (size < 2 || size > 4) {
324        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Vector size out of range 2-4.");
325        return nullptr;
326    }
327    void *id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, size);
328    return new Element(id, rs, dt, RS_KIND_USER, false, size);
329}
330
331android::RSC::sp<const Element> Element::createPixel(android::RSC::sp<RS> rs, RsDataType dt, RsDataKind dk) {
332    if (!(dk == RS_KIND_PIXEL_L ||
333          dk == RS_KIND_PIXEL_A ||
334          dk == RS_KIND_PIXEL_LA ||
335          dk == RS_KIND_PIXEL_RGB ||
336          dk == RS_KIND_PIXEL_RGBA ||
337          dk == RS_KIND_PIXEL_DEPTH ||
338          dk == RS_KIND_PIXEL_YUV)) {
339        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataKind");
340        return nullptr;
341    }
342    if (!(dt == RS_TYPE_UNSIGNED_8 ||
343          dt == RS_TYPE_UNSIGNED_16 ||
344          dt == RS_TYPE_UNSIGNED_5_6_5 ||
345          dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
346          dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
347        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataType");
348        return nullptr;
349    }
350    if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
351        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
352        return nullptr;
353    }
354    if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
355        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
356        return nullptr;
357    }
358    if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
359        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
360        return nullptr;
361    }
362    if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
363        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
364        return nullptr;
365    }
366
367    int size = 1;
368    switch (dk) {
369    case RS_KIND_PIXEL_LA:
370        size = 2;
371        break;
372    case RS_KIND_PIXEL_RGB:
373        size = 3;
374        break;
375    case RS_KIND_PIXEL_RGBA:
376        size = 4;
377        break;
378    case RS_KIND_PIXEL_DEPTH:
379        size = 2;
380        break;
381    default:
382        break;
383    }
384
385    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, dk, true, size);
386    return new Element(id, rs, dt, dk, true, size);
387}
388
389bool Element::isCompatible(android::RSC::sp<const Element>e) const {
390    // Try strict BaseObj equality to start with.
391    if (this == e.get()) {
392        return true;
393    }
394
395    /*
396     * Ignore mKind because it is allowed to be different (user vs. pixel).
397     * We also ignore mNormalized because it can be different. The mType
398     * field must be non-null since we require name equivalence for
399     * user-created Elements.
400     */
401    return ((mSizeBytes == e->mSizeBytes) &&
402            (mType != RS_TYPE_NONE) &&
403            (mType == e->mType) &&
404            (mVectorSize == e->mVectorSize));
405}
406
407Element::Builder::Builder(android::RSC::sp<RS> rs) {
408    mRS = rs.get();
409    mSkipPadding = false;
410    mElementsVecSize = 8;
411    mElementsCount = 0;
412    // Initialize space.
413    mElements = (android::RSC::sp<const Element> *)calloc(mElementsVecSize, sizeof(android::RSC::sp<Element>));
414    mElementNames = (char **)calloc(mElementsVecSize, sizeof(char *));
415    mElementNameLengths = (size_t*)calloc(mElementsVecSize, sizeof(size_t));
416    mArraySizes = (uint32_t*)calloc(mElementsVecSize, sizeof(uint32_t));
417}
418
419Element::Builder::~Builder() {
420    // Free allocated space.
421    free(mElements);
422    for (size_t ct = 0; ct < mElementsCount; ct++ ) {
423        free(mElementNames[ct]);
424    }
425    free(mElementNameLengths);
426    free(mElementNames);
427    free(mArraySizes);
428}
429
430void Element::Builder::add(android::RSC::sp<const Element>e, const char * name, uint32_t arraySize) {
431    // Skip padding fields after a vector 3 type.
432    if (mSkipPadding) {
433        const char *s1 = "#padding_";
434        const char *s2 = name;
435        size_t len = strlen(s1);
436        if (strlen(s2) >= len) {
437            if (!memcmp(s1, s2, len)) {
438                mSkipPadding = false;
439                return;
440            }
441        }
442    }
443
444    if (e->mVectorSize == 3) {
445        mSkipPadding = true;
446    } else {
447        mSkipPadding = false;
448    }
449
450    if (mElementsCount >= mElementsVecSize) {
451        // If pre-allocated space is full, allocate a larger one.
452        mElementsVecSize += 8;
453
454        android::RSC::sp<const Element> * newElements = (android::RSC::sp<const Element> *)calloc(mElementsVecSize, sizeof(android::RSC::sp<Element>));
455        char ** newElementNames = (char **)calloc(mElementsVecSize, sizeof(char *));
456        size_t * newElementNameLengths = (size_t*)calloc(mElementsVecSize, sizeof(size_t));
457        uint32_t * newArraySizes = (uint32_t*)calloc(mElementsVecSize, sizeof(uint32_t));
458
459        memcpy(newElements, mElements, mElementsCount * sizeof(android::RSC::sp<Element>));
460        memcpy(newElementNames, mElementNames, mElementsCount * sizeof(char *));
461        memcpy(newElementNameLengths, mElementNameLengths, mElementsCount * sizeof(size_t));
462        memcpy(newArraySizes, mArraySizes, mElementsCount * sizeof(uint32_t));
463
464        // Free the old arrays.
465        free(mElements);
466        free(mElementNames);
467        free(mArraySizes);
468        free(mElementNameLengths);
469
470        mElements = newElements;
471        mElementNames = newElementNames;
472        mArraySizes = newArraySizes;
473        mElementNameLengths = newElementNameLengths;
474    }
475    mElements[mElementsCount] = e;
476    mArraySizes[mElementsCount] = arraySize;
477
478    size_t nameLen = strlen(name);
479    mElementNameLengths[mElementsCount] = nameLen + 1;
480    mElementNames[mElementsCount] = (char *)calloc(nameLen + 1, sizeof(char));
481    memcpy(mElementNames[mElementsCount], name, nameLen);
482    mElementNames[mElementsCount][nameLen] = 0;
483
484    mElementsCount++;
485}
486
487android::RSC::sp<const Element> Element::Builder::create() {
488    size_t fieldCount = mElementsCount;
489    void ** elementArray = (void **)calloc(fieldCount, sizeof(void *));
490
491    for (size_t ct = 0; ct < fieldCount; ct++) {
492        elementArray[ct] = mElements[ct]->getID();
493    }
494
495    void *id = RS::dispatch->ElementCreate2(mRS->getContext(),
496                                            (RsElement *)elementArray, fieldCount,
497                                            (const char **)mElementNames, fieldCount, mElementNameLengths,
498                                            mArraySizes, fieldCount);
499    free(elementArray);
500    return new Element(id, mRS, mElements, mElementsCount, (const char **)mElementNames, mElementNameLengths, mArraySizes);
501}
502