rsType.cpp revision 39f2ef6fed00a99c5c389e12c4597884027d4858
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_TypeBegin(Context *rsc, RsElement vse) 385{ 386 TypeState * stc = &rsc->mStateType; 387 388 stc->mX = 0; 389 stc->mY = 0; 390 stc->mZ = 0; 391 stc->mLOD = false; 392 stc->mFaces = false; 393 stc->mElement.set(static_cast<const Element *>(vse)); 394} 395 396void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value) 397{ 398 TypeState * stc = &rsc->mStateType; 399 400 if (dim < 0) { 401 //error 402 return; 403 } 404 405 406 switch (dim) { 407 case RS_DIMENSION_X: 408 stc->mX = value; 409 return; 410 case RS_DIMENSION_Y: 411 stc->mY = value; 412 return; 413 case RS_DIMENSION_Z: 414 stc->mZ = value; 415 return; 416 case RS_DIMENSION_FACE: 417 stc->mFaces = (value != 0); 418 return; 419 case RS_DIMENSION_LOD: 420 stc->mLOD = (value != 0); 421 return; 422 default: 423 break; 424 } 425 426 if ((dim < 0) || (dim > RS_DIMENSION_MAX)) { 427 LOGE("rsTypeAdd: Bad dimension"); 428 //error 429 return; 430 } 431 432 // todo: implement array support 433 434} 435 436RsType rsi_TypeCreate(Context *rsc) 437{ 438 TypeState * stc = &rsc->mStateType; 439 440 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 441 Type *t = stc->mTypes[ct]; 442 if (t->getElement() != stc->mElement.get()) continue; 443 if (t->getDimX() != stc->mX) continue; 444 if (t->getDimY() != stc->mY) continue; 445 if (t->getDimZ() != stc->mZ) continue; 446 if (t->getDimLOD() != stc->mLOD) continue; 447 if (t->getDimFaces() != stc->mFaces) continue; 448 t->incUserRef(); 449 return t; 450 } 451 452 Type * st = new Type(rsc); 453 st->incUserRef(); 454 st->setDimX(stc->mX); 455 st->setDimY(stc->mY); 456 st->setDimZ(stc->mZ); 457 st->setElement(stc->mElement.get()); 458 st->setDimLOD(stc->mLOD); 459 st->setDimFaces(stc->mFaces); 460 st->compute(); 461 stc->mElement.clear(); 462 stc->mTypes.push(st); 463 return st; 464} 465 466void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize) 467{ 468 rsAssert(typeDataSize == 6); 469 // Pack the data in the follofing way mDimX; mDimY; mDimZ; 470 // mDimLOD; mDimFaces; mElement; into typeData 471 Type *t = static_cast<Type *>(type); 472 473 (*typeData++) = t->getDimX(); 474 (*typeData++) = t->getDimY(); 475 (*typeData++) = t->getDimZ(); 476 (*typeData++) = t->getDimLOD(); 477 (*typeData++) = t->getDimFaces() ? 1 : 0; 478 (*typeData++) = (uint32_t)t->getElement(); 479 480} 481 482 483} 484} 485 486