1/* 2 * Copyright (C) 2009 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 18#include "rsContext.h" 19 20using namespace android; 21using namespace android::renderscript; 22 23 24Element::Element(Context *rsc) : ObjectBase(rsc) { 25 mBits = 0; 26 mBitsUnpadded = 0; 27 mFields = NULL; 28 mFieldCount = 0; 29 mHasReference = false; 30 memset(&mHal, 0, sizeof(mHal)); 31} 32 33Element::~Element() { 34 clear(); 35} 36 37void Element::preDestroy() const { 38 for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) { 39 if (mRSC->mStateElement.mElements[ct] == this) { 40 mRSC->mStateElement.mElements.removeAt(ct); 41 break; 42 } 43 } 44} 45 46void Element::clear() { 47 if (mFields) { 48 for (size_t i = 0; i < mFieldCount; i++) { 49 delete[] mFields[i].name; 50 } 51 delete [] mFields; 52 } 53 mFields = NULL; 54 mFieldCount = 0; 55 mHasReference = false; 56 57 delete [] mHal.state.fields; 58 delete [] mHal.state.fieldArraySizes; 59 delete [] mHal.state.fieldNames; 60 delete [] mHal.state.fieldNameLengths; 61 delete [] mHal.state.fieldOffsetBytes; 62} 63 64size_t Element::getSizeBits() const { 65 if (!mFieldCount) { 66 return mBits; 67 } 68 69 size_t total = 0; 70 for (size_t ct=0; ct < mFieldCount; ct++) { 71 total += mFields[ct].e->mBits * mFields[ct].arraySize; 72 } 73 return total; 74} 75 76size_t Element::getSizeBitsUnpadded() const { 77 if (!mFieldCount) { 78 return mBitsUnpadded; 79 } 80 81 size_t total = 0; 82 for (size_t ct=0; ct < mFieldCount; ct++) { 83 total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize; 84 } 85 return total; 86} 87 88void Element::dumpLOGV(const char *prefix) const { 89 ObjectBase::dumpLOGV(prefix); 90 ALOGV("%s Element: fieldCount: %zu, size bytes: %zu", prefix, mFieldCount, getSizeBytes()); 91 mComponent.dumpLOGV(prefix); 92 for (uint32_t ct = 0; ct < mFieldCount; ct++) { 93 ALOGV("%s Element field index: %u ------------------", prefix, ct); 94 ALOGV("%s name: %s, offsetBits: %u, arraySize: %u", 95 prefix, mFields[ct].name, mFields[ct].offsetBits, mFields[ct].arraySize); 96 mFields[ct].e->dumpLOGV(prefix); 97 } 98} 99 100void Element::serialize(Context *rsc, OStream *stream) const { 101 // Need to identify ourselves 102 stream->addU32((uint32_t)getClassId()); 103 stream->addString(getName()); 104 105 mComponent.serialize(stream); 106 107 // Now serialize all the fields 108 stream->addU32(mFieldCount); 109 for (uint32_t ct = 0; ct < mFieldCount; ct++) { 110 stream->addString(mFields[ct].name); 111 stream->addU32(mFields[ct].arraySize); 112 mFields[ct].e->serialize(rsc, stream); 113 } 114} 115 116Element *Element::createFromStream(Context *rsc, IStream *stream) { 117 // First make sure we are reading the correct object 118 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 119 if (classID != RS_A3D_CLASS_ID_ELEMENT) { 120 ALOGE("element loading skipped due to invalid class id\n"); 121 return NULL; 122 } 123 124 const char *name = stream->loadString(); 125 126 Component component; 127 component.loadFromStream(stream); 128 129 uint32_t fieldCount = stream->loadU32(); 130 if (!fieldCount) { 131 return (Element *)Element::create(rsc, 132 component.getType(), 133 component.getKind(), 134 component.getIsNormalized(), 135 component.getVectorSize()); 136 } 137 138 const Element **subElems = new const Element *[fieldCount]; 139 const char **subElemNames = new const char *[fieldCount]; 140 size_t *subElemNamesLengths = new size_t[fieldCount]; 141 uint32_t *arraySizes = new uint32_t[fieldCount]; 142 143 for (uint32_t ct = 0; ct < fieldCount; ct ++) { 144 subElemNames[ct] = stream->loadString(); 145 subElemNamesLengths[ct] = strlen(subElemNames[ct]); 146 arraySizes[ct] = stream->loadU32(); 147 subElems[ct] = Element::createFromStream(rsc, stream); 148 } 149 150 const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames, 151 subElemNamesLengths, arraySizes); 152 for (uint32_t ct = 0; ct < fieldCount; ct ++) { 153 delete [] subElemNames[ct]; 154 subElems[ct]->decUserRef(); 155 } 156 delete[] name; 157 delete[] subElems; 158 delete[] subElemNames; 159 delete[] subElemNamesLengths; 160 delete[] arraySizes; 161 162 return (Element *)elem; 163} 164 165void Element::compute() { 166 mHal.state.dataType = mComponent.getType(); 167 mHal.state.dataKind = mComponent.getKind(); 168 mHal.state.vectorSize = mComponent.getVectorSize(); 169 170 if (mFieldCount == 0) { 171 mBits = mComponent.getBits(); 172 mBitsUnpadded = mComponent.getBitsUnpadded(); 173 mHasReference = mComponent.isReference(); 174 175 mHal.state.elementSizeBytes = getSizeBytes(); 176 return; 177 } 178 179 uint32_t noPaddingFieldCount = 0; 180 for (uint32_t ct = 0; ct < mFieldCount; ct ++) { 181 if (mFields[ct].name[0] != '#') { 182 noPaddingFieldCount ++; 183 } 184 } 185 186 mHal.state.fields = new const Element*[noPaddingFieldCount]; 187 mHal.state.fieldArraySizes = new uint32_t[noPaddingFieldCount]; 188 mHal.state.fieldNames = new const char*[noPaddingFieldCount]; 189 mHal.state.fieldNameLengths = new uint32_t[noPaddingFieldCount]; 190 mHal.state.fieldOffsetBytes = new uint32_t[noPaddingFieldCount]; 191 mHal.state.fieldsCount = noPaddingFieldCount; 192 193 size_t bits = 0; 194 size_t bitsUnpadded = 0; 195 for (size_t ct = 0, ctNoPadding = 0; ct < mFieldCount; ct++) { 196 mFields[ct].offsetBits = bits; 197 mFields[ct].offsetBitsUnpadded = bitsUnpadded; 198 bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize; 199 bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize; 200 201 if (mFields[ct].e->mHasReference) { 202 mHasReference = true; 203 } 204 205 if (mFields[ct].name[0] == '#') { 206 continue; 207 } 208 209 mHal.state.fields[ctNoPadding] = mFields[ct].e.get(); 210 mHal.state.fieldArraySizes[ctNoPadding] = mFields[ct].arraySize; 211 mHal.state.fieldNames[ctNoPadding] = mFields[ct].name; 212 mHal.state.fieldNameLengths[ctNoPadding] = strlen(mFields[ct].name) + 1; // to include 0 213 mHal.state.fieldOffsetBytes[ctNoPadding] = mFields[ct].offsetBits >> 3; 214 215 ctNoPadding ++; 216 } 217 218 mHal.state.elementSizeBytes = getSizeBytes(); 219} 220 221ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk, 222 bool isNorm, uint32_t vecSize) { 223 ObjectBaseRef<const Element> returnRef; 224 // Look for an existing match. 225 ObjectBase::asyncLock(); 226 for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { 227 const Element *ee = rsc->mStateElement.mElements[ct]; 228 if (!ee->getFieldCount() && 229 (ee->getComponent().getType() == dt) && 230 (ee->getComponent().getKind() == dk) && 231 (ee->getComponent().getIsNormalized() == isNorm) && 232 (ee->getComponent().getVectorSize() == vecSize)) { 233 // Match 234 returnRef.set(ee); 235 ObjectBase::asyncUnlock(); 236 return ee; 237 } 238 } 239 ObjectBase::asyncUnlock(); 240 241 Element *e = new Element(rsc); 242 returnRef.set(e); 243 e->mComponent.set(dt, dk, isNorm, vecSize); 244 e->compute(); 245 246 ObjectBase::asyncLock(); 247 rsc->mStateElement.mElements.push(e); 248 ObjectBase::asyncUnlock(); 249 250 return returnRef; 251} 252 253ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein, 254 const char **nin, const size_t * lengths, const uint32_t *asin) { 255 256 ObjectBaseRef<const Element> returnRef; 257 // Look for an existing match. 258 ObjectBase::asyncLock(); 259 for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { 260 const Element *ee = rsc->mStateElement.mElements[ct]; 261 if (ee->getFieldCount() == count) { 262 bool match = true; 263 for (uint32_t i=0; i < count; i++) { 264 size_t len; 265 uint32_t asize = 1; 266 if (lengths) { 267 len = lengths[i]; 268 } else { 269 len = strlen(nin[i]); 270 } 271 if (asin) { 272 asize = asin[i]; 273 } 274 275 if ((ee->mFields[i].e.get() != ein[i]) || 276 (strlen(ee->mFields[i].name) != len) || 277 strcmp(ee->mFields[i].name, nin[i]) || 278 (ee->mFields[i].arraySize != asize)) { 279 match = false; 280 break; 281 } 282 } 283 if (match) { 284 returnRef.set(ee); 285 ObjectBase::asyncUnlock(); 286 return returnRef; 287 } 288 } 289 } 290 ObjectBase::asyncUnlock(); 291 292 Element *e = new Element(rsc); 293 returnRef.set(e); 294 e->mFields = new ElementField_t [count]; 295 e->mFieldCount = count; 296 for (size_t ct=0; ct < count; ct++) { 297 size_t len; 298 uint32_t asize = 1; 299 if (lengths) { 300 len = lengths[ct]; 301 } else { 302 len = strlen(nin[ct]); 303 } 304 if (asin) { 305 asize = asin[ct]; 306 } 307 308 e->mFields[ct].e.set(ein[ct]); 309 e->mFields[ct].name = rsuCopyString(nin[ct], len); 310 e->mFields[ct].arraySize = asize; 311 } 312 e->compute(); 313 314 ObjectBase::asyncLock(); 315 rsc->mStateElement.mElements.push(e); 316 ObjectBase::asyncUnlock(); 317 318 return returnRef; 319} 320 321void Element::incRefs(const void *ptr) const { 322 if (!mFieldCount) { 323 if (mComponent.isReference()) { 324 ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr); 325 ObjectBase *ob = obp[0]; 326 if (ob) ob->incSysRef(); 327 } 328 return; 329 } 330 331 const uint8_t *p = static_cast<const uint8_t *>(ptr); 332 for (uint32_t i=0; i < mFieldCount; i++) { 333 if (mFields[i].e->mHasReference) { 334 const uint8_t *p2 = &p[mFields[i].offsetBits >> 3]; 335 for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) { 336 mFields[i].e->incRefs(p2); 337 p2 += mFields[i].e->getSizeBytes(); 338 } 339 } 340 } 341} 342 343void Element::decRefs(const void *ptr) const { 344 if (!mFieldCount) { 345 if (mComponent.isReference()) { 346 ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr); 347 ObjectBase *ob = obp[0]; 348 if (ob) ob->decSysRef(); 349 } 350 return; 351 } 352 353 const uint8_t *p = static_cast<const uint8_t *>(ptr); 354 for (uint32_t i=0; i < mFieldCount; i++) { 355 if (mFields[i].e->mHasReference) { 356 const uint8_t *p2 = &p[mFields[i].offsetBits >> 3]; 357 for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) { 358 mFields[i].e->decRefs(p2); 359 p2 += mFields[i].e->getSizeBytes(); 360 } 361 } 362 } 363} 364 365ElementState::ElementState() { 366} 367 368ElementState::~ElementState() { 369 rsAssert(!mElements.size()); 370} 371 372///////////////////////////////////////// 373// 374 375namespace android { 376namespace renderscript { 377 378RsElement rsi_ElementCreate(Context *rsc, 379 RsDataType dt, 380 RsDataKind dk, 381 bool norm, 382 uint32_t vecSize) { 383 return (RsElement)Element::create(rsc, dt, dk, norm, vecSize); 384} 385 386 387RsElement rsi_ElementCreate2(Context *rsc, 388 const RsElement * ein, 389 size_t ein_length, 390 391 const char ** names, 392 size_t nameLengths_length, 393 const size_t * nameLengths, 394 395 const uint32_t * arraySizes, 396 size_t arraySizes_length) { 397 return (RsElement)Element::create(rsc, ein_length, (const Element **)ein, 398 names, nameLengths, arraySizes); 399} 400 401} 402} 403 404extern "C" void rsaElementGetNativeData(RsContext con, RsElement elem, 405 uint32_t *elemData, uint32_t elemDataSize) { 406 rsAssert(elemDataSize == 5); 407 // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements 408 Element *e = static_cast<Element *>(elem); 409 410 (*elemData++) = (uint32_t)e->getType(); 411 (*elemData++) = (uint32_t)e->getKind(); 412 (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0; 413 (*elemData++) = e->getComponent().getVectorSize(); 414 (*elemData++) = e->getFieldCount(); 415} 416 417extern "C" void rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, 418 const char **names, size_t *arraySizes, uint32_t dataSize) { 419 Element *e = static_cast<Element *>(elem); 420 rsAssert(e->getFieldCount() == dataSize); 421 422 for (uint32_t i = 0; i < dataSize; i ++) { 423 e->getField(i)->incUserRef(); 424 ids[i] = (uintptr_t)e->getField(i); 425 names[i] = e->getFieldName(i); 426 arraySizes[i] = e->getFieldArraySize(i); 427 } 428} 429