Home | History | Annotate | Download | only in driver
      1 /*
      2  * Copyright (C) 2016 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 "rsovAllocation.h"
     18 
     19 #include "rsAllocation.h"
     20 #include "rsContext.h"
     21 #include "rsCppUtils.h"
     22 #include "rsElement.h"
     23 #include "rsType.h"
     24 #include "rsovContext.h"
     25 #include "rsovCore.h"
     26 
     27 namespace android {
     28 namespace renderscript {
     29 namespace rsov {
     30 
     31 namespace {
     32 
     33 size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
     34   // For the flexible YCbCr format, layout is initialized during call to
     35   // Allocation::ioReceive.  Return early and avoid clobberring any
     36   // pre-existing layout.
     37   if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
     38     return 0;
     39   }
     40 
     41   // YUV only supports basic 2d
     42   // so we can stash the plane pointers in the mipmap levels.
     43   size_t uvSize = 0;
     44   state->lod[1].dimX = state->lod[0].dimX / 2;
     45   state->lod[1].dimY = state->lod[0].dimY / 2;
     46   state->lod[2].dimX = state->lod[0].dimX / 2;
     47   state->lod[2].dimY = state->lod[0].dimY / 2;
     48   state->yuv.shift = 1;
     49   state->yuv.step = 1;
     50   state->lodCount = 3;
     51 
     52   switch (yuv) {
     53     case HAL_PIXEL_FORMAT_YV12:
     54       state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
     55       state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
     56                                 (state->lod[0].stride * state->lod[0].dimY);
     57       uvSize += state->lod[2].stride * state->lod[2].dimY;
     58 
     59       state->lod[1].stride = state->lod[2].stride;
     60       state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
     61                                 (state->lod[2].stride * state->lod[2].dimY);
     62       uvSize += state->lod[1].stride * state->lod[2].dimY;
     63       break;
     64     case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
     65       // state->lod[1].dimX = state->lod[0].dimX;
     66       state->lod[1].stride = state->lod[0].stride;
     67       state->lod[2].stride = state->lod[0].stride;
     68       state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
     69                                 (state->lod[0].stride * state->lod[0].dimY);
     70       state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1;
     71       uvSize += state->lod[1].stride * state->lod[1].dimY;
     72       state->yuv.step = 2;
     73       break;
     74     default:
     75       rsAssert(0);
     76   }
     77 
     78   return uvSize;
     79 }
     80 
     81 // TODO: Dedup this with the same code under frameworks/rs/driver
     82 size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
     83                                    const Type *type, uint8_t *ptr,
     84                                    size_t requiredAlignment) {
     85   alloc->mHal.drvState.lod[0].dimX = type->getDimX();
     86   alloc->mHal.drvState.lod[0].dimY = type->getDimY();
     87   alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
     88   alloc->mHal.drvState.lod[0].mallocPtr = 0;
     89   // Stride needs to be aligned to a boundary defined by requiredAlignment!
     90   size_t stride =
     91       alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
     92   alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment);
     93   alloc->mHal.drvState.lodCount = type->getLODCount();
     94   alloc->mHal.drvState.faceCount = type->getDimFaces();
     95 
     96   size_t offsets[Allocation::MAX_LOD];
     97   memset(offsets, 0, sizeof(offsets));
     98 
     99   size_t o = alloc->mHal.drvState.lod[0].stride *
    100              rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
    101              rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
    102   if (alloc->mHal.state.yuv) {
    103     o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
    104 
    105     for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
    106       offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
    107     }
    108   } else if (alloc->mHal.drvState.lodCount > 1) {
    109     uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
    110     uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
    111     uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
    112     for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) {
    113       alloc->mHal.drvState.lod[lod].dimX = tx;
    114       alloc->mHal.drvState.lod[lod].dimY = ty;
    115       alloc->mHal.drvState.lod[lod].dimZ = tz;
    116       alloc->mHal.drvState.lod[lod].stride =
    117           rsRound(tx * type->getElementSizeBytes(), requiredAlignment);
    118       offsets[lod] = o;
    119       o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
    120       if (tx > 1) tx >>= 1;
    121       if (ty > 1) ty >>= 1;
    122       if (tz > 1) tz >>= 1;
    123     }
    124   }
    125 
    126   alloc->mHal.drvState.faceOffset = o;
    127 
    128   alloc->mHal.drvState.lod[0].mallocPtr = ptr;
    129   for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) {
    130     alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
    131   }
    132 
    133   size_t allocSize = alloc->mHal.drvState.faceOffset;
    134   if (alloc->mHal.drvState.faceCount) {
    135     allocSize *= 6;
    136   }
    137 
    138   return allocSize;
    139 }
    140 
    141 size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
    142                                    const Type *type, uint8_t *ptr) {
    143   return AllocationBuildPointerTable(rsc, alloc, type, ptr,
    144                                      Allocation::kMinimumRSAlignment);
    145 }
    146 
    147 uint8_t *GetOffsetPtr(const Allocation *alloc, uint32_t xoff, uint32_t yoff,
    148                       uint32_t zoff, uint32_t lod,
    149                       RsAllocationCubemapFace face) {
    150   uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
    151   ptr += face * alloc->mHal.drvState.faceOffset;
    152   ptr += zoff * alloc->mHal.drvState.lod[lod].dimY *
    153          alloc->mHal.drvState.lod[lod].stride;
    154   ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
    155   ptr += xoff * alloc->mHal.state.elementSizeBytes;
    156   return ptr;
    157 }
    158 
    159 void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
    160   uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
    161   uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
    162 
    163   for (uint32_t y = 0; y < h; y++) {
    164     uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
    165     const uint16_t *i1 =
    166         (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2, lod, face);
    167     const uint16_t *i2 =
    168         (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2 + 1, lod, face);
    169 
    170     for (uint32_t x = 0; x < w; x++) {
    171       *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
    172       oPtr++;
    173       i1 += 2;
    174       i2 += 2;
    175     }
    176   }
    177 }
    178 
    179 void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
    180   uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
    181   uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
    182 
    183   for (uint32_t y = 0; y < h; y++) {
    184     uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
    185     const uint32_t *i1 =
    186         (uint32_t *)GetOffsetPtr(alloc, 0, y * 2, 0, lod, face);
    187     const uint32_t *i2 =
    188         (uint32_t *)GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face);
    189 
    190     for (uint32_t x = 0; x < w; x++) {
    191       *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
    192       oPtr++;
    193       i1 += 2;
    194       i2 += 2;
    195     }
    196   }
    197 }
    198 
    199 void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
    200   uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
    201   uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
    202 
    203   for (uint32_t y = 0; y < h; y++) {
    204     uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
    205     const uint8_t *i1 = GetOffsetPtr(alloc, 0, y * 2, 0, lod, face);
    206     const uint8_t *i2 = GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face);
    207 
    208     for (uint32_t x = 0; x < w; x++) {
    209       *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
    210       oPtr++;
    211       i1 += 2;
    212       i2 += 2;
    213     }
    214   }
    215 }
    216 
    217 }  // anonymous namespace
    218 
    219 RSoVAllocation::RSoVAllocation(RSoVContext *context, const Type *type,
    220                                size_t bufferSize)
    221     : mBuffer(new RSoVBuffer(context, bufferSize)),
    222       mType(type),
    223       mWidth(type->getDimX()),
    224       mHeight(type->getDimY()),
    225       mDepth(type->getDimZ()) {}
    226 
    227 RSoVBuffer::RSoVBuffer(RSoVContext *context, size_t size)
    228     : mRSoV(context), mDevice(context->getDevice()) {
    229   InitBuffer(size);
    230 }
    231 
    232 RSoVBuffer::~RSoVBuffer() {
    233   vkUnmapMemory(mDevice, mMem);
    234   vkDestroyBuffer(mDevice, mBuf, nullptr);
    235   vkFreeMemory(mDevice, mMem, nullptr);
    236 }
    237 
    238 void RSoVBuffer::InitBuffer(size_t bufferSize) {
    239   VkResult res;
    240 
    241   VkBufferCreateInfo buf_info = {
    242       .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
    243       .pNext = nullptr,
    244       .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    245       .size = bufferSize,
    246       .queueFamilyIndexCount = 0,
    247       .pQueueFamilyIndices = nullptr,
    248       .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
    249       .flags = 0,
    250   };
    251   res = vkCreateBuffer(mDevice, &buf_info, nullptr, &mBuf);
    252   rsAssert(res == VK_SUCCESS);
    253 
    254   VkMemoryRequirements mem_reqs;
    255   vkGetBufferMemoryRequirements(mDevice, mBuf, &mem_reqs);
    256 
    257   VkMemoryAllocateInfo allocateInfo = {
    258       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
    259       .pNext = nullptr,
    260       .memoryTypeIndex = 0,
    261       .allocationSize = mem_reqs.size,
    262   };
    263 
    264   bool pass;
    265   pass =
    266       mRSoV->MemoryTypeFromProperties(mem_reqs.memoryTypeBits,
    267                                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    268                                           VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    269                                       &allocateInfo.memoryTypeIndex);
    270   rsAssert(pass);
    271 
    272   // TODO: Make this aligned
    273   res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem);
    274   rsAssert(res == VK_SUCCESS);
    275 
    276   res = vkBindBufferMemory(mDevice, mBuf, mMem, 0);
    277   rsAssert(res == VK_SUCCESS);
    278 
    279   mBufferInfo.buffer = mBuf;
    280   mBufferInfo.offset = 0;
    281   mBufferInfo.range = bufferSize;
    282 
    283   res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr);
    284   rsAssert(res == VK_SUCCESS);
    285 }
    286 
    287 }  // namespace rsov
    288 }  // namespace renderscript
    289 }  // namespace android
    290 
    291 using android::renderscript::Allocation;
    292 using android::renderscript::Context;
    293 using android::renderscript::Element;
    294 using android::renderscript::Type;
    295 using android::renderscript::rs_allocation;
    296 using android::renderscript::rsMax;
    297 using namespace android::renderscript::rsov;
    298 
    299 bool rsovAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
    300   RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv);
    301   RSoVContext *rsov = hal->mRSoV;
    302   const Type *type = alloc->getType();
    303 
    304   // Calculate the object size.
    305   size_t allocSize = AllocationBuildPointerTable(rsc, alloc, type, nullptr);
    306   RSoVAllocation *rsovAlloc = new RSoVAllocation(rsov, type, allocSize);
    307   alloc->mHal.drv = rsovAlloc;
    308   AllocationBuildPointerTable(rsc, alloc, type,
    309                               (uint8_t *)rsovAlloc->getHostPtr());
    310   return true;
    311 }
    312 
    313 void rsovAllocationDestroy(const Context *rsc, Allocation *alloc) {
    314   RSoVAllocation *rsovAlloc = static_cast<RSoVAllocation *>(alloc->mHal.drv);
    315   delete rsovAlloc;
    316   alloc->mHal.drv = nullptr;
    317 }
    318 
    319 void rsovAllocationData1D(const Context *rsc, const Allocation *alloc,
    320                           uint32_t xoff, uint32_t lod, size_t count,
    321                           const void *data, size_t sizeBytes) {
    322   const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    323   uint8_t *ptr =
    324       GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    325   size_t size = count * eSize;
    326   if (ptr != data) {
    327     // Skip the copy if we are the same allocation. This can arise from
    328     // our Bitmap optimization, where we share the same storage.
    329     if (alloc->mHal.state.hasReferences) {
    330       alloc->incRefs(data, count);
    331       alloc->decRefs(ptr, count);
    332     }
    333     memcpy(ptr, data, size);
    334   }
    335 }
    336 
    337 void rsovAllocationData2D(const Context *rsc, const Allocation *alloc,
    338                           uint32_t xoff, uint32_t yoff, uint32_t lod,
    339                           RsAllocationCubemapFace face, uint32_t w, uint32_t h,
    340                           const void *data, size_t sizeBytes, size_t stride) {
    341   size_t eSize = alloc->mHal.state.elementSizeBytes;
    342   size_t lineSize = eSize * w;
    343   if (!stride) {
    344     stride = lineSize;
    345   }
    346 
    347   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    348     const uint8_t *src = static_cast<const uint8_t *>(data);
    349     uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    350 
    351     for (uint32_t line = yoff; line < (yoff + h); line++) {
    352       if (alloc->mHal.state.hasReferences) {
    353         alloc->incRefs(src, w);
    354         alloc->decRefs(dst, w);
    355       }
    356       memcpy(dst, src, lineSize);
    357       src += stride;
    358       dst += alloc->mHal.drvState.lod[lod].stride;
    359     }
    360     // TODO: handle YUV Allocations
    361     if (alloc->mHal.state.yuv) {
    362       size_t clineSize = lineSize;
    363       int lod = 1;
    364       int maxLod = 2;
    365       if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) {
    366         maxLod = 3;
    367         clineSize >>= 1;
    368       } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
    369         lod = 2;
    370         maxLod = 3;
    371       }
    372 
    373       while (lod < maxLod) {
    374         uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    375 
    376         for (uint32_t line = (yoff >> 1); line < ((yoff + h) >> 1); line++) {
    377           memcpy(dst, src, clineSize);
    378           // When copying from an array to an Allocation, the src pointer
    379           // to the array should just move by the number of bytes copied.
    380           src += clineSize;
    381           dst += alloc->mHal.drvState.lod[lod].stride;
    382         }
    383         lod++;
    384       }
    385     }
    386   }
    387 }
    388 
    389 void rsovAllocationData3D(const Context *rsc, const Allocation *alloc,
    390                           uint32_t xoff, uint32_t yoff, uint32_t zoff,
    391                           uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
    392                           const void *data, size_t sizeBytes, size_t stride) {
    393   uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    394   uint32_t lineSize = eSize * w;
    395   if (!stride) {
    396     stride = lineSize;
    397   }
    398 
    399   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    400     const uint8_t *src = static_cast<const uint8_t *>(data);
    401     for (uint32_t z = zoff; z < (d + zoff); z++) {
    402       uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
    403                                   RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    404       for (uint32_t line = yoff; line < (yoff + h); line++) {
    405         if (alloc->mHal.state.hasReferences) {
    406           alloc->incRefs(src, w);
    407           alloc->decRefs(dst, w);
    408         }
    409         memcpy(dst, src, lineSize);
    410         src += stride;
    411         dst += alloc->mHal.drvState.lod[lod].stride;
    412       }
    413     }
    414   }
    415 }
    416 
    417 void rsovAllocationRead1D(const Context *rsc, const Allocation *alloc,
    418                           uint32_t xoff, uint32_t lod, size_t count, void *data,
    419                           size_t sizeBytes) {
    420   const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    421   const uint8_t *ptr =
    422       GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    423   if (data != ptr) {
    424     // Skip the copy if we are the same allocation. This can arise from
    425     // our Bitmap optimization, where we share the same storage.
    426     memcpy(data, ptr, count * eSize);
    427   }
    428 }
    429 
    430 void rsovAllocationRead2D(const Context *rsc, const Allocation *alloc,
    431                           uint32_t xoff, uint32_t yoff, uint32_t lod,
    432                           RsAllocationCubemapFace face, uint32_t w, uint32_t h,
    433                           void *data, size_t sizeBytes, size_t stride) {
    434   size_t eSize = alloc->mHal.state.elementSizeBytes;
    435   size_t lineSize = eSize * w;
    436   if (!stride) {
    437     stride = lineSize;
    438   }
    439 
    440   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    441     uint8_t *dst = static_cast<uint8_t *>(data);
    442     const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    443     if (dst == src) {
    444       // Skip the copy if we are the same allocation. This can arise from
    445       // our Bitmap optimization, where we share the same storage.
    446       return;
    447     }
    448 
    449     for (uint32_t line = yoff; line < (yoff + h); line++) {
    450       memcpy(dst, src, lineSize);
    451       dst += stride;
    452       src += alloc->mHal.drvState.lod[lod].stride;
    453     }
    454   } else {
    455     ALOGE("Add code to readback from non-script memory");
    456   }
    457 }
    458 
    459 void rsovAllocationRead3D(const Context *rsc, const Allocation *alloc,
    460                           uint32_t xoff, uint32_t yoff, uint32_t zoff,
    461                           uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
    462                           void *data, size_t sizeBytes, size_t stride) {
    463   uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    464   uint32_t lineSize = eSize * w;
    465   if (!stride) {
    466     stride = lineSize;
    467   }
    468 
    469   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    470     uint8_t *dst = static_cast<uint8_t *>(data);
    471     for (uint32_t z = zoff; z < (d + zoff); z++) {
    472       const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
    473                                         RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    474       if (dst == src) {
    475         // Skip the copy if we are the same allocation. This can arise from
    476         // our Bitmap optimization, where we share the same storage.
    477         return;
    478       }
    479 
    480       for (uint32_t line = yoff; line < (yoff + h); line++) {
    481         memcpy(dst, src, lineSize);
    482         dst += stride;
    483         src += alloc->mHal.drvState.lod[lod].stride;
    484       }
    485     }
    486   }
    487 }
    488 
    489 void *rsovAllocationLock1D(const Context *rsc, const Allocation *alloc) {
    490   return alloc->mHal.drvState.lod[0].mallocPtr;
    491 }
    492 
    493 void rsovAllocationUnlock1D(const Context *rsc, const Allocation *alloc) {}
    494 
    495 void rsovAllocationData1D_alloc(const Context *rsc, const Allocation *dstAlloc,
    496                                 uint32_t dstXoff, uint32_t dstLod, size_t count,
    497                                 const Allocation *srcAlloc, uint32_t srcXoff,
    498                                 uint32_t srcLod) {}
    499 
    500 void rsovAllocationData2D_alloc_script(
    501     const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
    502     uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
    503     uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
    504     uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
    505   size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
    506   for (uint32_t i = 0; i < h; i++) {
    507     uint8_t *dstPtr =
    508         GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
    509     uint8_t *srcPtr =
    510         GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
    511     memcpy(dstPtr, srcPtr, w * elementSize);
    512   }
    513 }
    514 
    515 void rsovAllocationData3D_alloc_script(
    516     const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
    517     uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
    518     uint32_t d, const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff,
    519     uint32_t srcZoff, uint32_t srcLod) {
    520   uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
    521   for (uint32_t j = 0; j < d; j++) {
    522     for (uint32_t i = 0; i < h; i++) {
    523       uint8_t *dstPtr =
    524           GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, dstLod,
    525                        RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    526       uint8_t *srcPtr =
    527           GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, srcLod,
    528                        RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    529       memcpy(dstPtr, srcPtr, w * elementSize);
    530     }
    531   }
    532 }
    533 
    534 void rsovAllocationData2D_alloc(
    535     const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
    536     uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
    537     uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
    538     uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
    539   if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
    540     rsc->setError(RS_ERROR_FATAL_DRIVER,
    541                   "Non-script allocation copies not "
    542                   "yet implemented.");
    543     return;
    544   }
    545   rsovAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstLod,
    546                                     dstFace, w, h, srcAlloc, srcXoff, srcYoff,
    547                                     srcLod, srcFace);
    548 }
    549 
    550 void rsovAllocationData3D_alloc(const Context *rsc, const Allocation *dstAlloc,
    551                                 uint32_t dstXoff, uint32_t dstYoff,
    552                                 uint32_t dstZoff, uint32_t dstLod, uint32_t w,
    553                                 uint32_t h, uint32_t d,
    554                                 const Allocation *srcAlloc, uint32_t srcXoff,
    555                                 uint32_t srcYoff, uint32_t srcZoff,
    556                                 uint32_t srcLod) {
    557   if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
    558     rsc->setError(RS_ERROR_FATAL_DRIVER,
    559                   "Non-script allocation copies not "
    560                   "yet implemented.");
    561     return;
    562   }
    563   rsovAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
    564                                     dstLod, w, h, d, srcAlloc, srcXoff, srcYoff,
    565                                     srcZoff, srcLod);
    566 }
    567 
    568 void rsovAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
    569   // Get a base pointer to the new LOD
    570   const Allocation *base = alloc->mHal.state.baseAlloc;
    571   const Type *type = alloc->mHal.state.type;
    572   if (base == nullptr) {
    573     return;
    574   }
    575 
    576   const int lodBias = alloc->mHal.state.originLOD;
    577   uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
    578   for (uint32_t lod = 0; lod < lodCount; lod++) {
    579     alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
    580     alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(
    581         alloc, alloc->mHal.state.originX, alloc->mHal.state.originY,
    582         alloc->mHal.state.originZ, lodBias,
    583         (RsAllocationCubemapFace)alloc->mHal.state.originFace);
    584   }
    585 }
    586 
    587 bool rsovAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
    588 // TODO: may need a RSoV Allocation here
    589 #if 0
    590     DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
    591     if (!drv) {
    592         return false;
    593     }
    594     alloc->mHal.drv = drv;
    595 #endif
    596   // We need to build an allocation that looks like a subset of the parent
    597   // allocation
    598   rsovAllocationAdapterOffset(rsc, alloc);
    599 
    600   return true;
    601 }
    602 
    603 void rsovAllocationSyncAll(const Context *rsc, const Allocation *alloc,
    604                            RsAllocationUsageType src) {
    605   // TODO: anything to do here?
    606 }
    607 
    608 void rsovAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
    609   // TODO: anything to do here?
    610 }
    611 
    612 void rsovAllocationResize(const Context *rsc, const Allocation *alloc,
    613                           const Type *newType, bool zeroNew) {
    614   // TODO: implement this
    615   // can this be done without copying, if the new size is greater than the
    616   // original?
    617 }
    618 
    619 void rsovAllocationGenerateMipmaps(const Context *rsc,
    620                                    const Allocation *alloc) {
    621   if (!alloc->mHal.drvState.lod[0].mallocPtr) {
    622     return;
    623   }
    624   uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
    625   for (uint32_t face = 0; face < numFaces; face++) {
    626     for (uint32_t lod = 0; lod < (alloc->getType()->getLODCount() - 1); lod++) {
    627       switch (alloc->getType()->getElement()->getSizeBits()) {
    628         case 32:
    629           mip8888(alloc, lod, (RsAllocationCubemapFace)face);
    630           break;
    631         case 16:
    632           mip565(alloc, lod, (RsAllocationCubemapFace)face);
    633           break;
    634         case 8:
    635           mip8(alloc, lod, (RsAllocationCubemapFace)face);
    636           break;
    637       }
    638     }
    639   }
    640 }
    641 
    642 uint32_t rsovAllocationGrallocBits(const Context *rsc, Allocation *alloc) {
    643   return 0;
    644 }
    645 
    646 void rsovAllocationUpdateCachedObject(const Context *rsc,
    647                                       const Allocation *alloc,
    648                                       rs_allocation *obj) {
    649   obj->p = alloc;
    650 #ifdef __LP64__
    651   obj->unused1 = nullptr;
    652   obj->unused2 = nullptr;
    653   obj->unused3 = nullptr;
    654 #endif
    655 }
    656 
    657 void rsovAllocationSetSurface(const Context *rsc, Allocation *alloc,
    658                               ANativeWindow *nw) {
    659   // TODO: implement this
    660 }
    661 
    662 void rsovAllocationIoSend(const Context *rsc, Allocation *alloc) {
    663   // TODO: implement this
    664 }
    665 
    666 void rsovAllocationIoReceive(const Context *rsc, Allocation *alloc) {
    667   // TODO: implement this
    668 }
    669 
    670 void rsovAllocationElementData(const Context *rsc, const Allocation *alloc,
    671                                uint32_t x, uint32_t y, uint32_t z,
    672                                const void *data, uint32_t cIdx,
    673                                size_t sizeBytes) {
    674   uint8_t *ptr =
    675       GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    676 
    677   const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
    678   ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
    679 
    680   if (alloc->mHal.state.hasReferences) {
    681     e->incRefs(data);
    682     e->decRefs(ptr);
    683   }
    684 
    685   memcpy(ptr, data, sizeBytes);
    686 }
    687 
    688 void rsovAllocationElementRead(const Context *rsc, const Allocation *alloc,
    689                                uint32_t x, uint32_t y, uint32_t z, void *data,
    690                                uint32_t cIdx, size_t sizeBytes) {
    691   uint8_t *ptr =
    692       GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    693 
    694   const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
    695   ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
    696 
    697   memcpy(data, ptr, sizeBytes);
    698 }
    699