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