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