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