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