rsType.cpp revision be504f2d0c5db4485e6db5b406e9e8b8c390dea9
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#include <GLES/gl.h>
19
20using namespace android;
21using namespace android::renderscript;
22
23Type::Type(Context *rsc) : ObjectBase(rsc)
24{
25    mAllocFile = __FILE__;
26    mAllocLine = __LINE__;
27    mLODs = 0;
28    mLODCount = 0;
29    clear();
30}
31
32Type::~Type()
33{
34    if (mLODs) {
35        delete [] mLODs;
36    }
37}
38
39void Type::clear()
40{
41    if (mLODs) {
42        delete [] mLODs;
43        mLODs = NULL;
44    }
45    mDimX = 0;
46    mDimY = 0;
47    mDimZ = 0;
48    mDimLOD = 0;
49    mFaces = false;
50    mElement.clear();
51}
52
53TypeState::TypeState()
54{
55}
56
57TypeState::~TypeState()
58{
59}
60
61size_t Type::getOffsetForFace(uint32_t face) const
62{
63    rsAssert(mFaces);
64    return 0;
65}
66
67void Type::compute()
68{
69    uint32_t oldLODCount = mLODCount;
70    if (mDimLOD) {
71        uint32_t l2x = rsFindHighBit(mDimX) + 1;
72        uint32_t l2y = rsFindHighBit(mDimY) + 1;
73        uint32_t l2z = rsFindHighBit(mDimZ) + 1;
74
75        mLODCount = rsMax(l2x, l2y);
76        mLODCount = rsMax(mLODCount, l2z);
77    } else {
78        mLODCount = 1;
79    }
80    if (mLODCount != oldLODCount) {
81        delete [] mLODs;
82        mLODs = new LOD[mLODCount];
83    }
84
85    uint32_t tx = mDimX;
86    uint32_t ty = mDimY;
87    uint32_t tz = mDimZ;
88    size_t offset = 0;
89    for (uint32_t lod=0; lod < mLODCount; lod++) {
90        mLODs[lod].mX = tx;
91        mLODs[lod].mY = ty;
92        mLODs[lod].mZ = tz;
93        mLODs[lod].mOffset = offset;
94        offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
95        if (tx > 1) tx >>= 1;
96        if (ty > 1) ty >>= 1;
97        if (tz > 1) tz >>= 1;
98    }
99
100    // At this point the offset is the size of a mipmap chain;
101    mMipChainSizeBytes = offset;
102
103    if (mFaces) {
104        offset *= 6;
105    }
106    mTotalSizeBytes = offset;
107
108    makeGLComponents();
109}
110
111uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const
112{
113    uint32_t offset = mLODs[lod].mOffset;
114    offset += x * mElement->getSizeBytes();
115    return offset;
116}
117
118uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const
119{
120    uint32_t offset = mLODs[lod].mOffset;
121    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
122    return offset;
123}
124
125uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const
126{
127    uint32_t offset = mLODs[lod].mOffset;
128    offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes();
129    return offset;
130}
131
132
133void Type::makeGLComponents()
134{
135    uint32_t userNum = 0;
136
137    for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) {
138        const Component &c = getElement()->getField(ct)->getComponent();
139
140        switch(c.getKind()) {
141        case RS_KIND_USER:
142            mGL.mUser[userNum].size = c.getVectorSize();
143            mGL.mUser[userNum].offset = mElement->getFieldOffsetBytes(ct);
144            mGL.mUser[userNum].type = c.getGLType();
145            mGL.mUser[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
146            mGL.mUser[userNum].name.setTo(getElement()->getFieldName(ct));
147            userNum ++;
148            break;
149
150        case RS_KIND_POSITION:
151            rsAssert(mGL.mVtx.size == 0);
152            mGL.mVtx.size = c.getVectorSize();
153            mGL.mVtx.offset = mElement->getFieldOffsetBytes(ct);
154            mGL.mVtx.type = c.getGLType();
155            mGL.mVtx.normalized = false;
156            mGL.mVtx.name.setTo("Position");
157            break;
158
159        case RS_KIND_COLOR:
160            rsAssert(mGL.mColor.size == 0);
161            mGL.mColor.size = c.getVectorSize();
162            mGL.mColor.offset = mElement->getFieldOffsetBytes(ct);
163            mGL.mColor.type = c.getGLType();
164            mGL.mColor.normalized = c.getType() != RS_TYPE_FLOAT_32;
165            mGL.mColor.name.setTo("Color");
166            break;
167
168        case RS_KIND_NORMAL:
169            rsAssert(mGL.mNorm.size == 0);
170            mGL.mNorm.size = c.getVectorSize();
171            mGL.mNorm.offset = mElement->getFieldOffsetBytes(ct);
172            mGL.mNorm.type = c.getGLType();
173            mGL.mNorm.normalized = false;
174            mGL.mNorm.name.setTo("Normal");
175            break;
176
177        case RS_KIND_TEXTURE:
178            rsAssert(mGL.mTex.size == 0);
179            mGL.mTex.size = c.getVectorSize();
180            mGL.mTex.offset = mElement->getFieldOffsetBytes(ct);
181            mGL.mTex.type = c.getGLType();
182            mGL.mTex.normalized = false;
183            mGL.mTex.name.setTo("Texture");
184            break;
185
186        case RS_KIND_POINT_SIZE:
187            rsAssert(!mGL.mPointSize.size);
188            mGL.mPointSize.size = c.getVectorSize();
189            mGL.mPointSize.offset = mElement->getFieldOffsetBytes(ct);
190            mGL.mPointSize.type = c.getGLType();
191            mGL.mPointSize.normalized = false;
192            mGL.mPointSize.name.setTo("PointSize");
193        break;
194
195        default:
196            break;
197        }
198    }
199}
200
201void Type::enableGLVertexBuffer(VertexArray *va) const
202{
203    // Note: We are only going to enable buffers and never disable them
204    // here.  The reason is more than one Allocation may be used as a vertex
205    // source.  So we cannot disable arrays that may have been in use by
206    // another allocation.
207
208    uint32_t stride = mElement->getSizeBytes();
209    if (mGL.mVtx.size) {
210        va->addLegacy(mGL.mVtx.type,
211                      mGL.mVtx.size,
212                      stride,
213                      RS_KIND_POSITION,
214                      false,
215                      mGL.mVtx.offset);
216    }
217
218    if (mGL.mNorm.size) {
219        va->addLegacy(mGL.mNorm.type,
220                     3,
221                     stride,
222                     RS_KIND_NORMAL,
223                     false,
224                     mGL.mNorm.offset);
225    }
226
227    if (mGL.mColor.size) {
228        va->addLegacy(mGL.mColor.type,
229                     mGL.mColor.size,
230                     stride,
231                     RS_KIND_COLOR,
232                     true,
233                     mGL.mColor.offset);
234    }
235
236    if (mGL.mTex.size) {
237        va->addLegacy(mGL.mTex.type,
238                     mGL.mTex.size,
239                     stride,
240                     RS_KIND_TEXTURE,
241                     false,
242                     mGL.mTex.offset);
243    }
244
245    if (mGL.mPointSize.size) {
246        va->addLegacy(mGL.mPointSize.type,
247                     1,
248                     stride,
249                     RS_KIND_POINT_SIZE,
250                     false,
251                     mGL.mPointSize.offset);
252    }
253
254}
255
256void Type::enableGLVertexBuffer2(VertexArray *va) const
257{
258    // Do legacy buffers
259    enableGLVertexBuffer(va);
260
261    uint32_t stride = mElement->getSizeBytes();
262    for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) {
263        if (mGL.mUser[ct].size) {
264            va->addUser(mGL.mUser[ct], stride);
265        }
266    }
267}
268
269
270
271void Type::dumpLOGV(const char *prefix) const
272{
273    char buf[1024];
274    ObjectBase::dumpLOGV(prefix);
275    LOGV("%s   Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
276    sprintf(buf, "%s element: ", prefix);
277    mElement->dumpLOGV(buf);
278}
279
280
281//////////////////////////////////////////////////
282//
283namespace android {
284namespace renderscript {
285
286void rsi_TypeBegin(Context *rsc, RsElement vse)
287{
288    TypeState * stc = &rsc->mStateType;
289
290    stc->mX = 0;
291    stc->mY = 0;
292    stc->mZ = 0;
293    stc->mLOD = false;
294    stc->mFaces = false;
295    stc->mElement.set(static_cast<const Element *>(vse));
296}
297
298void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value)
299{
300    TypeState * stc = &rsc->mStateType;
301
302    if (dim < 0) {
303        //error
304        return;
305    }
306
307
308    switch (dim) {
309    case RS_DIMENSION_X:
310        stc->mX = value;
311        return;
312    case RS_DIMENSION_Y:
313        stc->mY = value;
314        return;
315    case RS_DIMENSION_Z:
316        stc->mZ = value;
317        return;
318    case RS_DIMENSION_FACE:
319        stc->mFaces = (value != 0);
320        return;
321    case RS_DIMENSION_LOD:
322        stc->mLOD = (value != 0);
323        return;
324    default:
325        break;
326    }
327
328
329    int32_t arrayNum = dim - RS_DIMENSION_ARRAY_0;
330    if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
331        LOGE("rsTypeAdd: Bad dimension");
332        //error
333        return;
334    }
335
336    // todo: implement array support
337
338}
339
340RsType rsi_TypeCreate(Context *rsc)
341{
342    TypeState * stc = &rsc->mStateType;
343
344    Type * st = new Type(rsc);
345    st->incUserRef();
346    st->setDimX(stc->mX);
347    st->setDimY(stc->mY);
348    st->setDimZ(stc->mZ);
349    st->setElement(stc->mElement.get());
350    st->setDimLOD(stc->mLOD);
351    st->setDimFaces(stc->mFaces);
352    st->compute();
353    stc->mElement.clear();
354
355    return st;
356}
357
358
359}
360}
361
362