rsdAllocation.cpp revision b010bc019c6ad11224ff6f73c22bce13cdab06e3
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 "rsdCore.h"
18#include "rsdAllocation.h"
19
20#include "rsAllocation.h"
21
22#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
23#include "system/window.h"
24#include "ui/Rect.h"
25#include "ui/GraphicBufferMapper.h"
26#endif
27
28#ifdef RS_COMPATIBILITY_LIB
29#include "rsCompatibilityLib.h"
30#else
31#include "rsdFrameBufferObj.h"
32#include "gui/GLConsumer.h"
33#include "gui/CpuConsumer.h"
34#include "gui/Surface.h"
35#include "hardware/gralloc.h"
36
37#include <GLES/gl.h>
38#include <GLES2/gl2.h>
39#include <GLES/glext.h>
40#endif
41
42#ifdef RS_SERVER
43// server requires malloc.h for memalign
44#include <malloc.h>
45#endif
46
47using namespace android;
48using namespace android::renderscript;
49
50#ifndef RS_COMPATIBILITY_LIB
51const static GLenum gFaceOrder[] = {
52    GL_TEXTURE_CUBE_MAP_POSITIVE_X,
53    GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
54    GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
55    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
56    GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
57    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
58};
59
60GLenum rsdTypeToGLType(RsDataType t) {
61    switch (t) {
62    case RS_TYPE_UNSIGNED_5_6_5:    return GL_UNSIGNED_SHORT_5_6_5;
63    case RS_TYPE_UNSIGNED_5_5_5_1:  return GL_UNSIGNED_SHORT_5_5_5_1;
64    case RS_TYPE_UNSIGNED_4_4_4_4:  return GL_UNSIGNED_SHORT_4_4_4_4;
65
66    //case RS_TYPE_FLOAT_16:      return GL_HALF_FLOAT;
67    case RS_TYPE_FLOAT_32:      return GL_FLOAT;
68    case RS_TYPE_UNSIGNED_8:    return GL_UNSIGNED_BYTE;
69    case RS_TYPE_UNSIGNED_16:   return GL_UNSIGNED_SHORT;
70    case RS_TYPE_SIGNED_8:      return GL_BYTE;
71    case RS_TYPE_SIGNED_16:     return GL_SHORT;
72    default:    break;
73    }
74    return 0;
75}
76
77GLenum rsdKindToGLFormat(RsDataKind k) {
78    switch (k) {
79    case RS_KIND_PIXEL_L: return GL_LUMINANCE;
80    case RS_KIND_PIXEL_A: return GL_ALPHA;
81    case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
82    case RS_KIND_PIXEL_RGB: return GL_RGB;
83    case RS_KIND_PIXEL_RGBA: return GL_RGBA;
84    case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
85    default: break;
86    }
87    return 0;
88}
89#endif
90
91uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
92                      uint32_t xoff, uint32_t yoff, uint32_t zoff,
93                      uint32_t lod, RsAllocationCubemapFace face) {
94    uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
95    ptr += face * alloc->mHal.drvState.faceOffset;
96    ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * alloc->mHal.drvState.lod[lod].stride;
97    ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
98    ptr += xoff * alloc->mHal.state.elementSizeBytes;
99    return ptr;
100}
101
102
103static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
104                            uint32_t xoff, uint32_t yoff, uint32_t lod,
105                            RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
106#ifndef RS_COMPATIBILITY_LIB
107    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
108
109    rsAssert(drv->textureID);
110    RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
111    RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
112    GLenum t = GL_TEXTURE_2D;
113    if (alloc->mHal.state.hasFaces) {
114        t = gFaceOrder[face];
115    }
116    RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
117#endif
118}
119
120
121#ifndef RS_COMPATIBILITY_LIB
122static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
123    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
124
125    RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
126    RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
127
128    uint32_t faceCount = 1;
129    if (alloc->mHal.state.hasFaces) {
130        faceCount = 6;
131    }
132
133    rsdGLCheckError(rsc, "Upload2DTexture 1 ");
134    for (uint32_t face = 0; face < faceCount; face ++) {
135        for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
136            const uint8_t *p = GetOffsetPtr(alloc, 0, 0, 0, lod, (RsAllocationCubemapFace)face);
137
138            GLenum t = GL_TEXTURE_2D;
139            if (alloc->mHal.state.hasFaces) {
140                t = gFaceOrder[face];
141            }
142
143            if (isFirstUpload) {
144                RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat,
145                             alloc->mHal.state.type->getLODDimX(lod),
146                             alloc->mHal.state.type->getLODDimY(lod),
147                             0, drv->glFormat, drv->glType, p);
148            } else {
149                RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0,
150                                alloc->mHal.state.type->getLODDimX(lod),
151                                alloc->mHal.state.type->getLODDimY(lod),
152                                drv->glFormat, drv->glType, p);
153            }
154        }
155    }
156
157    if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
158        RSD_CALL_GL(glGenerateMipmap, drv->glTarget);
159    }
160    rsdGLCheckError(rsc, "Upload2DTexture");
161}
162#endif
163
164static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
165#ifndef RS_COMPATIBILITY_LIB
166    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
167
168    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
169        if (!drv->textureID) {
170            RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
171        }
172        return;
173    }
174
175    if (!drv->glType || !drv->glFormat) {
176        return;
177    }
178
179    if (!alloc->mHal.drvState.lod[0].mallocPtr) {
180        return;
181    }
182
183    bool isFirstUpload = false;
184
185    if (!drv->textureID) {
186        RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
187        isFirstUpload = true;
188    }
189
190    Upload2DTexture(rsc, alloc, isFirstUpload);
191
192    if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
193        if (alloc->mHal.drvState.lod[0].mallocPtr) {
194            free(alloc->mHal.drvState.lod[0].mallocPtr);
195            alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
196        }
197    }
198    rsdGLCheckError(rsc, "UploadToTexture");
199#endif
200}
201
202static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
203#ifndef RS_COMPATIBILITY_LIB
204    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
205
206    if (!drv->glFormat) {
207        return;
208    }
209
210    if (!drv->renderTargetID) {
211        RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID);
212
213        if (!drv->renderTargetID) {
214            // This should generally not happen
215            ALOGE("allocateRenderTarget failed to gen mRenderTargetID");
216            rsc->dumpDebug();
217            return;
218        }
219        RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID);
220        RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat,
221                    alloc->mHal.drvState.lod[0].dimX, alloc->mHal.drvState.lod[0].dimY);
222    }
223    rsdGLCheckError(rsc, "AllocateRenderTarget");
224#endif
225}
226
227static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
228#ifndef RS_COMPATIBILITY_LIB
229    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
230
231    rsAssert(!alloc->mHal.state.type->getDimY());
232    rsAssert(!alloc->mHal.state.type->getDimZ());
233
234    //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
235
236    if (!drv->bufferID) {
237        RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID);
238    }
239    if (!drv->bufferID) {
240        ALOGE("Upload to buffer object failed");
241        drv->uploadDeferred = true;
242        return;
243    }
244    RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
245    RSD_CALL_GL(glBufferData, drv->glTarget,
246                alloc->mHal.state.type->getPackedSizeBytes(),
247                alloc->mHal.drvState.lod[0].mallocPtr, GL_DYNAMIC_DRAW);
248    RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
249    rsdGLCheckError(rsc, "UploadToBufferObject");
250#endif
251}
252
253
254static size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
255#ifndef RS_COMPATIBILITY_LIB
256    // For the flexible YCbCr format, layout is initialized during call to
257    // Allocation::ioReceive.  Return early and avoid clobberring any
258    // pre-existing layout.
259    if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
260        return 0;
261    }
262#endif
263
264    // YUV only supports basic 2d
265    // so we can stash the plane pointers in the mipmap levels.
266    size_t uvSize = 0;
267    state->lod[1].dimX = state->lod[0].dimX / 2;
268    state->lod[1].dimY = state->lod[0].dimY / 2;
269    state->lod[2].dimX = state->lod[0].dimX / 2;
270    state->lod[2].dimY = state->lod[0].dimY / 2;
271    state->yuv.shift = 1;
272    state->yuv.step = 1;
273    state->lodCount = 3;
274
275#ifndef RS_SERVER
276    switch(yuv) {
277    case HAL_PIXEL_FORMAT_YV12:
278        state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
279        state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
280                (state->lod[0].stride * state->lod[0].dimY);
281        uvSize += state->lod[2].stride * state->lod[2].dimY;
282
283        state->lod[1].stride = state->lod[2].stride;
284        state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
285                (state->lod[2].stride * state->lod[2].dimY);
286        uvSize += state->lod[1].stride * state->lod[2].dimY;
287        break;
288    case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
289        //state->lod[1].dimX = state->lod[0].dimX;
290        state->lod[1].stride = state->lod[0].stride;
291        state->lod[2].stride = state->lod[0].stride;
292        state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
293                (state->lod[0].stride * state->lod[0].dimY);
294        state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1;
295        uvSize += state->lod[1].stride * state->lod[1].dimY;
296        state->yuv.step = 2;
297        break;
298    default:
299        rsAssert(0);
300    }
301#endif
302    return uvSize;
303}
304
305
306static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
307        const Type *type, uint8_t *ptr) {
308    alloc->mHal.drvState.lod[0].dimX = type->getDimX();
309    alloc->mHal.drvState.lod[0].dimY = type->getDimY();
310    alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
311    alloc->mHal.drvState.lod[0].mallocPtr = 0;
312    // Stride needs to be 16-byte aligned too!
313    size_t stride = alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
314    alloc->mHal.drvState.lod[0].stride = rsRound(stride, 16);
315    alloc->mHal.drvState.lodCount = type->getLODCount();
316    alloc->mHal.drvState.faceCount = type->getDimFaces();
317
318    size_t offsets[Allocation::MAX_LOD];
319    memset(offsets, 0, sizeof(offsets));
320
321    size_t o = alloc->mHal.drvState.lod[0].stride * rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
322            rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
323    if (alloc->mHal.state.yuv) {
324        o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
325
326        for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
327            offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
328        }
329    } else if(alloc->mHal.drvState.lodCount > 1) {
330        uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
331        uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
332        uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
333        for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
334            alloc->mHal.drvState.lod[lod].dimX = tx;
335            alloc->mHal.drvState.lod[lod].dimY = ty;
336            alloc->mHal.drvState.lod[lod].dimZ = tz;
337            alloc->mHal.drvState.lod[lod].stride =
338                    rsRound(tx * type->getElementSizeBytes(), 16);
339            offsets[lod] = o;
340            o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
341            if (tx > 1) tx >>= 1;
342            if (ty > 1) ty >>= 1;
343            if (tz > 1) tz >>= 1;
344        }
345    }
346
347    alloc->mHal.drvState.faceOffset = o;
348
349    alloc->mHal.drvState.lod[0].mallocPtr = ptr;
350    for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
351        alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
352    }
353
354    size_t allocSize = alloc->mHal.drvState.faceOffset;
355    if(alloc->mHal.drvState.faceCount) {
356        allocSize *= 6;
357    }
358
359    return allocSize;
360}
361
362static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero) {
363    // We align all allocations to a 16-byte boundary.
364    uint8_t* ptr = (uint8_t *)memalign(16, allocSize);
365    if (!ptr) {
366        return nullptr;
367    }
368    if (forceZero) {
369        memset(ptr, 0, allocSize);
370    }
371    return ptr;
372}
373
374bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
375    DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
376    if (!drv) {
377        return false;
378    }
379    alloc->mHal.drv = drv;
380
381    // Calculate the object size.
382    size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), nullptr);
383
384    uint8_t * ptr = nullptr;
385    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
386
387    } else if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
388        // Allocation is allocated when the surface is created
389        // in getSurface
390    } else if (alloc->mHal.state.userProvidedPtr != nullptr) {
391        // user-provided allocation
392        // limitations: no faces, no LOD, USAGE_SCRIPT or SCRIPT+TEXTURE only
393        if (!(alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED) ||
394              alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE))) {
395            ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT | USAGE_SHARED or USAGE_SCRIPT | USAGE_SHARED | USAGE_GRAPHICS_TEXTURE");
396            return false;
397        }
398        if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
399            ALOGE("User-allocated buffers must not have multiple faces or LODs");
400            return false;
401        }
402
403        // rows must be 16-byte aligned
404        // validate that here, otherwise fall back to not use the user-backed allocation
405        if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % 16) != 0) {
406            ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation");
407            drv->useUserProvidedPtr = false;
408
409            ptr = allocAlignedMemory(allocSize, forceZero);
410            if (!ptr) {
411                alloc->mHal.drv = nullptr;
412                free(drv);
413                return false;
414            }
415
416        } else {
417            drv->useUserProvidedPtr = true;
418            ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
419        }
420    } else {
421        ptr = allocAlignedMemory(allocSize, forceZero);
422        if (!ptr) {
423            alloc->mHal.drv = nullptr;
424            free(drv);
425            return false;
426        }
427    }
428    // Build the pointer tables
429    size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr);
430    if(allocSize != verifySize) {
431        rsAssert(!"Size mismatch");
432    }
433
434#ifndef RS_SERVER
435    drv->glTarget = GL_NONE;
436    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
437        if (alloc->mHal.state.hasFaces) {
438            drv->glTarget = GL_TEXTURE_CUBE_MAP;
439        } else {
440            drv->glTarget = GL_TEXTURE_2D;
441        }
442    } else {
443        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
444            drv->glTarget = GL_ARRAY_BUFFER;
445        }
446    }
447#endif
448
449#ifndef RS_COMPATIBILITY_LIB
450    drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
451    drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
452#else
453    drv->glType = 0;
454    drv->glFormat = 0;
455#endif
456
457    if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
458        drv->uploadDeferred = true;
459    }
460
461
462    drv->readBackFBO = nullptr;
463
464    // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted
465    if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) {
466        rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0);
467    }
468
469
470#ifdef RS_FIND_OFFSETS
471    ALOGE("pointer for allocation: %p", alloc);
472    ALOGE("pointer for allocation.drv: %p", &alloc->mHal.drv);
473#endif
474
475
476    return true;
477}
478
479void rsdAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
480    //ALOGE("rsdAllocationAdapterOffset");
481
482    // Get a base pointer to the new LOD
483    const Allocation *base = alloc->mHal.state.baseAlloc;
484    const Type *type = alloc->mHal.state.type;
485    if (base == nullptr) {
486        return;
487    }
488
489    //ALOGE("rsdAllocationAdapterOffset  %p  %p", ptrA, ptrB);
490    //ALOGE("rsdAllocationAdapterOffset  lodCount %i", alloc->mHal.drvState.lodCount);
491
492    const int lodBias = alloc->mHal.state.originLOD;
493    uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
494    for (uint32_t lod=0; lod < lodCount; lod++) {
495        alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
496        alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(alloc,
497                      alloc->mHal.state.originX, alloc->mHal.state.originY, alloc->mHal.state.originZ,
498                      lodBias, (RsAllocationCubemapFace)alloc->mHal.state.originFace);
499    }
500}
501
502bool rsdAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
503    DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
504    if (!drv) {
505        return false;
506    }
507    alloc->mHal.drv = drv;
508
509    // We need to build an allocation that looks like a subset of the parent allocation
510    rsdAllocationAdapterOffset(rsc, alloc);
511
512    return true;
513}
514
515void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
516    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
517
518    if (alloc->mHal.state.baseAlloc == nullptr) {
519#ifndef RS_COMPATIBILITY_LIB
520        if (drv->bufferID) {
521            // Causes a SW crash....
522            //ALOGV(" mBufferID %i", mBufferID);
523            //glDeleteBuffers(1, &mBufferID);
524            //mBufferID = 0;
525        }
526        if (drv->textureID) {
527            RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
528            drv->textureID = 0;
529        }
530        if (drv->renderTargetID) {
531            RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
532            drv->renderTargetID = 0;
533        }
534#endif
535
536        if (alloc->mHal.drvState.lod[0].mallocPtr) {
537            // don't free user-allocated ptrs or IO_OUTPUT buffers
538            if (!(drv->useUserProvidedPtr) &&
539                !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
540                !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
541                    free(alloc->mHal.drvState.lod[0].mallocPtr);
542            }
543            alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
544        }
545
546#ifndef RS_COMPATIBILITY_LIB
547        if (drv->readBackFBO != nullptr) {
548            delete drv->readBackFBO;
549            drv->readBackFBO = nullptr;
550        }
551
552        if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
553            (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
554
555            DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
556            ANativeWindow *nw = drv->wndSurface;
557            if (nw) {
558                GraphicBufferMapper &mapper = GraphicBufferMapper::get();
559                mapper.unlock(drv->wndBuffer->handle);
560                int32_t r = nw->cancelBuffer(nw, drv->wndBuffer, -1);
561
562                drv->wndSurface = nullptr;
563                native_window_api_disconnect(nw, NATIVE_WINDOW_API_CPU);
564                nw->decStrong(nullptr);
565            }
566        }
567#endif
568    }
569
570    free(drv);
571    alloc->mHal.drv = nullptr;
572}
573
574void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
575                         const Type *newType, bool zeroNew) {
576    const uint32_t oldDimX = alloc->mHal.drvState.lod[0].dimX;
577    const uint32_t dimX = newType->getDimX();
578
579    // can't resize Allocations with user-allocated buffers
580    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
581        ALOGE("Resize cannot be called on a USAGE_SHARED allocation");
582        return;
583    }
584    void * oldPtr = alloc->mHal.drvState.lod[0].mallocPtr;
585    // Calculate the object size
586    size_t s = AllocationBuildPointerTable(rsc, alloc, newType, nullptr);
587    uint8_t *ptr = (uint8_t *)realloc(oldPtr, s);
588    // Build the relative pointer tables.
589    size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr);
590    if(s != verifySize) {
591        rsAssert(!"Size mismatch");
592    }
593
594
595    if (dimX > oldDimX) {
596        size_t stride = alloc->mHal.state.elementSizeBytes;
597        memset(((uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr) + stride * oldDimX,
598                 0, stride * (dimX - oldDimX));
599    }
600}
601
602static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
603#ifndef RS_COMPATIBILITY_LIB
604    if (!alloc->getIsScript()) {
605        return; // nothing to sync
606    }
607
608    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
609    RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer;
610
611    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
612    if (!drv->textureID && !drv->renderTargetID) {
613        return; // nothing was rendered here yet, so nothing to sync
614    }
615    if (drv->readBackFBO == nullptr) {
616        drv->readBackFBO = new RsdFrameBufferObj();
617        drv->readBackFBO->setColorTarget(drv, 0);
618        drv->readBackFBO->setDimensions(alloc->getType()->getDimX(),
619                                        alloc->getType()->getDimY());
620    }
621
622    // Bind the framebuffer object so we can read back from it
623    drv->readBackFBO->setActive(rsc);
624
625    // Do the readback
626    RSD_CALL_GL(glReadPixels, 0, 0, alloc->mHal.drvState.lod[0].dimX,
627                alloc->mHal.drvState.lod[0].dimY,
628                drv->glFormat, drv->glType, alloc->mHal.drvState.lod[0].mallocPtr);
629
630    // Revert framebuffer to its original
631    lastFbo->setActive(rsc);
632#endif
633}
634
635
636void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
637                         RsAllocationUsageType src) {
638    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
639
640    if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
641        if(!alloc->getIsRenderTarget()) {
642            rsc->setError(RS_ERROR_FATAL_DRIVER,
643                          "Attempting to sync allocation from render target, "
644                          "for non-render target allocation");
645        } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
646            rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
647                                                 "render target");
648        } else {
649            rsdAllocationSyncFromFBO(rsc, alloc);
650        }
651        return;
652    }
653
654    rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT || src == RS_ALLOCATION_USAGE_SHARED);
655
656    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
657        UploadToTexture(rsc, alloc);
658    } else {
659        if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) &&
660            !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
661            AllocateRenderTarget(rsc, alloc);
662        }
663    }
664    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
665        UploadToBufferObject(rsc, alloc);
666    }
667
668    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
669
670        if (src == RS_ALLOCATION_USAGE_SHARED) {
671            // just a memory fence for the CPU driver
672            // vendor drivers probably want to flush any dirty cachelines for
673            // this particular Allocation
674            __sync_synchronize();
675        }
676    }
677
678    drv->uploadDeferred = false;
679}
680
681void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
682    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
683    drv->uploadDeferred = true;
684}
685
686#ifndef RS_COMPATIBILITY_LIB
687static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
688    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
689
690    int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer);
691    if (r) {
692        rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer.");
693        return false;
694    }
695
696    // Must lock the whole surface
697    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
698    Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height);
699
700    void *dst = nullptr;
701    mapper.lock(drv->wndBuffer->handle,
702            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
703            bounds, &dst);
704    alloc->mHal.drvState.lod[0].mallocPtr = dst;
705    alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
706    rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0);
707
708    return true;
709}
710#endif
711
712void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
713#ifndef RS_COMPATIBILITY_LIB
714    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
715    ANativeWindow *old = drv->wndSurface;
716
717    if (nw) {
718        nw->incStrong(nullptr);
719    }
720
721    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
722        //TODO finish support for render target + script
723        drv->wnd = nw;
724        return;
725    }
726
727    // Cleanup old surface if there is one.
728    if (drv->wndSurface) {
729        ANativeWindow *old = drv->wndSurface;
730        GraphicBufferMapper &mapper = GraphicBufferMapper::get();
731        mapper.unlock(drv->wndBuffer->handle);
732        old->cancelBuffer(old, drv->wndBuffer, -1);
733        drv->wndSurface = nullptr;
734
735        native_window_api_disconnect(old, NATIVE_WINDOW_API_CPU);
736        old->decStrong(nullptr);
737    }
738
739    if (nw != nullptr) {
740        int32_t r;
741        uint32_t flags = 0;
742
743        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
744            flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
745        }
746        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
747            flags |= GRALLOC_USAGE_HW_RENDER;
748        }
749
750        r = native_window_api_connect(nw, NATIVE_WINDOW_API_CPU);
751        if (r) {
752            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
753            goto error;
754        }
755
756        r = native_window_set_usage(nw, flags);
757        if (r) {
758            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
759            goto error;
760        }
761
762        r = native_window_set_buffers_dimensions(nw, alloc->mHal.drvState.lod[0].dimX,
763                                                 alloc->mHal.drvState.lod[0].dimY);
764        if (r) {
765            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions.");
766            goto error;
767        }
768
769        int format = 0;
770        const Element *e = alloc->mHal.state.type->getElement();
771        if ((e->getType() != RS_TYPE_UNSIGNED_8) ||
772            (e->getVectorSize() != 4)) {
773            // We do not check for RGBA, RGBx, to allow for interop with U8_4
774
775            rsc->setError(RS_ERROR_DRIVER, "Surface passed to setSurface is not U8_4, RGBA.");
776            goto error;
777        }
778        format = PIXEL_FORMAT_RGBA_8888;
779
780        r = native_window_set_buffers_format(nw, format);
781        if (r) {
782            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer format.");
783            goto error;
784        }
785
786        IoGetBuffer(rsc, alloc, nw);
787        drv->wndSurface = nw;
788    }
789
790    return;
791
792 error:
793
794    if (nw) {
795        nw->decStrong(nullptr);
796    }
797
798
799#endif
800}
801
802void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
803#ifndef RS_COMPATIBILITY_LIB
804    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
805    ANativeWindow *nw = drv->wndSurface;
806    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
807        RsdHal *dc = (RsdHal *)rsc->mHal.drv;
808        RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
809        return;
810    }
811    if (nw) {
812        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
813            GraphicBufferMapper &mapper = GraphicBufferMapper::get();
814            mapper.unlock(drv->wndBuffer->handle);
815            int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
816            if (r) {
817                rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
818                return;
819            }
820
821            IoGetBuffer(rsc, alloc, nw);
822        }
823    } else {
824        rsc->setError(RS_ERROR_DRIVER, "Sent IO buffer with no attached surface.");
825        return;
826    }
827#endif
828}
829
830void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
831#ifndef RS_COMPATIBILITY_LIB
832    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
833    if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
834        drv->surfaceTexture->updateTexImage();
835    }
836#endif
837    if (alloc->mHal.state.yuv) {
838        DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
839    }
840}
841
842
843void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
844                         uint32_t xoff, uint32_t lod, size_t count,
845                         const void *data, size_t sizeBytes) {
846    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
847
848    const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
849    uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
850    size_t size = count * eSize;
851    if (ptr != data) {
852        // Skip the copy if we are the same allocation. This can arise from
853        // our Bitmap optimization, where we share the same storage.
854        if (alloc->mHal.state.hasReferences) {
855            alloc->incRefs(data, count);
856            alloc->decRefs(ptr, count);
857        }
858        memcpy(ptr, data, size);
859    }
860    drv->uploadDeferred = true;
861}
862
863void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
864                         uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
865                         uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
866    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
867
868    size_t eSize = alloc->mHal.state.elementSizeBytes;
869    size_t lineSize = eSize * w;
870    if (!stride) {
871        stride = lineSize;
872    }
873
874    if (alloc->mHal.drvState.lod[0].mallocPtr) {
875        const uint8_t *src = static_cast<const uint8_t *>(data);
876        uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
877        if (dst == src) {
878            // Skip the copy if we are the same allocation. This can arise from
879            // our Bitmap optimization, where we share the same storage.
880            drv->uploadDeferred = true;
881            return;
882        }
883
884        for (uint32_t line=yoff; line < (yoff+h); line++) {
885            if (alloc->mHal.state.hasReferences) {
886                alloc->incRefs(src, w);
887                alloc->decRefs(dst, w);
888            }
889            memcpy(dst, src, lineSize);
890            src += stride;
891            dst += alloc->mHal.drvState.lod[lod].stride;
892        }
893        if (alloc->mHal.state.yuv) {
894            size_t clineSize = lineSize;
895            int lod = 1;
896            int maxLod = 2;
897            if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) {
898                maxLod = 3;
899                clineSize >>= 1;
900            } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
901                lod = 2;
902                maxLod = 3;
903            }
904
905            while (lod < maxLod) {
906                uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
907
908                for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) {
909                    memcpy(dst, src, clineSize);
910                    src += alloc->mHal.drvState.lod[lod].stride;
911                    dst += alloc->mHal.drvState.lod[lod].stride;
912                }
913                lod++;
914            }
915
916        }
917        drv->uploadDeferred = true;
918    } else {
919        Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
920    }
921}
922
923void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
924                         uint32_t xoff, uint32_t yoff, uint32_t zoff,
925                         uint32_t lod,
926                         uint32_t w, uint32_t h, uint32_t d, const void *data,
927                         size_t sizeBytes, size_t stride) {
928    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
929
930    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
931    uint32_t lineSize = eSize * w;
932    if (!stride) {
933        stride = lineSize;
934    }
935
936    if (alloc->mHal.drvState.lod[0].mallocPtr) {
937        const uint8_t *src = static_cast<const uint8_t *>(data);
938        for (uint32_t z = zoff; z < (d + zoff); z++) {
939            uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
940                                        RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
941            if (dst == src) {
942                // Skip the copy if we are the same allocation. This can arise from
943                // our Bitmap optimization, where we share the same storage.
944                drv->uploadDeferred = true;
945                return;
946            }
947
948            for (uint32_t line=yoff; line < (yoff+h); line++) {
949                if (alloc->mHal.state.hasReferences) {
950                    alloc->incRefs(src, w);
951                    alloc->decRefs(dst, w);
952                }
953                memcpy(dst, src, lineSize);
954                src += stride;
955                dst += alloc->mHal.drvState.lod[lod].stride;
956            }
957        }
958        drv->uploadDeferred = true;
959    }
960}
961
962void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
963                         uint32_t xoff, uint32_t lod, size_t count,
964                         void *data, size_t sizeBytes) {
965    const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
966    const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
967    if (data != ptr) {
968        // Skip the copy if we are the same allocation. This can arise from
969        // our Bitmap optimization, where we share the same storage.
970        memcpy(data, ptr, count * eSize);
971    }
972}
973
974void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
975                                uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
976                                uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) {
977    size_t eSize = alloc->mHal.state.elementSizeBytes;
978    size_t lineSize = eSize * w;
979    if (!stride) {
980        stride = lineSize;
981    }
982
983    if (alloc->mHal.drvState.lod[0].mallocPtr) {
984        uint8_t *dst = static_cast<uint8_t *>(data);
985        const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
986        if (dst == src) {
987            // Skip the copy if we are the same allocation. This can arise from
988            // our Bitmap optimization, where we share the same storage.
989            return;
990        }
991
992        for (uint32_t line=yoff; line < (yoff+h); line++) {
993            memcpy(dst, src, lineSize);
994            dst += stride;
995            src += alloc->mHal.drvState.lod[lod].stride;
996        }
997    } else {
998        ALOGE("Add code to readback from non-script memory");
999    }
1000}
1001
1002
1003void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
1004                         uint32_t xoff, uint32_t yoff, uint32_t zoff,
1005                         uint32_t lod,
1006                         uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) {
1007    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
1008    uint32_t lineSize = eSize * w;
1009    if (!stride) {
1010        stride = lineSize;
1011    }
1012
1013    if (alloc->mHal.drvState.lod[0].mallocPtr) {
1014        uint8_t *dst = static_cast<uint8_t *>(data);
1015        for (uint32_t z = zoff; z < (d + zoff); z++) {
1016            const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
1017                                              RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1018            if (dst == src) {
1019                // Skip the copy if we are the same allocation. This can arise from
1020                // our Bitmap optimization, where we share the same storage.
1021                return;
1022            }
1023
1024            for (uint32_t line=yoff; line < (yoff+h); line++) {
1025                memcpy(dst, src, lineSize);
1026                dst += stride;
1027                src += alloc->mHal.drvState.lod[lod].stride;
1028            }
1029        }
1030    }
1031}
1032
1033void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
1034                          const android::renderscript::Allocation *alloc) {
1035    return alloc->mHal.drvState.lod[0].mallocPtr;
1036}
1037
1038void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
1039                          const android::renderscript::Allocation *alloc) {
1040
1041}
1042
1043void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
1044                               const android::renderscript::Allocation *dstAlloc,
1045                               uint32_t dstXoff, uint32_t dstLod, size_t count,
1046                               const android::renderscript::Allocation *srcAlloc,
1047                               uint32_t srcXoff, uint32_t srcLod) {
1048}
1049
1050
1051void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
1052                                      const android::renderscript::Allocation *dstAlloc,
1053                                      uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
1054                                      RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
1055                                      const android::renderscript::Allocation *srcAlloc,
1056                                      uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
1057                                      RsAllocationCubemapFace srcFace) {
1058    size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
1059    for (uint32_t i = 0; i < h; i ++) {
1060        uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
1061        uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
1062        memcpy(dstPtr, srcPtr, w * elementSize);
1063
1064        //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
1065        //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
1066    }
1067}
1068
1069void rsdAllocationData3D_alloc_script(const android::renderscript::Context *rsc,
1070                                      const android::renderscript::Allocation *dstAlloc,
1071                                      uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod,
1072                                      uint32_t w, uint32_t h, uint32_t d,
1073                                      const android::renderscript::Allocation *srcAlloc,
1074                                      uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod) {
1075    uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
1076    for (uint32_t j = 0; j < d; j++) {
1077        for (uint32_t i = 0; i < h; i ++) {
1078            uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j,
1079                                           dstLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1080            uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j,
1081                                           srcLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1082            memcpy(dstPtr, srcPtr, w * elementSize);
1083
1084            //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
1085            //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
1086        }
1087    }
1088}
1089
1090void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
1091                               const android::renderscript::Allocation *dstAlloc,
1092                               uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
1093                               RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
1094                               const android::renderscript::Allocation *srcAlloc,
1095                               uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
1096                               RsAllocationCubemapFace srcFace) {
1097    if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
1098        rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
1099                                             "yet implemented.");
1100        return;
1101    }
1102    rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
1103                                     dstLod, dstFace, w, h, srcAlloc,
1104                                     srcXoff, srcYoff, srcLod, srcFace);
1105}
1106
1107void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
1108                               const android::renderscript::Allocation *dstAlloc,
1109                               uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
1110                               uint32_t dstLod,
1111                               uint32_t w, uint32_t h, uint32_t d,
1112                               const android::renderscript::Allocation *srcAlloc,
1113                               uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
1114                               uint32_t srcLod) {
1115    if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
1116        rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
1117                                             "yet implemented.");
1118        return;
1119    }
1120    rsdAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
1121                                     dstLod, w, h, d, srcAlloc,
1122                                     srcXoff, srcYoff, srcZoff, srcLod);
1123}
1124
1125void rsdAllocationElementData(const Context *rsc, const Allocation *alloc,
1126                              uint32_t x, uint32_t y, uint32_t z,
1127                              const void *data, uint32_t cIdx, size_t sizeBytes) {
1128    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
1129
1130    uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1131
1132    const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
1133    ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
1134
1135    if (alloc->mHal.state.hasReferences) {
1136        e->incRefs(data);
1137        e->decRefs(ptr);
1138    }
1139
1140    memcpy(ptr, data, sizeBytes);
1141    drv->uploadDeferred = true;
1142}
1143
1144void rsdAllocationElementRead(const Context *rsc, const Allocation *alloc,
1145                              uint32_t x, uint32_t y, uint32_t z,
1146                              void *data, uint32_t cIdx, size_t sizeBytes) {
1147    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
1148
1149    uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1150
1151    const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
1152    ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
1153
1154    memcpy(data, ptr, sizeBytes);
1155}
1156
1157static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1158    uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1159    uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1160
1161    for (uint32_t y=0; y < h; y++) {
1162        uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1163        const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2, lod, face);
1164        const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2+1, lod, face);
1165
1166        for (uint32_t x=0; x < w; x++) {
1167            *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
1168            oPtr ++;
1169            i1 += 2;
1170            i2 += 2;
1171        }
1172    }
1173}
1174
1175static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1176    uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1177    uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1178
1179    for (uint32_t y=0; y < h; y++) {
1180        uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1181        const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
1182        const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
1183
1184        for (uint32_t x=0; x < w; x++) {
1185            *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
1186            oPtr ++;
1187            i1 += 2;
1188            i2 += 2;
1189        }
1190    }
1191}
1192
1193static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1194    uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1195    uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1196
1197    for (uint32_t y=0; y < h; y++) {
1198        uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1199        const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
1200        const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
1201
1202        for (uint32_t x=0; x < w; x++) {
1203            *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
1204            oPtr ++;
1205            i1 += 2;
1206            i2 += 2;
1207        }
1208    }
1209}
1210
1211void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) {
1212    if(!alloc->mHal.drvState.lod[0].mallocPtr) {
1213        return;
1214    }
1215    uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
1216    for (uint32_t face = 0; face < numFaces; face ++) {
1217        for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) {
1218            switch (alloc->getType()->getElement()->getSizeBits()) {
1219            case 32:
1220                mip8888(alloc, lod, (RsAllocationCubemapFace)face);
1221                break;
1222            case 16:
1223                mip565(alloc, lod, (RsAllocationCubemapFace)face);
1224                break;
1225            case 8:
1226                mip8(alloc, lod, (RsAllocationCubemapFace)face);
1227                break;
1228            }
1229        }
1230    }
1231}
1232
1233uint32_t rsdAllocationGrallocBits(const android::renderscript::Context *rsc,
1234                                  android::renderscript::Allocation *alloc)
1235{
1236    return 0;
1237}
1238
1239void rsdAllocationUpdateCachedObject(const Context *rsc,
1240                                     const Allocation *alloc,
1241                                     rs_allocation *obj)
1242{
1243    obj->p = alloc;
1244#ifdef __LP64__
1245    if (alloc != nullptr) {
1246        obj->r = alloc->mHal.drvState.lod[0].mallocPtr;
1247        obj->v1 = alloc->mHal.drv;
1248        obj->v2 = (void *)alloc->mHal.drvState.lod[0].stride;
1249    } else {
1250        obj->r = nullptr;
1251        obj->v1 = nullptr;
1252        obj->v2 = nullptr;
1253    }
1254#endif
1255}
1256