Element.cpp revision 10913a5c37ba119bef335320d3e8be25212c05ad
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
22using namespace android;
23using namespace RSC;
24
25android::RSC::sp<const Element> Element::getSubElement(uint32_t index) {
26    if (!mVisibleElementMap.size()) {
27        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
28        return NULL;
29    }
30    if (index >= mVisibleElementMap.size()) {
31        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
32        return NULL;
33    }
34    return mElements[mVisibleElementMap[index]];
35}
36
37const char * Element::getSubElementName(uint32_t index) {
38    if (!mVisibleElementMap.size()) {
39        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
40        return NULL;
41    }
42    if (index >= mVisibleElementMap.size()) {
43        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
44        return NULL;
45    }
46    return mElementNames[mVisibleElementMap[index]].c_str();
47}
48
49size_t Element::getSubElementArraySize(uint32_t index) {
50    if (!mVisibleElementMap.size()) {
51        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
52        return 0;
53    }
54    if (index >= mVisibleElementMap.size()) {
55        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
56        return 0;
57    }
58    return mArraySizes[mVisibleElementMap[index]];
59}
60
61uint32_t Element::getSubElementOffsetBytes(uint32_t index) {
62    if (mVisibleElementMap.size()) {
63        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
64        return 0;
65    }
66    if (index >= mVisibleElementMap.size()) {
67        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
68        return 0;
69    }
70    return mOffsetInBytes[mVisibleElementMap[index]];
71}
72
73
74#define CREATE_USER(N, T) android::RSC::sp<const Element> Element::N(android::RSC::sp<RS> rs) { \
75    if (rs->mElements.N == NULL) {                                  \
76        rs->mElements.N = (createUser(rs, RS_TYPE_##T)).get();      \
77    }                                                               \
78    return rs->mElements.N;                                         \
79    }
80
81CREATE_USER(BOOLEAN, BOOLEAN);
82CREATE_USER(U8, UNSIGNED_8);
83CREATE_USER(I8, SIGNED_8);
84CREATE_USER(U16, UNSIGNED_16);
85CREATE_USER(I16, SIGNED_16);
86CREATE_USER(U32, UNSIGNED_32);
87CREATE_USER(I32, SIGNED_32);
88CREATE_USER(U64, UNSIGNED_64);
89CREATE_USER(I64, SIGNED_64);
90CREATE_USER(F32, FLOAT_32);
91CREATE_USER(F64, FLOAT_64);
92CREATE_USER(ELEMENT, ELEMENT);
93CREATE_USER(TYPE, TYPE);
94CREATE_USER(ALLOCATION, ALLOCATION);
95CREATE_USER(SAMPLER, SAMPLER);
96CREATE_USER(SCRIPT, SCRIPT);
97CREATE_USER(MESH, MESH);
98CREATE_USER(PROGRAM_FRAGMENT, PROGRAM_FRAGMENT);
99CREATE_USER(PROGRAM_VERTEX, PROGRAM_VERTEX);
100CREATE_USER(PROGRAM_RASTER, PROGRAM_RASTER);
101CREATE_USER(PROGRAM_STORE, PROGRAM_STORE);
102CREATE_USER(MATRIX_4X4, MATRIX_4X4);
103CREATE_USER(MATRIX_3X3, MATRIX_3X3);
104CREATE_USER(MATRIX_2X2, MATRIX_2X2);
105
106#define CREATE_PIXEL(N, T, K) android::RSC::sp<const Element> Element::N(android::RSC::sp<RS> rs) { \
107    return createPixel(rs, RS_TYPE_##T, RS_KIND_##K); \
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);
114
115#define CREATE_VECTOR(N, T) android::RSC::sp<const Element> Element::N##_2(android::RSC::sp<RS> rs) { \
116    return createVector(rs, RS_TYPE_##T, 2); \
117} \
118android::RSC::sp<const Element> Element::N##_3(android::RSC::sp<RS> rs) { \
119    return createVector(rs, RS_TYPE_##T, 3); \
120} \
121android::RSC::sp<const Element> Element::N##_4(android::RSC::sp<RS> rs) { \
122    return createVector(rs, RS_TYPE_##T, 4); \
123}
124CREATE_VECTOR(U8, UNSIGNED_8);
125CREATE_VECTOR(I8, SIGNED_8);
126CREATE_VECTOR(U16, UNSIGNED_16);
127CREATE_VECTOR(I16, SIGNED_16);
128CREATE_VECTOR(U32, UNSIGNED_32);
129CREATE_VECTOR(I32, SIGNED_32);
130CREATE_VECTOR(U64, UNSIGNED_64);
131CREATE_VECTOR(I64, SIGNED_64);
132CREATE_VECTOR(F32, FLOAT_32);
133CREATE_VECTOR(F64, FLOAT_64);
134
135
136void Element::updateVisibleSubElements() {
137    if (!mElements.size()) {
138        return;
139    }
140    mVisibleElementMap.clear();
141
142    int noPaddingFieldCount = 0;
143    size_t fieldCount = mElementNames.size();
144    // Find out how many elements are not padding
145    for (size_t ct = 0; ct < fieldCount; ct ++) {
146        if (mElementNames[ct].c_str()[0] != '#') {
147            noPaddingFieldCount ++;
148        }
149    }
150
151    // Make a map that points us at non-padding elements
152    for (size_t ct = 0; ct < fieldCount; ct ++) {
153        if (mElementNames[ct].c_str()[0] != '#') {
154            mVisibleElementMap.push_back((uint32_t)ct);
155        }
156    }
157}
158
159Element::Element(void *id, android::RSC::sp<RS> rs,
160                 std::vector<android::RSC::sp<Element> > &elements,
161                 std::vector<std::string> &elementNames,
162                 std::vector<uint32_t> &arraySizes) : BaseObj(id, rs) {
163    mSizeBytes = 0;
164    mVectorSize = 1;
165    mElements = elements;
166    mArraySizes = arraySizes;
167    mElementNames = elementNames;
168
169    mType = RS_TYPE_NONE;
170    mKind = RS_KIND_USER;
171
172    for (size_t ct = 0; ct < mElements.size(); ct++ ) {
173        mOffsetInBytes.push_back(mSizeBytes);
174        mSizeBytes += mElements[ct]->mSizeBytes * mArraySizes[ct];
175    }
176    updateVisibleSubElements();
177}
178
179
180static uint32_t GetSizeInBytesForType(RsDataType dt) {
181    switch(dt) {
182    case RS_TYPE_NONE:
183        return 0;
184    case RS_TYPE_SIGNED_8:
185    case RS_TYPE_UNSIGNED_8:
186    case RS_TYPE_BOOLEAN:
187        return 1;
188
189    case RS_TYPE_FLOAT_16:
190    case RS_TYPE_SIGNED_16:
191    case RS_TYPE_UNSIGNED_16:
192    case RS_TYPE_UNSIGNED_5_6_5:
193    case RS_TYPE_UNSIGNED_5_5_5_1:
194    case RS_TYPE_UNSIGNED_4_4_4_4:
195        return 2;
196
197    case RS_TYPE_FLOAT_32:
198    case RS_TYPE_SIGNED_32:
199    case RS_TYPE_UNSIGNED_32:
200        return 4;
201
202    case RS_TYPE_FLOAT_64:
203    case RS_TYPE_SIGNED_64:
204    case RS_TYPE_UNSIGNED_64:
205        return 8;
206
207    case RS_TYPE_MATRIX_4X4:
208        return 16 * 4;
209    case RS_TYPE_MATRIX_3X3:
210        return 9 * 4;
211    case RS_TYPE_MATRIX_2X2:
212        return 4 * 4;
213
214    case RS_TYPE_TYPE:
215    case RS_TYPE_ALLOCATION:
216    case RS_TYPE_SAMPLER:
217    case RS_TYPE_SCRIPT:
218    case RS_TYPE_MESH:
219    case RS_TYPE_PROGRAM_FRAGMENT:
220    case RS_TYPE_PROGRAM_VERTEX:
221    case RS_TYPE_PROGRAM_RASTER:
222    case RS_TYPE_PROGRAM_STORE:
223        return 4;
224
225    default:
226        break;
227    }
228
229    ALOGE("Missing type %i", dt);
230    return 0;
231}
232
233Element::Element(void *id, android::RSC::sp<RS> rs,
234                 RsDataType dt, RsDataKind dk, bool norm, uint32_t size) :
235    BaseObj(id, rs)
236{
237    uint32_t tsize = GetSizeInBytesForType(dt);
238    if ((dt != RS_TYPE_UNSIGNED_5_6_5) &&
239        (dt != RS_TYPE_UNSIGNED_4_4_4_4) &&
240        (dt != RS_TYPE_UNSIGNED_5_5_5_1)) {
241        if (size == 3) {
242            mSizeBytes = tsize * 4;
243        } else {
244            mSizeBytes = tsize * size;
245        }
246    } else {
247        mSizeBytes = tsize;
248    }
249    mType = dt;
250    mKind = dk;
251    mNormalized = norm;
252    mVectorSize = size;
253}
254
255Element::~Element() {
256}
257
258void Element::updateFromNative() {
259    BaseObj::updateFromNative();
260    updateVisibleSubElements();
261}
262
263android::RSC::sp<const Element> Element::createUser(android::RSC::sp<RS> rs, RsDataType dt) {
264    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, 1);
265    return new Element(id, rs, dt, RS_KIND_USER, false, 1);
266}
267
268android::RSC::sp<const Element> Element::createVector(android::RSC::sp<RS> rs, RsDataType dt, uint32_t size) {
269    if (size < 2 || size > 4) {
270        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Vector size out of range 2-4.");
271        return NULL;
272    }
273    void *id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, size);
274    return new Element(id, rs, dt, RS_KIND_USER, false, size);
275}
276
277android::RSC::sp<const Element> Element::createPixel(android::RSC::sp<RS> rs, RsDataType dt, RsDataKind dk) {
278    if (!(dk == RS_KIND_PIXEL_L ||
279          dk == RS_KIND_PIXEL_A ||
280          dk == RS_KIND_PIXEL_LA ||
281          dk == RS_KIND_PIXEL_RGB ||
282          dk == RS_KIND_PIXEL_RGBA ||
283          dk == RS_KIND_PIXEL_DEPTH)) {
284        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataKind");
285        return NULL;
286    }
287    if (!(dt == RS_TYPE_UNSIGNED_8 ||
288          dt == RS_TYPE_UNSIGNED_16 ||
289          dt == RS_TYPE_UNSIGNED_5_6_5 ||
290          dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
291          dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
292        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataType");
293        return NULL;
294    }
295    if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
296        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
297        return NULL;
298    }
299    if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
300        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
301        return NULL;
302    }
303    if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
304        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
305        return NULL;
306    }
307    if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
308        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
309        return NULL;
310    }
311
312    int size = 1;
313    switch (dk) {
314    case RS_KIND_PIXEL_LA:
315        size = 2;
316        break;
317    case RS_KIND_PIXEL_RGB:
318        size = 3;
319        break;
320    case RS_KIND_PIXEL_RGBA:
321        size = 4;
322        break;
323    case RS_KIND_PIXEL_DEPTH:
324        size = 2;
325        break;
326    default:
327        break;
328    }
329
330    void * id = RS::dispatch->ElementCreate(rs->getContext(), dt, dk, true, size);
331    return new Element(id, rs, dt, dk, true, size);
332}
333
334bool Element::isCompatible(android::RSC::sp<const Element>e) const {
335    // Try strict BaseObj equality to start with.
336    if (this == e.get()) {
337        return true;
338    }
339
340    // Ignore mKind because it is allowed to be different (user vs. pixel).
341    // We also ignore mNormalized because it can be different. The mType
342    // field must be non-null since we require name equivalence for
343    // user-created Elements.
344    return ((mSizeBytes == e->mSizeBytes) &&
345            (mType != RS_TYPE_NONE) &&
346            (mType == e->mType) &&
347            (mVectorSize == e->mVectorSize));
348}
349
350Element::Builder::Builder(android::RSC::sp<RS> rs) {
351    mRS = rs;
352    mSkipPadding = false;
353}
354
355void Element::Builder::add(android::RSC::sp</*const*/ Element>e, std::string &name, uint32_t arraySize) {
356    // Skip padding fields after a vector 3 type.
357    if (mSkipPadding) {
358        const char *s1 = "#padding_";
359        const char *s2 = name.c_str();
360        size_t len = strlen(s1);
361        if (strlen(s2) >= len) {
362            if (!memcmp(s1, s2, len)) {
363                mSkipPadding = false;
364                return;
365            }
366        }
367    }
368
369    if (e->mVectorSize == 3) {
370        mSkipPadding = true;
371    } else {
372        mSkipPadding = false;
373    }
374
375    mElements.push_back(e);
376    mElementNames.push_back(name);
377    mArraySizes.push_back(arraySize);
378}
379
380android::RSC::sp<const Element> Element::Builder::create() {
381    size_t fieldCount = mElements.size();
382    const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
383    const Element ** elementArray = (const Element **)calloc(fieldCount, sizeof(Element *));
384    size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
385
386    for (size_t ct = 0; ct < fieldCount; ct++) {
387        nameArray[ct] = mElementNames[ct].c_str();
388        elementArray[ct] = mElements[ct].get();
389        sizeArray[ct] = mElementNames[ct].length();
390    }
391
392    void *id = RS::dispatch->ElementCreate2(mRS->getContext(),
393                                (RsElement *)elementArray, fieldCount,
394                                nameArray, fieldCount * sizeof(size_t),  sizeArray,
395                                (const uint32_t *)&mArraySizes[0], fieldCount);
396
397
398    free(nameArray);
399    free(sizeArray);
400    free(elementArray);
401    return new Element(id, mRS, mElements, mElementNames, mArraySizes);
402}
403
404