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