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