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   ALOGV("TypeBits = 0x%08X", mem_reqs.memoryTypeBits);
    271   rsAssert(pass);
    272 
    273   // TODO: Make this aligned
    274   res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem);
    275   rsAssert(res == VK_SUCCESS);
    276 
    277   res = vkBindBufferMemory(mDevice, mBuf, mMem, 0);
    278   rsAssert(res == VK_SUCCESS);
    279 
    280   mBufferInfo.buffer = mBuf;
    281   mBufferInfo.offset = 0;
    282   mBufferInfo.range = bufferSize;
    283 
    284   res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr);
    285   rsAssert(res == VK_SUCCESS);
    286 }
    287 
    288 }  // namespace rsov
    289 }  // namespace renderscript
    290 }  // namespace android
    291 
    292 using android::renderscript::Allocation;
    293 using android::renderscript::Context;
    294 using android::renderscript::Element;
    295 using android::renderscript::Type;
    296 using android::renderscript::rs_allocation;
    297 using android::renderscript::rsMax;
    298 using namespace android::renderscript::rsov;
    299 
    300 bool rsovAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
    301   RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv);
    302   RSoVContext *rsov = hal->mRSoV;
    303   const Type *type = alloc->getType();
    304 
    305   // Calculate the object size.
    306   size_t allocSize = AllocationBuildPointerTable(rsc, alloc, type, nullptr);
    307   RSoVAllocation *rsovAlloc = new RSoVAllocation(rsov, type, allocSize);
    308   alloc->mHal.drv = rsovAlloc;
    309   AllocationBuildPointerTable(rsc, alloc, type,
    310                               (uint8_t *)rsovAlloc->getHostPtr());
    311   return true;
    312 }
    313 
    314 void rsovAllocationDestroy(const Context *rsc, Allocation *alloc) {
    315   RSoVAllocation *rsovAlloc = static_cast<RSoVAllocation *>(alloc->mHal.drv);
    316   delete rsovAlloc;
    317   alloc->mHal.drv = nullptr;
    318 }
    319 
    320 void rsovAllocationData1D(const Context *rsc, const Allocation *alloc,
    321                           uint32_t xoff, uint32_t lod, size_t count,
    322                           const void *data, size_t sizeBytes) {
    323   const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    324   uint8_t *ptr =
    325       GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    326   size_t size = count * eSize;
    327   if (ptr != data) {
    328     // Skip the copy if we are the same allocation. This can arise from
    329     // our Bitmap optimization, where we share the same storage.
    330     if (alloc->mHal.state.hasReferences) {
    331       alloc->incRefs(data, count);
    332       alloc->decRefs(ptr, count);
    333     }
    334     memcpy(ptr, data, size);
    335   }
    336 }
    337 
    338 void rsovAllocationData2D(const Context *rsc, const Allocation *alloc,
    339                           uint32_t xoff, uint32_t yoff, uint32_t lod,
    340                           RsAllocationCubemapFace face, uint32_t w, uint32_t h,
    341                           const void *data, size_t sizeBytes, size_t stride) {
    342   size_t eSize = alloc->mHal.state.elementSizeBytes;
    343   size_t lineSize = eSize * w;
    344   if (!stride) {
    345     stride = lineSize;
    346   }
    347 
    348   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    349     const uint8_t *src = static_cast<const uint8_t *>(data);
    350     uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    351 
    352     for (uint32_t line = yoff; line < (yoff + h); line++) {
    353       if (alloc->mHal.state.hasReferences) {
    354         alloc->incRefs(src, w);
    355         alloc->decRefs(dst, w);
    356       }
    357       memcpy(dst, src, lineSize);
    358       src += stride;
    359       dst += alloc->mHal.drvState.lod[lod].stride;
    360     }
    361     // TODO: handle YUV Allocations
    362     if (alloc->mHal.state.yuv) {
    363       size_t clineSize = lineSize;
    364       int lod = 1;
    365       int maxLod = 2;
    366       if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) {
    367         maxLod = 3;
    368         clineSize >>= 1;
    369       } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
    370         lod = 2;
    371         maxLod = 3;
    372       }
    373 
    374       while (lod < maxLod) {
    375         uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    376 
    377         for (uint32_t line = (yoff >> 1); line < ((yoff + h) >> 1); line++) {
    378           memcpy(dst, src, clineSize);
    379           // When copying from an array to an Allocation, the src pointer
    380           // to the array should just move by the number of bytes copied.
    381           src += clineSize;
    382           dst += alloc->mHal.drvState.lod[lod].stride;
    383         }
    384         lod++;
    385       }
    386     }
    387   }
    388 }
    389 
    390 void rsovAllocationData3D(const Context *rsc, const Allocation *alloc,
    391                           uint32_t xoff, uint32_t yoff, uint32_t zoff,
    392                           uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
    393                           const void *data, size_t sizeBytes, size_t stride) {
    394   uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    395   uint32_t lineSize = eSize * w;
    396   if (!stride) {
    397     stride = lineSize;
    398   }
    399 
    400   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    401     const uint8_t *src = static_cast<const uint8_t *>(data);
    402     for (uint32_t z = zoff; z < (d + zoff); z++) {
    403       uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
    404                                   RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    405       for (uint32_t line = yoff; line < (yoff + h); line++) {
    406         if (alloc->mHal.state.hasReferences) {
    407           alloc->incRefs(src, w);
    408           alloc->decRefs(dst, w);
    409         }
    410         memcpy(dst, src, lineSize);
    411         src += stride;
    412         dst += alloc->mHal.drvState.lod[lod].stride;
    413       }
    414     }
    415   }
    416 }
    417 
    418 void rsovAllocationRead1D(const Context *rsc, const Allocation *alloc,
    419                           uint32_t xoff, uint32_t lod, size_t count, void *data,
    420                           size_t sizeBytes) {
    421   const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    422   const uint8_t *ptr =
    423       GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    424   if (data != ptr) {
    425     // Skip the copy if we are the same allocation. This can arise from
    426     // our Bitmap optimization, where we share the same storage.
    427     memcpy(data, ptr, count * eSize);
    428   }
    429 }
    430 
    431 void rsovAllocationRead2D(const Context *rsc, const Allocation *alloc,
    432                           uint32_t xoff, uint32_t yoff, uint32_t lod,
    433                           RsAllocationCubemapFace face, uint32_t w, uint32_t h,
    434                           void *data, size_t sizeBytes, size_t stride) {
    435   size_t eSize = alloc->mHal.state.elementSizeBytes;
    436   size_t lineSize = eSize * w;
    437   if (!stride) {
    438     stride = lineSize;
    439   }
    440 
    441   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    442     uint8_t *dst = static_cast<uint8_t *>(data);
    443     const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    444     if (dst == src) {
    445       // Skip the copy if we are the same allocation. This can arise from
    446       // our Bitmap optimization, where we share the same storage.
    447       return;
    448     }
    449 
    450     for (uint32_t line = yoff; line < (yoff + h); line++) {
    451       memcpy(dst, src, lineSize);
    452       dst += stride;
    453       src += alloc->mHal.drvState.lod[lod].stride;
    454     }
    455   } else {
    456     ALOGE("Add code to readback from non-script memory");
    457   }
    458 }
    459 
    460 void rsovAllocationRead3D(const Context *rsc, const Allocation *alloc,
    461                           uint32_t xoff, uint32_t yoff, uint32_t zoff,
    462                           uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
    463                           void *data, size_t sizeBytes, size_t stride) {
    464   uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    465   uint32_t lineSize = eSize * w;
    466   if (!stride) {
    467     stride = lineSize;
    468   }
    469 
    470   if (alloc->mHal.drvState.lod[0].mallocPtr) {
    471     uint8_t *dst = static_cast<uint8_t *>(data);
    472     for (uint32_t z = zoff; z < (d + zoff); z++) {
    473       const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
    474                                         RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    475       if (dst == src) {
    476         // Skip the copy if we are the same allocation. This can arise from
    477         // our Bitmap optimization, where we share the same storage.
    478         return;
    479       }
    480 
    481       for (uint32_t line = yoff; line < (yoff + h); line++) {
    482         memcpy(dst, src, lineSize);
    483         dst += stride;
    484         src += alloc->mHal.drvState.lod[lod].stride;
    485       }
    486     }
    487   }
    488 }
    489 
    490 void *rsovAllocationLock1D(const Context *rsc, const Allocation *alloc) {
    491   return alloc->mHal.drvState.lod[0].mallocPtr;
    492 }
    493 
    494 void rsovAllocationUnlock1D(const Context *rsc, const Allocation *alloc) {}
    495 
    496 void rsovAllocationData1D_alloc(const Context *rsc, const Allocation *dstAlloc,
    497                                 uint32_t dstXoff, uint32_t dstLod, size_t count,
    498                                 const Allocation *srcAlloc, uint32_t srcXoff,
    499                                 uint32_t srcLod) {}
    500 
    501 void rsovAllocationData2D_alloc_script(
    502     const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
    503     uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
    504     uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
    505     uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
    506   size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
    507   for (uint32_t i = 0; i < h; i++) {
    508     uint8_t *dstPtr =
    509         GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
    510     uint8_t *srcPtr =
    511         GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
    512     memcpy(dstPtr, srcPtr, w * elementSize);
    513   }
    514 }
    515 
    516 void rsovAllocationData3D_alloc_script(
    517     const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
    518     uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
    519     uint32_t d, const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff,
    520     uint32_t srcZoff, uint32_t srcLod) {
    521   uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
    522   for (uint32_t j = 0; j < d; j++) {
    523     for (uint32_t i = 0; i < h; i++) {
    524       uint8_t *dstPtr =
    525           GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, dstLod,
    526                        RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    527       uint8_t *srcPtr =
    528           GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, srcLod,
    529                        RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    530       memcpy(dstPtr, srcPtr, w * elementSize);
    531     }
    532   }
    533 }
    534 
    535 void rsovAllocationData2D_alloc(
    536     const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
    537     uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
    538     uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
    539     uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
    540   if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
    541     rsc->setError(RS_ERROR_FATAL_DRIVER,
    542                   "Non-script allocation copies not "
    543                   "yet implemented.");
    544     return;
    545   }
    546   rsovAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstLod,
    547                                     dstFace, w, h, srcAlloc, srcXoff, srcYoff,
    548                                     srcLod, srcFace);
    549 }
    550 
    551 void rsovAllocationData3D_alloc(const Context *rsc, const Allocation *dstAlloc,
    552                                 uint32_t dstXoff, uint32_t dstYoff,
    553                                 uint32_t dstZoff, uint32_t dstLod, uint32_t w,
    554                                 uint32_t h, uint32_t d,
    555                                 const Allocation *srcAlloc, uint32_t srcXoff,
    556                                 uint32_t srcYoff, uint32_t srcZoff,
    557                                 uint32_t srcLod) {
    558   if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
    559     rsc->setError(RS_ERROR_FATAL_DRIVER,
    560                   "Non-script allocation copies not "
    561                   "yet implemented.");
    562     return;
    563   }
    564   rsovAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
    565                                     dstLod, w, h, d, srcAlloc, srcXoff, srcYoff,
    566                                     srcZoff, srcLod);
    567 }
    568 
    569 void rsovAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
    570   // Get a base pointer to the new LOD
    571   const Allocation *base = alloc->mHal.state.baseAlloc;
    572   const Type *type = alloc->mHal.state.type;
    573   if (base == nullptr) {
    574     return;
    575   }
    576 
    577   const int lodBias = alloc->mHal.state.originLOD;
    578   uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
    579   for (uint32_t lod = 0; lod < lodCount; lod++) {
    580     alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
    581     alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(
    582         alloc, alloc->mHal.state.originX, alloc->mHal.state.originY,
    583         alloc->mHal.state.originZ, lodBias,
    584         (RsAllocationCubemapFace)alloc->mHal.state.originFace);
    585   }
    586 }
    587 
    588 bool rsovAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
    589 // TODO: may need a RSoV Allocation here
    590 #if 0
    591     DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
    592     if (!drv) {
    593         return false;
    594     }
    595     alloc->mHal.drv = drv;
    596 #endif
    597   // We need to build an allocation that looks like a subset of the parent
    598   // allocation
    599   rsovAllocationAdapterOffset(rsc, alloc);
    600 
    601   return true;
    602 }
    603 
    604 void rsovAllocationSyncAll(const Context *rsc, const Allocation *alloc,
    605                            RsAllocationUsageType src) {
    606   // TODO: anything to do here?
    607 }
    608 
    609 void rsovAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
    610   // TODO: anything to do here?
    611 }
    612 
    613 void rsovAllocationResize(const Context *rsc, const Allocation *alloc,
    614                           const Type *newType, bool zeroNew) {
    615   // TODO: implement this
    616   // can this be done without copying, if the new size is greater than the
    617   // original?
    618 }
    619 
    620 void rsovAllocationGenerateMipmaps(const Context *rsc,
    621                                    const Allocation *alloc) {
    622   if (!alloc->mHal.drvState.lod[0].mallocPtr) {
    623     return;
    624   }
    625   uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
    626   for (uint32_t face = 0; face < numFaces; face++) {
    627     for (uint32_t lod = 0; lod < (alloc->getType()->getLODCount() - 1); lod++) {
    628       switch (alloc->getType()->getElement()->getSizeBits()) {
    629         case 32:
    630           mip8888(alloc, lod, (RsAllocationCubemapFace)face);
    631           break;
    632         case 16:
    633           mip565(alloc, lod, (RsAllocationCubemapFace)face);
    634           break;
    635         case 8:
    636           mip8(alloc, lod, (RsAllocationCubemapFace)face);
    637           break;
    638       }
    639     }
    640   }
    641 }
    642 
    643 uint32_t rsovAllocationGrallocBits(const Context *rsc, Allocation *alloc) {
    644   return 0;
    645 }
    646 
    647 void rsovAllocationUpdateCachedObject(const Context *rsc,
    648                                       const Allocation *alloc,
    649                                       rs_allocation *obj) {
    650   obj->p = alloc;
    651 #ifdef __LP64__
    652   obj->unused1 = nullptr;
    653   obj->unused2 = nullptr;
    654   obj->unused3 = nullptr;
    655 #endif
    656 }
    657 
    658 void rsovAllocationSetSurface(const Context *rsc, Allocation *alloc,
    659                               ANativeWindow *nw) {
    660   // TODO: implement this
    661 }
    662 
    663 void rsovAllocationIoSend(const Context *rsc, Allocation *alloc) {
    664   // TODO: implement this
    665 }
    666 
    667 void rsovAllocationIoReceive(const Context *rsc, Allocation *alloc) {
    668   // TODO: implement this
    669 }
    670 
    671 void rsovAllocationElementData(const Context *rsc, const Allocation *alloc,
    672                                uint32_t x, uint32_t y, uint32_t z,
    673                                const void *data, uint32_t cIdx,
    674                                size_t sizeBytes) {
    675   uint8_t *ptr =
    676       GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    677 
    678   const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
    679   ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
    680 
    681   if (alloc->mHal.state.hasReferences) {
    682     e->incRefs(data);
    683     e->decRefs(ptr);
    684   }
    685 
    686   memcpy(ptr, data, sizeBytes);
    687 }
    688 
    689 void rsovAllocationElementRead(const Context *rsc, const Allocation *alloc,
    690                                uint32_t x, uint32_t y, uint32_t z, void *data,
    691                                uint32_t cIdx, size_t sizeBytes) {
    692   uint8_t *ptr =
    693       GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    694 
    695   const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
    696   ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
    697 
    698   memcpy(data, ptr, sizeBytes);
    699 }
    700