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