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