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