rsType.cpp revision 77d9f4bd05b2d2a161f30c12a2248f9c97eaac42
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#include "rsContext.h"
18
19using namespace android;
20using namespace android::renderscript;
21
22Type::Type(Context *rsc) : ObjectBase(rsc) {
23    mLODs = 0;
24    mLODCount = 0;
25    clear();
26}
27
28void Type::preDestroy() {
29    for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
30        if (mRSC->mStateType.mTypes[ct] == this) {
31            mRSC->mStateType.mTypes.removeAt(ct);
32            break;
33        }
34    }
35}
36
37Type::~Type() {
38    if (mLODs) {
39        delete [] mLODs;
40        mLODs = NULL;
41    }
42}
43
44void Type::clear() {
45    if (mLODs) {
46        delete [] mLODs;
47        mLODs = NULL;
48    }
49    mDimX = 0;
50    mDimY = 0;
51    mDimZ = 0;
52    mDimLOD = 0;
53    mFaces = false;
54    mElement.clear();
55}
56
57TypeState::TypeState() {
58}
59
60TypeState::~TypeState() {
61}
62
63size_t Type::getOffsetForFace(uint32_t face) const {
64    rsAssert(mFaces);
65    return 0;
66}
67
68void Type::compute() {
69    uint32_t oldLODCount = mLODCount;
70    if (mDimLOD) {
71        uint32_t l2x = rsFindHighBit(mDimX) + 1;
72        uint32_t l2y = rsFindHighBit(mDimY) + 1;
73        uint32_t l2z = rsFindHighBit(mDimZ) + 1;
74
75        mLODCount = rsMax(l2x, l2y);
76        mLODCount = rsMax(mLODCount, l2z);
77    } else {
78        mLODCount = 1;
79    }
80    if (mLODCount != oldLODCount) {
81        if (mLODs){
82            delete [] mLODs;
83        }
84        mLODs = new LOD[mLODCount];
85    }
86
87    uint32_t tx = mDimX;
88    uint32_t ty = mDimY;
89    uint32_t tz = mDimZ;
90    size_t offset = 0;
91    for (uint32_t lod=0; lod < mLODCount; lod++) {
92        mLODs[lod].mX = tx;
93        mLODs[lod].mY = ty;
94        mLODs[lod].mZ = tz;
95        mLODs[lod].mOffset = offset;
96        offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
97        if (tx > 1) tx >>= 1;
98        if (ty > 1) ty >>= 1;
99        if (tz > 1) tz >>= 1;
100    }
101
102    // At this point the offset is the size of a mipmap chain;
103    mMipChainSizeBytes = offset;
104
105    if (mFaces) {
106        offset *= 6;
107    }
108    mTotalSizeBytes = offset;
109}
110
111uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const {
112    uint32_t offset = mLODs[lod].mOffset;
113    offset += x * mElement->getSizeBytes();
114    return offset;
115}
116
117uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const {
118    uint32_t offset = mLODs[lod].mOffset;
119    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
120    return offset;
121}
122
123uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const {
124    uint32_t offset = mLODs[lod].mOffset;
125    offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes();
126    return offset;
127}
128
129uint32_t Type::getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const {
130    uint32_t offset = mLODs[lod].mOffset;
131    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
132
133    if (face != 0) {
134        uint32_t faceOffset = getSizeBytes() / 6;
135        offset += faceOffset * face;
136    }
137    return offset;
138}
139
140void Type::dumpLOGV(const char *prefix) const {
141    char buf[1024];
142    ObjectBase::dumpLOGV(prefix);
143    LOGV("%s   Type: x=%zu y=%zu z=%zu mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
144    snprintf(buf, sizeof(buf), "%s element: ", prefix);
145    mElement->dumpLOGV(buf);
146}
147
148void Type::serialize(OStream *stream) const {
149    // Need to identify ourselves
150    stream->addU32((uint32_t)getClassId());
151
152    String8 name(getName());
153    stream->addString(&name);
154
155    mElement->serialize(stream);
156
157    stream->addU32(mDimX);
158    stream->addU32(mDimY);
159    stream->addU32(mDimZ);
160
161    stream->addU8((uint8_t)(mDimLOD ? 1 : 0));
162    stream->addU8((uint8_t)(mFaces ? 1 : 0));
163}
164
165Type *Type::createFromStream(Context *rsc, IStream *stream) {
166    // First make sure we are reading the correct object
167    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
168    if (classID != RS_A3D_CLASS_ID_TYPE) {
169        LOGE("type loading skipped due to invalid class id\n");
170        return NULL;
171    }
172
173    String8 name;
174    stream->loadString(&name);
175
176    Element *elem = Element::createFromStream(rsc, stream);
177    if (!elem) {
178        return NULL;
179    }
180
181    uint32_t x = stream->loadU32();
182    uint32_t y = stream->loadU32();
183    uint32_t z = stream->loadU32();
184    uint8_t lod = stream->loadU8();
185    uint8_t faces = stream->loadU8();
186    return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 );
187}
188
189bool Type::getIsNp2() const {
190    uint32_t x = getDimX();
191    uint32_t y = getDimY();
192    uint32_t z = getDimZ();
193
194    if (x && (x & (x-1))) {
195        return true;
196    }
197    if (y && (y & (y-1))) {
198        return true;
199    }
200    if (z && (z & (z-1))) {
201        return true;
202    }
203    return false;
204}
205
206bool Type::isEqual(const Type *other) const {
207    if (other == NULL) {
208        return false;
209    }
210    if (other->getElement()->isEqual(getElement()) &&
211        other->getDimX() == mDimX &&
212        other->getDimY() == mDimY &&
213        other->getDimZ() == mDimZ &&
214        other->getDimLOD() == mDimLOD &&
215        other->getDimFaces() == mFaces) {
216        return true;
217    }
218    return false;
219}
220
221Type * Type::getType(Context *rsc, const Element *e,
222                     uint32_t dimX, uint32_t dimY, uint32_t dimZ,
223                     bool dimLOD, bool dimFaces) {
224    TypeState * stc = &rsc->mStateType;
225
226    ObjectBase::asyncLock();
227    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
228        Type *t = stc->mTypes[ct];
229        if (t->getElement() != e) continue;
230        if (t->getDimX() != dimX) continue;
231        if (t->getDimY() != dimY) continue;
232        if (t->getDimZ() != dimZ) continue;
233        if (t->getDimLOD() != dimLOD) continue;
234        if (t->getDimFaces() != dimFaces) continue;
235        t->incUserRef();
236        ObjectBase::asyncUnlock();
237        return t;
238    }
239    ObjectBase::asyncUnlock();
240
241
242    Type *nt = new Type(rsc);
243    nt->mElement.set(e);
244    nt->mDimX = dimX;
245    nt->mDimY = dimY;
246    nt->mDimZ = dimZ;
247    nt->mDimLOD = dimLOD;
248    nt->mFaces = dimFaces;
249    nt->compute();
250    nt->incUserRef();
251
252    ObjectBase::asyncLock();
253    stc->mTypes.push(nt);
254    ObjectBase::asyncUnlock();
255
256    return nt;
257}
258
259Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
260    return getType(rsc, mElement.get(), dimX,
261                   mDimY, mDimZ, mDimLOD, mFaces);
262}
263
264Type * Type::cloneAndResize2D(Context *rsc,
265                              uint32_t dimX,
266                              uint32_t dimY) const {
267    return getType(rsc, mElement.get(), dimX, dimY,
268                   mDimZ, mDimLOD, mFaces);
269}
270
271
272//////////////////////////////////////////////////
273//
274namespace android {
275namespace renderscript {
276
277}
278}
279
280RsType rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimX,
281                     uint32_t dimY, uint32_t dimZ, bool mips, bool faces) {
282    Context *rsc = static_cast<Context *>(con);
283    Element *e = static_cast<Element *>(_e);
284
285    return Type::getType(rsc, e, dimX, dimY, dimZ, mips, faces);
286}
287
288void rsaTypeGetNativeData(RsContext con, RsType type, uint32_t *typeData, uint32_t typeDataSize) {
289    rsAssert(typeDataSize == 6);
290    // Pack the data in the follofing way mDimX; mDimY; mDimZ;
291    // mDimLOD; mDimFaces; mElement; into typeData
292    Type *t = static_cast<Type *>(type);
293
294    (*typeData++) = t->getDimX();
295    (*typeData++) = t->getDimY();
296    (*typeData++) = t->getDimZ();
297    (*typeData++) = t->getDimLOD();
298    (*typeData++) = t->getDimFaces() ? 1 : 0;
299    (*typeData++) = (uint32_t)t->getElement();
300    t->getElement()->incUserRef();
301}
302