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