rsType.cpp revision f0c1df480304a72ce41e7d4b088319cbd7f0938a
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#ifndef ANDROID_RS_BUILD_FOR_HOST 18#include "rsContext.h" 19#include <GLES/gl.h> 20#else 21#include "rsContextHostStub.h" 22#include <OpenGL/gl.h> 23#endif 24 25using namespace android; 26using namespace android::renderscript; 27 28Type::Type(Context *rsc) : ObjectBase(rsc) 29{ 30 mLODs = 0; 31 mLODCount = 0; 32 mAttribs = NULL; 33 mAttribsSize = 0; 34 clear(); 35} 36 37void Type::preDestroy() 38{ 39 for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) { 40 if (mRSC->mStateType.mTypes[ct] == this) { 41 mRSC->mStateType.mTypes.removeAt(ct); 42 break; 43 } 44 } 45} 46 47Type::~Type() 48{ 49 if (mLODs) { 50 delete [] mLODs; 51 mLODs = NULL; 52 } 53 if(mAttribs) { 54 delete [] mAttribs; 55 mAttribs = NULL; 56 } 57} 58 59void Type::clear() 60{ 61 if (mLODs) { 62 delete [] mLODs; 63 mLODs = NULL; 64 } 65 mDimX = 0; 66 mDimY = 0; 67 mDimZ = 0; 68 mDimLOD = 0; 69 mFaces = false; 70 mElement.clear(); 71} 72 73TypeState::TypeState() 74{ 75} 76 77TypeState::~TypeState() 78{ 79} 80 81size_t Type::getOffsetForFace(uint32_t face) const 82{ 83 rsAssert(mFaces); 84 return 0; 85} 86 87void Type::compute() 88{ 89 uint32_t oldLODCount = mLODCount; 90 if (mDimLOD) { 91 uint32_t l2x = rsFindHighBit(mDimX) + 1; 92 uint32_t l2y = rsFindHighBit(mDimY) + 1; 93 uint32_t l2z = rsFindHighBit(mDimZ) + 1; 94 95 mLODCount = rsMax(l2x, l2y); 96 mLODCount = rsMax(mLODCount, l2z); 97 } else { 98 mLODCount = 1; 99 } 100 if (mLODCount != oldLODCount) { 101 if(mLODs){ 102 delete [] mLODs; 103 } 104 mLODs = new LOD[mLODCount]; 105 } 106 107 uint32_t tx = mDimX; 108 uint32_t ty = mDimY; 109 uint32_t tz = mDimZ; 110 size_t offset = 0; 111 for (uint32_t lod=0; lod < mLODCount; lod++) { 112 mLODs[lod].mX = tx; 113 mLODs[lod].mY = ty; 114 mLODs[lod].mZ = tz; 115 mLODs[lod].mOffset = offset; 116 offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes(); 117 if (tx > 1) tx >>= 1; 118 if (ty > 1) ty >>= 1; 119 if (tz > 1) tz >>= 1; 120 } 121 122 // At this point the offset is the size of a mipmap chain; 123 mMipChainSizeBytes = offset; 124 125 if (mFaces) { 126 offset *= 6; 127 } 128 mTotalSizeBytes = offset; 129 130 makeGLComponents(); 131} 132 133uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const 134{ 135 uint32_t offset = mLODs[lod].mOffset; 136 offset += x * mElement->getSizeBytes(); 137 return offset; 138} 139 140uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const 141{ 142 uint32_t offset = mLODs[lod].mOffset; 143 offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes(); 144 return offset; 145} 146 147uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const 148{ 149 uint32_t offset = mLODs[lod].mOffset; 150 offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes(); 151 return offset; 152} 153 154bool Type::isValidGLComponent(uint32_t fieldIdx) { 155 // Do not create attribs for padding 156 if(mElement->getFieldName(fieldIdx)[0] == '#') { 157 return false; 158 } 159 160 // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted. 161 // Filter rs types accordingly 162 RsDataType dt = mElement->getField(fieldIdx)->getComponent().getType(); 163 if(dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 && 164 dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 && 165 dt != RS_TYPE_SIGNED_16) { 166 return false; 167 } 168 169 // Now make sure they are not arrays 170 uint32_t arraySize = mElement->getFieldArraySize(fieldIdx); 171 if(arraySize != 1) { 172 return false; 173 } 174 175 return true; 176} 177 178void Type::makeGLComponents() 179{ 180 // Count the number of gl attrs to initialize 181 mAttribsSize = 0; 182 183 for (uint32_t ct=0; ct < mElement->getFieldCount(); ct++) { 184 if(isValidGLComponent(ct)) { 185 mAttribsSize ++; 186 } 187 } 188 if(mAttribs) { 189 delete [] mAttribs; 190 mAttribs = NULL; 191 } 192 if(mAttribsSize) { 193 mAttribs = new VertexArray::Attrib[mAttribsSize]; 194 } 195 196 uint32_t userNum = 0; 197 for (uint32_t ct=0; ct < mElement->getFieldCount(); ct++) { 198 const Component &c = mElement->getField(ct)->getComponent(); 199 200 if(!isValidGLComponent(ct)) { 201 continue; 202 } 203 204 mAttribs[userNum].size = c.getVectorSize(); 205 mAttribs[userNum].offset = mElement->getFieldOffsetBytes(ct); 206 mAttribs[userNum].type = c.getGLType(); 207 mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized(); 208 String8 tmp(RS_SHADER_ATTR); 209 tmp.append(mElement->getFieldName(ct)); 210 mAttribs[userNum].name.setTo(tmp.string()); 211 212 userNum ++; 213 } 214} 215 216 217void Type::enableGLVertexBuffer(VertexArray *va) const 218{ 219 uint32_t stride = mElement->getSizeBytes(); 220 for (uint32_t ct=0; ct < mAttribsSize; ct++) { 221 // Load up to RS_MAX_ATTRIBS inputs 222 // TODO: grow vertexarray dynamically 223 if(ct >= RS_MAX_ATTRIBS) { 224 LOGE("More GL attributes than we can handle"); 225 break; 226 } 227 if (mAttribs[ct].size) { 228 va->add(mAttribs[ct], stride); 229 } 230 } 231} 232 233 234 235void Type::dumpLOGV(const char *prefix) const 236{ 237 char buf[1024]; 238 ObjectBase::dumpLOGV(prefix); 239 LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); 240 sprintf(buf, "%s element: ", prefix); 241 mElement->dumpLOGV(buf); 242} 243 244void Type::serialize(OStream *stream) const 245{ 246 // Need to identify ourselves 247 stream->addU32((uint32_t)getClassId()); 248 249 String8 name(getName()); 250 stream->addString(&name); 251 252 mElement->serialize(stream); 253 254 stream->addU32(mDimX); 255 stream->addU32(mDimY); 256 stream->addU32(mDimZ); 257 258 stream->addU8((uint8_t)(mDimLOD ? 1 : 0)); 259 stream->addU8((uint8_t)(mFaces ? 1 : 0)); 260} 261 262Type *Type::createFromStream(Context *rsc, IStream *stream) 263{ 264 // First make sure we are reading the correct object 265 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 266 if(classID != RS_A3D_CLASS_ID_TYPE) { 267 LOGE("type loading skipped due to invalid class id\n"); 268 return NULL; 269 } 270 271 String8 name; 272 stream->loadString(&name); 273 274 Element *elem = Element::createFromStream(rsc, stream); 275 if(!elem) { 276 return NULL; 277 } 278 279 uint32_t x = stream->loadU32(); 280 uint32_t y = stream->loadU32(); 281 uint32_t z = stream->loadU32(); 282 uint8_t lod = stream->loadU8(); 283 uint8_t faces = stream->loadU8(); 284 return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 ); 285} 286 287bool Type::getIsNp2() const 288{ 289 uint32_t x = getDimX(); 290 uint32_t y = getDimY(); 291 uint32_t z = getDimZ(); 292 293 if (x && (x & (x-1))) { 294 return true; 295 } 296 if (y && (y & (y-1))) { 297 return true; 298 } 299 if (z && (z & (z-1))) { 300 return true; 301 } 302 return false; 303} 304 305bool Type::isEqual(const Type *other) const { 306 if(other == NULL) { 307 return false; 308 } 309 if (other->getElement()->isEqual(getElement()) && 310 other->getDimX() == mDimX && 311 other->getDimY() == mDimY && 312 other->getDimZ() == mDimZ && 313 other->getDimLOD() == mDimLOD && 314 other->getDimFaces() == mFaces) { 315 return true; 316 } 317 return false; 318} 319 320Type * Type::getType(Context *rsc, const Element *e, 321 uint32_t dimX, uint32_t dimY, uint32_t dimZ, 322 bool dimLOD, bool dimFaces) 323{ 324 TypeState * stc = &rsc->mStateType; 325 326 ObjectBase::asyncLock(); 327 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 328 Type *t = stc->mTypes[ct]; 329 if (t->getElement() != e) continue; 330 if (t->getDimX() != dimX) continue; 331 if (t->getDimY() != dimY) continue; 332 if (t->getDimZ() != dimZ) continue; 333 if (t->getDimLOD() != dimLOD) continue; 334 if (t->getDimFaces() != dimFaces) continue; 335 t->incUserRef(); 336 ObjectBase::asyncUnlock(); 337 return t; 338 } 339 ObjectBase::asyncUnlock(); 340 341 342 Type *nt = new Type(rsc); 343 nt->mElement.set(e); 344 nt->mDimX = dimX; 345 nt->mDimY = dimY; 346 nt->mDimZ = dimZ; 347 nt->mDimLOD = dimLOD; 348 nt->mFaces = dimFaces; 349 nt->compute(); 350 nt->incUserRef(); 351 352 ObjectBase::asyncLock(); 353 stc->mTypes.push(nt); 354 ObjectBase::asyncUnlock(); 355 356 return nt; 357} 358 359Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const 360{ 361 return getType(rsc, mElement.get(), dimX, 362 mDimY, mDimZ, mDimLOD, mFaces); 363} 364 365Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const 366{ 367 return getType(rsc, mElement.get(), dimX, dimY, 368 mDimZ, mDimLOD, mFaces); 369} 370 371 372////////////////////////////////////////////////// 373// 374namespace android { 375namespace renderscript { 376 377void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize) 378{ 379 rsAssert(typeDataSize == 6); 380 // Pack the data in the follofing way mDimX; mDimY; mDimZ; 381 // mDimLOD; mDimFaces; mElement; into typeData 382 Type *t = static_cast<Type *>(type); 383 384 (*typeData++) = t->getDimX(); 385 (*typeData++) = t->getDimY(); 386 (*typeData++) = t->getDimZ(); 387 (*typeData++) = t->getDimLOD(); 388 (*typeData++) = t->getDimFaces() ? 1 : 0; 389 (*typeData++) = (uint32_t)t->getElement(); 390 t->getElement()->incUserRef(); 391} 392 393 394} 395} 396 397RsType rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimCount, 398 const RsDimension *dims, const uint32_t *vals) 399{ 400 Context *rsc = static_cast<Context *>(con); 401 Element *e = static_cast<Element *>(_e); 402 TypeState * stc = &rsc->mStateType; 403 404 uint32_t dimX = 0; 405 uint32_t dimY = 0; 406 uint32_t dimZ = 0; 407 uint32_t dimLOD = 0; 408 uint32_t dimFaces = 0; 409 410 for (uint32_t ct=0; ct < dimCount; ct++) { 411 switch(dims[ct]) { 412 case RS_DIMENSION_X: dimX = vals[ct]; break; 413 case RS_DIMENSION_Y: dimY = vals[ct]; break; 414 case RS_DIMENSION_Z: dimZ = vals[ct]; break; 415 case RS_DIMENSION_LOD: dimLOD = vals[ct]; break; 416 case RS_DIMENSION_FACE: dimFaces = vals[ct]; break; 417 418 default: 419 LOGE("rsaTypeCreate: Bad dimension"); 420 rsAssert(0); 421 } 422 } 423 424 return Type::getType(rsc, e, dimX, dimY, dimZ, dimLOD, dimFaces); 425} 426 427