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