Element.cpp revision bc10dff26207bb8c02051b28326bb134a8f28eb3
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
215
216static uint32_t GetSizeInBytesForType(RsDataType dt) {
217    switch(dt) {
218    case RS_TYPE_NONE:
219        return 0;
220    case RS_TYPE_SIGNED_8:
221    case RS_TYPE_UNSIGNED_8:
222    case RS_TYPE_BOOLEAN:
223        return 1;
224
225    case RS_TYPE_FLOAT_16:
226    case RS_TYPE_SIGNED_16:
227    case RS_TYPE_UNSIGNED_16:
228    case RS_TYPE_UNSIGNED_5_6_5:
229    case RS_TYPE_UNSIGNED_5_5_5_1:
230    case RS_TYPE_UNSIGNED_4_4_4_4:
231        return 2;
232
233    case RS_TYPE_FLOAT_32:
234    case RS_TYPE_SIGNED_32:
235    case RS_TYPE_UNSIGNED_32:
236        return 4;
237
238    case RS_TYPE_FLOAT_64:
239    case RS_TYPE_SIGNED_64:
240    case RS_TYPE_UNSIGNED_64:
241        return 8;
242
243    case RS_TYPE_MATRIX_4X4:
244        return 16 * 4;
245    case RS_TYPE_MATRIX_3X3:
246        return 9 * 4;
247    case RS_TYPE_MATRIX_2X2:
248        return 4 * 4;
249
250    case RS_TYPE_TYPE:
251    case RS_TYPE_ALLOCATION:
252    case RS_TYPE_SAMPLER:
253    case RS_TYPE_SCRIPT:
254    case RS_TYPE_MESH:
255    case RS_TYPE_PROGRAM_FRAGMENT:
256    case RS_TYPE_PROGRAM_VERTEX:
257    case RS_TYPE_PROGRAM_RASTER:
258    case RS_TYPE_PROGRAM_STORE:
259        return 4;
260
261    default:
262        break;
263    }
264
265    ALOGE("Missing type %i", dt);
266    return 0;
267}
268
269Element::Element(void *id, android::RSC::sp<RS> rs,
270                 RsDataType dt, RsDataKind dk, bool norm, uint32_t size) :
271    BaseObj(id, rs)
272{
273    uint32_t tsize = GetSizeInBytesForType(dt);
274    if ((dt != RS_TYPE_UNSIGNED_5_6_5) &&
275        (dt != RS_TYPE_UNSIGNED_4_4_4_4) &&
276        (dt != RS_TYPE_UNSIGNED_5_5_5_1)) {
277        if (size == 3) {
278            mSizeBytes = tsize * 4;
279        } else {
280            mSizeBytes = tsize * size;
281        }
282    } else {
283        mSizeBytes = tsize;
284    }
285    mType = dt;
286    mKind = dk;
287    mNormalized = norm;
288    mVectorSize = size;
289    mElementsCount = 0;
290    mVisibleElementMap = 0;
291}
292
293Element::~Element() {
294    if (mElementsCount) {
295        free(mElements);
296        for (size_t ct = 0; ct < mElementsCount; ct++ ) {
297            free(mElementNames[ct]);
298        }
299        free(mElementNames);
300        free(mElementNameLengths);
301        free(mArraySizes);
302        free(mOffsetInBytes);
303    }
304    if (mVisibleElementMapSize) {
305        free(mVisibleElementMap);
306    }
307}
308
309void Element::updateFromNative() {
310    BaseObj::updateFromNative();
311    updateVisibleSubElements();
312}
313
314android::RSC::sp<const Element> Element::createUser(android::RSC::sp<RS> rs, RsDataType dt) {
315    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, 1);
316    return new Element(id, rs, dt, RS_KIND_USER, false, 1);
317}
318
319android::RSC::sp<const Element> Element::createVector(android::RSC::sp<RS> rs, RsDataType dt, uint32_t size) {
320    if (size < 2 || size > 4) {
321        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Vector size out of range 2-4.");
322        return nullptr;
323    }
324    void *id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, size);
325    return new Element(id, rs, dt, RS_KIND_USER, false, size);
326}
327
328android::RSC::sp<const Element> Element::createPixel(android::RSC::sp<RS> rs, RsDataType dt, RsDataKind dk) {
329    if (!(dk == RS_KIND_PIXEL_L ||
330          dk == RS_KIND_PIXEL_A ||
331          dk == RS_KIND_PIXEL_LA ||
332          dk == RS_KIND_PIXEL_RGB ||
333          dk == RS_KIND_PIXEL_RGBA ||
334          dk == RS_KIND_PIXEL_DEPTH)) {
335        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataKind");
336        return nullptr;
337    }
338    if (!(dt == RS_TYPE_UNSIGNED_8 ||
339          dt == RS_TYPE_UNSIGNED_16 ||
340          dt == RS_TYPE_UNSIGNED_5_6_5 ||
341          dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
342          dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
343        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataType");
344        return nullptr;
345    }
346    if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
347        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
348        return nullptr;
349    }
350    if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
351        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
352        return nullptr;
353    }
354    if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && 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_16 && dk != RS_KIND_PIXEL_DEPTH) {
359        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
360        return nullptr;
361    }
362
363    int size = 1;
364    switch (dk) {
365    case RS_KIND_PIXEL_LA:
366        size = 2;
367        break;
368    case RS_KIND_PIXEL_RGB:
369        size = 3;
370        break;
371    case RS_KIND_PIXEL_RGBA:
372        size = 4;
373        break;
374    case RS_KIND_PIXEL_DEPTH:
375        size = 2;
376        break;
377    default:
378        break;
379    }
380
381    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, dk, true, size);
382    return new Element(id, rs, dt, dk, true, size);
383}
384
385bool Element::isCompatible(android::RSC::sp<const Element>e) const {
386    // Try strict BaseObj equality to start with.
387    if (this == e.get()) {
388        return true;
389    }
390
391    // Ignore mKind because it is allowed to be different (user vs. pixel).
392    // We also ignore mNormalized because it can be different. The mType
393    // field must be non-null since we require name equivalence for
394    // user-created Elements.
395    return ((mSizeBytes == e->mSizeBytes) &&
396            (mType != RS_TYPE_NONE) &&
397            (mType == e->mType) &&
398            (mVectorSize == e->mVectorSize));
399}
400
401Element::Builder::Builder(android::RSC::sp<RS> rs) {
402    mRS = rs.get();
403    mSkipPadding = false;
404    mElementsVecSize = 8;
405    mElementsCount = 0;
406    // Initialize space
407    mElements = (android::RSC::sp<const Element> *)calloc(mElementsVecSize, sizeof(android::RSC::sp<Element>));
408    mElementNames = (char **)calloc(mElementsVecSize, sizeof(char *));
409    mElementNameLengths = (size_t*)calloc(mElementsVecSize, sizeof(size_t));
410    mArraySizes = (uint32_t*)calloc(mElementsVecSize, sizeof(uint32_t));
411}
412
413Element::Builder::~Builder() {
414    // free allocated space
415    free(mElements);
416    for (size_t ct = 0; ct < mElementsCount; ct++ ) {
417        free(mElementNames[ct]);
418    }
419    free(mElementNameLengths);
420    free(mElementNames);
421    free(mArraySizes);
422}
423
424void Element::Builder::add(android::RSC::sp<const Element>e, const char * name, uint32_t arraySize) {
425    // Skip padding fields after a vector 3 type.
426    if (mSkipPadding) {
427        const char *s1 = "#padding_";
428        const char *s2 = name;
429        size_t len = strlen(s1);
430        if (strlen(s2) >= len) {
431            if (!memcmp(s1, s2, len)) {
432                mSkipPadding = false;
433                return;
434            }
435        }
436    }
437
438    if (e->mVectorSize == 3) {
439        mSkipPadding = true;
440    } else {
441        mSkipPadding = false;
442    }
443
444    if (mElementsCount >= mElementsVecSize) {
445        //if pre-allocated space is full, allocate a larger one.
446        mElementsVecSize += 8;
447
448        android::RSC::sp<const Element> * newElements = (android::RSC::sp<const Element> *)calloc(mElementsVecSize, sizeof(android::RSC::sp<Element>));
449        char ** newElementNames = (char **)calloc(mElementsVecSize, sizeof(char *));
450        size_t * newElementNameLengths = (size_t*)calloc(mElementsVecSize, sizeof(size_t));
451        uint32_t * newArraySizes = (uint32_t*)calloc(mElementsVecSize, sizeof(uint32_t));
452
453        memcpy(newElements, mElements, mElementsCount * sizeof(android::RSC::sp<Element>));
454        memcpy(newElementNames, mElementNames, mElementsCount * sizeof(char *));
455        memcpy(newElementNameLengths, mElementNameLengths, mElementsCount * sizeof(size_t));
456        memcpy(newArraySizes, mArraySizes, mElementsCount * sizeof(uint32_t));
457
458        //free the old arrays
459        free(mElements);
460        free(mElementNames);
461        free(mArraySizes);
462        free(mElementNameLengths);
463
464        mElements = newElements;
465        mElementNames = newElementNames;
466        mArraySizes = newArraySizes;
467        mElementNameLengths = newElementNameLengths;
468    }
469    mElements[mElementsCount] = e;
470    mArraySizes[mElementsCount] = arraySize;
471
472    size_t nameLen = strlen(name);
473    mElementNameLengths[mElementsCount] = nameLen + 1;
474    mElementNames[mElementsCount] = (char *)calloc(nameLen + 1, sizeof(char));
475    memcpy(mElementNames[mElementsCount], name, nameLen);
476    mElementNames[mElementsCount][nameLen] = 0;
477
478    mElementsCount++;
479}
480
481android::RSC::sp<const Element> Element::Builder::create() {
482    size_t fieldCount = mElementsCount;
483    void ** elementArray = (void **)calloc(fieldCount, sizeof(void *));
484
485    for (size_t ct = 0; ct < fieldCount; ct++) {
486        elementArray[ct] = mElements[ct]->getID();
487    }
488
489    void *id = RS::dispatch->ElementCreate2(mRS->getContext(),
490                                            (RsElement *)elementArray, fieldCount,
491                                            (const char **)mElementNames, fieldCount, mElementNameLengths,
492                                            mArraySizes, fieldCount);
493    free(elementArray);
494    return new Element(id, mRS, mElements, mElementsCount, (const char **)mElementNames, mElementNameLengths, mArraySizes);
495}
496