1 /* 2 * Copyright (C) 2013 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 "rsContext.h" 18 19 #ifndef RS_COMPATIBILITY_LIB 20 #include "system/graphics.h" 21 #else 22 #include "rsCompatibilityLib.h" 23 #endif 24 25 namespace android { 26 namespace renderscript { 27 28 Type::Type(Context *rsc) : ObjectBase(rsc) { 29 memset(&mHal, 0, sizeof(mHal)); 30 mDimLOD = false; 31 } 32 33 void Type::preDestroy() const { 34 auto& types = mRSC->mStateType.mTypes; 35 for (uint32_t ct = 0; ct < types.size(); ct++) { 36 if (types[ct] == this) { 37 types.erase(types.begin() + ct); 38 break; 39 } 40 } 41 } 42 43 Type::~Type() { 44 clear(); 45 } 46 47 void Type::operator delete(void* ptr) { 48 if (ptr) { 49 Type *t = (Type*) ptr; 50 t->getContext()->mHal.funcs.freeRuntimeMem(ptr); 51 } 52 } 53 54 void Type::clear() { 55 if (mHal.state.lodCount) { 56 delete [] mHal.state.lodDimX; 57 delete [] mHal.state.lodDimY; 58 delete [] mHal.state.lodDimZ; 59 } 60 if (mHal.state.arrayCount > 0) { 61 delete [] mHal.state.arrays; 62 } 63 mElement.clear(); 64 memset(&mHal, 0, sizeof(mHal)); 65 } 66 67 TypeState::TypeState() { 68 } 69 70 TypeState::~TypeState() { 71 rsAssert(!mTypes.size()); 72 } 73 74 void Type::compute() { 75 uint32_t oldLODCount = mHal.state.lodCount; 76 if (mDimLOD) { 77 uint32_t l2x = rsFindHighBit(mHal.state.dimX) + 1; 78 uint32_t l2y = rsFindHighBit(mHal.state.dimY) + 1; 79 uint32_t l2z = rsFindHighBit(mHal.state.dimZ) + 1; 80 81 mHal.state.lodCount = rsMax(l2x, l2y); 82 mHal.state.lodCount = rsMax(mHal.state.lodCount, l2z); 83 } else { 84 if (mHal.state.dimYuv) { 85 mHal.state.lodCount = 3; 86 } else { 87 mHal.state.lodCount = 1; 88 } 89 } 90 if (mHal.state.lodCount != oldLODCount) { 91 if (oldLODCount) { 92 delete [] mHal.state.lodDimX; 93 delete [] mHal.state.lodDimY; 94 delete [] mHal.state.lodDimZ; 95 } 96 mHal.state.lodDimX = new uint32_t[mHal.state.lodCount]; 97 mHal.state.lodDimY = new uint32_t[mHal.state.lodCount]; 98 mHal.state.lodDimZ = new uint32_t[mHal.state.lodCount]; 99 } 100 101 uint32_t tx = mHal.state.dimX; 102 uint32_t ty = mHal.state.dimY; 103 uint32_t tz = mHal.state.dimZ; 104 mCellCount = 0; 105 if (!mHal.state.dimYuv) { 106 for (uint32_t lod=0; lod < mHal.state.lodCount; lod++) { 107 mHal.state.lodDimX[lod] = tx; 108 mHal.state.lodDimY[lod] = ty; 109 mHal.state.lodDimZ[lod] = tz; 110 mCellCount += tx * rsMax(ty, 1u) * rsMax(tz, 1u); 111 if (tx > 1) tx >>= 1; 112 if (ty > 1) ty >>= 1; 113 if (tz > 1) tz >>= 1; 114 } 115 } 116 117 if (mHal.state.faces) { 118 mCellCount *= 6; 119 } 120 // YUV only supports basic 2d 121 // so we can stash the plane pointers in the mipmap levels. 122 if (mHal.state.dimYuv) { 123 mHal.state.lodDimX[0] = tx; 124 mHal.state.lodDimY[0] = ty; 125 mHal.state.lodDimZ[0] = tz; 126 mHal.state.lodDimX[1] = mHal.state.lodDimX[0] / 2; 127 mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2; 128 mHal.state.lodDimX[2] = mHal.state.lodDimX[0] / 2; 129 mHal.state.lodDimY[2] = mHal.state.lodDimY[0] / 2; 130 mCellCount += mHal.state.lodDimX[0] * mHal.state.lodDimY[0]; 131 mCellCount += mHal.state.lodDimX[1] * mHal.state.lodDimY[1]; 132 mCellCount += mHal.state.lodDimX[2] * mHal.state.lodDimY[2]; 133 134 switch(mHal.state.dimYuv) { 135 case HAL_PIXEL_FORMAT_YV12: 136 break; 137 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 138 mHal.state.lodDimX[1] = mHal.state.lodDimX[0]; 139 break; 140 #ifndef RS_COMPATIBILITY_LIB 141 case HAL_PIXEL_FORMAT_YCbCr_420_888: 142 break; 143 #endif 144 default: 145 rsAssert(0); 146 } 147 } 148 mHal.state.element = mElement.get(); 149 } 150 151 void Type::dumpLOGV(const char *prefix) const { 152 char buf[1024]; 153 ObjectBase::dumpLOGV(prefix); 154 ALOGV("%s Type: x=%u y=%u z=%u mip=%i face=%i", prefix, 155 mHal.state.dimX, 156 mHal.state.dimY, 157 mHal.state.dimZ, 158 mHal.state.lodCount, 159 mHal.state.faces); 160 snprintf(buf, sizeof(buf), "%s element: ", prefix); 161 mElement->dumpLOGV(buf); 162 } 163 164 void Type::serialize(Context *rsc, OStream *stream) const { 165 // Need to identify ourselves 166 stream->addU32((uint32_t)getClassId()); 167 stream->addString(getName()); 168 169 mElement->serialize(rsc, stream); 170 171 stream->addU32(mHal.state.dimX); 172 stream->addU32(mHal.state.dimY); 173 stream->addU32(mHal.state.dimZ); 174 175 stream->addU8((uint8_t)(mHal.state.lodCount ? 1 : 0)); 176 stream->addU8((uint8_t)(mHal.state.faces ? 1 : 0)); 177 } 178 179 Type *Type::createFromStream(Context *rsc, IStream *stream) { 180 // First make sure we are reading the correct object 181 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 182 if (classID != RS_A3D_CLASS_ID_TYPE) { 183 ALOGE("type loading skipped due to invalid class id\n"); 184 return nullptr; 185 } 186 187 const char *name = stream->loadString(); 188 189 Element *elem = Element::createFromStream(rsc, stream); 190 if (!elem) { 191 return nullptr; 192 } 193 194 RsTypeCreateParams p; 195 memset(&p, 0, sizeof(p)); 196 p.dimX = stream->loadU32(); 197 p.dimY = stream->loadU32(); 198 p.dimZ = stream->loadU32(); 199 p.mipmaps = stream->loadU8(); 200 p.faces = stream->loadU8(); 201 Type *type = Type::getType(rsc, elem, &p, sizeof(p)); 202 elem->decUserRef(); 203 204 delete [] name; 205 return type; 206 } 207 208 bool Type::getIsNp2() const { 209 uint32_t x = getDimX(); 210 uint32_t y = getDimY(); 211 uint32_t z = getDimZ(); 212 213 if (x && (x & (x-1))) { 214 return true; 215 } 216 if (y && (y & (y-1))) { 217 return true; 218 } 219 if (z && (z & (z-1))) { 220 return true; 221 } 222 return false; 223 } 224 225 ObjectBaseRef<Type> Type::getTypeRef(Context *rsc, const Element *e, 226 const RsTypeCreateParams *params, size_t len) { 227 ObjectBaseRef<Type> returnRef; 228 229 TypeState * stc = &rsc->mStateType; 230 231 ObjectBase::asyncLock(); 232 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 233 Type *t = stc->mTypes[ct]; 234 if (t->getElement() != e) continue; 235 if (t->getDimX() != params->dimX) continue; 236 if (t->getDimY() != params->dimY) continue; 237 if (t->getDimZ() != params->dimZ) continue; 238 if (t->getDimLOD() != params->mipmaps) continue; 239 if (t->getDimFaces() != params->faces) continue; 240 if (t->getDimYuv() != params->yuv) continue; 241 if (t->getArray(0) != params->array0) continue; 242 if (t->getArray(1) != params->array1) continue; 243 if (t->getArray(2) != params->array2) continue; 244 if (t->getArray(3) != params->array3) continue; 245 returnRef.set(t); 246 ObjectBase::asyncUnlock(); 247 return returnRef; 248 } 249 ObjectBase::asyncUnlock(); 250 251 // Type objects must use allocator specified by the driver 252 void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Type), 0); 253 if (!allocMem) { 254 rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Type"); 255 return nullptr; 256 } 257 258 Type *nt = new (allocMem) Type(rsc); 259 260 #ifdef RS_FIND_OFFSETS 261 ALOGE("pointer for type: %p", nt); 262 ALOGE("pointer for type.drv: %p", &nt->mHal.drv); 263 #endif 264 265 nt->mDimLOD = params->mipmaps; 266 returnRef.set(nt); 267 nt->mElement.set(e); 268 nt->mHal.state.dimX = params->dimX; 269 nt->mHal.state.dimY = params->dimY; 270 nt->mHal.state.dimZ = params->dimZ; 271 nt->mHal.state.faces = params->faces; 272 nt->mHal.state.dimYuv = params->yuv; 273 274 nt->mHal.state.arrayCount = 0; 275 if (params->array0 > 0) nt->mHal.state.arrayCount ++; 276 if (params->array1 > 0) nt->mHal.state.arrayCount ++; 277 if (params->array2 > 0) nt->mHal.state.arrayCount ++; 278 if (params->array3 > 0) nt->mHal.state.arrayCount ++; 279 if (nt->mHal.state.arrayCount > 0) { 280 nt->mHal.state.arrays = new uint32_t[nt->mHal.state.arrayCount]; 281 if (params->array0 > 0) nt->mHal.state.arrays[0] = params->array0; 282 if (params->array1 > 1) nt->mHal.state.arrays[1] = params->array1; 283 if (params->array2 > 2) nt->mHal.state.arrays[2] = params->array2; 284 if (params->array3 > 3) nt->mHal.state.arrays[3] = params->array3; 285 } 286 287 nt->compute(); 288 289 ObjectBase::asyncLock(); 290 stc->mTypes.push_back(nt); 291 ObjectBase::asyncUnlock(); 292 293 return returnRef; 294 } 295 296 ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const { 297 RsTypeCreateParams p; 298 memset(&p, 0, sizeof(p)); 299 p.dimX = dimX; 300 p.dimY = getDimY(); 301 p.dimZ = getDimZ(); 302 p.mipmaps = getDimLOD(); 303 return getTypeRef(rsc, mElement.get(), &p, sizeof(p)); 304 } 305 306 ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc, 307 uint32_t dimX, 308 uint32_t dimY) const { 309 RsTypeCreateParams p; 310 memset(&p, 0, sizeof(p)); 311 p.dimX = dimX; 312 p.dimY = dimY; 313 p.dimZ = getDimZ(); 314 p.mipmaps = getDimLOD(); 315 p.faces = getDimFaces(); 316 p.yuv = getDimYuv(); 317 return getTypeRef(rsc, mElement.get(), &p, sizeof(p)); 318 } 319 320 321 void Type::incRefs(const void *ptr, size_t ct, size_t startOff) const { 322 const uint8_t *p = static_cast<const uint8_t *>(ptr); 323 const Element *e = mHal.state.element; 324 uint32_t stride = e->getSizeBytes(); 325 326 p += stride * startOff; 327 while (ct > 0) { 328 e->incRefs(p); 329 ct--; 330 p += stride; 331 } 332 } 333 334 335 void Type::decRefs(const void *ptr, size_t ct, size_t startOff) const { 336 if (!mHal.state.element->getHasReferences()) { 337 return; 338 } 339 const uint8_t *p = static_cast<const uint8_t *>(ptr); 340 const Element *e = mHal.state.element; 341 uint32_t stride = e->getSizeBytes(); 342 343 p += stride * startOff; 344 while (ct > 0) { 345 e->decRefs(p); 346 ct--; 347 p += stride; 348 } 349 } 350 351 void Type::callUpdateCacheObject(const Context *rsc, void *dstObj) const { 352 if (rsc->mHal.funcs.type.updateCachedObject != nullptr) { 353 rsc->mHal.funcs.type.updateCachedObject(rsc, this, (rs_type *)dstObj); 354 } else { 355 *((const void **)dstObj) = this; 356 } 357 } 358 359 ////////////////////////////////////////////////// 360 // 361 362 RsType rsi_TypeCreate(Context *rsc, RsElement _e, uint32_t dimX, 363 uint32_t dimY, uint32_t dimZ, bool mipmaps, bool faces, uint32_t yuv) { 364 Element *e = static_cast<Element *>(_e); 365 366 RsTypeCreateParams p; 367 memset(&p, 0, sizeof(p)); 368 p.dimX = dimX; 369 p.dimY = dimY; 370 p.dimZ = dimZ; 371 p.mipmaps = mipmaps; 372 p.faces = faces; 373 p.yuv = yuv; 374 return Type::getType(rsc, e, &p, sizeof(p)); 375 } 376 377 RsType rsi_TypeCreate2(Context *rsc, const RsTypeCreateParams *p, size_t len) { 378 Element *e = static_cast<Element *>(p->e); 379 return Type::getType(rsc, e, p, len); 380 } 381 382 } // namespace renderscript 383 } // namespace android 384