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