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