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