rsType.cpp revision 700ba38f022208686523ab4280c4fc9f102aa273
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    mAttribs = NULL;
35    mAttribsSize = 0;
36    clear();
37}
38
39Type::~Type()
40{
41    for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
42        if (mRSC->mStateType.mTypes[ct] == this) {
43            mRSC->mStateType.mTypes.removeAt(ct);
44            break;
45        }
46    }
47    if (mLODs) {
48        delete [] mLODs;
49        mLODs = NULL;
50    }
51    if(mAttribs) {
52        delete [] mAttribs;
53        mAttribs = NULL;
54    }
55}
56
57void Type::clear()
58{
59    if (mLODs) {
60        delete [] mLODs;
61        mLODs = NULL;
62    }
63    mDimX = 0;
64    mDimY = 0;
65    mDimZ = 0;
66    mDimLOD = 0;
67    mFaces = false;
68    mElement.clear();
69}
70
71TypeState::TypeState()
72{
73}
74
75TypeState::~TypeState()
76{
77}
78
79size_t Type::getOffsetForFace(uint32_t face) const
80{
81    rsAssert(mFaces);
82    return 0;
83}
84
85void Type::compute()
86{
87    uint32_t oldLODCount = mLODCount;
88    if (mDimLOD) {
89        uint32_t l2x = rsFindHighBit(mDimX) + 1;
90        uint32_t l2y = rsFindHighBit(mDimY) + 1;
91        uint32_t l2z = rsFindHighBit(mDimZ) + 1;
92
93        mLODCount = rsMax(l2x, l2y);
94        mLODCount = rsMax(mLODCount, l2z);
95    } else {
96        mLODCount = 1;
97    }
98    if (mLODCount != oldLODCount) {
99        if(mLODs){
100            delete [] mLODs;
101        }
102        mLODs = new LOD[mLODCount];
103    }
104
105    uint32_t tx = mDimX;
106    uint32_t ty = mDimY;
107    uint32_t tz = mDimZ;
108    size_t offset = 0;
109    for (uint32_t lod=0; lod < mLODCount; lod++) {
110        mLODs[lod].mX = tx;
111        mLODs[lod].mY = ty;
112        mLODs[lod].mZ = tz;
113        mLODs[lod].mOffset = offset;
114        offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
115        if (tx > 1) tx >>= 1;
116        if (ty > 1) ty >>= 1;
117        if (tz > 1) tz >>= 1;
118    }
119
120    // At this point the offset is the size of a mipmap chain;
121    mMipChainSizeBytes = offset;
122
123    if (mFaces) {
124        offset *= 6;
125    }
126    mTotalSizeBytes = offset;
127
128    makeGLComponents();
129}
130
131uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const
132{
133    uint32_t offset = mLODs[lod].mOffset;
134    offset += x * mElement->getSizeBytes();
135    return offset;
136}
137
138uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const
139{
140    uint32_t offset = mLODs[lod].mOffset;
141    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
142    return offset;
143}
144
145uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const
146{
147    uint32_t offset = mLODs[lod].mOffset;
148    offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes();
149    return offset;
150}
151
152
153void Type::makeGLComponents()
154{
155    // Count the number of gl attrs to initialize
156    mAttribsSize = 0;
157    for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) {
158        if(getElement()->getFieldName(ct)[0] != '#') {
159            mAttribsSize ++;
160        }
161    }
162    if(mAttribs) {
163        delete [] mAttribs;
164        mAttribs = NULL;
165    }
166    if(mAttribsSize) {
167        mAttribs = new VertexArray::Attrib[mAttribsSize];
168    }
169
170    uint32_t userNum = 0;
171    for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) {
172        const Component &c = getElement()->getField(ct)->getComponent();
173
174        if(getElement()->getFieldName(ct)[0] == '#') {
175            continue;
176        }
177
178        mAttribs[userNum].size = c.getVectorSize();
179        mAttribs[userNum].offset = mElement->getFieldOffsetBytes(ct);
180        mAttribs[userNum].type = c.getGLType();
181        mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
182        String8 tmp(RS_SHADER_ATTR);
183        tmp.append(getElement()->getFieldName(ct));
184        mAttribs[userNum].name.setTo(tmp.string());
185
186        userNum ++;
187    }
188}
189
190
191void Type::enableGLVertexBuffer(VertexArray *va) const
192{
193    uint32_t stride = mElement->getSizeBytes();
194    for (uint32_t ct=0; ct < mAttribsSize; ct++) {
195        // Load up to RS_MAX_ATTRIBS inputs
196        // TODO: grow vertexarray dynamically
197        if(ct >= RS_MAX_ATTRIBS) {
198            LOGE("More GL attributes than we can handle");
199            break;
200        }
201        if (mAttribs[ct].size) {
202            va->add(mAttribs[ct], stride);
203        }
204    }
205}
206
207
208
209void Type::dumpLOGV(const char *prefix) const
210{
211    char buf[1024];
212    ObjectBase::dumpLOGV(prefix);
213    LOGV("%s   Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
214    sprintf(buf, "%s element: ", prefix);
215    mElement->dumpLOGV(buf);
216}
217
218void Type::serialize(OStream *stream) const
219{
220    // Need to identify ourselves
221    stream->addU32((uint32_t)getClassId());
222
223    String8 name(getName());
224    stream->addString(&name);
225
226    mElement->serialize(stream);
227
228    stream->addU32(mDimX);
229    stream->addU32(mDimY);
230    stream->addU32(mDimZ);
231
232    stream->addU8((uint8_t)(mDimLOD ? 1 : 0));
233    stream->addU8((uint8_t)(mFaces ? 1 : 0));
234}
235
236Type *Type::createFromStream(Context *rsc, IStream *stream)
237{
238    // First make sure we are reading the correct object
239    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
240    if(classID != RS_A3D_CLASS_ID_TYPE) {
241        LOGE("type loading skipped due to invalid class id\n");
242        return NULL;
243    }
244
245    String8 name;
246    stream->loadString(&name);
247
248    Element *elem = Element::createFromStream(rsc, stream);
249    if(!elem) {
250        return NULL;
251    }
252
253    Type *type = new Type(rsc);
254    type->mDimX = stream->loadU32();
255    type->mDimY = stream->loadU32();
256    type->mDimZ = stream->loadU32();
257
258    uint8_t temp = stream->loadU8();
259    type->mDimLOD = temp != 0;
260
261    temp = stream->loadU8();
262    type->mFaces = temp != 0;
263
264    type->setElement(elem);
265
266    return type;
267}
268
269bool Type::getIsNp2() const
270{
271    uint32_t x = getDimX();
272    uint32_t y = getDimY();
273    uint32_t z = getDimZ();
274
275    if (x && (x & (x-1))) {
276        return true;
277    }
278    if (y && (y & (y-1))) {
279        return true;
280    }
281    if (z && (z & (z-1))) {
282        return true;
283    }
284    return false;
285}
286
287bool Type::isEqual(const Type *other) const {
288    if(other == NULL) {
289        return false;
290    }
291    if (other->getElement()->isEqual(getElement()) &&
292        other->getDimX() == mDimX &&
293        other->getDimY() == mDimY &&
294        other->getDimZ() == mDimZ &&
295        other->getDimLOD() == mDimLOD &&
296        other->getDimFaces() == mFaces) {
297        return true;
298    }
299    return false;
300}
301
302Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
303{
304    TypeState * stc = &rsc->mStateType;
305    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
306        Type *t = stc->mTypes[ct];
307        if (t->getElement() != mElement.get()) continue;
308        if (t->getDimX() != dimX) continue;
309        if (t->getDimY() != mDimY) continue;
310        if (t->getDimZ() != mDimZ) continue;
311        if (t->getDimLOD() != mDimLOD) continue;
312        if (t->getDimFaces() != mFaces) continue;
313        t->incUserRef();
314        return t;
315    }
316
317    Type *nt = new Type(rsc);
318    nt->mElement.set(mElement);
319    nt->mDimX = dimX;
320    nt->mDimY = mDimY;
321    nt->mDimZ = mDimZ;
322    nt->mDimLOD = mDimLOD;
323    nt->mFaces = mFaces;
324    nt->compute();
325    return nt;
326}
327
328Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const
329{
330    TypeState * stc = &rsc->mStateType;
331    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
332        Type *t = stc->mTypes[ct];
333        if (t->getElement() != mElement.get()) continue;
334        if (t->getDimX() != dimX) continue;
335        if (t->getDimY() != dimY) continue;
336        if (t->getDimZ() != mDimZ) continue;
337        if (t->getDimLOD() != mDimLOD) continue;
338        if (t->getDimFaces() != mFaces) continue;
339        t->incUserRef();
340        return t;
341    }
342
343    Type *nt = new Type(rsc);
344    nt->mElement.set(mElement);
345    nt->mDimX = dimX;
346    nt->mDimY = dimY;
347    nt->mDimZ = mDimZ;
348    nt->mDimLOD = mDimLOD;
349    nt->mFaces = mFaces;
350    nt->compute();
351    return nt;
352}
353
354
355//////////////////////////////////////////////////
356//
357namespace android {
358namespace renderscript {
359
360void rsi_TypeBegin(Context *rsc, RsElement vse)
361{
362    TypeState * stc = &rsc->mStateType;
363
364    stc->mX = 0;
365    stc->mY = 0;
366    stc->mZ = 0;
367    stc->mLOD = false;
368    stc->mFaces = false;
369    stc->mElement.set(static_cast<const Element *>(vse));
370}
371
372void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value)
373{
374    TypeState * stc = &rsc->mStateType;
375
376    if (dim < 0) {
377        //error
378        return;
379    }
380
381
382    switch (dim) {
383    case RS_DIMENSION_X:
384        stc->mX = value;
385        return;
386    case RS_DIMENSION_Y:
387        stc->mY = value;
388        return;
389    case RS_DIMENSION_Z:
390        stc->mZ = value;
391        return;
392    case RS_DIMENSION_FACE:
393        stc->mFaces = (value != 0);
394        return;
395    case RS_DIMENSION_LOD:
396        stc->mLOD = (value != 0);
397        return;
398    default:
399        break;
400    }
401
402    if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
403        LOGE("rsTypeAdd: Bad dimension");
404        //error
405        return;
406    }
407
408    // todo: implement array support
409
410}
411
412RsType rsi_TypeCreate(Context *rsc)
413{
414    TypeState * stc = &rsc->mStateType;
415
416    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
417        Type *t = stc->mTypes[ct];
418        if (t->getElement() != stc->mElement.get()) continue;
419        if (t->getDimX() != stc->mX) continue;
420        if (t->getDimY() != stc->mY) continue;
421        if (t->getDimZ() != stc->mZ) continue;
422        if (t->getDimLOD() != stc->mLOD) continue;
423        if (t->getDimFaces() != stc->mFaces) continue;
424        t->incUserRef();
425        return t;
426    }
427
428    Type * st = new Type(rsc);
429    st->incUserRef();
430    st->setDimX(stc->mX);
431    st->setDimY(stc->mY);
432    st->setDimZ(stc->mZ);
433    st->setElement(stc->mElement.get());
434    st->setDimLOD(stc->mLOD);
435    st->setDimFaces(stc->mFaces);
436    st->compute();
437    stc->mElement.clear();
438    stc->mTypes.push(st);
439    return st;
440}
441
442void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize)
443{
444    rsAssert(typeDataSize == 6);
445    // Pack the data in the follofing way mDimX; mDimY; mDimZ;
446    // mDimLOD; mDimFaces; mElement; into typeData
447    Type *t = static_cast<Type *>(type);
448
449    (*typeData++) = t->getDimX();
450    (*typeData++) = t->getDimY();
451    (*typeData++) = t->getDimZ();
452    (*typeData++) = t->getDimLOD();
453    (*typeData++) = t->getDimFaces() ? 1 : 0;
454    (*typeData++) = (uint32_t)t->getElement();
455
456}
457
458
459}
460}
461
462