blob: c621c8272f85f9f25fd25259ac4ddbaad78bf7a5 [file] [log] [blame]
Jason Samsf70b0fc82012-02-22 15:22:41 -08001/*
2 * Copyright (C) 2008-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 <utils/Log.h>
18#include <malloc.h>
19#include <string.h>
20
21#include "RenderScript.h"
22#include "Element.h"
23
24
25const Element * Element::getSubElement(uint32_t index) {
26 if (!mVisibleElementMap.size()) {
27 ALOGE("Element contains no sub-elements");
28 return NULL;
29 }
30 if (index >= mVisibleElementMap.size()) {
31 ALOGE("Illegal sub-element index");
32 }
33 return mElements[mVisibleElementMap[index]];
34}
35
36const char * Element::getSubElementName(uint32_t index) {
37 if (!mVisibleElementMap.size()) {
38 ALOGE("Element contains no sub-elements");
39 }
40 if (index >= mVisibleElementMap.size()) {
41 ALOGE("Illegal sub-element index");
42 }
43 return mElementNames[mVisibleElementMap[index]];
44}
45
46size_t Element::getSubElementArraySize(uint32_t index) {
47 if (!mVisibleElementMap.size()) {
48 ALOGE("Element contains no sub-elements");
49 }
50 if (index >= mVisibleElementMap.size()) {
51 ALOGE("Illegal sub-element index");
52 }
53 return mArraySizes[mVisibleElementMap[index]];
54}
55
56uint32_t Element::getSubElementOffsetBytes(uint32_t index) {
57 if (mVisibleElementMap.size()) {
58 ALOGE("Element contains no sub-elements");
59 }
60 if (index >= mVisibleElementMap.size()) {
61 ALOGE("Illegal sub-element index");
62 }
63 return mOffsetInBytes[mVisibleElementMap[index]];
64}
65
66
67#define CREATE_USER(N, T) const Element * Element::N(RenderScript *rs) { \
68 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
95#define CREATE_PIXEL(N, T, K) const Element * Element::N(RenderScript *rs) { \
96 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
104#define CREATE_VECTOR(N, T) const Element * Element::N##_2(RenderScript *rs) { \
105 return createVector(rs, RS_TYPE_##T, 2); \
106} \
107const Element * Element::N##_3(RenderScript *rs) { \
108 return createVector(rs, RS_TYPE_##T, 3); \
109} \
110const Element * Element::N##_4(RenderScript *rs) { \
111 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
148Element::Element(void *id, RenderScript *rs,
149 android::Vector<const Element *> &elements,
150 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
222Element::Element(void *id, RenderScript *rs,
223 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
247 /*
248 Element(int id, RenderScript rs) {
249 super(id, rs);
250 }
251 */
252
253void Element::updateFromNative() {
254 BaseObj::updateFromNative();
255/*
256 // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
257 int[] dataBuffer = new int[5];
258 mRS.nElementGetNativeData(getID(), dataBuffer);
259
260 mNormalized = dataBuffer[2] == 1 ? true : false;
261 mVectorSize = dataBuffer[3];
262 mSize = 0;
263 for (DataType dt: DataType.values()) {
264 if(dt.mID == dataBuffer[0]){
265 mType = dt;
266 mSize = mType.mSize * mVectorSize;
267 }
268 }
269 for (DataKind dk: DataKind.values()) {
270 if(dk.mID == dataBuffer[1]){
271 mKind = dk;
272 }
273 }
274
275 int numSubElements = dataBuffer[4];
276 if(numSubElements > 0) {
277 mElements = new Element[numSubElements];
278 mElementNames = new String[numSubElements];
279 mArraySizes = new int[numSubElements];
280 mOffsetInBytes = new int[numSubElements];
281
282 int[] subElementIds = new int[numSubElements];
283 mRS.nElementGetSubElements(getID(), subElementIds, mElementNames, mArraySizes);
284 for(int i = 0; i < numSubElements; i ++) {
285 mElements[i] = new Element(subElementIds[i], mRS);
286 mElements[i].updateFromNative();
287 mOffsetInBytes[i] = mSize;
288 mSize += mElements[i].mSize * mArraySizes[i];
289 }
290 }
291 */
292 updateVisibleSubElements();
293}
294
295const Element * Element::createUser(RenderScript *rs, RsDataType dt) {
296 ALOGE("createUser %p %i", rs, dt);
297 void * id = rsElementCreate(rs->mContext, dt, RS_KIND_USER, false, 1);
298 return new Element(id, rs, dt, RS_KIND_USER, false, 1);
299}
300
301const Element * Element::createVector(RenderScript *rs, RsDataType dt, uint32_t size) {
302 if (size < 2 || size > 4) {
303 ALOGE("Vector size out of range 2-4.");
304 return NULL;
305 }
306 void *id = rsElementCreate(rs->mContext, dt, RS_KIND_USER, false, size);
307 return new Element(id, rs, dt, RS_KIND_USER, false, size);
308}
309
310const Element * Element::createPixel(RenderScript *rs, RsDataType dt, RsDataKind dk) {
311 ALOGE("createPixel %p %i %i", rs, dt, dk);
312 if (!(dk == RS_KIND_PIXEL_L ||
313 dk == RS_KIND_PIXEL_A ||
314 dk == RS_KIND_PIXEL_LA ||
315 dk == RS_KIND_PIXEL_RGB ||
316 dk == RS_KIND_PIXEL_RGBA ||
317 dk == RS_KIND_PIXEL_DEPTH)) {
318 ALOGE("Unsupported DataKind");
319 return NULL;
320 }
321 if (!(dt == RS_TYPE_UNSIGNED_8 ||
322 dt == RS_TYPE_UNSIGNED_16 ||
323 dt == RS_TYPE_UNSIGNED_5_6_5 ||
324 dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
325 dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
326 ALOGE("Unsupported DataType");
327 return NULL;
328 }
329 if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
330 ALOGE("Bad kind and type combo");
331 return NULL;
332 }
333 if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
334 ALOGE("Bad kind and type combo");
335 return NULL;
336 }
337 if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
338 ALOGE("Bad kind and type combo");
339 return NULL;
340 }
341 if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
342 ALOGE("Bad kind and type combo");
343 return NULL;
344 }
345
346 int size = 1;
347 switch (dk) {
348 case RS_KIND_PIXEL_LA:
349 size = 2;
350 break;
351 case RS_KIND_PIXEL_RGB:
352 size = 3;
353 break;
354 case RS_KIND_PIXEL_RGBA:
355 size = 4;
356 break;
357 case RS_KIND_PIXEL_DEPTH:
358 size = 2;
359 break;
360 default:
361 break;
362 }
363
364 void * id = rsElementCreate(rs->mContext, dt, dk, true, size);
365 return new Element(id, rs, dt, dk, true, size);
366}
367
368bool Element::isCompatible(const Element *e) {
369 // Try strict BaseObj equality to start with.
370 if (this == e) {
371 return true;
372 }
373
374 // Ignore mKind because it is allowed to be different (user vs. pixel).
375 // We also ignore mNormalized because it can be different. The mType
376 // field must be non-null since we require name equivalence for
377 // user-created Elements.
378 return ((mSizeBytes == e->mSizeBytes) &&
379 (mType != NULL) &&
380 (mType == e->mType) &&
381 (mVectorSize == e->mVectorSize));
382}
383
384Element::Builder::Builder(RenderScript *rs) {
385 mRS = rs;
386 mSkipPadding = false;
387}
388
389void Element::Builder::add(const Element *e, android::String8 &name, uint32_t arraySize) {
390 // Skip padding fields after a vector 3 type.
391 if (mSkipPadding) {
392 const char *s1 = "#padding_";
393 const char *s2 = name;
394 size_t len = strlen(s1);
395 if (strlen(s2) >= len) {
396 if (!memcmp(s1, s2, len)) {
397 mSkipPadding = false;
398 return;
399 }
400 }
401 }
402
403 if (e->mVectorSize == 3) {
404 mSkipPadding = true;
405 } else {
406 mSkipPadding = false;
407 }
408
409 mElements.add(e);
410 mElementNames.add(name);
411 mArraySizes.add(arraySize);
412}
413
414const Element * Element::Builder::create() {
415 size_t fieldCount = mElements.size();
416 const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
417 size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
418
419 for (size_t ct = 0; ct < fieldCount; ct++) {
420 nameArray[ct] = mElementNames[ct].string();
421 sizeArray[ct] = mElementNames[ct].length();
422 }
423
424 void *id = rsElementCreate2(mRS->mContext,
425 (RsElement *)mElements.array(), fieldCount,
426 nameArray, fieldCount * sizeof(size_t), sizeArray,
427 (const uint32_t *)mArraySizes.array(), fieldCount);
428
429
430 free(nameArray);
431 free(sizeArray);
432
433 Element *e = new Element(id, mRS, mElements, mElementNames, mArraySizes);
434 return e;
435}
436