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