/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "rsContext.h" #include using namespace android; using namespace android::renderscript; Type::Type(Context *rsc) : ObjectBase(rsc) { mAllocFile = __FILE__; mAllocLine = __LINE__; mLODs = 0; mLODCount = 0; clear(); } Type::~Type() { if (mLODs) { delete [] mLODs; } } void Type::clear() { if (mLODs) { delete [] mLODs; mLODs = NULL; } mDimX = 0; mDimY = 0; mDimZ = 0; mDimLOD = 0; mFaces = false; mElement.clear(); } TypeState::TypeState() { } TypeState::~TypeState() { } size_t Type::getOffsetForFace(uint32_t face) const { rsAssert(mFaces); return 0; } void Type::compute() { uint32_t oldLODCount = mLODCount; if (mDimLOD) { uint32_t l2x = rsFindHighBit(mDimX) + 1; uint32_t l2y = rsFindHighBit(mDimY) + 1; uint32_t l2z = rsFindHighBit(mDimZ) + 1; mLODCount = rsMax(l2x, l2y); mLODCount = rsMax(mLODCount, l2z); } else { mLODCount = 1; } if (mLODCount != oldLODCount) { delete [] mLODs; mLODs = new LOD[mLODCount]; } uint32_t tx = mDimX; uint32_t ty = mDimY; uint32_t tz = mDimZ; size_t offset = 0; for (uint32_t lod=0; lod < mLODCount; lod++) { mLODs[lod].mX = tx; mLODs[lod].mY = ty; mLODs[lod].mZ = tz; mLODs[lod].mOffset = offset; offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes(); if (tx > 1) tx >>= 1; if (ty > 1) ty >>= 1; if (tz > 1) tz >>= 1; } // At this point the offset is the size of a mipmap chain; mMipChainSizeBytes = offset; if (mFaces) { offset *= 6; } mTotalSizeBytes = offset; makeGLComponents(); } uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const { uint32_t offset = mLODs[lod].mOffset; offset += x * mElement->getSizeBytes(); return offset; } uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const { uint32_t offset = mLODs[lod].mOffset; offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes(); return offset; } uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const { uint32_t offset = mLODs[lod].mOffset; offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes(); return offset; } void Type::makeGLComponents() { uint32_t userNum = 0; for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) { const Component &c = getElement()->getField(ct)->getComponent(); switch(c.getKind()) { case RS_KIND_USER: mGL.mUser[userNum].size = c.getVectorSize(); mGL.mUser[userNum].offset = mElement->getFieldOffsetBytes(ct); mGL.mUser[userNum].type = c.getGLType(); mGL.mUser[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized(); mGL.mUser[userNum].name.setTo(getElement()->getFieldName(ct)); userNum ++; break; case RS_KIND_POSITION: rsAssert(mGL.mVtx.size == 0); mGL.mVtx.size = c.getVectorSize(); mGL.mVtx.offset = mElement->getFieldOffsetBytes(ct); mGL.mVtx.type = c.getGLType(); mGL.mVtx.normalized = false; mGL.mVtx.name.setTo("Position"); break; case RS_KIND_COLOR: rsAssert(mGL.mColor.size == 0); mGL.mColor.size = c.getVectorSize(); mGL.mColor.offset = mElement->getFieldOffsetBytes(ct); mGL.mColor.type = c.getGLType(); mGL.mColor.normalized = c.getType() != RS_TYPE_FLOAT_32; mGL.mColor.name.setTo("Color"); break; case RS_KIND_NORMAL: rsAssert(mGL.mNorm.size == 0); mGL.mNorm.size = c.getVectorSize(); mGL.mNorm.offset = mElement->getFieldOffsetBytes(ct); mGL.mNorm.type = c.getGLType(); mGL.mNorm.normalized = false; mGL.mNorm.name.setTo("Normal"); break; case RS_KIND_TEXTURE: rsAssert(mGL.mTex.size == 0); mGL.mTex.size = c.getVectorSize(); mGL.mTex.offset = mElement->getFieldOffsetBytes(ct); mGL.mTex.type = c.getGLType(); mGL.mTex.normalized = false; mGL.mTex.name.setTo("Texture"); break; case RS_KIND_POINT_SIZE: rsAssert(!mGL.mPointSize.size); mGL.mPointSize.size = c.getVectorSize(); mGL.mPointSize.offset = mElement->getFieldOffsetBytes(ct); mGL.mPointSize.type = c.getGLType(); mGL.mPointSize.normalized = false; mGL.mPointSize.name.setTo("PointSize"); break; default: break; } } } void Type::enableGLVertexBuffer(VertexArray *va) const { // Note: We are only going to enable buffers and never disable them // here. The reason is more than one Allocation may be used as a vertex // source. So we cannot disable arrays that may have been in use by // another allocation. uint32_t stride = mElement->getSizeBytes(); if (mGL.mVtx.size) { va->setPosition(mGL.mVtx.size, mGL.mVtx.type, stride, mGL.mVtx.offset); } if (mGL.mNorm.size) { va->setNormal(mGL.mNorm.type, stride, mGL.mNorm.offset); } if (mGL.mColor.size) { va->setColor(mGL.mColor.size, mGL.mColor.type, stride, mGL.mColor.offset); } if (mGL.mTex.size) { va->setTexture(mGL.mTex.size, mGL.mTex.type, stride, mGL.mTex.offset); } if (mGL.mPointSize.size) { va->setPointSize(mGL.mPointSize.type, stride, mGL.mPointSize.offset); } } void Type::enableGLVertexBuffer2(VertexArray *va) const { // Do legacy buffers enableGLVertexBuffer(va); uint32_t stride = mElement->getSizeBytes(); for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) { if (mGL.mUser[ct].size) { va->setUser(mGL.mUser[ct], stride); } } } void Type::dumpLOGV(const char *prefix) const { char buf[1024]; ObjectBase::dumpLOGV(prefix); LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); sprintf(buf, "%s element: ", prefix); mElement->dumpLOGV(buf); } ////////////////////////////////////////////////// // namespace android { namespace renderscript { void rsi_TypeBegin(Context *rsc, RsElement vse) { TypeState * stc = &rsc->mStateType; stc->mX = 0; stc->mY = 0; stc->mZ = 0; stc->mLOD = false; stc->mFaces = false; stc->mElement.set(static_cast(vse)); } void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value) { TypeState * stc = &rsc->mStateType; if (dim < 0) { //error return; } switch (dim) { case RS_DIMENSION_X: stc->mX = value; return; case RS_DIMENSION_Y: stc->mY = value; return; case RS_DIMENSION_Z: stc->mZ = value; return; case RS_DIMENSION_FACE: stc->mFaces = (value != 0); return; case RS_DIMENSION_LOD: stc->mLOD = (value != 0); return; default: break; } int32_t arrayNum = dim - RS_DIMENSION_ARRAY_0; if ((dim < 0) || (dim > RS_DIMENSION_MAX)) { LOGE("rsTypeAdd: Bad dimension"); //error return; } // todo: implement array support } RsType rsi_TypeCreate(Context *rsc) { TypeState * stc = &rsc->mStateType; Type * st = new Type(rsc); st->incUserRef(); st->setDimX(stc->mX); st->setDimY(stc->mY); st->setDimZ(stc->mZ); st->setElement(stc->mElement.get()); st->setDimLOD(stc->mLOD); st->setDimFaces(stc->mFaces); st->compute(); stc->mElement.clear(); return st; } } }