diff options
Diffstat (limited to 'rsov/driver/rsovAllocation.cpp')
-rw-r--r-- | rsov/driver/rsovAllocation.cpp | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/rsov/driver/rsovAllocation.cpp b/rsov/driver/rsovAllocation.cpp new file mode 100644 index 00000000..fdb477d1 --- /dev/null +++ b/rsov/driver/rsovAllocation.cpp @@ -0,0 +1,790 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rsovAllocation.h" + +#include <map> + +#include "rsAllocation.h" +#include "rsContext.h" +#include "rsCppUtils.h" +#include "rsElement.h" +#include "rsType.h" +#include "rsovContext.h" +#include "rsovCore.h" + +namespace android { +namespace renderscript { +namespace rsov { + +namespace { + +using std::make_pair; + +// TODO: handle 8-bit, 16-bit, and 64-bit integers and floating point numbers +const std::map<std::pair<RsDataType, uint32_t>, VkFormat> mapElementToFormat{ + make_pair(make_pair(RS_TYPE_FLOAT_32, 1), VK_FORMAT_R32_SFLOAT), + make_pair(make_pair(RS_TYPE_FLOAT_32, 2), VK_FORMAT_R32G32_SFLOAT), + make_pair(make_pair(RS_TYPE_FLOAT_32, 3), VK_FORMAT_R32G32B32_SFLOAT), + make_pair(make_pair(RS_TYPE_FLOAT_32, 4), VK_FORMAT_R32G32B32A32_SFLOAT), + + make_pair(make_pair(RS_TYPE_SIGNED_32, 1), VK_FORMAT_R32_SINT), + make_pair(make_pair(RS_TYPE_SIGNED_32, 2), VK_FORMAT_R32G32_SINT), + make_pair(make_pair(RS_TYPE_SIGNED_32, 3), VK_FORMAT_R32G32B32_SINT), + make_pair(make_pair(RS_TYPE_SIGNED_32, 4), VK_FORMAT_R32G32B32A32_SINT), + + make_pair(make_pair(RS_TYPE_UNSIGNED_32, 1), VK_FORMAT_R32_UINT), + make_pair(make_pair(RS_TYPE_UNSIGNED_32, 2), VK_FORMAT_R32G32_UINT), + make_pair(make_pair(RS_TYPE_UNSIGNED_32, 3), VK_FORMAT_R32G32B32_UINT), + make_pair(make_pair(RS_TYPE_UNSIGNED_32, 4), VK_FORMAT_R32G32B32A32_UINT), +}; + +VkFormat VkFormatFromRSElement(const Element &elem) { + // TODO: reject struct, allocation, and other non-numeric element + rsAssert(!elem.getFieldCount()); + + RsDataType dataType = elem.getType(); + uint32_t vectorWidth = elem.getVectorSize(); + + auto it = mapElementToFormat.find(make_pair(dataType, vectorWidth)); + if (it != mapElementToFormat.end()) { + return it->second; + } + + rsAssert(0 && "Unexpected RS Element to map to VkFormat"); + + return VK_FORMAT_R32G32B32A32_SFLOAT; +} + +size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) { + // For the flexible YCbCr format, layout is initialized during call to + // Allocation::ioReceive. Return early and avoid clobberring any + // pre-existing layout. + if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) { + return 0; + } + + // YUV only supports basic 2d + // so we can stash the plane pointers in the mipmap levels. + size_t uvSize = 0; + state->lod[1].dimX = state->lod[0].dimX / 2; + state->lod[1].dimY = state->lod[0].dimY / 2; + state->lod[2].dimX = state->lod[0].dimX / 2; + state->lod[2].dimY = state->lod[0].dimY / 2; + state->yuv.shift = 1; + state->yuv.step = 1; + state->lodCount = 3; + + switch (yuv) { + case HAL_PIXEL_FORMAT_YV12: + state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16); + state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + + (state->lod[0].stride * state->lod[0].dimY); + uvSize += state->lod[2].stride * state->lod[2].dimY; + + state->lod[1].stride = state->lod[2].stride; + state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + + (state->lod[2].stride * state->lod[2].dimY); + uvSize += state->lod[1].stride * state->lod[2].dimY; + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 + // state->lod[1].dimX = state->lod[0].dimX; + state->lod[1].stride = state->lod[0].stride; + state->lod[2].stride = state->lod[0].stride; + state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + + (state->lod[0].stride * state->lod[0].dimY); + state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1; + uvSize += state->lod[1].stride * state->lod[1].dimY; + state->yuv.step = 2; + break; + default: + rsAssert(0); + } + + return uvSize; +} + +// TODO: Dedup this with the same code under frameworks/rs/driver +size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, + const Type *type, uint8_t *ptr, + size_t requiredAlignment) { + alloc->mHal.drvState.lod[0].dimX = type->getDimX(); + alloc->mHal.drvState.lod[0].dimY = type->getDimY(); + alloc->mHal.drvState.lod[0].dimZ = type->getDimZ(); + alloc->mHal.drvState.lod[0].mallocPtr = 0; + // Stride needs to be aligned to a boundary defined by requiredAlignment! + size_t stride = + alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes(); + alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment); + alloc->mHal.drvState.lodCount = type->getLODCount(); + alloc->mHal.drvState.faceCount = type->getDimFaces(); + + size_t offsets[Allocation::MAX_LOD]; + memset(offsets, 0, sizeof(offsets)); + + size_t o = alloc->mHal.drvState.lod[0].stride * + rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) * + rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u); + if (alloc->mHal.state.yuv) { + o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState); + + for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) { + offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr; + } + } else if (alloc->mHal.drvState.lodCount > 1) { + uint32_t tx = alloc->mHal.drvState.lod[0].dimX; + uint32_t ty = alloc->mHal.drvState.lod[0].dimY; + uint32_t tz = alloc->mHal.drvState.lod[0].dimZ; + for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) { + alloc->mHal.drvState.lod[lod].dimX = tx; + alloc->mHal.drvState.lod[lod].dimY = ty; + alloc->mHal.drvState.lod[lod].dimZ = tz; + alloc->mHal.drvState.lod[lod].stride = + rsRound(tx * type->getElementSizeBytes(), requiredAlignment); + offsets[lod] = o; + o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u); + if (tx > 1) tx >>= 1; + if (ty > 1) ty >>= 1; + if (tz > 1) tz >>= 1; + } + } + + alloc->mHal.drvState.faceOffset = o; + + alloc->mHal.drvState.lod[0].mallocPtr = ptr; + for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) { + alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod]; + } + + size_t allocSize = alloc->mHal.drvState.faceOffset; + if (alloc->mHal.drvState.faceCount) { + allocSize *= 6; + } + + return allocSize; +} + +size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, + const Type *type, uint8_t *ptr) { + return AllocationBuildPointerTable(rsc, alloc, type, ptr, + Allocation::kMinimumRSAlignment); +} + +uint8_t *GetOffsetPtr(const Allocation *alloc, uint32_t xoff, uint32_t yoff, + uint32_t zoff, uint32_t lod, + RsAllocationCubemapFace face) { + uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; + ptr += face * alloc->mHal.drvState.faceOffset; + ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * + alloc->mHal.drvState.lod[lod].stride; + ptr += yoff * alloc->mHal.drvState.lod[lod].stride; + ptr += xoff * alloc->mHal.state.elementSizeBytes; + return ptr; +} + +void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { + uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; + uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; + + for (uint32_t y = 0; y < h; y++) { + uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); + const uint16_t *i1 = + (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2, lod, face); + const uint16_t *i2 = + (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2 + 1, lod, face); + + for (uint32_t x = 0; x < w; x++) { + *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); + oPtr++; + i1 += 2; + i2 += 2; + } + } +} + +void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { + uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; + uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; + + for (uint32_t y = 0; y < h; y++) { + uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); + const uint32_t *i1 = + (uint32_t *)GetOffsetPtr(alloc, 0, y * 2, 0, lod, face); + const uint32_t *i2 = + (uint32_t *)GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face); + + for (uint32_t x = 0; x < w; x++) { + *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); + oPtr++; + i1 += 2; + i2 += 2; + } + } +} + +void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { + uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; + uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; + + for (uint32_t y = 0; y < h; y++) { + uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); + const uint8_t *i1 = GetOffsetPtr(alloc, 0, y * 2, 0, lod, face); + const uint8_t *i2 = GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face); + + for (uint32_t x = 0; x < w; x++) { + *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); + oPtr++; + i1 += 2; + i2 += 2; + } + } +} + +} // anonymous namespace + +RSoVAllocation::RSoVAllocation(RSoVContext *context, const Type *type) + : mRSoV(context), + mDevice(context->getDevice()), + mType(type), + mWidth(type->getDimX()), + mHeight(type->getDimY()), + mDepth(type->getDimZ()) { + InitImage(); +} + +RSoVAllocation::~RSoVAllocation() { + vkDestroyImageView(mDevice, mImageView, nullptr); + vkDestroyImage(mDevice, mImage, nullptr); + vkFreeMemory(mDevice, mMem, nullptr); +} + +void RSoVAllocation::InitImage() { + VkResult res; + + mFormat = VkFormatFromRSElement(*mType->getElement()); + + const uint32_t width = mWidth; + const uint32_t height = mHeight; + const uint32_t depth = mDepth; + + VkImageType imageType = + depth > 0 ? VK_IMAGE_TYPE_3D + : (height > 0 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D); + + VkImageCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .imageType = imageType, + .format = mFormat, + .extent = {width, rsMax(height, 1U), rsMax(depth, 1U)}, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_LINEAR, + .usage = VK_IMAGE_USAGE_STORAGE_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED, + }; + + res = vkCreateImage(mDevice, &createInfo, nullptr, &mImage); + rsAssert(res == VK_SUCCESS); + + VkMemoryRequirements mem_reqs; + vkGetImageMemoryRequirements(mDevice, mImage, &mem_reqs); + + ALOGI("size of memory needed = %u", (uint)mem_reqs.size); + + VkMemoryAllocateInfo allocateInfo = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = nullptr, + .allocationSize = mem_reqs.size, + }; + + /* Use the memory properties to determine the type of memory required */ + bool pass; + pass = mRSoV->MemoryTypeFromProperties( + mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &allocateInfo.memoryTypeIndex); + ALOGI("TypeBits = 0x%08X", mem_reqs.memoryTypeBits); + rsAssert(pass); + + // TODO: Make this aligned + res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem); + rsAssert(res == VK_SUCCESS); + + res = vkBindImageMemory(mDevice, mImage, mMem, 0); + rsAssert(res == VK_SUCCESS); + + VkImageViewType viewType = + depth > 0 ? VK_IMAGE_VIEW_TYPE_3D + : (height > 0 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D); + + VkImageViewCreateInfo view_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .image = mImage, + .viewType = viewType, + .format = mFormat, + .components = + { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }, + .subresourceRange = + { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + res = vkCreateImageView(mDevice, &view_info, nullptr, &mImageView); + rsAssert(res == VK_SUCCESS); + + mImageLayout = VK_IMAGE_LAYOUT_GENERAL; + + mImageInfo = { + .imageView = mImageView, .imageLayout = mImageLayout, + }; + + res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr); + rsAssert(res == VK_SUCCESS); +} + +} // namespace rsov +} // namespace renderscript +} // namespace android + +using android::renderscript::Allocation; +using android::renderscript::Context; +using android::renderscript::Element; +using android::renderscript::Type; +using android::renderscript::rs_allocation; +using android::renderscript::rsMax; +using namespace android::renderscript::rsov; + +bool rsovAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { + RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv); + RSoVContext *rsov = hal->mRSoV; + const Type *type = alloc->getType(); + + RSoVAllocation *rsovAlloc = new RSoVAllocation(rsov, type); + alloc->mHal.drv = rsovAlloc; + AllocationBuildPointerTable(rsc, alloc, type, + (uint8_t *)rsovAlloc->getHostPtr()); + return true; +} + +void rsovAllocationDestroy(const Context *rsc, Allocation *alloc) { + RSoVAllocation *rsovAlloc = static_cast<RSoVAllocation *>(alloc->mHal.drv); + delete rsovAlloc; + alloc->mHal.drv = nullptr; +} + +void rsovAllocationData1D(const Context *rsc, const Allocation *alloc, + uint32_t xoff, uint32_t lod, size_t count, + const void *data, size_t sizeBytes) { + const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); + uint8_t *ptr = + GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + size_t size = count * eSize; + if (ptr != data) { + // Skip the copy if we are the same allocation. This can arise from + // our Bitmap optimization, where we share the same storage. + if (alloc->mHal.state.hasReferences) { + alloc->incRefs(data, count); + alloc->decRefs(ptr, count); + } + memcpy(ptr, data, size); + } +} + +void rsovAllocationData2D(const Context *rsc, const Allocation *alloc, + uint32_t xoff, uint32_t yoff, uint32_t lod, + RsAllocationCubemapFace face, uint32_t w, uint32_t h, + const void *data, size_t sizeBytes, size_t stride) { + size_t eSize = alloc->mHal.state.elementSizeBytes; + size_t lineSize = eSize * w; + if (!stride) { + stride = lineSize; + } + + if (alloc->mHal.drvState.lod[0].mallocPtr) { + const uint8_t *src = static_cast<const uint8_t *>(data); + uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); + + for (uint32_t line = yoff; line < (yoff + h); line++) { + if (alloc->mHal.state.hasReferences) { + alloc->incRefs(src, w); + alloc->decRefs(dst, w); + } + memcpy(dst, src, lineSize); + src += stride; + dst += alloc->mHal.drvState.lod[lod].stride; + } + // TODO: handle YUV Allocations + if (alloc->mHal.state.yuv) { + size_t clineSize = lineSize; + int lod = 1; + int maxLod = 2; + if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) { + maxLod = 3; + clineSize >>= 1; + } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) { + lod = 2; + maxLod = 3; + } + + while (lod < maxLod) { + uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); + + for (uint32_t line = (yoff >> 1); line < ((yoff + h) >> 1); line++) { + memcpy(dst, src, clineSize); + // When copying from an array to an Allocation, the src pointer + // to the array should just move by the number of bytes copied. + src += clineSize; + dst += alloc->mHal.drvState.lod[lod].stride; + } + lod++; + } + } + } +} + +void rsovAllocationData3D(const Context *rsc, const Allocation *alloc, + uint32_t xoff, uint32_t yoff, uint32_t zoff, + uint32_t lod, uint32_t w, uint32_t h, uint32_t d, + const void *data, size_t sizeBytes, size_t stride) { + uint32_t eSize = alloc->mHal.state.elementSizeBytes; + uint32_t lineSize = eSize * w; + if (!stride) { + stride = lineSize; + } + + if (alloc->mHal.drvState.lod[0].mallocPtr) { + const uint8_t *src = static_cast<const uint8_t *>(data); + for (uint32_t z = zoff; z < (d + zoff); z++) { + uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod, + RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + for (uint32_t line = yoff; line < (yoff + h); line++) { + if (alloc->mHal.state.hasReferences) { + alloc->incRefs(src, w); + alloc->decRefs(dst, w); + } + memcpy(dst, src, lineSize); + src += stride; + dst += alloc->mHal.drvState.lod[lod].stride; + } + } + } +} + +void rsovAllocationRead1D(const Context *rsc, const Allocation *alloc, + uint32_t xoff, uint32_t lod, size_t count, void *data, + size_t sizeBytes) { + const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); + const uint8_t *ptr = + GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + if (data != ptr) { + // Skip the copy if we are the same allocation. This can arise from + // our Bitmap optimization, where we share the same storage. + memcpy(data, ptr, count * eSize); + } +} + +void rsovAllocationRead2D(const Context *rsc, const Allocation *alloc, + uint32_t xoff, uint32_t yoff, uint32_t lod, + RsAllocationCubemapFace face, uint32_t w, uint32_t h, + void *data, size_t sizeBytes, size_t stride) { + size_t eSize = alloc->mHal.state.elementSizeBytes; + size_t lineSize = eSize * w; + if (!stride) { + stride = lineSize; + } + + if (alloc->mHal.drvState.lod[0].mallocPtr) { + uint8_t *dst = static_cast<uint8_t *>(data); + const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); + if (dst == src) { + // Skip the copy if we are the same allocation. This can arise from + // our Bitmap optimization, where we share the same storage. + return; + } + + for (uint32_t line = yoff; line < (yoff + h); line++) { + memcpy(dst, src, lineSize); + dst += stride; + src += alloc->mHal.drvState.lod[lod].stride; + } + } else { + ALOGE("Add code to readback from non-script memory"); + } +} + +void rsovAllocationRead3D(const Context *rsc, const Allocation *alloc, + uint32_t xoff, uint32_t yoff, uint32_t zoff, + uint32_t lod, uint32_t w, uint32_t h, uint32_t d, + void *data, size_t sizeBytes, size_t stride) { + uint32_t eSize = alloc->mHal.state.elementSizeBytes; + uint32_t lineSize = eSize * w; + if (!stride) { + stride = lineSize; + } + + if (alloc->mHal.drvState.lod[0].mallocPtr) { + uint8_t *dst = static_cast<uint8_t *>(data); + for (uint32_t z = zoff; z < (d + zoff); z++) { + const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod, + RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + if (dst == src) { + // Skip the copy if we are the same allocation. This can arise from + // our Bitmap optimization, where we share the same storage. + return; + } + + for (uint32_t line = yoff; line < (yoff + h); line++) { + memcpy(dst, src, lineSize); + dst += stride; + src += alloc->mHal.drvState.lod[lod].stride; + } + } + } +} + +void *rsovAllocationLock1D(const Context *rsc, const Allocation *alloc) { + return alloc->mHal.drvState.lod[0].mallocPtr; +} + +void rsovAllocationUnlock1D(const Context *rsc, const Allocation *alloc) {} + +void rsovAllocationData1D_alloc(const Context *rsc, const Allocation *dstAlloc, + uint32_t dstXoff, uint32_t dstLod, size_t count, + const Allocation *srcAlloc, uint32_t srcXoff, + uint32_t srcLod) {} + +void rsovAllocationData2D_alloc_script( + const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff, + uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace, + uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff, + uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) { + size_t elementSize = dstAlloc->getType()->getElementSizeBytes(); + for (uint32_t i = 0; i < h; i++) { + uint8_t *dstPtr = + GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace); + uint8_t *srcPtr = + GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace); + memcpy(dstPtr, srcPtr, w * elementSize); + } +} + +void rsovAllocationData3D_alloc_script( + const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff, + uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h, + uint32_t d, const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff, + uint32_t srcZoff, uint32_t srcLod) { + uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); + for (uint32_t j = 0; j < d; j++) { + for (uint32_t i = 0; i < h; i++) { + uint8_t *dstPtr = + GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, dstLod, + RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + uint8_t *srcPtr = + GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, srcLod, + RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + memcpy(dstPtr, srcPtr, w * elementSize); + } + } +} + +void rsovAllocationData2D_alloc( + const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff, + uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace, + uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff, + uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) { + if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { + rsc->setError(RS_ERROR_FATAL_DRIVER, + "Non-script allocation copies not " + "yet implemented."); + return; + } + rsovAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstLod, + dstFace, w, h, srcAlloc, srcXoff, srcYoff, + srcLod, srcFace); +} + +void rsovAllocationData3D_alloc(const Context *rsc, const Allocation *dstAlloc, + uint32_t dstXoff, uint32_t dstYoff, + uint32_t dstZoff, uint32_t dstLod, uint32_t w, + uint32_t h, uint32_t d, + const Allocation *srcAlloc, uint32_t srcXoff, + uint32_t srcYoff, uint32_t srcZoff, + uint32_t srcLod) { + if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { + rsc->setError(RS_ERROR_FATAL_DRIVER, + "Non-script allocation copies not " + "yet implemented."); + return; + } + rsovAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff, + dstLod, w, h, d, srcAlloc, srcXoff, srcYoff, + srcZoff, srcLod); +} + +void rsovAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) { + // Get a base pointer to the new LOD + const Allocation *base = alloc->mHal.state.baseAlloc; + const Type *type = alloc->mHal.state.type; + if (base == nullptr) { + return; + } + + const int lodBias = alloc->mHal.state.originLOD; + uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1); + for (uint32_t lod = 0; lod < lodCount; lod++) { + alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias]; + alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr( + alloc, alloc->mHal.state.originX, alloc->mHal.state.originY, + alloc->mHal.state.originZ, lodBias, + (RsAllocationCubemapFace)alloc->mHal.state.originFace); + } +} + +bool rsovAllocationAdapterInit(const Context *rsc, Allocation *alloc) { +// TODO: may need a RSoV Allocation here +#if 0 + DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); + if (!drv) { + return false; + } + alloc->mHal.drv = drv; +#endif + // We need to build an allocation that looks like a subset of the parent + // allocation + rsovAllocationAdapterOffset(rsc, alloc); + + return true; +} + +void rsovAllocationSyncAll(const Context *rsc, const Allocation *alloc, + RsAllocationUsageType src) { + // TODO: anything to do here? +} + +void rsovAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { + // TODO: anything to do here? +} + +void rsovAllocationResize(const Context *rsc, const Allocation *alloc, + const Type *newType, bool zeroNew) { + // TODO: implement this + // can this be done without copying, if the new size is greater than the + // original? +} + +void rsovAllocationGenerateMipmaps(const Context *rsc, + const Allocation *alloc) { + if (!alloc->mHal.drvState.lod[0].mallocPtr) { + return; + } + uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; + for (uint32_t face = 0; face < numFaces; face++) { + for (uint32_t lod = 0; lod < (alloc->getType()->getLODCount() - 1); lod++) { + switch (alloc->getType()->getElement()->getSizeBits()) { + case 32: + mip8888(alloc, lod, (RsAllocationCubemapFace)face); + break; + case 16: + mip565(alloc, lod, (RsAllocationCubemapFace)face); + break; + case 8: + mip8(alloc, lod, (RsAllocationCubemapFace)face); + break; + } + } + } +} + +uint32_t rsovAllocationGrallocBits(const Context *rsc, Allocation *alloc) { + return 0; +} + +void rsovAllocationUpdateCachedObject(const Context *rsc, + const Allocation *alloc, + rs_allocation *obj) { + obj->p = alloc; +#ifdef __LP64__ + if (alloc != nullptr) { + obj->r = alloc->mHal.drvState.lod[0].mallocPtr; + obj->v1 = alloc->mHal.drv; + obj->v2 = (void *)alloc->mHal.drvState.lod[0].stride; + } else { + obj->r = nullptr; + obj->v1 = nullptr; + obj->v2 = nullptr; + } +#endif +} + +void rsovAllocationSetSurface(const Context *rsc, Allocation *alloc, + ANativeWindow *nw) { + // TODO: implement this +} + +void rsovAllocationIoSend(const Context *rsc, Allocation *alloc) { + // TODO: implement this +} + +void rsovAllocationIoReceive(const Context *rsc, Allocation *alloc) { + // TODO: implement this +} + +void rsovAllocationElementData(const Context *rsc, const Allocation *alloc, + uint32_t x, uint32_t y, uint32_t z, + const void *data, uint32_t cIdx, + size_t sizeBytes) { + uint8_t *ptr = + GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + + const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx); + ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); + + if (alloc->mHal.state.hasReferences) { + e->incRefs(data); + e->decRefs(ptr); + } + + memcpy(ptr, data, sizeBytes); +} + +void rsovAllocationElementRead(const Context *rsc, const Allocation *alloc, + uint32_t x, uint32_t y, uint32_t z, void *data, + uint32_t cIdx, size_t sizeBytes) { + uint8_t *ptr = + GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + + const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx); + ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); + + memcpy(data, ptr, sizeBytes); +} |