1 /*
2 * Copyright (C) 2013 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
19 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
20 #include "system/graphics.h"
21 #endif
22
23 #ifdef RS_COMPATIBILITY_LIB
24 #include "rsCompatibilityLib.h"
25 #endif
26
27 using namespace android;
28 using namespace android::renderscript;
29
Type(Context * rsc)30 Type::Type(Context *rsc) : ObjectBase(rsc) {
31 memset(&mHal, 0, sizeof(mHal));
32 mDimLOD = false;
33 }
34
preDestroy() const35 void Type::preDestroy() const {
36 for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
37 if (mRSC->mStateType.mTypes[ct] == this) {
38 mRSC->mStateType.mTypes.removeAt(ct);
39 break;
40 }
41 }
42 }
43
~Type()44 Type::~Type() {
45 clear();
46 }
47
clear()48 void Type::clear() {
49 if (mHal.state.lodCount) {
50 delete [] mHal.state.lodDimX;
51 delete [] mHal.state.lodDimY;
52 delete [] mHal.state.lodDimZ;
53 }
54 mElement.clear();
55 memset(&mHal, 0, sizeof(mHal));
56 }
57
TypeState()58 TypeState::TypeState() {
59 }
60
~TypeState()61 TypeState::~TypeState() {
62 rsAssert(!mTypes.size());
63 }
64
compute()65 void Type::compute() {
66 uint32_t oldLODCount = mHal.state.lodCount;
67 if (mDimLOD) {
68 uint32_t l2x = rsFindHighBit(mHal.state.dimX) + 1;
69 uint32_t l2y = rsFindHighBit(mHal.state.dimY) + 1;
70 uint32_t l2z = rsFindHighBit(mHal.state.dimZ) + 1;
71
72 mHal.state.lodCount = rsMax(l2x, l2y);
73 mHal.state.lodCount = rsMax(mHal.state.lodCount, l2z);
74 } else {
75 mHal.state.lodCount = 1;
76 }
77 if (mHal.state.lodCount != oldLODCount) {
78 if (oldLODCount) {
79 delete [] mHal.state.lodDimX;
80 delete [] mHal.state.lodDimY;
81 delete [] mHal.state.lodDimZ;
82 }
83 mHal.state.lodDimX = new uint32_t[mHal.state.lodCount];
84 mHal.state.lodDimY = new uint32_t[mHal.state.lodCount];
85 mHal.state.lodDimZ = new uint32_t[mHal.state.lodCount];
86 }
87
88 uint32_t tx = mHal.state.dimX;
89 uint32_t ty = mHal.state.dimY;
90 uint32_t tz = mHal.state.dimZ;
91 mCellCount = 0;
92 for (uint32_t lod=0; lod < mHal.state.lodCount; lod++) {
93 mHal.state.lodDimX[lod] = tx;
94 mHal.state.lodDimY[lod] = ty;
95 mHal.state.lodDimZ[lod] = tz;
96 mCellCount += tx * rsMax(ty, 1u) * rsMax(tz, 1u);
97 if (tx > 1) tx >>= 1;
98 if (ty > 1) ty >>= 1;
99 if (tz > 1) tz >>= 1;
100 }
101
102 if (mHal.state.faces) {
103 mCellCount *= 6;
104 }
105 #ifndef RS_SERVER
106 // YUV only supports basic 2d
107 // so we can stash the plane pointers in the mipmap levels.
108 if (mHal.state.dimYuv) {
109 mHal.state.lodDimX[1] = mHal.state.lodDimX[0] / 2;
110 mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2;
111 mHal.state.lodDimX[2] = mHal.state.lodDimX[0] / 2;
112 mHal.state.lodDimY[2] = mHal.state.lodDimY[0] / 2;
113 mCellCount += mHal.state.lodDimX[1] * mHal.state.lodDimY[1];
114 mCellCount += mHal.state.lodDimX[2] * mHal.state.lodDimY[2];
115
116 switch(mHal.state.dimYuv) {
117 case HAL_PIXEL_FORMAT_YV12:
118 break;
119 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
120 mHal.state.lodDimX[1] = mHal.state.lodDimX[0];
121 break;
122 #ifndef RS_COMPATIBILITY_LIB
123 case HAL_PIXEL_FORMAT_YCbCr_420_888:
124 break;
125 #endif
126 default:
127 rsAssert(0);
128 }
129 }
130 #endif
131 mHal.state.element = mElement.get();
132 }
133
dumpLOGV(const char * prefix) const134 void Type::dumpLOGV(const char *prefix) const {
135 char buf[1024];
136 ObjectBase::dumpLOGV(prefix);
137 ALOGV("%s Type: x=%u y=%u z=%u mip=%i face=%i", prefix,
138 mHal.state.dimX,
139 mHal.state.dimY,
140 mHal.state.dimZ,
141 mHal.state.lodCount,
142 mHal.state.faces);
143 snprintf(buf, sizeof(buf), "%s element: ", prefix);
144 mElement->dumpLOGV(buf);
145 }
146
serialize(Context * rsc,OStream * stream) const147 void Type::serialize(Context *rsc, OStream *stream) const {
148 // Need to identify ourselves
149 stream->addU32((uint32_t)getClassId());
150 stream->addString(getName());
151
152 mElement->serialize(rsc, stream);
153
154 stream->addU32(mHal.state.dimX);
155 stream->addU32(mHal.state.dimY);
156 stream->addU32(mHal.state.dimZ);
157
158 stream->addU8((uint8_t)(mHal.state.lodCount ? 1 : 0));
159 stream->addU8((uint8_t)(mHal.state.faces ? 1 : 0));
160 }
161
createFromStream(Context * rsc,IStream * stream)162 Type *Type::createFromStream(Context *rsc, IStream *stream) {
163 // First make sure we are reading the correct object
164 RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
165 if (classID != RS_A3D_CLASS_ID_TYPE) {
166 ALOGE("type loading skipped due to invalid class id\n");
167 return NULL;
168 }
169
170 const char *name = stream->loadString();
171
172 Element *elem = Element::createFromStream(rsc, stream);
173 if (!elem) {
174 return NULL;
175 }
176
177 uint32_t x = stream->loadU32();
178 uint32_t y = stream->loadU32();
179 uint32_t z = stream->loadU32();
180 uint8_t lod = stream->loadU8();
181 uint8_t faces = stream->loadU8();
182 Type *type = Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0, 0);
183 elem->decUserRef();
184
185 delete [] name;
186 return type;
187 }
188
getIsNp2() const189 bool Type::getIsNp2() const {
190 uint32_t x = getDimX();
191 uint32_t y = getDimY();
192 uint32_t z = getDimZ();
193
194 if (x && (x & (x-1))) {
195 return true;
196 }
197 if (y && (y & (y-1))) {
198 return true;
199 }
200 if (z && (z & (z-1))) {
201 return true;
202 }
203 return false;
204 }
205
getTypeRef(Context * rsc,const Element * e,uint32_t dimX,uint32_t dimY,uint32_t dimZ,bool dimLOD,bool dimFaces,uint32_t dimYuv)206 ObjectBaseRef<Type> Type::getTypeRef(Context *rsc, const Element *e,
207 uint32_t dimX, uint32_t dimY, uint32_t dimZ,
208 bool dimLOD, bool dimFaces, uint32_t dimYuv) {
209 ObjectBaseRef<Type> returnRef;
210
211 TypeState * stc = &rsc->mStateType;
212
213 ObjectBase::asyncLock();
214 for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
215 Type *t = stc->mTypes[ct];
216 if (t->getElement() != e) continue;
217 if (t->getDimX() != dimX) continue;
218 if (t->getDimY() != dimY) continue;
219 if (t->getDimZ() != dimZ) continue;
220 if (t->getDimLOD() != dimLOD) continue;
221 if (t->getDimFaces() != dimFaces) continue;
222 if (t->getDimYuv() != dimYuv) continue;
223 returnRef.set(t);
224 ObjectBase::asyncUnlock();
225 return returnRef;
226 }
227 ObjectBase::asyncUnlock();
228
229
230 Type *nt = new Type(rsc);
231 nt->mDimLOD = dimLOD;
232 returnRef.set(nt);
233 nt->mElement.set(e);
234 nt->mHal.state.dimX = dimX;
235 nt->mHal.state.dimY = dimY;
236 nt->mHal.state.dimZ = dimZ;
237 nt->mHal.state.faces = dimFaces;
238 nt->mHal.state.dimYuv = dimYuv;
239 nt->compute();
240
241 ObjectBase::asyncLock();
242 stc->mTypes.push(nt);
243 ObjectBase::asyncUnlock();
244
245 return returnRef;
246 }
247
cloneAndResize1D(Context * rsc,uint32_t dimX) const248 ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
249 return getTypeRef(rsc, mElement.get(), dimX,
250 getDimY(), getDimZ(), getDimLOD(), getDimFaces(), getDimYuv());
251 }
252
cloneAndResize2D(Context * rsc,uint32_t dimX,uint32_t dimY) const253 ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc,
254 uint32_t dimX,
255 uint32_t dimY) const {
256 return getTypeRef(rsc, mElement.get(), dimX, dimY,
257 getDimZ(), getDimLOD(), getDimFaces(), getDimYuv());
258 }
259
260
incRefs(const void * ptr,size_t ct,size_t startOff) const261 void Type::incRefs(const void *ptr, size_t ct, size_t startOff) const {
262 const uint8_t *p = static_cast<const uint8_t *>(ptr);
263 const Element *e = mHal.state.element;
264 uint32_t stride = e->getSizeBytes();
265
266 p += stride * startOff;
267 while (ct > 0) {
268 e->incRefs(p);
269 ct--;
270 p += stride;
271 }
272 }
273
274
decRefs(const void * ptr,size_t ct,size_t startOff) const275 void Type::decRefs(const void *ptr, size_t ct, size_t startOff) const {
276 if (!mHal.state.element->getHasReferences()) {
277 return;
278 }
279 const uint8_t *p = static_cast<const uint8_t *>(ptr);
280 const Element *e = mHal.state.element;
281 uint32_t stride = e->getSizeBytes();
282
283 p += stride * startOff;
284 while (ct > 0) {
285 e->decRefs(p);
286 ct--;
287 p += stride;
288 }
289 }
290
291
292 //////////////////////////////////////////////////
293 //
294 namespace android {
295 namespace renderscript {
296
rsi_TypeCreate(Context * rsc,RsElement _e,uint32_t dimX,uint32_t dimY,uint32_t dimZ,bool mips,bool faces,uint32_t yuv)297 RsType rsi_TypeCreate(Context *rsc, RsElement _e, uint32_t dimX,
298 uint32_t dimY, uint32_t dimZ, bool mips, bool faces, uint32_t yuv) {
299 Element *e = static_cast<Element *>(_e);
300
301 return Type::getType(rsc, e, dimX, dimY, dimZ, mips, faces, yuv);
302 }
303
304 }
305 }
306
rsaTypeGetNativeData(RsContext con,RsType type,uintptr_t * typeData,uint32_t typeDataSize)307 extern "C" void rsaTypeGetNativeData(RsContext con, RsType type, uintptr_t *typeData, uint32_t typeDataSize) {
308 rsAssert(typeDataSize == 6);
309 // Pack the data in the follofing way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
310 // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
311 Type *t = static_cast<Type *>(type);
312
313 (*typeData++) = t->getDimX();
314 (*typeData++) = t->getDimY();
315 (*typeData++) = t->getDimZ();
316 (*typeData++) = t->getDimLOD() ? 1 : 0;
317 (*typeData++) = t->getDimFaces() ? 1 : 0;
318 (*typeData++) = (uintptr_t)t->getElement();
319 t->getElement()->incUserRef();
320 }
321