• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 using namespace android;
24 using namespace RSC;
25 
getSubElement(uint32_t index)26 android::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 
getSubElementName(uint32_t index)38 const 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 
getSubElementArraySize(uint32_t index)50 size_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 
getSubElementOffsetBytes(uint32_t index)62 uint32_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 
82 CREATE_USER(BOOLEAN, BOOLEAN);
83 CREATE_USER(U8, UNSIGNED_8);
84 CREATE_USER(I8, SIGNED_8);
85 CREATE_USER(U16, UNSIGNED_16);
86 CREATE_USER(I16, SIGNED_16);
87 CREATE_USER(U32, UNSIGNED_32);
88 CREATE_USER(I32, SIGNED_32);
89 CREATE_USER(U64, UNSIGNED_64);
90 CREATE_USER(I64, SIGNED_64);
91 CREATE_USER(F16, FLOAT_16);
92 CREATE_USER(F32, FLOAT_32);
93 CREATE_USER(F64, FLOAT_64);
94 CREATE_USER(ELEMENT, ELEMENT);
95 CREATE_USER(TYPE, TYPE);
96 CREATE_USER(ALLOCATION, ALLOCATION);
97 CREATE_USER(SAMPLER, SAMPLER);
98 CREATE_USER(SCRIPT, SCRIPT);
99 CREATE_USER(MATRIX_4X4, MATRIX_4X4);
100 CREATE_USER(MATRIX_3X3, MATRIX_3X3);
101 CREATE_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 
110 CREATE_PIXEL(A_8, UNSIGNED_8, PIXEL_A);
111 CREATE_PIXEL(RGB_565, UNSIGNED_5_6_5, PIXEL_RGB);
112 CREATE_PIXEL(RGB_888, UNSIGNED_8, PIXEL_RGB);
113 CREATE_PIXEL(RGBA_4444, UNSIGNED_4_4_4_4, PIXEL_RGBA);
114 CREATE_PIXEL(RGBA_8888, UNSIGNED_8, PIXEL_RGBA);
115 CREATE_PIXEL(YUV, UNSIGNED_8, PIXEL_YUV);
116 CREATE_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 }                                                                         \
124 android::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 } \
130 android::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 }
136 CREATE_VECTOR(U8, UNSIGNED_8);
137 CREATE_VECTOR(I8, SIGNED_8);
138 CREATE_VECTOR(U16, UNSIGNED_16);
139 CREATE_VECTOR(I16, SIGNED_16);
140 CREATE_VECTOR(U32, UNSIGNED_32);
141 CREATE_VECTOR(I32, SIGNED_32);
142 CREATE_VECTOR(U64, UNSIGNED_64);
143 CREATE_VECTOR(I64, SIGNED_64);
144 CREATE_VECTOR(F16, FLOAT_16);
145 CREATE_VECTOR(F32, FLOAT_32);
146 CREATE_VECTOR(F64, FLOAT_64);
147 
148 
updateVisibleSubElements()149 void 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 
Element(void * id,android::RSC::sp<RS> rs,android::RSC::sp<const Element> * elements,size_t elementCount,const char ** elementNames,size_t * elementNameLengths,uint32_t * arraySizes)178 Element::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 
Element(void * id,android::RSC::sp<RS> rs)217 Element::Element(void *id, android::RSC::sp<RS> rs) :
218     BaseObj(id, rs) {
219 }
220 
GetSizeInBytesForType(RsDataType dt)221 static 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 
Element(void * id,android::RSC::sp<RS> rs,RsDataType dt,RsDataKind dk,bool norm,uint32_t size)274 Element::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 
~Element()298 Element::~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 
updateFromNative()314 void Element::updateFromNative() {
315     BaseObj::updateFromNative();
316     updateVisibleSubElements();
317 }
318 
createUser(android::RSC::sp<RS> rs,RsDataType dt)319 android::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 
createVector(android::RSC::sp<RS> rs,RsDataType dt,uint32_t size)324 android::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 
createPixel(android::RSC::sp<RS> rs,RsDataType dt,RsDataKind dk)333 android::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 
isCompatible(android::RSC::sp<const Element> e) const391 bool 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 
Builder(android::RSC::sp<RS> rs)409 Element::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 
~Builder()421 Element::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 
add(android::RSC::sp<const Element> e,const char * name,uint32_t arraySize)432 void 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 
create()489 android::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