blob: 51a96cd2a1004b4651694609432c570297ff1e00 [file] [log] [blame]
Jason Sams221a4b12012-02-22 15:22:41 -08001/*
Jason Sams69cccdf2012-04-02 19:11:49 -07002 * Copyright (C) 2012 The Android Open Source Project
Jason Sams221a4b12012-02-22 15:22:41 -08003 *
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
Jason Sams221a4b12012-02-22 15:22:41 -080017#include <malloc.h>
18#include <string.h>
19
20#include "RenderScript.h"
Tim Murrayb206ace2013-02-13 14:52:20 -080021#include <rs.h>
Jason Sams221a4b12012-02-22 15:22:41 -080022
Jason Sams69cccdf2012-04-02 19:11:49 -070023using namespace android;
Tim Murray9eb7f4b2012-11-16 14:02:18 -080024using namespace RSC;
Jason Sams221a4b12012-02-22 15:22:41 -080025
Jason Sams69cccdf2012-04-02 19:11:49 -070026sp<const Element> Element::getSubElement(uint32_t index) {
Jason Sams221a4b12012-02-22 15:22:41 -080027 if (!mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080028 mRS->throwError("Element contains no sub-elements");
Jason Sams221a4b12012-02-22 15:22:41 -080029 }
30 if (index >= mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080031 mRS->throwError("Illegal sub-element index");
Jason Sams221a4b12012-02-22 15:22:41 -080032 }
33 return mElements[mVisibleElementMap[index]];
34}
35
36const char * Element::getSubElementName(uint32_t index) {
37 if (!mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080038 mRS->throwError("Element contains no sub-elements");
Jason Sams221a4b12012-02-22 15:22:41 -080039 }
40 if (index >= mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080041 mRS->throwError("Illegal sub-element index");
Jason Sams221a4b12012-02-22 15:22:41 -080042 }
Tim Murray0b575de2013-03-15 15:56:43 -070043 return mElementNames[mVisibleElementMap[index]].string();
Jason Sams221a4b12012-02-22 15:22:41 -080044}
45
46size_t Element::getSubElementArraySize(uint32_t index) {
47 if (!mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080048 mRS->throwError("Element contains no sub-elements");
Jason Sams221a4b12012-02-22 15:22:41 -080049 }
50 if (index >= mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080051 mRS->throwError("Illegal sub-element index");
Jason Sams221a4b12012-02-22 15:22:41 -080052 }
53 return mArraySizes[mVisibleElementMap[index]];
54}
55
56uint32_t Element::getSubElementOffsetBytes(uint32_t index) {
57 if (mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080058 mRS->throwError("Element contains no sub-elements");
Jason Sams221a4b12012-02-22 15:22:41 -080059 }
60 if (index >= mVisibleElementMap.size()) {
Jason Samsb2e3dc52012-02-23 17:14:39 -080061 mRS->throwError("Illegal sub-element index");
Jason Sams221a4b12012-02-22 15:22:41 -080062 }
63 return mOffsetInBytes[mVisibleElementMap[index]];
64}
65
66
Tim Murray84bf2b82012-10-31 16:03:16 -070067#define CREATE_USER(N, T) sp<const Element> Element::N(sp<RS> rs) { \
Jason Sams221a4b12012-02-22 15:22:41 -080068 return createUser(rs, RS_TYPE_##T); \
69}
70CREATE_USER(BOOLEAN, BOOLEAN);
71CREATE_USER(U8, UNSIGNED_8);
72CREATE_USER(I8, SIGNED_8);
73CREATE_USER(U16, UNSIGNED_16);
74CREATE_USER(I16, SIGNED_16);
75CREATE_USER(U32, UNSIGNED_32);
76CREATE_USER(I32, SIGNED_32);
77CREATE_USER(U64, UNSIGNED_64);
78CREATE_USER(I64, SIGNED_64);
79CREATE_USER(F32, FLOAT_32);
80CREATE_USER(F64, FLOAT_64);
81CREATE_USER(ELEMENT, ELEMENT);
82CREATE_USER(TYPE, TYPE);
83CREATE_USER(ALLOCATION, ALLOCATION);
84CREATE_USER(SAMPLER, SAMPLER);
85CREATE_USER(SCRIPT, SCRIPT);
86CREATE_USER(MESH, MESH);
87CREATE_USER(PROGRAM_FRAGMENT, PROGRAM_FRAGMENT);
88CREATE_USER(PROGRAM_VERTEX, PROGRAM_VERTEX);
89CREATE_USER(PROGRAM_RASTER, PROGRAM_RASTER);
90CREATE_USER(PROGRAM_STORE, PROGRAM_STORE);
91CREATE_USER(MATRIX_4X4, MATRIX_4X4);
92CREATE_USER(MATRIX_3X3, MATRIX_3X3);
93CREATE_USER(MATRIX_2X2, MATRIX_2X2);
94
Tim Murray84bf2b82012-10-31 16:03:16 -070095#define CREATE_PIXEL(N, T, K) sp<const Element> Element::N(sp<RS> rs) { \
Jason Sams221a4b12012-02-22 15:22:41 -080096 return createPixel(rs, RS_TYPE_##T, RS_KIND_##K); \
97}
98CREATE_PIXEL(A_8, UNSIGNED_8, PIXEL_A);
99CREATE_PIXEL(RGB_565, UNSIGNED_5_6_5, PIXEL_RGB);
100CREATE_PIXEL(RGB_888, UNSIGNED_8, PIXEL_RGB);
101CREATE_PIXEL(RGBA_4444, UNSIGNED_4_4_4_4, PIXEL_RGBA);
102CREATE_PIXEL(RGBA_8888, UNSIGNED_8, PIXEL_RGBA);
103
Tim Murray84bf2b82012-10-31 16:03:16 -0700104#define CREATE_VECTOR(N, T) sp<const Element> Element::N##_2(sp<RS> rs) { \
Jason Sams221a4b12012-02-22 15:22:41 -0800105 return createVector(rs, RS_TYPE_##T, 2); \
106} \
Tim Murray84bf2b82012-10-31 16:03:16 -0700107sp<const Element> Element::N##_3(sp<RS> rs) { \
Jason Sams221a4b12012-02-22 15:22:41 -0800108 return createVector(rs, RS_TYPE_##T, 3); \
109} \
Tim Murray84bf2b82012-10-31 16:03:16 -0700110sp<const Element> Element::N##_4(sp<RS> rs) { \
Jason Sams221a4b12012-02-22 15:22:41 -0800111 return createVector(rs, RS_TYPE_##T, 4); \
112}
113CREATE_VECTOR(U8, UNSIGNED_8);
114CREATE_VECTOR(I8, SIGNED_8);
115CREATE_VECTOR(U16, UNSIGNED_16);
116CREATE_VECTOR(I16, SIGNED_16);
117CREATE_VECTOR(U32, UNSIGNED_32);
118CREATE_VECTOR(I32, SIGNED_32);
119CREATE_VECTOR(U64, UNSIGNED_64);
120CREATE_VECTOR(I64, SIGNED_64);
121CREATE_VECTOR(F32, FLOAT_32);
122CREATE_VECTOR(F64, FLOAT_64);
123
124
125void Element::updateVisibleSubElements() {
126 if (!mElements.size()) {
127 return;
128 }
129 mVisibleElementMap.clear();
130
131 int noPaddingFieldCount = 0;
132 size_t fieldCount = mElementNames.size();
133 // Find out how many elements are not padding
134 for (size_t ct = 0; ct < fieldCount; ct ++) {
135 if (mElementNames[ct].string()[0] != '#') {
136 noPaddingFieldCount ++;
137 }
138 }
139
140 // Make a map that points us at non-padding elements
141 for (size_t ct = 0; ct < fieldCount; ct ++) {
142 if (mElementNames[ct].string()[0] != '#') {
143 mVisibleElementMap.push((uint32_t)ct);
144 }
145 }
146}
147
Tim Murray84bf2b82012-10-31 16:03:16 -0700148Element::Element(void *id, sp<RS> rs,
149 android::Vector<sp<Element> > &elements,
Jason Sams221a4b12012-02-22 15:22:41 -0800150 android::Vector<android::String8> &elementNames,
151 android::Vector<uint32_t> &arraySizes) : BaseObj(id, rs) {
152 mSizeBytes = 0;
153 mVectorSize = 1;
154 mElements = elements;
155 mArraySizes = arraySizes;
156 mElementNames = elementNames;
157
158 mType = RS_TYPE_NONE;
159 mKind = RS_KIND_USER;
160
161 for (size_t ct = 0; ct < mElements.size(); ct++ ) {
162 mOffsetInBytes.push(mSizeBytes);
163 mSizeBytes += mElements[ct]->mSizeBytes * mArraySizes[ct];
164 }
165 updateVisibleSubElements();
166}
167
168
169static uint32_t GetSizeInBytesForType(RsDataType dt) {
170 switch(dt) {
171 case RS_TYPE_NONE:
172 return 0;
173 case RS_TYPE_SIGNED_8:
174 case RS_TYPE_UNSIGNED_8:
175 case RS_TYPE_BOOLEAN:
176 return 1;
177
178 case RS_TYPE_FLOAT_16:
179 case RS_TYPE_SIGNED_16:
180 case RS_TYPE_UNSIGNED_16:
181 case RS_TYPE_UNSIGNED_5_6_5:
182 case RS_TYPE_UNSIGNED_5_5_5_1:
183 case RS_TYPE_UNSIGNED_4_4_4_4:
184 return 2;
185
186 case RS_TYPE_FLOAT_32:
187 case RS_TYPE_SIGNED_32:
188 case RS_TYPE_UNSIGNED_32:
189 return 4;
190
191 case RS_TYPE_FLOAT_64:
192 case RS_TYPE_SIGNED_64:
193 case RS_TYPE_UNSIGNED_64:
194 return 8;
195
196 case RS_TYPE_MATRIX_4X4:
197 return 16 * 4;
198 case RS_TYPE_MATRIX_3X3:
199 return 9 * 4;
200 case RS_TYPE_MATRIX_2X2:
201 return 4 * 4;
202
203 case RS_TYPE_TYPE:
204 case RS_TYPE_ALLOCATION:
205 case RS_TYPE_SAMPLER:
206 case RS_TYPE_SCRIPT:
207 case RS_TYPE_MESH:
208 case RS_TYPE_PROGRAM_FRAGMENT:
209 case RS_TYPE_PROGRAM_VERTEX:
210 case RS_TYPE_PROGRAM_RASTER:
211 case RS_TYPE_PROGRAM_STORE:
212 return 4;
213
214 default:
215 break;
216 }
217
218 ALOGE("Missing type %i", dt);
219 return 0;
220}
221
Tim Murray84bf2b82012-10-31 16:03:16 -0700222Element::Element(void *id, sp<RS> rs,
Jason Sams221a4b12012-02-22 15:22:41 -0800223 RsDataType dt, RsDataKind dk, bool norm, uint32_t size) :
224 BaseObj(id, rs)
225{
226 uint32_t tsize = GetSizeInBytesForType(dt);
227 if ((dt != RS_TYPE_UNSIGNED_5_6_5) &&
228 (dt != RS_TYPE_UNSIGNED_4_4_4_4) &&
229 (dt != RS_TYPE_UNSIGNED_5_5_5_1)) {
230 if (size == 3) {
231 mSizeBytes = tsize * 4;
232 } else {
233 mSizeBytes = tsize * size;
234 }
235 } else {
236 mSizeBytes = tsize;
237 }
238 mType = dt;
239 mKind = dk;
240 mNormalized = norm;
241 mVectorSize = size;
242}
243
244Element::~Element() {
245}
246
Jason Sams221a4b12012-02-22 15:22:41 -0800247void Element::updateFromNative() {
248 BaseObj::updateFromNative();
Jason Sams221a4b12012-02-22 15:22:41 -0800249 updateVisibleSubElements();
250}
251
Tim Murray84bf2b82012-10-31 16:03:16 -0700252sp<const Element> Element::createUser(sp<RS> rs, RsDataType dt) {
253 void * id = rsElementCreate(rs->getContext(), dt, RS_KIND_USER, false, 1);
Jason Sams221a4b12012-02-22 15:22:41 -0800254 return new Element(id, rs, dt, RS_KIND_USER, false, 1);
255}
256
Tim Murray84bf2b82012-10-31 16:03:16 -0700257sp<const Element> Element::createVector(sp<RS> rs, RsDataType dt, uint32_t size) {
Jason Sams221a4b12012-02-22 15:22:41 -0800258 if (size < 2 || size > 4) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800259 rs->throwError("Vector size out of range 2-4.");
Jason Sams221a4b12012-02-22 15:22:41 -0800260 }
Tim Murray84bf2b82012-10-31 16:03:16 -0700261 void *id = rsElementCreate(rs->getContext(), dt, RS_KIND_USER, false, size);
Jason Sams221a4b12012-02-22 15:22:41 -0800262 return new Element(id, rs, dt, RS_KIND_USER, false, size);
263}
264
Tim Murray84bf2b82012-10-31 16:03:16 -0700265sp<const Element> Element::createPixel(sp<RS> rs, RsDataType dt, RsDataKind dk) {
Jason Sams221a4b12012-02-22 15:22:41 -0800266 if (!(dk == RS_KIND_PIXEL_L ||
267 dk == RS_KIND_PIXEL_A ||
268 dk == RS_KIND_PIXEL_LA ||
269 dk == RS_KIND_PIXEL_RGB ||
270 dk == RS_KIND_PIXEL_RGBA ||
271 dk == RS_KIND_PIXEL_DEPTH)) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800272 rs->throwError("Unsupported DataKind");
Jason Sams221a4b12012-02-22 15:22:41 -0800273 }
274 if (!(dt == RS_TYPE_UNSIGNED_8 ||
275 dt == RS_TYPE_UNSIGNED_16 ||
276 dt == RS_TYPE_UNSIGNED_5_6_5 ||
277 dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
278 dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800279 rs->throwError("Unsupported DataType");
Jason Sams221a4b12012-02-22 15:22:41 -0800280 }
281 if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800282 rs->throwError("Bad kind and type combo");
Jason Sams221a4b12012-02-22 15:22:41 -0800283 }
284 if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800285 rs->throwError("Bad kind and type combo");
Jason Sams221a4b12012-02-22 15:22:41 -0800286 }
287 if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800288 rs->throwError("Bad kind and type combo");
Jason Sams221a4b12012-02-22 15:22:41 -0800289 }
290 if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
Jason Samsb2e3dc52012-02-23 17:14:39 -0800291 rs->throwError("Bad kind and type combo");
Jason Sams221a4b12012-02-22 15:22:41 -0800292 }
293
294 int size = 1;
295 switch (dk) {
296 case RS_KIND_PIXEL_LA:
297 size = 2;
298 break;
299 case RS_KIND_PIXEL_RGB:
300 size = 3;
301 break;
302 case RS_KIND_PIXEL_RGBA:
303 size = 4;
304 break;
305 case RS_KIND_PIXEL_DEPTH:
306 size = 2;
307 break;
308 default:
309 break;
310 }
311
Tim Murray84bf2b82012-10-31 16:03:16 -0700312 void * id = rsElementCreate(rs->getContext(), dt, dk, true, size);
Jason Sams221a4b12012-02-22 15:22:41 -0800313 return new Element(id, rs, dt, dk, true, size);
314}
315
Jason Sams69cccdf2012-04-02 19:11:49 -0700316bool Element::isCompatible(sp<const Element>e) {
Jason Sams221a4b12012-02-22 15:22:41 -0800317 // Try strict BaseObj equality to start with.
Jason Sams69cccdf2012-04-02 19:11:49 -0700318 if (this == e.get()) {
Jason Sams221a4b12012-02-22 15:22:41 -0800319 return true;
320 }
321
322 // Ignore mKind because it is allowed to be different (user vs. pixel).
323 // We also ignore mNormalized because it can be different. The mType
324 // field must be non-null since we require name equivalence for
325 // user-created Elements.
326 return ((mSizeBytes == e->mSizeBytes) &&
Jason Sams69cccdf2012-04-02 19:11:49 -0700327 (mType != RS_TYPE_NONE) &&
Jason Sams221a4b12012-02-22 15:22:41 -0800328 (mType == e->mType) &&
329 (mVectorSize == e->mVectorSize));
330}
331
Tim Murray84bf2b82012-10-31 16:03:16 -0700332Element::Builder::Builder(sp<RS> rs) {
Jason Sams221a4b12012-02-22 15:22:41 -0800333 mRS = rs;
334 mSkipPadding = false;
335}
336
Jason Sams69cccdf2012-04-02 19:11:49 -0700337void Element::Builder::add(sp</*const*/ Element>e, android::String8 &name, uint32_t arraySize) {
Jason Sams221a4b12012-02-22 15:22:41 -0800338 // Skip padding fields after a vector 3 type.
339 if (mSkipPadding) {
340 const char *s1 = "#padding_";
Tim Murray0b575de2013-03-15 15:56:43 -0700341 const char *s2 = name.string();
Jason Sams221a4b12012-02-22 15:22:41 -0800342 size_t len = strlen(s1);
343 if (strlen(s2) >= len) {
344 if (!memcmp(s1, s2, len)) {
345 mSkipPadding = false;
346 return;
347 }
348 }
349 }
350
351 if (e->mVectorSize == 3) {
352 mSkipPadding = true;
353 } else {
354 mSkipPadding = false;
355 }
356
357 mElements.add(e);
358 mElementNames.add(name);
359 mArraySizes.add(arraySize);
360}
361
Jason Sams69cccdf2012-04-02 19:11:49 -0700362sp<const Element> Element::Builder::create() {
Jason Sams221a4b12012-02-22 15:22:41 -0800363 size_t fieldCount = mElements.size();
364 const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
Jason Sams69cccdf2012-04-02 19:11:49 -0700365 const Element ** elementArray = (const Element **)calloc(fieldCount, sizeof(Element *));
Jason Sams221a4b12012-02-22 15:22:41 -0800366 size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
367
368 for (size_t ct = 0; ct < fieldCount; ct++) {
369 nameArray[ct] = mElementNames[ct].string();
Jason Sams69cccdf2012-04-02 19:11:49 -0700370 elementArray[ct] = mElements[ct].get();
Jason Sams221a4b12012-02-22 15:22:41 -0800371 sizeArray[ct] = mElementNames[ct].length();
372 }
373
Tim Murray84bf2b82012-10-31 16:03:16 -0700374 void *id = rsElementCreate2(mRS->getContext(),
Jason Sams69cccdf2012-04-02 19:11:49 -0700375 (RsElement *)elementArray, fieldCount,
Jason Sams221a4b12012-02-22 15:22:41 -0800376 nameArray, fieldCount * sizeof(size_t), sizeArray,
377 (const uint32_t *)mArraySizes.array(), fieldCount);
378
379
380 free(nameArray);
381 free(sizeArray);
Jason Sams69cccdf2012-04-02 19:11:49 -0700382 free(elementArray);
383 return new Element(id, mRS, mElements, mElementNames, mArraySizes);
Jason Sams221a4b12012-02-22 15:22:41 -0800384}
385