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