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          dk == RS_KIND_PIXEL_YUV)) {
336        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataKind");
337        return nullptr;
338    }
339    if (!(dt == RS_TYPE_UNSIGNED_8 ||
340          dt == RS_TYPE_UNSIGNED_16 ||
341          dt == RS_TYPE_UNSIGNED_5_6_5 ||
342          dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
343          dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
344        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataType");
345        return nullptr;
346    }
347    if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
348        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
349        return nullptr;
350    }
351    if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
352        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
353        return nullptr;
354    }
355    if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
356        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
357        return nullptr;
358    }
359    if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
360        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
361        return nullptr;
362    }
363
364    int size = 1;
365    switch (dk) {
366    case RS_KIND_PIXEL_LA:
367        size = 2;
368        break;
369    case RS_KIND_PIXEL_RGB:
370        size = 3;
371        break;
372    case RS_KIND_PIXEL_RGBA:
373        size = 4;
374        break;
375    case RS_KIND_PIXEL_DEPTH:
376        size = 2;
377        break;
378    default:
379        break;
380    }
381
382    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, dk, true, size);
383    return new Element(id, rs, dt, dk, true, size);
384}
385
386bool Element::isCompatible(android::RSC::sp<const Element>e) const {
387    // Try strict BaseObj equality to start with.
388    if (this == e.get()) {
389        return true;
390    }
391
392    // Ignore mKind because it is allowed to be different (user vs. pixel).
393    // We also ignore mNormalized because it can be different. The mType
394    // field must be non-null since we require name equivalence for
395    // user-created Elements.
396    return ((mSizeBytes == e->mSizeBytes) &&
397            (mType != RS_TYPE_NONE) &&
398            (mType == e->mType) &&
399            (mVectorSize == e->mVectorSize));
400}
401
402Element::Builder::Builder(android::RSC::sp<RS> rs) {
403    mRS = rs.get();
404    mSkipPadding = false;
405    mElementsVecSize = 8;
406    mElementsCount = 0;
407    // Initialize space
408    mElements = (android::RSC::sp<const Element> *)calloc(mElementsVecSize, sizeof(android::RSC::sp<Element>));
409    mElementNames = (char **)calloc(mElementsVecSize, sizeof(char *));
410    mElementNameLengths = (size_t*)calloc(mElementsVecSize, sizeof(size_t));
411    mArraySizes = (uint32_t*)calloc(mElementsVecSize, sizeof(uint32_t));
412}
413
414Element::Builder::~Builder() {
415    // free allocated space
416    free(mElements);
417    for (size_t ct = 0; ct < mElementsCount; ct++ ) {
418        free(mElementNames[ct]);
419    }
420    free(mElementNameLengths);
421    free(mElementNames);
422    free(mArraySizes);
423}
424
425void Element::Builder::add(android::RSC::sp<const Element>e, const char * name, uint32_t arraySize) {
426    // Skip padding fields after a vector 3 type.
427    if (mSkipPadding) {
428        const char *s1 = "#padding_";
429        const char *s2 = name;
430        size_t len = strlen(s1);
431        if (strlen(s2) >= len) {
432            if (!memcmp(s1, s2, len)) {
433                mSkipPadding = false;
434                return;
435            }
436        }
437    }
438
439    if (e->mVectorSize == 3) {
440        mSkipPadding = true;
441    } else {
442        mSkipPadding = false;
443    }
444
445    if (mElementsCount >= mElementsVecSize) {
446        //if pre-allocated space is full, allocate a larger one.
447        mElementsVecSize += 8;
448
449        android::RSC::sp<const Element> * newElements = (android::RSC::sp<const Element> *)calloc(mElementsVecSize, sizeof(android::RSC::sp<Element>));
450        char ** newElementNames = (char **)calloc(mElementsVecSize, sizeof(char *));
451        size_t * newElementNameLengths = (size_t*)calloc(mElementsVecSize, sizeof(size_t));
452        uint32_t * newArraySizes = (uint32_t*)calloc(mElementsVecSize, sizeof(uint32_t));
453
454        memcpy(newElements, mElements, mElementsCount * sizeof(android::RSC::sp<Element>));
455        memcpy(newElementNames, mElementNames, mElementsCount * sizeof(char *));
456        memcpy(newElementNameLengths, mElementNameLengths, mElementsCount * sizeof(size_t));
457        memcpy(newArraySizes, mArraySizes, mElementsCount * sizeof(uint32_t));
458
459        //free the old arrays
460        free(mElements);
461        free(mElementNames);
462        free(mArraySizes);
463        free(mElementNameLengths);
464
465        mElements = newElements;
466        mElementNames = newElementNames;
467        mArraySizes = newArraySizes;
468        mElementNameLengths = newElementNameLengths;
469    }
470    mElements[mElementsCount] = e;
471    mArraySizes[mElementsCount] = arraySize;
472
473    size_t nameLen = strlen(name);
474    mElementNameLengths[mElementsCount] = nameLen + 1;
475    mElementNames[mElementsCount] = (char *)calloc(nameLen + 1, sizeof(char));
476    memcpy(mElementNames[mElementsCount], name, nameLen);
477    mElementNames[mElementsCount][nameLen] = 0;
478
479    mElementsCount++;
480}
481
482android::RSC::sp<const Element> Element::Builder::create() {
483    size_t fieldCount = mElementsCount;
484    void ** elementArray = (void **)calloc(fieldCount, sizeof(void *));
485
486    for (size_t ct = 0; ct < fieldCount; ct++) {
487        elementArray[ct] = mElements[ct]->getID();
488    }
489
490    void *id = RS::dispatch->ElementCreate2(mRS->getContext(),
491                                            (RsElement *)elementArray, fieldCount,
492                                            (const char **)mElementNames, fieldCount, mElementNameLengths,
493                                            mArraySizes, fieldCount);
494    free(elementArray);
495    return new Element(id, mRS, mElements, mElementsCount, (const char **)mElementNames, mElementNameLengths, mArraySizes);
496}
497