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
20 using namespace android;
21 using namespace android::renderscript;
22
Type(Context * rsc)23 Type::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
~Type()33 Type::~Type()
34 {
35 if (mLODs) {
36 delete [] mLODs;
37 }
38 }
39
clear()40 void 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
TypeState()54 TypeState::TypeState()
55 {
56 }
57
~TypeState()58 TypeState::~TypeState()
59 {
60 }
61
getOffsetForFace(uint32_t face) const62 size_t Type::getOffsetForFace(uint32_t face) const
63 {
64 rsAssert(mFaces);
65 return 0;
66 }
67
compute()68 void 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
getLODOffset(uint32_t lod,uint32_t x) const112 uint32_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
getLODOffset(uint32_t lod,uint32_t x,uint32_t y) const119 uint32_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
getLODOffset(uint32_t lod,uint32_t x,uint32_t y,uint32_t z) const126 uint32_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
makeGLComponents()134 void 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
enableGLVertexBuffer() const248 void 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
dumpLOGV(const char * prefix) const305 void Type::dumpLOGV(const char *prefix) const
306 {
307 char buf[1024];
308 ObjectBase::dumpLOGV(prefix);
309 LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
310 sprintf(buf, "%s element: ", prefix);
311 mElement->dumpLOGV(buf);
312 }
313
314
315 //////////////////////////////////////////////////
316 //
317 namespace android {
318 namespace renderscript {
319
rsi_TypeBegin(Context * rsc,RsElement vse)320 void rsi_TypeBegin(Context *rsc, RsElement vse)
321 {
322 TypeState * stc = &rsc->mStateType;
323
324 stc->mX = 0;
325 stc->mY = 0;
326 stc->mZ = 0;
327 stc->mLOD = false;
328 stc->mFaces = false;
329 stc->mElement.set(static_cast<const Element *>(vse));
330 }
331
rsi_TypeAdd(Context * rsc,RsDimension dim,size_t value)332 void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value)
333 {
334 TypeState * stc = &rsc->mStateType;
335
336 if (dim < 0) {
337 //error
338 return;
339 }
340
341
342 switch (dim) {
343 case RS_DIMENSION_X:
344 stc->mX = value;
345 return;
346 case RS_DIMENSION_Y:
347 stc->mY = value;
348 return;
349 case RS_DIMENSION_Z:
350 stc->mZ = value;
351 return;
352 case RS_DIMENSION_FACE:
353 stc->mFaces = (value != 0);
354 return;
355 case RS_DIMENSION_LOD:
356 stc->mLOD = (value != 0);
357 return;
358 default:
359 break;
360 }
361
362
363 int32_t arrayNum = dim - RS_DIMENSION_ARRAY_0;
364 if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
365 LOGE("rsTypeAdd: Bad dimension");
366 //error
367 return;
368 }
369
370 // todo: implement array support
371
372 }
373
rsi_TypeCreate(Context * rsc)374 RsType rsi_TypeCreate(Context *rsc)
375 {
376 TypeState * stc = &rsc->mStateType;
377
378 Type * st = new Type(rsc);
379 st->incUserRef();
380 st->setDimX(stc->mX);
381 st->setDimY(stc->mY);
382 st->setDimZ(stc->mZ);
383 st->setElement(stc->mElement.get());
384 st->setDimLOD(stc->mLOD);
385 st->setDimFaces(stc->mFaces);
386 st->compute();
387 stc->mElement.clear();
388
389 return st;
390 }
391
392
393 }
394 }
395
396