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 20 namespace android { 21 namespace renderscript { 22 23 Element::Element(Context *rsc) : ObjectBase(rsc) { 24 mBits = 0; 25 mBitsUnpadded = 0; 26 mFields = nullptr; 27 mFieldCount = 0; 28 mHasReference = false; 29 memset(&mHal, 0, sizeof(mHal)); 30 } 31 32 Element::~Element() { 33 clear(); 34 } 35 36 void Element::operator delete(void* ptr) { 37 if (ptr) { 38 Element *e = (Element*) ptr; 39 e->getContext()->mHal.funcs.freeRuntimeMem(ptr); 40 } 41 } 42 43 void Element::preDestroy() const { 44 auto& elements = mRSC->mStateElement.mElements; 45 for (uint32_t ct = 0; ct < elements.size(); ct++) { 46 if (elements[ct] == this) { 47 elements.erase(elements.begin() + ct); 48 break; 49 } 50 } 51 } 52 53 void 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 71 size_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 83 size_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 95 void 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 107 void 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 123 Element *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 } 144 145 const Element **subElems = new const Element *[fieldCount]; 146 const char **subElemNames = new const char *[fieldCount]; 147 size_t *subElemNamesLengths = new size_t[fieldCount]; 148 uint32_t *arraySizes = new uint32_t[fieldCount]; 149 150 for (uint32_t ct = 0; ct < fieldCount; ct ++) { 151 subElemNames[ct] = stream->loadString(); 152 subElemNamesLengths[ct] = strlen(subElemNames[ct]); 153 arraySizes[ct] = stream->loadU32(); 154 subElems[ct] = Element::createFromStream(rsc, stream); 155 } 156 157 const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames, 158 subElemNamesLengths, arraySizes); 159 for (uint32_t ct = 0; ct < fieldCount; ct ++) { 160 delete [] subElemNames[ct]; 161 subElems[ct]->decUserRef(); 162 } 163 delete[] name; 164 delete[] subElems; 165 delete[] subElemNames; 166 delete[] subElemNamesLengths; 167 delete[] arraySizes; 168 169 return (Element *)elem; 170 } 171 172 void Element::compute() { 173 mHal.state.dataType = mComponent.getType(); 174 mHal.state.dataKind = mComponent.getKind(); 175 mHal.state.vectorSize = mComponent.getVectorSize(); 176 177 if (mFieldCount == 0) { 178 mBits = mComponent.getBits(); 179 mBitsUnpadded = mComponent.getBitsUnpadded(); 180 mHasReference = mComponent.isReference(); 181 182 mHal.state.elementSizeBytes = getSizeBytes(); 183 return; 184 } 185 186 uint32_t noPaddingFieldCount = 0; 187 for (uint32_t ct = 0; ct < mFieldCount; ct ++) { 188 if (mFields[ct].name[0] != '#') { 189 noPaddingFieldCount ++; 190 } 191 } 192 193 mHal.state.fields = new const Element*[noPaddingFieldCount]; 194 mHal.state.fieldArraySizes = new uint32_t[noPaddingFieldCount]; 195 mHal.state.fieldNames = new const char*[noPaddingFieldCount]; 196 mHal.state.fieldNameLengths = new uint32_t[noPaddingFieldCount]; 197 mHal.state.fieldOffsetBytes = new uint32_t[noPaddingFieldCount]; 198 mHal.state.fieldsCount = noPaddingFieldCount; 199 200 size_t bits = 0; 201 size_t bitsUnpadded = 0; 202 for (size_t ct = 0, ctNoPadding = 0; ct < mFieldCount; ct++) { 203 mFields[ct].offsetBits = bits; 204 mFields[ct].offsetBitsUnpadded = bitsUnpadded; 205 bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize; 206 bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize; 207 208 if (mFields[ct].e->mHasReference) { 209 mHasReference = true; 210 } 211 212 if (mFields[ct].name[0] == '#') { 213 continue; 214 } 215 216 mHal.state.fields[ctNoPadding] = mFields[ct].e.get(); 217 mHal.state.fieldArraySizes[ctNoPadding] = mFields[ct].arraySize; 218 mHal.state.fieldNames[ctNoPadding] = mFields[ct].name; 219 mHal.state.fieldNameLengths[ctNoPadding] = strlen(mFields[ct].name) + 1; // to include 0 220 mHal.state.fieldOffsetBytes[ctNoPadding] = mFields[ct].offsetBits >> 3; 221 222 ctNoPadding ++; 223 } 224 225 mBits = bits; 226 mBitsUnpadded = bitsUnpadded; 227 mHal.state.elementSizeBytes = getSizeBytes(); 228 } 229 230 ObjectBaseRef<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_back(e); 270 ObjectBase::asyncUnlock(); 271 272 return returnRef; 273 } 274 275 ObjectBaseRef<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_back(e); 345 ObjectBase::asyncUnlock(); 346 347 return returnRef; 348 } 349 350 void 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 372 void 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 394 void 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 402 ElementState::ElementState() { 403 } 404 405 ElementState::~ElementState() { 406 rsAssert(!mElements.size()); 407 } 408 409 ///////////////////////////////////////// 410 // 411 412 RsElement rsi_ElementCreate(Context *rsc, 413 RsDataType dt, 414 RsDataKind dk, 415 bool norm, 416 uint32_t vecSize) { 417 return (RsElement)Element::create(rsc, dt, dk, norm, vecSize); 418 } 419 420 421 RsElement rsi_ElementCreate2(Context *rsc, 422 const RsElement * ein, 423 size_t ein_length, 424 425 const char ** names, 426 size_t nameLengths_length, 427 const size_t * nameLengths, 428 429 const uint32_t * arraySizes, 430 size_t arraySizes_length) { 431 return (RsElement)Element::create(rsc, ein_length, (const Element **)ein, 432 names, nameLengths, arraySizes); 433 } 434 435 } // namespace renderscript 436 } // namespace android 437