• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 #include <GLES/gl.h>
20 #include <GLES/glext.h>
21 
22 using namespace android;
23 using namespace android::renderscript;
24 
Allocation(Context * rsc,const Type * type)25 Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc)
26 {
27     mAllocFile = __FILE__;
28     mAllocLine = __LINE__;
29     mPtr = NULL;
30 
31     mCpuWrite = false;
32     mCpuRead = false;
33     mGpuWrite = false;
34     mGpuRead = false;
35 
36     mReadWriteRatio = 0;
37     mUpdateSize = 0;
38 
39     mIsTexture = false;
40     mTextureID = 0;
41 
42     mIsVertexBuffer = false;
43     mBufferID = 0;
44 
45     mType.set(type);
46     rsAssert(type);
47     mPtr = malloc(mType->getSizeBytes());
48     if (!mPtr) {
49         LOGE("Allocation::Allocation, alloc failure");
50     }
51 }
52 
~Allocation()53 Allocation::~Allocation()
54 {
55     free(mPtr);
56     mPtr = NULL;
57 
58     if (mBufferID) {
59         // Causes a SW crash....
60         //LOGV(" mBufferID %i", mBufferID);
61         //glDeleteBuffers(1, &mBufferID);
62         //mBufferID = 0;
63     }
64     if (mTextureID) {
65         glDeleteTextures(1, &mTextureID);
66         mTextureID = 0;
67     }
68 }
69 
setCpuWritable(bool)70 void Allocation::setCpuWritable(bool)
71 {
72 }
73 
setGpuWritable(bool)74 void Allocation::setGpuWritable(bool)
75 {
76 }
77 
setCpuReadable(bool)78 void Allocation::setCpuReadable(bool)
79 {
80 }
81 
setGpuReadable(bool)82 void Allocation::setGpuReadable(bool)
83 {
84 }
85 
fixAllocation()86 bool Allocation::fixAllocation()
87 {
88     return false;
89 }
90 
uploadToTexture(uint32_t lodOffset)91 void Allocation::uploadToTexture(uint32_t lodOffset)
92 {
93     //rsAssert(!mTextureId);
94     rsAssert(lodOffset < mType->getLODCount());
95 
96     GLenum type = mType->getElement()->getGLType();
97     GLenum format = mType->getElement()->getGLFormat();
98 
99     if (!type || !format) {
100         return;
101     }
102 
103     if (!mTextureID) {
104         glGenTextures(1, &mTextureID);
105     }
106     glBindTexture(GL_TEXTURE_2D, mTextureID);
107     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
108 
109     Adapter2D adapt(getContext(), this);
110     for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) {
111         adapt.setLOD(lod+lodOffset);
112 
113         uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
114         glTexImage2D(GL_TEXTURE_2D, lod, format,
115                      adapt.getDimX(), adapt.getDimY(),
116                      0, format, type, ptr);
117     }
118 }
119 
uploadToBufferObject()120 void Allocation::uploadToBufferObject()
121 {
122     rsAssert(!mType->getDimY());
123     rsAssert(!mType->getDimZ());
124 
125     if (!mBufferID) {
126         glGenBuffers(1, &mBufferID);
127     }
128     glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
129     glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
130     glBindBuffer(GL_ARRAY_BUFFER, 0);
131 }
132 
133 
data(const void * data,uint32_t sizeBytes)134 void Allocation::data(const void *data, uint32_t sizeBytes)
135 {
136     uint32_t size = mType->getSizeBytes();
137     if (size != sizeBytes) {
138         LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
139         return;
140     }
141     memcpy(mPtr, data, size);
142 }
143 
read(void * data)144 void Allocation::read(void *data)
145 {
146     memcpy(data, mPtr, mType->getSizeBytes());
147 }
148 
subData(uint32_t xoff,uint32_t count,const void * data,uint32_t sizeBytes)149 void Allocation::subData(uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
150 {
151     uint32_t eSize = mType->getElementSizeBytes();
152     uint8_t * ptr = static_cast<uint8_t *>(mPtr);
153     ptr += eSize * xoff;
154     uint32_t size = count * eSize;
155 
156     if (size != sizeBytes) {
157         LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
158         mType->dumpLOGV("type info");
159         return;
160     }
161     memcpy(ptr, data, size);
162 }
163 
subData(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const void * data,uint32_t sizeBytes)164 void Allocation::subData(uint32_t xoff, uint32_t yoff,
165              uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
166 {
167     uint32_t eSize = mType->getElementSizeBytes();
168     uint32_t lineSize = eSize * w;
169     uint32_t destW = mType->getDimX();
170 
171     const uint8_t *src = static_cast<const uint8_t *>(data);
172     uint8_t *dst = static_cast<uint8_t *>(mPtr);
173     dst += eSize * (xoff + yoff * destW);
174 
175     if ((lineSize * eSize * h) != sizeBytes) {
176         rsAssert(!"Allocation::subData called with mismatched size");
177         return;
178     }
179 
180     for (uint32_t line=yoff; line < (yoff+h); line++) {
181         uint8_t * ptr = static_cast<uint8_t *>(mPtr);
182         memcpy(dst, src, lineSize);
183         src += lineSize;
184         dst += destW * eSize;
185     }
186 }
187 
subData(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d,const void * data,uint32_t sizeBytes)188 void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
189              uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes)
190 {
191 }
192 
193 
194 
195 /////////////////
196 //
197 
198 
199 namespace android {
200 namespace renderscript {
201 
rsi_AllocationCreateTyped(Context * rsc,RsType vtype)202 RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
203 {
204     const Type * type = static_cast<const Type *>(vtype);
205 
206     Allocation * alloc = new Allocation(rsc, type);
207     alloc->incUserRef();
208     return alloc;
209 }
210 
rsi_AllocationCreateSized(Context * rsc,RsElement e,size_t count)211 RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
212 {
213     Type * type = new Type(rsc);
214     type->setDimX(count);
215     type->setElement(static_cast<Element *>(e));
216     type->compute();
217     return rsi_AllocationCreateTyped(rsc, type);
218 }
219 
rsi_AllocationUploadToTexture(Context * rsc,RsAllocation va,uint32_t baseMipLevel)220 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel)
221 {
222     Allocation *alloc = static_cast<Allocation *>(va);
223     alloc->uploadToTexture(baseMipLevel);
224 }
225 
rsi_AllocationUploadToBufferObject(Context * rsc,RsAllocation va)226 void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
227 {
228     Allocation *alloc = static_cast<Allocation *>(va);
229     alloc->uploadToBufferObject();
230 }
231 
mip565(const Adapter2D & out,const Adapter2D & in)232 static void mip565(const Adapter2D &out, const Adapter2D &in)
233 {
234     uint32_t w = out.getDimX();
235     uint32_t h = out.getDimY();
236 
237     for (uint32_t y=0; y < h; y++) {
238         uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
239         const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
240         const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
241 
242         for (uint32_t x=0; x < w; x++) {
243             *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
244             oPtr ++;
245             i1 += 2;
246             i2 += 2;
247         }
248     }
249 }
250 
mip8888(const Adapter2D & out,const Adapter2D & in)251 static void mip8888(const Adapter2D &out, const Adapter2D &in)
252 {
253     uint32_t w = out.getDimX();
254     uint32_t h = out.getDimY();
255 
256     for (uint32_t y=0; y < h; y++) {
257         uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
258         const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
259         const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
260 
261         for (uint32_t x=0; x < w; x++) {
262             *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
263             oPtr ++;
264             i1 += 2;
265             i2 += 2;
266         }
267     }
268 }
269 
mip(const Adapter2D & out,const Adapter2D & in)270 static void mip(const Adapter2D &out, const Adapter2D &in)
271 {
272     switch(out.getBaseType()->getElement()->getSizeBits()) {
273     case 32:
274         mip8888(out, in);
275         break;
276     case 16:
277         mip565(out, in);
278         break;
279 
280     }
281 
282 }
283 
284 typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
285 
elementConverter_cpy_16(void * dst,const void * src,uint32_t count)286 static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
287 {
288     memcpy(dst, src, count * 2);
289 }
elementConverter_cpy_8(void * dst,const void * src,uint32_t count)290 static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
291 {
292     memcpy(dst, src, count);
293 }
elementConverter_cpy_32(void * dst,const void * src,uint32_t count)294 static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
295 {
296     memcpy(dst, src, count * 4);
297 }
298 
299 
elementConverter_888_to_565(void * dst,const void * src,uint32_t count)300 static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
301 {
302     uint16_t *d = static_cast<uint16_t *>(dst);
303     const uint8_t *s = static_cast<const uint8_t *>(src);
304 
305     while(count--) {
306         *d = rs888to565(s[0], s[1], s[2]);
307         d++;
308         s+= 3;
309     }
310 }
311 
elementConverter_8888_to_565(void * dst,const void * src,uint32_t count)312 static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
313 {
314     uint16_t *d = static_cast<uint16_t *>(dst);
315     const uint8_t *s = static_cast<const uint8_t *>(src);
316 
317     while(count--) {
318         *d = rs888to565(s[0], s[1], s[2]);
319         d++;
320         s+= 4;
321     }
322 }
323 
pickConverter(const Element * dst,const Element * src)324 static ElementConverter_t pickConverter(const Element *dst, const Element *src)
325 {
326     GLenum srcGLType = src->getGLType();
327     GLenum srcGLFmt = src->getGLFormat();
328     GLenum dstGLType = dst->getGLType();
329     GLenum dstGLFmt = dst->getGLFormat();
330 
331     if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
332         switch(dst->getSizeBytes()) {
333         case 4:
334             return elementConverter_cpy_32;
335         case 2:
336             return elementConverter_cpy_16;
337         case 1:
338             return elementConverter_cpy_8;
339         }
340     }
341 
342     if (srcGLType == GL_UNSIGNED_BYTE &&
343         srcGLFmt == GL_RGB &&
344         dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
345         dstGLType == GL_RGB) {
346 
347         return elementConverter_888_to_565;
348     }
349 
350     if (srcGLType == GL_UNSIGNED_BYTE &&
351         srcGLFmt == GL_RGBA &&
352         dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
353         dstGLType == GL_RGB) {
354 
355         return elementConverter_8888_to_565;
356     }
357 
358     LOGE("pickConverter, unsuported combo, src %p,  dst %p", src, dst);
359     return 0;
360 }
361 
362 
rsi_AllocationCreateFromBitmap(Context * rsc,uint32_t w,uint32_t h,RsElement _dst,RsElement _src,bool genMips,const void * data)363 RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
364 {
365     const Element *src = static_cast<const Element *>(_src);
366     const Element *dst = static_cast<const Element *>(_dst);
367     rsAssert(!(w & (w-1)));
368     rsAssert(!(h & (h-1)));
369 
370     //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips);
371     rsi_TypeBegin(rsc, _dst);
372     rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
373     rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
374     if (genMips) {
375         rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
376     }
377     RsType type = rsi_TypeCreate(rsc);
378 
379     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
380     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
381     if (texAlloc == NULL) {
382         LOGE("Memory allocation failure");
383         return NULL;
384     }
385     texAlloc->incUserRef();
386 
387     ElementConverter_t cvt = pickConverter(dst, src);
388     cvt(texAlloc->getPtr(), data, w * h);
389 
390     if (genMips) {
391         Adapter2D adapt(rsc, texAlloc);
392         Adapter2D adapt2(rsc, texAlloc);
393         for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
394             adapt.setLOD(lod);
395             adapt2.setLOD(lod + 1);
396             mip(adapt2, adapt);
397         }
398     }
399 
400     return texAlloc;
401 }
402 
rsi_AllocationCreateFromBitmapBoxed(Context * rsc,uint32_t w,uint32_t h,RsElement _dst,RsElement _src,bool genMips,const void * data)403 RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data)
404 {
405     const Element *srcE = static_cast<const Element *>(_src);
406     const Element *dstE = static_cast<const Element *>(_dst);
407     uint32_t w2 = rsHigherPow2(w);
408     uint32_t h2 = rsHigherPow2(h);
409 
410     if ((w2 == w) && (h2 == h)) {
411         return rsi_AllocationCreateFromBitmap(rsc, w, h, _dst, _src, genMips, data);
412     }
413 
414     uint32_t bpp = srcE->getSizeBytes();
415     size_t size = w2 * h2 * bpp;
416     uint8_t *tmp = static_cast<uint8_t *>(malloc(size));
417     memset(tmp, 0, size);
418 
419     const uint8_t * src = static_cast<const uint8_t *>(data);
420     for (uint32_t y = 0; y < h; y++) {
421         uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp];
422         memcpy(&ydst[((w2 - w) >> 1) * bpp], src, w * bpp);
423         src += w * bpp;
424     }
425 
426     RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp);
427     free(tmp);
428     return ret;
429 
430 
431 
432 
433 }
434 
rsi_AllocationData(Context * rsc,RsAllocation va,const void * data,uint32_t sizeBytes)435 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
436 {
437     Allocation *a = static_cast<Allocation *>(va);
438     a->data(data, sizeBytes);
439     rsc->allocationCheck(a);
440 }
441 
rsi_Allocation1DSubData(Context * rsc,RsAllocation va,uint32_t xoff,uint32_t count,const void * data,uint32_t sizeBytes)442 void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
443 {
444     Allocation *a = static_cast<Allocation *>(va);
445     a->subData(xoff, count, data, sizeBytes);
446     rsc->allocationCheck(a);
447 }
448 
rsi_Allocation2DSubData(Context * rsc,RsAllocation va,uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const void * data,uint32_t sizeBytes)449 void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
450 {
451     Allocation *a = static_cast<Allocation *>(va);
452     a->subData(xoff, yoff, w, h, data, sizeBytes);
453     rsc->allocationCheck(a);
454 }
455 
rsi_AllocationRead(Context * rsc,RsAllocation va,void * data)456 void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data)
457 {
458     Allocation *a = static_cast<Allocation *>(va);
459     a->read(data);
460 }
461 
462 
463 }
464 }
465