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