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