rsType.cpp revision 77d9f4bd05b2d2a161f30c12a2248f9c97eaac42
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#include "rsContext.h" 18 19using namespace android; 20using namespace android::renderscript; 21 22Type::Type(Context *rsc) : ObjectBase(rsc) { 23 mLODs = 0; 24 mLODCount = 0; 25 clear(); 26} 27 28void Type::preDestroy() { 29 for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) { 30 if (mRSC->mStateType.mTypes[ct] == this) { 31 mRSC->mStateType.mTypes.removeAt(ct); 32 break; 33 } 34 } 35} 36 37Type::~Type() { 38 if (mLODs) { 39 delete [] mLODs; 40 mLODs = NULL; 41 } 42} 43 44void Type::clear() { 45 if (mLODs) { 46 delete [] mLODs; 47 mLODs = NULL; 48 } 49 mDimX = 0; 50 mDimY = 0; 51 mDimZ = 0; 52 mDimLOD = 0; 53 mFaces = false; 54 mElement.clear(); 55} 56 57TypeState::TypeState() { 58} 59 60TypeState::~TypeState() { 61} 62 63size_t Type::getOffsetForFace(uint32_t face) const { 64 rsAssert(mFaces); 65 return 0; 66} 67 68void Type::compute() { 69 uint32_t oldLODCount = mLODCount; 70 if (mDimLOD) { 71 uint32_t l2x = rsFindHighBit(mDimX) + 1; 72 uint32_t l2y = rsFindHighBit(mDimY) + 1; 73 uint32_t l2z = rsFindHighBit(mDimZ) + 1; 74 75 mLODCount = rsMax(l2x, l2y); 76 mLODCount = rsMax(mLODCount, l2z); 77 } else { 78 mLODCount = 1; 79 } 80 if (mLODCount != oldLODCount) { 81 if (mLODs){ 82 delete [] mLODs; 83 } 84 mLODs = new LOD[mLODCount]; 85 } 86 87 uint32_t tx = mDimX; 88 uint32_t ty = mDimY; 89 uint32_t tz = mDimZ; 90 size_t offset = 0; 91 for (uint32_t lod=0; lod < mLODCount; lod++) { 92 mLODs[lod].mX = tx; 93 mLODs[lod].mY = ty; 94 mLODs[lod].mZ = tz; 95 mLODs[lod].mOffset = offset; 96 offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes(); 97 if (tx > 1) tx >>= 1; 98 if (ty > 1) ty >>= 1; 99 if (tz > 1) tz >>= 1; 100 } 101 102 // At this point the offset is the size of a mipmap chain; 103 mMipChainSizeBytes = offset; 104 105 if (mFaces) { 106 offset *= 6; 107 } 108 mTotalSizeBytes = offset; 109} 110 111uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const { 112 uint32_t offset = mLODs[lod].mOffset; 113 offset += x * mElement->getSizeBytes(); 114 return offset; 115} 116 117uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const { 118 uint32_t offset = mLODs[lod].mOffset; 119 offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes(); 120 return offset; 121} 122 123uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const { 124 uint32_t offset = mLODs[lod].mOffset; 125 offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes(); 126 return offset; 127} 128 129uint32_t Type::getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const { 130 uint32_t offset = mLODs[lod].mOffset; 131 offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes(); 132 133 if (face != 0) { 134 uint32_t faceOffset = getSizeBytes() / 6; 135 offset += faceOffset * face; 136 } 137 return offset; 138} 139 140void Type::dumpLOGV(const char *prefix) const { 141 char buf[1024]; 142 ObjectBase::dumpLOGV(prefix); 143 LOGV("%s Type: x=%zu y=%zu z=%zu mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); 144 snprintf(buf, sizeof(buf), "%s element: ", prefix); 145 mElement->dumpLOGV(buf); 146} 147 148void Type::serialize(OStream *stream) const { 149 // Need to identify ourselves 150 stream->addU32((uint32_t)getClassId()); 151 152 String8 name(getName()); 153 stream->addString(&name); 154 155 mElement->serialize(stream); 156 157 stream->addU32(mDimX); 158 stream->addU32(mDimY); 159 stream->addU32(mDimZ); 160 161 stream->addU8((uint8_t)(mDimLOD ? 1 : 0)); 162 stream->addU8((uint8_t)(mFaces ? 1 : 0)); 163} 164 165Type *Type::createFromStream(Context *rsc, IStream *stream) { 166 // First make sure we are reading the correct object 167 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 168 if (classID != RS_A3D_CLASS_ID_TYPE) { 169 LOGE("type loading skipped due to invalid class id\n"); 170 return NULL; 171 } 172 173 String8 name; 174 stream->loadString(&name); 175 176 Element *elem = Element::createFromStream(rsc, stream); 177 if (!elem) { 178 return NULL; 179 } 180 181 uint32_t x = stream->loadU32(); 182 uint32_t y = stream->loadU32(); 183 uint32_t z = stream->loadU32(); 184 uint8_t lod = stream->loadU8(); 185 uint8_t faces = stream->loadU8(); 186 return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 ); 187} 188 189bool 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 206bool Type::isEqual(const Type *other) const { 207 if (other == NULL) { 208 return false; 209 } 210 if (other->getElement()->isEqual(getElement()) && 211 other->getDimX() == mDimX && 212 other->getDimY() == mDimY && 213 other->getDimZ() == mDimZ && 214 other->getDimLOD() == mDimLOD && 215 other->getDimFaces() == mFaces) { 216 return true; 217 } 218 return false; 219} 220 221Type * Type::getType(Context *rsc, const Element *e, 222 uint32_t dimX, uint32_t dimY, uint32_t dimZ, 223 bool dimLOD, bool dimFaces) { 224 TypeState * stc = &rsc->mStateType; 225 226 ObjectBase::asyncLock(); 227 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 228 Type *t = stc->mTypes[ct]; 229 if (t->getElement() != e) continue; 230 if (t->getDimX() != dimX) continue; 231 if (t->getDimY() != dimY) continue; 232 if (t->getDimZ() != dimZ) continue; 233 if (t->getDimLOD() != dimLOD) continue; 234 if (t->getDimFaces() != dimFaces) continue; 235 t->incUserRef(); 236 ObjectBase::asyncUnlock(); 237 return t; 238 } 239 ObjectBase::asyncUnlock(); 240 241 242 Type *nt = new Type(rsc); 243 nt->mElement.set(e); 244 nt->mDimX = dimX; 245 nt->mDimY = dimY; 246 nt->mDimZ = dimZ; 247 nt->mDimLOD = dimLOD; 248 nt->mFaces = dimFaces; 249 nt->compute(); 250 nt->incUserRef(); 251 252 ObjectBase::asyncLock(); 253 stc->mTypes.push(nt); 254 ObjectBase::asyncUnlock(); 255 256 return nt; 257} 258 259Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const { 260 return getType(rsc, mElement.get(), dimX, 261 mDimY, mDimZ, mDimLOD, mFaces); 262} 263 264Type * Type::cloneAndResize2D(Context *rsc, 265 uint32_t dimX, 266 uint32_t dimY) const { 267 return getType(rsc, mElement.get(), dimX, dimY, 268 mDimZ, mDimLOD, mFaces); 269} 270 271 272////////////////////////////////////////////////// 273// 274namespace android { 275namespace renderscript { 276 277} 278} 279 280RsType rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimX, 281 uint32_t dimY, uint32_t dimZ, bool mips, bool faces) { 282 Context *rsc = static_cast<Context *>(con); 283 Element *e = static_cast<Element *>(_e); 284 285 return Type::getType(rsc, e, dimX, dimY, dimZ, mips, faces); 286} 287 288void rsaTypeGetNativeData(RsContext con, RsType type, uint32_t *typeData, uint32_t typeDataSize) { 289 rsAssert(typeDataSize == 6); 290 // Pack the data in the follofing way mDimX; mDimY; mDimZ; 291 // mDimLOD; mDimFaces; mElement; into typeData 292 Type *t = static_cast<Type *>(type); 293 294 (*typeData++) = t->getDimX(); 295 (*typeData++) = t->getDimY(); 296 (*typeData++) = t->getDimZ(); 297 (*typeData++) = t->getDimLOD(); 298 (*typeData++) = t->getDimFaces() ? 1 : 0; 299 (*typeData++) = (uint32_t)t->getElement(); 300 t->getElement()->incUserRef(); 301} 302