1/*
2 * Copyright (C) 2011-2012 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
18#include "rsdCore.h"
19#include "rsdBcc.h"
20#include "rsdRuntime.h"
21#include "rsdAllocation.h"
22//#include "rsdFrameBufferObj.h"
23
24#include "rsAllocation.h"
25
26#include "system/window.h"
27/*#include "hardware/gralloc.h"
28#include "ui/Rect.h"
29#include "ui/GraphicBufferMapper.h"
30#include "gui/SurfaceTexture.h"*/
31
32//#include <GLES/gl.h>
33//#include <GLES2/gl2.h>
34//#include <GLES/glext.h>
35
36using namespace android;
37using namespace android::renderscript;
38
39
40uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
41                      uint32_t xoff, uint32_t yoff, uint32_t lod,
42                      RsAllocationCubemapFace face) {
43    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
44    uint8_t *ptr = (uint8_t *)drv->lod[lod].mallocPtr;
45    ptr += face * drv->faceOffset;
46    ptr += yoff * drv->lod[lod].stride;
47    ptr += xoff * alloc->mHal.state.elementSizeBytes;
48    return ptr;
49}
50
51
52static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
53                            uint32_t xoff, uint32_t yoff, uint32_t lod,
54                            RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
55}
56
57
58static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
59}
60
61static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
62}
63
64static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
65}
66
67static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
68        const Type *type, uint8_t *ptr) {
69
70    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
71
72    drv->lod[0].dimX = type->getDimX();
73    drv->lod[0].dimY = type->getDimY();
74    drv->lod[0].mallocPtr = 0;
75    drv->lod[0].stride = drv->lod[0].dimX * type->getElementSizeBytes();
76    drv->lodCount = type->getLODCount();
77    drv->faceCount = type->getDimFaces();
78
79    size_t offsets[Allocation::MAX_LOD];
80    memset(offsets, 0, sizeof(offsets));
81
82    size_t o = drv->lod[0].stride * rsMax(drv->lod[0].dimY, 1u) * rsMax(drv->lod[0].dimZ, 1u);
83    if(drv->lodCount > 1) {
84        uint32_t tx = drv->lod[0].dimX;
85        uint32_t ty = drv->lod[0].dimY;
86        uint32_t tz = drv->lod[0].dimZ;
87        for (uint32_t lod=1; lod < drv->lodCount; lod++) {
88            drv->lod[lod].dimX = tx;
89            drv->lod[lod].dimY = ty;
90            drv->lod[lod].dimZ = tz;
91            drv->lod[lod].stride = tx * type->getElementSizeBytes();
92            offsets[lod] = o;
93            o += drv->lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
94            if (tx > 1) tx >>= 1;
95            if (ty > 1) ty >>= 1;
96            if (tz > 1) tz >>= 1;
97        }
98    }
99    drv->faceOffset = o;
100
101    drv->lod[0].mallocPtr = ptr;
102    for (uint32_t lod=1; lod < drv->lodCount; lod++) {
103        drv->lod[lod].mallocPtr = ptr + offsets[lod];
104    }
105    alloc->mHal.drvState.strideLOD0 = drv->lod[0].stride;
106    alloc->mHal.drvState.mallocPtrLOD0 = ptr;
107
108    size_t allocSize = drv->faceOffset;
109    if(drv->faceCount) {
110        allocSize *= 6;
111    }
112
113    return allocSize;
114}
115
116bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
117    DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
118    if (!drv) {
119        return false;
120    }
121    alloc->mHal.drv = drv;
122
123    // Calculate the object size.
124    size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), NULL);
125
126    ALOGE("alloc usage %i", alloc->mHal.state.usageFlags);
127
128    uint8_t * ptr = NULL;
129    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
130    } else {
131
132        ptr = (uint8_t *)malloc(allocSize);
133        if (!ptr) {
134            free(drv);
135            return false;
136        }
137    }
138    // Build the pointer tables
139    size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr);
140    if(allocSize != verifySize) {
141        rsAssert(!"Size mismatch");
142    }
143
144    drv->glTarget = GL_NONE;
145    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
146        if (alloc->mHal.state.hasFaces) {
147            drv->glTarget = GL_TEXTURE_CUBE_MAP;
148        } else {
149            drv->glTarget = GL_TEXTURE_2D;
150        }
151    } else {
152        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
153            drv->glTarget = GL_ARRAY_BUFFER;
154        }
155    }
156
157    drv->glType = 0;
158    drv->glFormat = 0;
159
160    if (forceZero && ptr) {
161        memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
162    }
163
164    if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
165        drv->uploadDeferred = true;
166    }
167
168
169    drv->readBackFBO = NULL;
170
171    return true;
172}
173
174void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
175    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
176
177    if (alloc->mHal.drvState.mallocPtrLOD0) {
178        free(alloc->mHal.drvState.mallocPtrLOD0);
179        alloc->mHal.drvState.mallocPtrLOD0 = NULL;
180    }
181    free(drv);
182    alloc->mHal.drv = NULL;
183}
184
185void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
186                         const Type *newType, bool zeroNew) {
187    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
188
189    void * oldPtr = drv->lod[0].mallocPtr;
190    // Calculate the object size
191    size_t s = AllocationBuildPointerTable(rsc, alloc, newType, NULL);
192    uint8_t *ptr = (uint8_t *)realloc(oldPtr, s);
193    // Build the relative pointer tables.
194    size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr);
195    if(s != verifySize) {
196        rsAssert(!"Size mismatch");
197    }
198
199    const uint32_t oldDimX = alloc->mHal.state.dimensionX;
200    const uint32_t dimX = newType->getDimX();
201
202    if (dimX > oldDimX) {
203        uint32_t stride = alloc->mHal.state.elementSizeBytes;
204        memset(((uint8_t *)alloc->mHal.drvState.mallocPtrLOD0) + stride * oldDimX,
205                 0, stride * (dimX - oldDimX));
206    }
207}
208
209static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
210}
211
212
213void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
214                         RsAllocationUsageType src) {
215    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
216
217    if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
218        if(!alloc->getIsRenderTarget()) {
219            rsc->setError(RS_ERROR_FATAL_DRIVER,
220                          "Attempting to sync allocation from render target, "
221                          "for non-render target allocation");
222        } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
223            rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
224                                                 "render target");
225        } else {
226            rsdAllocationSyncFromFBO(rsc, alloc);
227        }
228        return;
229    }
230
231    rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
232
233    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
234        UploadToTexture(rsc, alloc);
235    } else {
236        if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) &&
237            !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
238            AllocateRenderTarget(rsc, alloc);
239        }
240    }
241    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
242        UploadToBufferObject(rsc, alloc);
243    }
244
245    drv->uploadDeferred = false;
246}
247
248void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
249    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
250    drv->uploadDeferred = true;
251}
252
253int32_t rsdAllocationInitSurfaceTexture(const Context *rsc, const Allocation *alloc) {
254  return 0;
255}
256
257void rsdAllocationSetSurfaceTexture(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
258}
259
260void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
261}
262
263void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
264}
265
266
267void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
268                         uint32_t xoff, uint32_t lod, uint32_t count,
269                         const void *data, size_t sizeBytes) {
270    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
271
272    const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
273    uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
274    uint32_t size = count * eSize;
275
276    if (alloc->mHal.state.hasReferences) {
277        alloc->incRefs(data, count);
278        alloc->decRefs(ptr, count);
279    }
280
281    memcpy(ptr, data, size);
282    drv->uploadDeferred = true;
283}
284
285void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
286                         uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
287                         uint32_t w, uint32_t h, const void *data, size_t sizeBytes) {
288    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
289
290    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
291    uint32_t lineSize = eSize * w;
292
293    if (drv->lod[0].mallocPtr) {
294        const uint8_t *src = static_cast<const uint8_t *>(data);
295        uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face);
296
297        for (uint32_t line=yoff; line < (yoff+h); line++) {
298            if (alloc->mHal.state.hasReferences) {
299                alloc->incRefs(src, w);
300                alloc->decRefs(dst, w);
301            }
302            memcpy(dst, src, lineSize);
303            src += lineSize;
304            dst += drv->lod[lod].stride;
305        }
306        drv->uploadDeferred = true;
307    } else {
308        Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
309    }
310}
311
312void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
313                         uint32_t xoff, uint32_t yoff, uint32_t zoff,
314                         uint32_t lod, RsAllocationCubemapFace face,
315                         uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
316
317}
318
319void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
320                         uint32_t xoff, uint32_t lod, uint32_t count,
321                         void *data, size_t sizeBytes) {
322    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
323
324    const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
325    const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
326    memcpy(data, ptr, count * eSize);
327}
328
329void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
330                         uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
331                         uint32_t w, uint32_t h, void *data, size_t sizeBytes) {
332    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
333
334    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
335    uint32_t lineSize = eSize * w;
336
337    if (drv->lod[0].mallocPtr) {
338        uint8_t *dst = static_cast<uint8_t *>(data);
339        const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, lod, face);
340
341        for (uint32_t line=yoff; line < (yoff+h); line++) {
342            memcpy(dst, src, lineSize);
343            dst += lineSize;
344            src += drv->lod[lod].stride;
345        }
346    } else {
347        ALOGE("Add code to readback from non-script memory");
348    }
349}
350
351void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
352                         uint32_t xoff, uint32_t yoff, uint32_t zoff,
353                         uint32_t lod, RsAllocationCubemapFace face,
354                         uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes) {
355
356}
357
358void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
359                          const android::renderscript::Allocation *alloc) {
360    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
361    return drv->lod[0].mallocPtr;
362}
363
364void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
365                          const android::renderscript::Allocation *alloc) {
366
367}
368
369void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
370                               const android::renderscript::Allocation *dstAlloc,
371                               uint32_t dstXoff, uint32_t dstLod, uint32_t count,
372                               const android::renderscript::Allocation *srcAlloc,
373                               uint32_t srcXoff, uint32_t srcLod) {
374}
375
376
377void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
378                                      const android::renderscript::Allocation *dstAlloc,
379                                      uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
380                                      RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
381                                      const android::renderscript::Allocation *srcAlloc,
382                                      uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
383                                      RsAllocationCubemapFace srcFace) {
384    uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
385    for (uint32_t i = 0; i < h; i ++) {
386        uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace);
387        uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
388        memcpy(dstPtr, srcPtr, w * elementSize);
389
390        //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
391        //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
392    }
393}
394
395void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
396                               const android::renderscript::Allocation *dstAlloc,
397                               uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
398                               RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
399                               const android::renderscript::Allocation *srcAlloc,
400                               uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
401                               RsAllocationCubemapFace srcFace) {
402    if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
403        rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
404                                             "yet implemented.");
405        return;
406    }
407    rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
408                                     dstLod, dstFace, w, h, srcAlloc,
409                                     srcXoff, srcYoff, srcLod, srcFace);
410}
411
412void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
413                               const android::renderscript::Allocation *dstAlloc,
414                               uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
415                               uint32_t dstLod, RsAllocationCubemapFace dstFace,
416                               uint32_t w, uint32_t h, uint32_t d,
417                               const android::renderscript::Allocation *srcAlloc,
418                               uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
419                               uint32_t srcLod, RsAllocationCubemapFace srcFace) {
420}
421
422void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
423                                uint32_t x,
424                                const void *data, uint32_t cIdx, uint32_t sizeBytes) {
425    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
426
427    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
428    uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
429
430    const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
431    ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
432
433    if (alloc->mHal.state.hasReferences) {
434        e->incRefs(data);
435        e->decRefs(ptr);
436    }
437
438    memcpy(ptr, data, sizeBytes);
439    drv->uploadDeferred = true;
440}
441
442void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc,
443                                uint32_t x, uint32_t y,
444                                const void *data, uint32_t cIdx, uint32_t sizeBytes) {
445    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
446
447    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
448    uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
449
450    const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
451    ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
452
453    if (alloc->mHal.state.hasReferences) {
454        e->incRefs(data);
455        e->decRefs(ptr);
456    }
457
458    memcpy(ptr, data, sizeBytes);
459    drv->uploadDeferred = true;
460}
461
462static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
463    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
464    uint32_t w = drv->lod[lod + 1].dimX;
465    uint32_t h = drv->lod[lod + 1].dimY;
466
467    for (uint32_t y=0; y < h; y++) {
468        uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face);
469        const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2, lod, face);
470        const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face);
471
472        for (uint32_t x=0; x < w; x++) {
473            *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
474            oPtr ++;
475            i1 += 2;
476            i2 += 2;
477        }
478    }
479}
480
481static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
482    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
483    uint32_t w = drv->lod[lod + 1].dimX;
484    uint32_t h = drv->lod[lod + 1].dimY;
485
486    for (uint32_t y=0; y < h; y++) {
487        uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face);
488        const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, lod, face);
489        const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face);
490
491        for (uint32_t x=0; x < w; x++) {
492            *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
493            oPtr ++;
494            i1 += 2;
495            i2 += 2;
496        }
497    }
498}
499
500static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
501    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
502    uint32_t w = drv->lod[lod + 1].dimX;
503    uint32_t h = drv->lod[lod + 1].dimY;
504
505    for (uint32_t y=0; y < h; y++) {
506        uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, lod + 1, face);
507        const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, lod, face);
508        const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, lod, face);
509
510        for (uint32_t x=0; x < w; x++) {
511            *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
512            oPtr ++;
513            i1 += 2;
514            i2 += 2;
515        }
516    }
517}
518
519void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) {
520    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
521    if(!drv->lod[0].mallocPtr) {
522        return;
523    }
524    uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
525    for (uint32_t face = 0; face < numFaces; face ++) {
526        for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) {
527            switch (alloc->getType()->getElement()->getSizeBits()) {
528            case 32:
529                mip8888(alloc, lod, (RsAllocationCubemapFace)face);
530                break;
531            case 16:
532                mip565(alloc, lod, (RsAllocationCubemapFace)face);
533                break;
534            case 8:
535                mip8(alloc, lod, (RsAllocationCubemapFace)face);
536                break;
537            }
538        }
539    }
540}
541
542
543