rsType.cpp revision 700ba38f022208686523ab4280c4fc9f102aa273
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 152 153void Type::makeGLComponents() 154{ 155 // Count the number of gl attrs to initialize 156 mAttribsSize = 0; 157 for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) { 158 if(getElement()->getFieldName(ct)[0] != '#') { 159 mAttribsSize ++; 160 } 161 } 162 if(mAttribs) { 163 delete [] mAttribs; 164 mAttribs = NULL; 165 } 166 if(mAttribsSize) { 167 mAttribs = new VertexArray::Attrib[mAttribsSize]; 168 } 169 170 uint32_t userNum = 0; 171 for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) { 172 const Component &c = getElement()->getField(ct)->getComponent(); 173 174 if(getElement()->getFieldName(ct)[0] == '#') { 175 continue; 176 } 177 178 mAttribs[userNum].size = c.getVectorSize(); 179 mAttribs[userNum].offset = mElement->getFieldOffsetBytes(ct); 180 mAttribs[userNum].type = c.getGLType(); 181 mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized(); 182 String8 tmp(RS_SHADER_ATTR); 183 tmp.append(getElement()->getFieldName(ct)); 184 mAttribs[userNum].name.setTo(tmp.string()); 185 186 userNum ++; 187 } 188} 189 190 191void Type::enableGLVertexBuffer(VertexArray *va) const 192{ 193 uint32_t stride = mElement->getSizeBytes(); 194 for (uint32_t ct=0; ct < mAttribsSize; ct++) { 195 // Load up to RS_MAX_ATTRIBS inputs 196 // TODO: grow vertexarray dynamically 197 if(ct >= RS_MAX_ATTRIBS) { 198 LOGE("More GL attributes than we can handle"); 199 break; 200 } 201 if (mAttribs[ct].size) { 202 va->add(mAttribs[ct], stride); 203 } 204 } 205} 206 207 208 209void Type::dumpLOGV(const char *prefix) const 210{ 211 char buf[1024]; 212 ObjectBase::dumpLOGV(prefix); 213 LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); 214 sprintf(buf, "%s element: ", prefix); 215 mElement->dumpLOGV(buf); 216} 217 218void Type::serialize(OStream *stream) const 219{ 220 // Need to identify ourselves 221 stream->addU32((uint32_t)getClassId()); 222 223 String8 name(getName()); 224 stream->addString(&name); 225 226 mElement->serialize(stream); 227 228 stream->addU32(mDimX); 229 stream->addU32(mDimY); 230 stream->addU32(mDimZ); 231 232 stream->addU8((uint8_t)(mDimLOD ? 1 : 0)); 233 stream->addU8((uint8_t)(mFaces ? 1 : 0)); 234} 235 236Type *Type::createFromStream(Context *rsc, IStream *stream) 237{ 238 // First make sure we are reading the correct object 239 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 240 if(classID != RS_A3D_CLASS_ID_TYPE) { 241 LOGE("type loading skipped due to invalid class id\n"); 242 return NULL; 243 } 244 245 String8 name; 246 stream->loadString(&name); 247 248 Element *elem = Element::createFromStream(rsc, stream); 249 if(!elem) { 250 return NULL; 251 } 252 253 Type *type = new Type(rsc); 254 type->mDimX = stream->loadU32(); 255 type->mDimY = stream->loadU32(); 256 type->mDimZ = stream->loadU32(); 257 258 uint8_t temp = stream->loadU8(); 259 type->mDimLOD = temp != 0; 260 261 temp = stream->loadU8(); 262 type->mFaces = temp != 0; 263 264 type->setElement(elem); 265 266 return type; 267} 268 269bool Type::getIsNp2() const 270{ 271 uint32_t x = getDimX(); 272 uint32_t y = getDimY(); 273 uint32_t z = getDimZ(); 274 275 if (x && (x & (x-1))) { 276 return true; 277 } 278 if (y && (y & (y-1))) { 279 return true; 280 } 281 if (z && (z & (z-1))) { 282 return true; 283 } 284 return false; 285} 286 287bool Type::isEqual(const Type *other) const { 288 if(other == NULL) { 289 return false; 290 } 291 if (other->getElement()->isEqual(getElement()) && 292 other->getDimX() == mDimX && 293 other->getDimY() == mDimY && 294 other->getDimZ() == mDimZ && 295 other->getDimLOD() == mDimLOD && 296 other->getDimFaces() == mFaces) { 297 return true; 298 } 299 return false; 300} 301 302Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const 303{ 304 TypeState * stc = &rsc->mStateType; 305 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 306 Type *t = stc->mTypes[ct]; 307 if (t->getElement() != mElement.get()) continue; 308 if (t->getDimX() != dimX) continue; 309 if (t->getDimY() != mDimY) continue; 310 if (t->getDimZ() != mDimZ) continue; 311 if (t->getDimLOD() != mDimLOD) continue; 312 if (t->getDimFaces() != mFaces) continue; 313 t->incUserRef(); 314 return t; 315 } 316 317 Type *nt = new Type(rsc); 318 nt->mElement.set(mElement); 319 nt->mDimX = dimX; 320 nt->mDimY = mDimY; 321 nt->mDimZ = mDimZ; 322 nt->mDimLOD = mDimLOD; 323 nt->mFaces = mFaces; 324 nt->compute(); 325 return nt; 326} 327 328Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const 329{ 330 TypeState * stc = &rsc->mStateType; 331 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 332 Type *t = stc->mTypes[ct]; 333 if (t->getElement() != mElement.get()) continue; 334 if (t->getDimX() != dimX) continue; 335 if (t->getDimY() != dimY) continue; 336 if (t->getDimZ() != mDimZ) continue; 337 if (t->getDimLOD() != mDimLOD) continue; 338 if (t->getDimFaces() != mFaces) continue; 339 t->incUserRef(); 340 return t; 341 } 342 343 Type *nt = new Type(rsc); 344 nt->mElement.set(mElement); 345 nt->mDimX = dimX; 346 nt->mDimY = dimY; 347 nt->mDimZ = mDimZ; 348 nt->mDimLOD = mDimLOD; 349 nt->mFaces = mFaces; 350 nt->compute(); 351 return nt; 352} 353 354 355////////////////////////////////////////////////// 356// 357namespace android { 358namespace renderscript { 359 360void rsi_TypeBegin(Context *rsc, RsElement vse) 361{ 362 TypeState * stc = &rsc->mStateType; 363 364 stc->mX = 0; 365 stc->mY = 0; 366 stc->mZ = 0; 367 stc->mLOD = false; 368 stc->mFaces = false; 369 stc->mElement.set(static_cast<const Element *>(vse)); 370} 371 372void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value) 373{ 374 TypeState * stc = &rsc->mStateType; 375 376 if (dim < 0) { 377 //error 378 return; 379 } 380 381 382 switch (dim) { 383 case RS_DIMENSION_X: 384 stc->mX = value; 385 return; 386 case RS_DIMENSION_Y: 387 stc->mY = value; 388 return; 389 case RS_DIMENSION_Z: 390 stc->mZ = value; 391 return; 392 case RS_DIMENSION_FACE: 393 stc->mFaces = (value != 0); 394 return; 395 case RS_DIMENSION_LOD: 396 stc->mLOD = (value != 0); 397 return; 398 default: 399 break; 400 } 401 402 if ((dim < 0) || (dim > RS_DIMENSION_MAX)) { 403 LOGE("rsTypeAdd: Bad dimension"); 404 //error 405 return; 406 } 407 408 // todo: implement array support 409 410} 411 412RsType rsi_TypeCreate(Context *rsc) 413{ 414 TypeState * stc = &rsc->mStateType; 415 416 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { 417 Type *t = stc->mTypes[ct]; 418 if (t->getElement() != stc->mElement.get()) continue; 419 if (t->getDimX() != stc->mX) continue; 420 if (t->getDimY() != stc->mY) continue; 421 if (t->getDimZ() != stc->mZ) continue; 422 if (t->getDimLOD() != stc->mLOD) continue; 423 if (t->getDimFaces() != stc->mFaces) continue; 424 t->incUserRef(); 425 return t; 426 } 427 428 Type * st = new Type(rsc); 429 st->incUserRef(); 430 st->setDimX(stc->mX); 431 st->setDimY(stc->mY); 432 st->setDimZ(stc->mZ); 433 st->setElement(stc->mElement.get()); 434 st->setDimLOD(stc->mLOD); 435 st->setDimFaces(stc->mFaces); 436 st->compute(); 437 stc->mElement.clear(); 438 stc->mTypes.push(st); 439 return st; 440} 441 442void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize) 443{ 444 rsAssert(typeDataSize == 6); 445 // Pack the data in the follofing way mDimX; mDimY; mDimZ; 446 // mDimLOD; mDimFaces; mElement; into typeData 447 Type *t = static_cast<Type *>(type); 448 449 (*typeData++) = t->getDimX(); 450 (*typeData++) = t->getDimY(); 451 (*typeData++) = t->getDimZ(); 452 (*typeData++) = t->getDimLOD(); 453 (*typeData++) = t->getDimFaces() ? 1 : 0; 454 (*typeData++) = (uint32_t)t->getElement(); 455 456} 457 458 459} 460} 461 462