rsovAllocation.cpp revision 30dfb1368d0a3440cfedc882c27cc236d799f77c
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 <map> 20 21#include "rsAllocation.h" 22#include "rsContext.h" 23#include "rsCppUtils.h" 24#include "rsElement.h" 25#include "rsType.h" 26#include "rsovContext.h" 27#include "rsovCore.h" 28 29namespace android { 30namespace renderscript { 31namespace rsov { 32 33namespace { 34 35using std::make_pair; 36 37// TODO: handle 8-bit, 16-bit, and 64-bit integers and floating point numbers 38const std::map<std::pair<RsDataType, uint32_t>, VkFormat> mapElementToFormat{ 39 make_pair(make_pair(RS_TYPE_FLOAT_32, 1), VK_FORMAT_R32_SFLOAT), 40 make_pair(make_pair(RS_TYPE_FLOAT_32, 2), VK_FORMAT_R32G32_SFLOAT), 41 make_pair(make_pair(RS_TYPE_FLOAT_32, 3), VK_FORMAT_R32G32B32_SFLOAT), 42 make_pair(make_pair(RS_TYPE_FLOAT_32, 4), VK_FORMAT_R32G32B32A32_SFLOAT), 43 44 make_pair(make_pair(RS_TYPE_SIGNED_32, 1), VK_FORMAT_R32_SINT), 45 make_pair(make_pair(RS_TYPE_SIGNED_32, 2), VK_FORMAT_R32G32_SINT), 46 make_pair(make_pair(RS_TYPE_SIGNED_32, 3), VK_FORMAT_R32G32B32_SINT), 47 make_pair(make_pair(RS_TYPE_SIGNED_32, 4), VK_FORMAT_R32G32B32A32_SINT), 48 49 make_pair(make_pair(RS_TYPE_UNSIGNED_32, 1), VK_FORMAT_R32_UINT), 50 make_pair(make_pair(RS_TYPE_UNSIGNED_32, 2), VK_FORMAT_R32G32_UINT), 51 make_pair(make_pair(RS_TYPE_UNSIGNED_32, 3), VK_FORMAT_R32G32B32_UINT), 52 make_pair(make_pair(RS_TYPE_UNSIGNED_32, 4), VK_FORMAT_R32G32B32A32_UINT), 53}; 54 55VkFormat VkFormatFromRSElement(const Element &elem) { 56 // TODO: reject struct, allocation, and other non-numeric element 57 rsAssert(!elem.getFieldCount()); 58 59 RsDataType dataType = elem.getType(); 60 uint32_t vectorWidth = elem.getVectorSize(); 61 62 auto it = mapElementToFormat.find(make_pair(dataType, vectorWidth)); 63 if (it != mapElementToFormat.end()) { 64 return it->second; 65 } 66 67 rsAssert(0 && "Unexpected RS Element to map to VkFormat"); 68 69 return VK_FORMAT_R32G32B32A32_SFLOAT; 70} 71 72size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) { 73 // For the flexible YCbCr format, layout is initialized during call to 74 // Allocation::ioReceive. Return early and avoid clobberring any 75 // pre-existing layout. 76 if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) { 77 return 0; 78 } 79 80 // YUV only supports basic 2d 81 // so we can stash the plane pointers in the mipmap levels. 82 size_t uvSize = 0; 83 state->lod[1].dimX = state->lod[0].dimX / 2; 84 state->lod[1].dimY = state->lod[0].dimY / 2; 85 state->lod[2].dimX = state->lod[0].dimX / 2; 86 state->lod[2].dimY = state->lod[0].dimY / 2; 87 state->yuv.shift = 1; 88 state->yuv.step = 1; 89 state->lodCount = 3; 90 91 switch (yuv) { 92 case HAL_PIXEL_FORMAT_YV12: 93 state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16); 94 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + 95 (state->lod[0].stride * state->lod[0].dimY); 96 uvSize += state->lod[2].stride * state->lod[2].dimY; 97 98 state->lod[1].stride = state->lod[2].stride; 99 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 100 (state->lod[2].stride * state->lod[2].dimY); 101 uvSize += state->lod[1].stride * state->lod[2].dimY; 102 break; 103 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 104 // state->lod[1].dimX = state->lod[0].dimX; 105 state->lod[1].stride = state->lod[0].stride; 106 state->lod[2].stride = state->lod[0].stride; 107 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + 108 (state->lod[0].stride * state->lod[0].dimY); 109 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1; 110 uvSize += state->lod[1].stride * state->lod[1].dimY; 111 state->yuv.step = 2; 112 break; 113 default: 114 rsAssert(0); 115 } 116 117 return uvSize; 118} 119 120// TODO: Dedup this with the same code under frameworks/rs/driver 121size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, 122 const Type *type, uint8_t *ptr, 123 size_t requiredAlignment) { 124 alloc->mHal.drvState.lod[0].dimX = type->getDimX(); 125 alloc->mHal.drvState.lod[0].dimY = type->getDimY(); 126 alloc->mHal.drvState.lod[0].dimZ = type->getDimZ(); 127 alloc->mHal.drvState.lod[0].mallocPtr = 0; 128 // Stride needs to be aligned to a boundary defined by requiredAlignment! 129 size_t stride = 130 alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes(); 131 alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment); 132 alloc->mHal.drvState.lodCount = type->getLODCount(); 133 alloc->mHal.drvState.faceCount = type->getDimFaces(); 134 135 size_t offsets[Allocation::MAX_LOD]; 136 memset(offsets, 0, sizeof(offsets)); 137 138 size_t o = alloc->mHal.drvState.lod[0].stride * 139 rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) * 140 rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u); 141 if (alloc->mHal.state.yuv) { 142 o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState); 143 144 for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) { 145 offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr; 146 } 147 } else if (alloc->mHal.drvState.lodCount > 1) { 148 uint32_t tx = alloc->mHal.drvState.lod[0].dimX; 149 uint32_t ty = alloc->mHal.drvState.lod[0].dimY; 150 uint32_t tz = alloc->mHal.drvState.lod[0].dimZ; 151 for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) { 152 alloc->mHal.drvState.lod[lod].dimX = tx; 153 alloc->mHal.drvState.lod[lod].dimY = ty; 154 alloc->mHal.drvState.lod[lod].dimZ = tz; 155 alloc->mHal.drvState.lod[lod].stride = 156 rsRound(tx * type->getElementSizeBytes(), requiredAlignment); 157 offsets[lod] = o; 158 o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u); 159 if (tx > 1) tx >>= 1; 160 if (ty > 1) ty >>= 1; 161 if (tz > 1) tz >>= 1; 162 } 163 } 164 165 alloc->mHal.drvState.faceOffset = o; 166 167 alloc->mHal.drvState.lod[0].mallocPtr = ptr; 168 for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) { 169 alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod]; 170 } 171 172 size_t allocSize = alloc->mHal.drvState.faceOffset; 173 if (alloc->mHal.drvState.faceCount) { 174 allocSize *= 6; 175 } 176 177 return allocSize; 178} 179 180size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, 181 const Type *type, uint8_t *ptr) { 182 return AllocationBuildPointerTable(rsc, alloc, type, ptr, 183 Allocation::kMinimumRSAlignment); 184} 185 186uint8_t *GetOffsetPtr(const Allocation *alloc, uint32_t xoff, uint32_t yoff, 187 uint32_t zoff, uint32_t lod, 188 RsAllocationCubemapFace face) { 189 uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 190 ptr += face * alloc->mHal.drvState.faceOffset; 191 ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * 192 alloc->mHal.drvState.lod[lod].stride; 193 ptr += yoff * alloc->mHal.drvState.lod[lod].stride; 194 ptr += xoff * alloc->mHal.state.elementSizeBytes; 195 return ptr; 196} 197 198void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 199 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 200 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 201 202 for (uint32_t y = 0; y < h; y++) { 203 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 204 const uint16_t *i1 = 205 (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2, lod, face); 206 const uint16_t *i2 = 207 (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2 + 1, lod, face); 208 209 for (uint32_t x = 0; x < w; x++) { 210 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 211 oPtr++; 212 i1 += 2; 213 i2 += 2; 214 } 215 } 216} 217 218void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 219 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 220 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 221 222 for (uint32_t y = 0; y < h; y++) { 223 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 224 const uint32_t *i1 = 225 (uint32_t *)GetOffsetPtr(alloc, 0, y * 2, 0, lod, face); 226 const uint32_t *i2 = 227 (uint32_t *)GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face); 228 229 for (uint32_t x = 0; x < w; x++) { 230 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 231 oPtr++; 232 i1 += 2; 233 i2 += 2; 234 } 235 } 236} 237 238void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 239 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 240 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 241 242 for (uint32_t y = 0; y < h; y++) { 243 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 244 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y * 2, 0, lod, face); 245 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face); 246 247 for (uint32_t x = 0; x < w; x++) { 248 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 249 oPtr++; 250 i1 += 2; 251 i2 += 2; 252 } 253 } 254} 255 256} // anonymous namespace 257 258RSoVAllocation::RSoVAllocation(RSoVContext *context, const Type *type, 259 size_t size) 260 : mRSoV(context), 261 mDevice(context->getDevice()), 262 mType(type), 263 mWidth(type->getDimX()), 264 mHeight(type->getDimY()), 265 mDepth(type->getDimZ()) { 266 InitBuffer(size); 267} 268 269RSoVAllocation::~RSoVAllocation() { 270 vkDestroyBuffer(mDevice, mBuf, nullptr); 271 vkFreeMemory(mDevice, mMem, nullptr); 272} 273 274void RSoVAllocation::InitBuffer(size_t bufferSize) { 275 VkResult res; 276 277 VkBufferCreateInfo buf_info = { 278 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 279 .pNext = nullptr, 280 .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 281 .size = bufferSize, 282 .queueFamilyIndexCount = 0, 283 .pQueueFamilyIndices = nullptr, 284 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 285 .flags = 0, 286 }; 287 res = vkCreateBuffer(mDevice, &buf_info, nullptr, &mBuf); 288 rsAssert(res == VK_SUCCESS); 289 290 VkMemoryRequirements mem_reqs; 291 vkGetBufferMemoryRequirements(mDevice, mBuf, &mem_reqs); 292 293 VkMemoryAllocateInfo allocateInfo = { 294 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 295 .pNext = nullptr, 296 .memoryTypeIndex = 0, 297 .allocationSize = mem_reqs.size, 298 }; 299 300 bool pass; 301 pass = mRSoV->MemoryTypeFromProperties( 302 mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 303 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 304 &allocateInfo.memoryTypeIndex); 305 ALOGV("TypeBits = 0x%08X", mem_reqs.memoryTypeBits); 306 rsAssert(pass); 307 308 // TODO: Make this aligned 309 res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem); 310 rsAssert(res == VK_SUCCESS); 311 312 res = vkBindBufferMemory(mDevice, mBuf, mMem, 0); 313 rsAssert(res == VK_SUCCESS); 314 315 mBufferInfo.buffer = mBuf; 316 mBufferInfo.offset = 0; 317 mBufferInfo.range = bufferSize; 318 319 res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr); 320 rsAssert(res == VK_SUCCESS); 321} 322 323void RSoVAllocation::InitImage() { 324 VkResult res; 325 326 mFormat = VkFormatFromRSElement(*mType->getElement()); 327 328 const uint32_t width = mWidth; 329 const uint32_t height = mHeight; 330 const uint32_t depth = mDepth; 331 332 VkImageType imageType = 333 depth > 0 ? VK_IMAGE_TYPE_3D 334 : (height > 0 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D); 335 336 VkImageCreateInfo createInfo = { 337 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 338 .pNext = nullptr, 339 .flags = 0, 340 .imageType = imageType, 341 .format = mFormat, 342 .extent = {width, rsMax(height, 1U), rsMax(depth, 1U)}, 343 .mipLevels = 1, 344 .arrayLayers = 1, 345 .samples = VK_SAMPLE_COUNT_1_BIT, 346 .tiling = VK_IMAGE_TILING_LINEAR, 347 .usage = VK_IMAGE_USAGE_STORAGE_BIT, 348 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 349 .queueFamilyIndexCount = 0, 350 .pQueueFamilyIndices = nullptr, 351 .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED, 352 }; 353 354 res = vkCreateImage(mDevice, &createInfo, nullptr, &mImage); 355 rsAssert(res == VK_SUCCESS); 356 357 VkMemoryRequirements mem_reqs; 358 vkGetImageMemoryRequirements(mDevice, mImage, &mem_reqs); 359 360 ALOGI("size of memory needed = %u", (uint)mem_reqs.size); 361 362 VkMemoryAllocateInfo allocateInfo = { 363 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 364 .pNext = nullptr, 365 .allocationSize = mem_reqs.size, 366 }; 367 368 /* Use the memory properties to determine the type of memory required */ 369 bool pass; 370 pass = mRSoV->MemoryTypeFromProperties( 371 mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 372 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 373 &allocateInfo.memoryTypeIndex); 374 ALOGI("TypeBits = 0x%08X", mem_reqs.memoryTypeBits); 375 rsAssert(pass); 376 377 // TODO: Make this aligned 378 res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem); 379 rsAssert(res == VK_SUCCESS); 380 381 res = vkBindImageMemory(mDevice, mImage, mMem, 0); 382 rsAssert(res == VK_SUCCESS); 383 384 VkImageViewType viewType = 385 depth > 0 ? VK_IMAGE_VIEW_TYPE_3D 386 : (height > 0 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D); 387 388 VkImageViewCreateInfo view_info = { 389 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 390 .pNext = nullptr, 391 .image = mImage, 392 .viewType = viewType, 393 .format = mFormat, 394 .components = 395 { 396 .r = VK_COMPONENT_SWIZZLE_IDENTITY, 397 .g = VK_COMPONENT_SWIZZLE_IDENTITY, 398 .b = VK_COMPONENT_SWIZZLE_IDENTITY, 399 .a = VK_COMPONENT_SWIZZLE_IDENTITY, 400 }, 401 .subresourceRange = 402 { 403 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 404 .baseMipLevel = 0, 405 .levelCount = 1, 406 .baseArrayLayer = 0, 407 .layerCount = 1, 408 }, 409 }; 410 411 res = vkCreateImageView(mDevice, &view_info, nullptr, &mImageView); 412 rsAssert(res == VK_SUCCESS); 413 414 mImageLayout = VK_IMAGE_LAYOUT_GENERAL; 415 416 mImageInfo = { 417 .imageView = mImageView, .imageLayout = mImageLayout, 418 }; 419 420 res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr); 421 rsAssert(res == VK_SUCCESS); 422} 423 424} // namespace rsov 425} // namespace renderscript 426} // namespace android 427 428using android::renderscript::Allocation; 429using android::renderscript::Context; 430using android::renderscript::Element; 431using android::renderscript::Type; 432using android::renderscript::rs_allocation; 433using android::renderscript::rsMax; 434using namespace android::renderscript::rsov; 435 436bool rsovAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { 437 RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv); 438 RSoVContext *rsov = hal->mRSoV; 439 const Type *type = alloc->getType(); 440 441 // Calculate the object size. 442 size_t allocSize = AllocationBuildPointerTable(rsc, alloc, type, nullptr); 443 RSoVAllocation *rsovAlloc = new RSoVAllocation(rsov, type, allocSize); 444 alloc->mHal.drv = rsovAlloc; 445 AllocationBuildPointerTable(rsc, alloc, type, 446 (uint8_t *)rsovAlloc->getHostPtr()); 447 return true; 448} 449 450void rsovAllocationDestroy(const Context *rsc, Allocation *alloc) { 451 RSoVAllocation *rsovAlloc = static_cast<RSoVAllocation *>(alloc->mHal.drv); 452 delete rsovAlloc; 453 alloc->mHal.drv = nullptr; 454} 455 456void rsovAllocationData1D(const Context *rsc, const Allocation *alloc, 457 uint32_t xoff, uint32_t lod, size_t count, 458 const void *data, size_t sizeBytes) { 459 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 460 uint8_t *ptr = 461 GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 462 size_t size = count * eSize; 463 if (ptr != data) { 464 // Skip the copy if we are the same allocation. This can arise from 465 // our Bitmap optimization, where we share the same storage. 466 if (alloc->mHal.state.hasReferences) { 467 alloc->incRefs(data, count); 468 alloc->decRefs(ptr, count); 469 } 470 memcpy(ptr, data, size); 471 } 472} 473 474void rsovAllocationData2D(const Context *rsc, const Allocation *alloc, 475 uint32_t xoff, uint32_t yoff, uint32_t lod, 476 RsAllocationCubemapFace face, uint32_t w, uint32_t h, 477 const void *data, size_t sizeBytes, size_t stride) { 478 size_t eSize = alloc->mHal.state.elementSizeBytes; 479 size_t lineSize = eSize * w; 480 if (!stride) { 481 stride = lineSize; 482 } 483 484 if (alloc->mHal.drvState.lod[0].mallocPtr) { 485 const uint8_t *src = static_cast<const uint8_t *>(data); 486 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 487 488 for (uint32_t line = yoff; line < (yoff + h); line++) { 489 if (alloc->mHal.state.hasReferences) { 490 alloc->incRefs(src, w); 491 alloc->decRefs(dst, w); 492 } 493 memcpy(dst, src, lineSize); 494 src += stride; 495 dst += alloc->mHal.drvState.lod[lod].stride; 496 } 497 // TODO: handle YUV Allocations 498 if (alloc->mHal.state.yuv) { 499 size_t clineSize = lineSize; 500 int lod = 1; 501 int maxLod = 2; 502 if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) { 503 maxLod = 3; 504 clineSize >>= 1; 505 } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) { 506 lod = 2; 507 maxLod = 3; 508 } 509 510 while (lod < maxLod) { 511 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 512 513 for (uint32_t line = (yoff >> 1); line < ((yoff + h) >> 1); line++) { 514 memcpy(dst, src, clineSize); 515 // When copying from an array to an Allocation, the src pointer 516 // to the array should just move by the number of bytes copied. 517 src += clineSize; 518 dst += alloc->mHal.drvState.lod[lod].stride; 519 } 520 lod++; 521 } 522 } 523 } 524} 525 526void rsovAllocationData3D(const Context *rsc, const Allocation *alloc, 527 uint32_t xoff, uint32_t yoff, uint32_t zoff, 528 uint32_t lod, uint32_t w, uint32_t h, uint32_t d, 529 const void *data, size_t sizeBytes, size_t stride) { 530 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 531 uint32_t lineSize = eSize * w; 532 if (!stride) { 533 stride = lineSize; 534 } 535 536 if (alloc->mHal.drvState.lod[0].mallocPtr) { 537 const uint8_t *src = static_cast<const uint8_t *>(data); 538 for (uint32_t z = zoff; z < (d + zoff); z++) { 539 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod, 540 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 541 for (uint32_t line = yoff; line < (yoff + h); line++) { 542 if (alloc->mHal.state.hasReferences) { 543 alloc->incRefs(src, w); 544 alloc->decRefs(dst, w); 545 } 546 memcpy(dst, src, lineSize); 547 src += stride; 548 dst += alloc->mHal.drvState.lod[lod].stride; 549 } 550 } 551 } 552} 553 554void rsovAllocationRead1D(const Context *rsc, const Allocation *alloc, 555 uint32_t xoff, uint32_t lod, size_t count, void *data, 556 size_t sizeBytes) { 557 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 558 const uint8_t *ptr = 559 GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 560 if (data != ptr) { 561 // Skip the copy if we are the same allocation. This can arise from 562 // our Bitmap optimization, where we share the same storage. 563 memcpy(data, ptr, count * eSize); 564 } 565} 566 567void rsovAllocationRead2D(const Context *rsc, const Allocation *alloc, 568 uint32_t xoff, uint32_t yoff, uint32_t lod, 569 RsAllocationCubemapFace face, uint32_t w, uint32_t h, 570 void *data, size_t sizeBytes, size_t stride) { 571 size_t eSize = alloc->mHal.state.elementSizeBytes; 572 size_t lineSize = eSize * w; 573 if (!stride) { 574 stride = lineSize; 575 } 576 577 if (alloc->mHal.drvState.lod[0].mallocPtr) { 578 uint8_t *dst = static_cast<uint8_t *>(data); 579 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 580 if (dst == src) { 581 // Skip the copy if we are the same allocation. This can arise from 582 // our Bitmap optimization, where we share the same storage. 583 return; 584 } 585 586 for (uint32_t line = yoff; line < (yoff + h); line++) { 587 memcpy(dst, src, lineSize); 588 dst += stride; 589 src += alloc->mHal.drvState.lod[lod].stride; 590 } 591 } else { 592 ALOGE("Add code to readback from non-script memory"); 593 } 594} 595 596void rsovAllocationRead3D(const Context *rsc, const Allocation *alloc, 597 uint32_t xoff, uint32_t yoff, uint32_t zoff, 598 uint32_t lod, uint32_t w, uint32_t h, uint32_t d, 599 void *data, size_t sizeBytes, size_t stride) { 600 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 601 uint32_t lineSize = eSize * w; 602 if (!stride) { 603 stride = lineSize; 604 } 605 606 if (alloc->mHal.drvState.lod[0].mallocPtr) { 607 uint8_t *dst = static_cast<uint8_t *>(data); 608 for (uint32_t z = zoff; z < (d + zoff); z++) { 609 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod, 610 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 611 if (dst == src) { 612 // Skip the copy if we are the same allocation. This can arise from 613 // our Bitmap optimization, where we share the same storage. 614 return; 615 } 616 617 for (uint32_t line = yoff; line < (yoff + h); line++) { 618 memcpy(dst, src, lineSize); 619 dst += stride; 620 src += alloc->mHal.drvState.lod[lod].stride; 621 } 622 } 623 } 624} 625 626void *rsovAllocationLock1D(const Context *rsc, const Allocation *alloc) { 627 return alloc->mHal.drvState.lod[0].mallocPtr; 628} 629 630void rsovAllocationUnlock1D(const Context *rsc, const Allocation *alloc) {} 631 632void rsovAllocationData1D_alloc(const Context *rsc, const Allocation *dstAlloc, 633 uint32_t dstXoff, uint32_t dstLod, size_t count, 634 const Allocation *srcAlloc, uint32_t srcXoff, 635 uint32_t srcLod) {} 636 637void rsovAllocationData2D_alloc_script( 638 const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff, 639 uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace, 640 uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff, 641 uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) { 642 size_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 643 for (uint32_t i = 0; i < h; i++) { 644 uint8_t *dstPtr = 645 GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace); 646 uint8_t *srcPtr = 647 GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace); 648 memcpy(dstPtr, srcPtr, w * elementSize); 649 } 650} 651 652void rsovAllocationData3D_alloc_script( 653 const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff, 654 uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h, 655 uint32_t d, const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff, 656 uint32_t srcZoff, uint32_t srcLod) { 657 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 658 for (uint32_t j = 0; j < d; j++) { 659 for (uint32_t i = 0; i < h; i++) { 660 uint8_t *dstPtr = 661 GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, dstLod, 662 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 663 uint8_t *srcPtr = 664 GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, srcLod, 665 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 666 memcpy(dstPtr, srcPtr, w * elementSize); 667 } 668 } 669} 670 671void rsovAllocationData2D_alloc( 672 const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff, 673 uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace, 674 uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff, 675 uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) { 676 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 677 rsc->setError(RS_ERROR_FATAL_DRIVER, 678 "Non-script allocation copies not " 679 "yet implemented."); 680 return; 681 } 682 rsovAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstLod, 683 dstFace, w, h, srcAlloc, srcXoff, srcYoff, 684 srcLod, srcFace); 685} 686 687void rsovAllocationData3D_alloc(const Context *rsc, const Allocation *dstAlloc, 688 uint32_t dstXoff, uint32_t dstYoff, 689 uint32_t dstZoff, uint32_t dstLod, uint32_t w, 690 uint32_t h, uint32_t d, 691 const Allocation *srcAlloc, uint32_t srcXoff, 692 uint32_t srcYoff, uint32_t srcZoff, 693 uint32_t srcLod) { 694 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 695 rsc->setError(RS_ERROR_FATAL_DRIVER, 696 "Non-script allocation copies not " 697 "yet implemented."); 698 return; 699 } 700 rsovAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff, 701 dstLod, w, h, d, srcAlloc, srcXoff, srcYoff, 702 srcZoff, srcLod); 703} 704 705void rsovAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) { 706 // Get a base pointer to the new LOD 707 const Allocation *base = alloc->mHal.state.baseAlloc; 708 const Type *type = alloc->mHal.state.type; 709 if (base == nullptr) { 710 return; 711 } 712 713 const int lodBias = alloc->mHal.state.originLOD; 714 uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1); 715 for (uint32_t lod = 0; lod < lodCount; lod++) { 716 alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias]; 717 alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr( 718 alloc, alloc->mHal.state.originX, alloc->mHal.state.originY, 719 alloc->mHal.state.originZ, lodBias, 720 (RsAllocationCubemapFace)alloc->mHal.state.originFace); 721 } 722} 723 724bool rsovAllocationAdapterInit(const Context *rsc, Allocation *alloc) { 725// TODO: may need a RSoV Allocation here 726#if 0 727 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 728 if (!drv) { 729 return false; 730 } 731 alloc->mHal.drv = drv; 732#endif 733 // We need to build an allocation that looks like a subset of the parent 734 // allocation 735 rsovAllocationAdapterOffset(rsc, alloc); 736 737 return true; 738} 739 740void rsovAllocationSyncAll(const Context *rsc, const Allocation *alloc, 741 RsAllocationUsageType src) { 742 // TODO: anything to do here? 743} 744 745void rsovAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 746 // TODO: anything to do here? 747} 748 749void rsovAllocationResize(const Context *rsc, const Allocation *alloc, 750 const Type *newType, bool zeroNew) { 751 // TODO: implement this 752 // can this be done without copying, if the new size is greater than the 753 // original? 754} 755 756void rsovAllocationGenerateMipmaps(const Context *rsc, 757 const Allocation *alloc) { 758 if (!alloc->mHal.drvState.lod[0].mallocPtr) { 759 return; 760 } 761 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; 762 for (uint32_t face = 0; face < numFaces; face++) { 763 for (uint32_t lod = 0; lod < (alloc->getType()->getLODCount() - 1); lod++) { 764 switch (alloc->getType()->getElement()->getSizeBits()) { 765 case 32: 766 mip8888(alloc, lod, (RsAllocationCubemapFace)face); 767 break; 768 case 16: 769 mip565(alloc, lod, (RsAllocationCubemapFace)face); 770 break; 771 case 8: 772 mip8(alloc, lod, (RsAllocationCubemapFace)face); 773 break; 774 } 775 } 776 } 777} 778 779uint32_t rsovAllocationGrallocBits(const Context *rsc, Allocation *alloc) { 780 return 0; 781} 782 783void rsovAllocationUpdateCachedObject(const Context *rsc, 784 const Allocation *alloc, 785 rs_allocation *obj) { 786 obj->p = alloc; 787#ifdef __LP64__ 788 if (alloc != nullptr) { 789 obj->r = alloc->mHal.drvState.lod[0].mallocPtr; 790 obj->v1 = alloc->mHal.drv; 791 obj->v2 = (void *)alloc->mHal.drvState.lod[0].stride; 792 } else { 793 obj->r = nullptr; 794 obj->v1 = nullptr; 795 obj->v2 = nullptr; 796 } 797#endif 798} 799 800void rsovAllocationSetSurface(const Context *rsc, Allocation *alloc, 801 ANativeWindow *nw) { 802 // TODO: implement this 803} 804 805void rsovAllocationIoSend(const Context *rsc, Allocation *alloc) { 806 // TODO: implement this 807} 808 809void rsovAllocationIoReceive(const Context *rsc, Allocation *alloc) { 810 // TODO: implement this 811} 812 813void rsovAllocationElementData(const Context *rsc, const Allocation *alloc, 814 uint32_t x, uint32_t y, uint32_t z, 815 const void *data, uint32_t cIdx, 816 size_t sizeBytes) { 817 uint8_t *ptr = 818 GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 819 820 const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx); 821 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 822 823 if (alloc->mHal.state.hasReferences) { 824 e->incRefs(data); 825 e->decRefs(ptr); 826 } 827 828 memcpy(ptr, data, sizeBytes); 829} 830 831void rsovAllocationElementRead(const Context *rsc, const Allocation *alloc, 832 uint32_t x, uint32_t y, uint32_t z, void *data, 833 uint32_t cIdx, size_t sizeBytes) { 834 uint8_t *ptr = 835 GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 836 837 const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx); 838 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 839 840 memcpy(data, ptr, sizeBytes); 841} 842