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