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