1 /* 2 * Copyright (C) 2013 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 "rsdAllocation.h" 18 #include "rsdCore.h" 19 20 #include <android/native_window.h> 21 22 #ifdef RS_COMPATIBILITY_LIB 23 #include "rsCompatibilityLib.h" 24 #else 25 #include "rsdFrameBufferObj.h" 26 #include <vndk/window.h> 27 28 #include <GLES/gl.h> 29 #include <GLES2/gl2.h> 30 #include <GLES/glext.h> 31 #endif 32 33 #include <unistd.h> // for close() 34 35 using android::renderscript::Allocation; 36 using android::renderscript::Context; 37 using android::renderscript::Element; 38 using android::renderscript::Type; 39 using android::renderscript::rs_allocation; 40 using android::renderscript::rsBoxFilter565; 41 using android::renderscript::rsBoxFilter8888; 42 using android::renderscript::rsMax; 43 using android::renderscript::rsRound; 44 45 #ifndef RS_COMPATIBILITY_LIB 46 const static GLenum gFaceOrder[] = { 47 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 48 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 49 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 50 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 51 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 52 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 53 }; 54 55 GLenum rsdTypeToGLType(RsDataType t) { 56 switch (t) { 57 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5; 58 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1; 59 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4; 60 61 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT; 62 case RS_TYPE_FLOAT_32: return GL_FLOAT; 63 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE; 64 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT; 65 case RS_TYPE_SIGNED_8: return GL_BYTE; 66 case RS_TYPE_SIGNED_16: return GL_SHORT; 67 default: break; 68 } 69 return 0; 70 } 71 72 GLenum rsdKindToGLFormat(RsDataKind k) { 73 switch (k) { 74 case RS_KIND_PIXEL_L: return GL_LUMINANCE; 75 case RS_KIND_PIXEL_A: return GL_ALPHA; 76 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA; 77 case RS_KIND_PIXEL_RGB: return GL_RGB; 78 case RS_KIND_PIXEL_RGBA: return GL_RGBA; 79 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16; 80 default: break; 81 } 82 return 0; 83 } 84 #endif 85 86 uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc, 87 uint32_t xoff, uint32_t yoff, uint32_t zoff, 88 uint32_t lod, RsAllocationCubemapFace face) { 89 uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 90 ptr += face * alloc->mHal.drvState.faceOffset; 91 ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * alloc->mHal.drvState.lod[lod].stride; 92 ptr += yoff * alloc->mHal.drvState.lod[lod].stride; 93 ptr += xoff * alloc->mHal.state.elementSizeBytes; 94 return ptr; 95 } 96 97 98 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr, 99 uint32_t xoff, uint32_t yoff, uint32_t lod, 100 RsAllocationCubemapFace face, uint32_t w, uint32_t h) { 101 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 102 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 103 104 rsAssert(drv->textureID); 105 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID); 106 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1); 107 GLenum t = GL_TEXTURE_2D; 108 if (alloc->mHal.state.hasFaces) { 109 t = gFaceOrder[face]; 110 } 111 RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr); 112 #endif 113 } 114 115 116 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 117 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) { 118 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 119 120 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID); 121 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1); 122 123 uint32_t faceCount = 1; 124 if (alloc->mHal.state.hasFaces) { 125 faceCount = 6; 126 } 127 128 rsdGLCheckError(rsc, "Upload2DTexture 1 "); 129 for (uint32_t face = 0; face < faceCount; face ++) { 130 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) { 131 const uint8_t *p = GetOffsetPtr(alloc, 0, 0, 0, lod, (RsAllocationCubemapFace)face); 132 133 GLenum t = GL_TEXTURE_2D; 134 if (alloc->mHal.state.hasFaces) { 135 t = gFaceOrder[face]; 136 } 137 138 if (isFirstUpload) { 139 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat, 140 alloc->mHal.state.type->getLODDimX(lod), 141 alloc->mHal.state.type->getLODDimY(lod), 142 0, drv->glFormat, drv->glType, p); 143 } else { 144 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0, 145 alloc->mHal.state.type->getLODDimX(lod), 146 alloc->mHal.state.type->getLODDimY(lod), 147 drv->glFormat, drv->glType, p); 148 } 149 } 150 } 151 152 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) { 153 RSD_CALL_GL(glGenerateMipmap, drv->glTarget); 154 } 155 rsdGLCheckError(rsc, "Upload2DTexture"); 156 } 157 #endif 158 159 static void UploadToTexture(const Context *rsc, const Allocation *alloc) { 160 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 161 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 162 163 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) { 164 if (!drv->textureID) { 165 RSD_CALL_GL(glGenTextures, 1, &drv->textureID); 166 } 167 return; 168 } 169 170 if (!drv->glType || !drv->glFormat) { 171 return; 172 } 173 174 if (!alloc->mHal.drvState.lod[0].mallocPtr) { 175 return; 176 } 177 178 bool isFirstUpload = false; 179 180 if (!drv->textureID) { 181 RSD_CALL_GL(glGenTextures, 1, &drv->textureID); 182 isFirstUpload = true; 183 } 184 185 Upload2DTexture(rsc, alloc, isFirstUpload); 186 187 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { 188 if (alloc->mHal.drvState.lod[0].mallocPtr) { 189 free(alloc->mHal.drvState.lod[0].mallocPtr); 190 alloc->mHal.drvState.lod[0].mallocPtr = nullptr; 191 } 192 } 193 rsdGLCheckError(rsc, "UploadToTexture"); 194 #endif 195 } 196 197 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) { 198 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 199 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 200 201 if (!drv->glFormat) { 202 return; 203 } 204 205 if (!drv->renderTargetID) { 206 RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID); 207 208 if (!drv->renderTargetID) { 209 // This should generally not happen 210 ALOGE("allocateRenderTarget failed to gen mRenderTargetID"); 211 rsc->dumpDebug(); 212 return; 213 } 214 RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID); 215 RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat, 216 alloc->mHal.drvState.lod[0].dimX, alloc->mHal.drvState.lod[0].dimY); 217 } 218 rsdGLCheckError(rsc, "AllocateRenderTarget"); 219 #endif 220 } 221 222 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) { 223 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 224 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 225 226 rsAssert(!alloc->mHal.state.type->getDimY()); 227 rsAssert(!alloc->mHal.state.type->getDimZ()); 228 229 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; 230 231 if (!drv->bufferID) { 232 RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID); 233 } 234 if (!drv->bufferID) { 235 ALOGE("Upload to buffer object failed"); 236 drv->uploadDeferred = true; 237 return; 238 } 239 RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID); 240 RSD_CALL_GL(glBufferData, drv->glTarget, 241 alloc->mHal.state.type->getPackedSizeBytes(), 242 alloc->mHal.drvState.lod[0].mallocPtr, GL_DYNAMIC_DRAW); 243 RSD_CALL_GL(glBindBuffer, drv->glTarget, 0); 244 rsdGLCheckError(rsc, "UploadToBufferObject"); 245 #endif 246 } 247 248 249 static size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) { 250 #ifndef RS_COMPATIBILITY_LIB 251 // For the flexible YCbCr format, layout is initialized during call to 252 // Allocation::ioReceive. Return early and avoid clobberring any 253 // pre-existing layout. 254 if (yuv == RS_YUV_420_888) { 255 return 0; 256 } 257 #endif 258 259 // YUV only supports basic 2d 260 // so we can stash the plane pointers in the mipmap levels. 261 size_t uvSize = 0; 262 state->lod[1].dimX = state->lod[0].dimX / 2; 263 state->lod[1].dimY = state->lod[0].dimY / 2; 264 state->lod[2].dimX = state->lod[0].dimX / 2; 265 state->lod[2].dimY = state->lod[0].dimY / 2; 266 state->yuv.shift = 1; 267 state->yuv.step = 1; 268 state->lodCount = 3; 269 270 switch(yuv) { 271 case RS_YUV_YV12: 272 state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16); 273 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + 274 (state->lod[0].stride * state->lod[0].dimY); 275 uvSize += state->lod[2].stride * state->lod[2].dimY; 276 277 state->lod[1].stride = state->lod[2].stride; 278 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 279 (state->lod[2].stride * state->lod[2].dimY); 280 uvSize += state->lod[1].stride * state->lod[2].dimY; 281 break; 282 case RS_YUV_NV21: 283 //state->lod[1].dimX = state->lod[0].dimX; 284 state->lod[1].stride = state->lod[0].stride; 285 state->lod[2].stride = state->lod[0].stride; 286 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + 287 (state->lod[0].stride * state->lod[0].dimY); 288 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1; 289 uvSize += state->lod[1].stride * state->lod[1].dimY; 290 state->yuv.step = 2; 291 break; 292 default: 293 rsAssert(0); 294 } 295 return uvSize; 296 } 297 298 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, 299 const Type *type, uint8_t *ptr, size_t requiredAlignment) { 300 alloc->mHal.drvState.lod[0].dimX = type->getDimX(); 301 alloc->mHal.drvState.lod[0].dimY = type->getDimY(); 302 alloc->mHal.drvState.lod[0].dimZ = type->getDimZ(); 303 alloc->mHal.drvState.lod[0].mallocPtr = 0; 304 // Stride needs to be aligned to a boundary defined by requiredAlignment! 305 size_t stride = alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes(); 306 alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment); 307 alloc->mHal.drvState.lodCount = type->getLODCount(); 308 alloc->mHal.drvState.faceCount = type->getDimFaces(); 309 310 size_t offsets[Allocation::MAX_LOD]; 311 memset(offsets, 0, sizeof(offsets)); 312 313 size_t o = alloc->mHal.drvState.lod[0].stride * rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) * 314 rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u); 315 if (alloc->mHal.state.yuv) { 316 o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState); 317 318 for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) { 319 offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr; 320 } 321 } else if(alloc->mHal.drvState.lodCount > 1) { 322 uint32_t tx = alloc->mHal.drvState.lod[0].dimX; 323 uint32_t ty = alloc->mHal.drvState.lod[0].dimY; 324 uint32_t tz = alloc->mHal.drvState.lod[0].dimZ; 325 for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) { 326 alloc->mHal.drvState.lod[lod].dimX = tx; 327 alloc->mHal.drvState.lod[lod].dimY = ty; 328 alloc->mHal.drvState.lod[lod].dimZ = tz; 329 alloc->mHal.drvState.lod[lod].stride = 330 rsRound(tx * type->getElementSizeBytes(), requiredAlignment); 331 offsets[lod] = o; 332 o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u); 333 if (tx > 1) tx >>= 1; 334 if (ty > 1) ty >>= 1; 335 if (tz > 1) tz >>= 1; 336 } 337 } 338 339 alloc->mHal.drvState.faceOffset = o; 340 341 alloc->mHal.drvState.lod[0].mallocPtr = ptr; 342 for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) { 343 alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod]; 344 } 345 346 size_t allocSize = alloc->mHal.drvState.faceOffset; 347 if(alloc->mHal.drvState.faceCount) { 348 allocSize *= 6; 349 } 350 351 return allocSize; 352 } 353 354 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, 355 const Type *type, uint8_t *ptr) { 356 return AllocationBuildPointerTable(rsc, alloc, type, ptr, Allocation::kMinimumRSAlignment); 357 } 358 359 static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero, size_t requiredAlignment) { 360 // We align all allocations to a boundary defined by requiredAlignment. 361 uint8_t* ptr = (uint8_t *)memalign(requiredAlignment, allocSize); 362 if (!ptr) { 363 return nullptr; 364 } 365 if (forceZero) { 366 memset(ptr, 0, allocSize); 367 } 368 return ptr; 369 } 370 371 bool rsdAllocationInitStrided(const Context *rsc, Allocation *alloc, bool forceZero, size_t requiredAlignment) { 372 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 373 if (!drv) { 374 return false; 375 } 376 alloc->mHal.drv = drv; 377 378 // Check if requiredAlignment is power of 2, also requiredAlignment should be larger or equal than kMinimumRSAlignment. 379 if ((requiredAlignment & (requiredAlignment-1)) != 0 || requiredAlignment < Allocation::kMinimumRSAlignment) { 380 ALOGE("requiredAlignment must be power of 2"); 381 return false; 382 } 383 // Calculate the object size. 384 size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), nullptr, requiredAlignment); 385 386 uint8_t * ptr = nullptr; 387 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) { 388 389 } else if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) { 390 // Allocation is allocated when the surface is created 391 // in getSurface 392 #ifdef RS_COMPATIBILITY_LIB 393 } else if (alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED)) { 394 if (alloc->mHal.state.userProvidedPtr == nullptr) { 395 ALOGE("User-backed buffer pointer cannot be null"); 396 return false; 397 } 398 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) { 399 ALOGE("User-allocated buffers must not have multiple faces or LODs"); 400 return false; 401 } 402 403 drv->useUserProvidedPtr = true; 404 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr; 405 #endif 406 } else if (alloc->mHal.state.userProvidedPtr != nullptr) { 407 // user-provided allocation 408 // limitations: no faces, no LOD, USAGE_SCRIPT or SCRIPT+TEXTURE only 409 if (!(alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED) || 410 alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE))) { 411 ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT | USAGE_SHARED or USAGE_SCRIPT | USAGE_SHARED | USAGE_GRAPHICS_TEXTURE"); 412 return false; 413 } 414 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) { 415 ALOGE("User-allocated buffers must not have multiple faces or LODs"); 416 return false; 417 } 418 419 // rows must be aligned based on requiredAlignment. 420 // validate that here, otherwise fall back to not use the user-backed allocation 421 if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % requiredAlignment) != 0) { 422 ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation"); 423 drv->useUserProvidedPtr = false; 424 425 ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment); 426 if (!ptr) { 427 alloc->mHal.drv = nullptr; 428 free(drv); 429 return false; 430 } 431 432 } else { 433 drv->useUserProvidedPtr = true; 434 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr; 435 } 436 } else { 437 ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment); 438 if (!ptr) { 439 alloc->mHal.drv = nullptr; 440 free(drv); 441 return false; 442 } 443 } 444 // Build the pointer tables 445 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr, requiredAlignment); 446 if(allocSize != verifySize) { 447 rsAssert(!"Size mismatch"); 448 } 449 450 drv->glTarget = GL_NONE; 451 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 452 if (alloc->mHal.state.hasFaces) { 453 drv->glTarget = GL_TEXTURE_CUBE_MAP; 454 } else { 455 drv->glTarget = GL_TEXTURE_2D; 456 } 457 } else { 458 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 459 drv->glTarget = GL_ARRAY_BUFFER; 460 } 461 } 462 463 #ifndef RS_COMPATIBILITY_LIB 464 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType()); 465 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind()); 466 #else 467 drv->glType = 0; 468 drv->glFormat = 0; 469 #endif 470 471 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { 472 drv->uploadDeferred = true; 473 } 474 475 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 476 drv->readBackFBO = nullptr; 477 #endif 478 479 // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted 480 if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) { 481 rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0); 482 } 483 484 485 #ifdef RS_FIND_OFFSETS 486 ALOGE("pointer for allocation: %p", alloc); 487 ALOGE("pointer for allocation.drv: %p", &alloc->mHal.drv); 488 #endif 489 490 491 return true; 492 } 493 494 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { 495 return rsdAllocationInitStrided(rsc, alloc, forceZero, Allocation::kMinimumRSAlignment); 496 } 497 498 void rsdAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) { 499 //ALOGE("rsdAllocationAdapterOffset"); 500 501 // Get a base pointer to the new LOD 502 const Allocation *base = alloc->mHal.state.baseAlloc; 503 const Type *type = alloc->mHal.state.type; 504 if (base == nullptr) { 505 return; 506 } 507 508 //ALOGE("rsdAllocationAdapterOffset %p %p", ptrA, ptrB); 509 //ALOGE("rsdAllocationAdapterOffset lodCount %i", alloc->mHal.drvState.lodCount); 510 511 const int lodBias = alloc->mHal.state.originLOD; 512 uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1); 513 for (uint32_t lod=0; lod < lodCount; lod++) { 514 alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias]; 515 alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(alloc, 516 alloc->mHal.state.originX, alloc->mHal.state.originY, alloc->mHal.state.originZ, 517 lodBias, (RsAllocationCubemapFace)alloc->mHal.state.originFace); 518 } 519 } 520 521 bool rsdAllocationAdapterInit(const Context *rsc, Allocation *alloc) { 522 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 523 if (!drv) { 524 return false; 525 } 526 alloc->mHal.drv = drv; 527 528 // We need to build an allocation that looks like a subset of the parent allocation 529 rsdAllocationAdapterOffset(rsc, alloc); 530 531 return true; 532 } 533 534 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { 535 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 536 537 if (alloc->mHal.state.baseAlloc == nullptr) { 538 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 539 if (drv->bufferID) { 540 // Causes a SW crash.... 541 //ALOGV(" mBufferID %i", mBufferID); 542 //glDeleteBuffers(1, &mBufferID); 543 //mBufferID = 0; 544 } 545 if (drv->textureID) { 546 RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID); 547 drv->textureID = 0; 548 } 549 if (drv->renderTargetID) { 550 RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID); 551 drv->renderTargetID = 0; 552 } 553 #endif 554 555 if (alloc->mHal.drvState.lod[0].mallocPtr) { 556 // don't free user-allocated ptrs or IO_OUTPUT buffers 557 if (!(drv->useUserProvidedPtr) && 558 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) && 559 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) { 560 free(alloc->mHal.drvState.lod[0].mallocPtr); 561 } 562 alloc->mHal.drvState.lod[0].mallocPtr = nullptr; 563 } 564 565 #ifndef RS_COMPATIBILITY_LIB 566 #ifndef RS_VENDOR_LIB 567 if (drv->readBackFBO != nullptr) { 568 delete drv->readBackFBO; 569 drv->readBackFBO = nullptr; 570 } 571 #endif 572 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) && 573 (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { 574 ANativeWindow *nw = drv->wndSurface; 575 if (nw) { 576 //If we have an attached surface, need to release it. 577 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer); 578 int fenceID = -1; 579 AHardwareBuffer_unlock(ahwb, &fenceID); 580 ANativeWindow_cancelBuffer(nw, drv->wndBuffer, fenceID); 581 ANativeWindow_release(nw); 582 drv->wndSurface = nullptr; 583 drv->wndBuffer = nullptr; 584 } 585 } 586 #endif 587 } 588 589 free(drv); 590 alloc->mHal.drv = nullptr; 591 } 592 593 void rsdAllocationResize(const Context *rsc, const Allocation *alloc, 594 const Type *newType, bool zeroNew) { 595 const uint32_t oldDimX = alloc->mHal.drvState.lod[0].dimX; 596 const uint32_t dimX = newType->getDimX(); 597 598 // can't resize Allocations with user-allocated buffers 599 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) { 600 ALOGE("Resize cannot be called on a USAGE_SHARED allocation"); 601 return; 602 } 603 void * oldPtr = alloc->mHal.drvState.lod[0].mallocPtr; 604 // Calculate the object size 605 size_t s = AllocationBuildPointerTable(rsc, alloc, newType, nullptr); 606 uint8_t *ptr = (uint8_t *)realloc(oldPtr, s); 607 // Build the relative pointer tables. 608 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr); 609 if(s != verifySize) { 610 rsAssert(!"Size mismatch"); 611 } 612 613 614 if (dimX > oldDimX) { 615 size_t stride = alloc->mHal.state.elementSizeBytes; 616 memset(((uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr) + stride * oldDimX, 617 0, stride * (dimX - oldDimX)); 618 } 619 } 620 621 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) { 622 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB) 623 if (!alloc->getIsScript()) { 624 return; // nothing to sync 625 } 626 627 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 628 RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer; 629 630 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 631 if (!drv->textureID && !drv->renderTargetID) { 632 return; // nothing was rendered here yet, so nothing to sync 633 } 634 if (drv->readBackFBO == nullptr) { 635 drv->readBackFBO = new RsdFrameBufferObj(); 636 drv->readBackFBO->setColorTarget(drv, 0); 637 drv->readBackFBO->setDimensions(alloc->getType()->getDimX(), 638 alloc->getType()->getDimY()); 639 } 640 641 // Bind the framebuffer object so we can read back from it 642 drv->readBackFBO->setActive(rsc); 643 644 // Do the readback 645 RSD_CALL_GL(glReadPixels, 0, 0, alloc->mHal.drvState.lod[0].dimX, 646 alloc->mHal.drvState.lod[0].dimY, 647 drv->glFormat, drv->glType, alloc->mHal.drvState.lod[0].mallocPtr); 648 649 // Revert framebuffer to its original 650 lastFbo->setActive(rsc); 651 #endif 652 } 653 654 655 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, 656 RsAllocationUsageType src) { 657 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 658 659 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 660 if(!alloc->getIsRenderTarget()) { 661 rsc->setError(RS_ERROR_FATAL_DRIVER, 662 "Attempting to sync allocation from render target, " 663 "for non-render target allocation"); 664 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) { 665 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA" 666 "render target"); 667 } else { 668 rsdAllocationSyncFromFBO(rsc, alloc); 669 } 670 return; 671 } 672 673 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT || src == RS_ALLOCATION_USAGE_SHARED); 674 675 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 676 UploadToTexture(rsc, alloc); 677 } else { 678 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) && 679 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) { 680 AllocateRenderTarget(rsc, alloc); 681 } 682 } 683 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 684 UploadToBufferObject(rsc, alloc); 685 } 686 687 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) { 688 689 if (src == RS_ALLOCATION_USAGE_SHARED) { 690 // just a memory fence for the CPU driver 691 // vendor drivers probably want to flush any dirty cachelines for 692 // this particular Allocation 693 __sync_synchronize(); 694 } 695 } 696 697 drv->uploadDeferred = false; 698 } 699 700 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 701 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 702 drv->uploadDeferred = true; 703 } 704 705 #ifndef RS_COMPATIBILITY_LIB 706 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 707 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 708 // Must lock the whole surface 709 int fenceID = -1; 710 int r = ANativeWindow_dequeueBuffer(nw, &drv->wndBuffer, &fenceID); 711 if (r) { 712 rsc->setError(RS_ERROR_DRIVER, "Error dequeueing IO output buffer."); 713 close(fenceID); 714 return false; 715 } 716 717 void *dst = nullptr; 718 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer); 719 r = AHardwareBuffer_lock(ahwb, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, 720 fenceID, NULL, &dst); 721 if (r) { 722 rsc->setError(RS_ERROR_DRIVER, "Error Locking IO output buffer."); 723 return false; 724 } 725 alloc->mHal.drvState.lod[0].mallocPtr = dst; 726 alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes; 727 rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0); 728 729 return true; 730 } 731 #endif 732 733 void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 734 #ifndef RS_COMPATIBILITY_LIB 735 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 736 737 // Cleanup old surface if there is one. 738 if (drv->wndSurface) { 739 ANativeWindow *old = drv->wndSurface; 740 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer); 741 int fenceID = -1; 742 int32_t r = AHardwareBuffer_unlock(ahwb, &fenceID); 743 if (r) { 744 rsc->setError(RS_ERROR_DRIVER, "Error unlocking output buffer."); 745 close(fenceID); 746 return; 747 } 748 r = ANativeWindow_cancelBuffer(old, drv->wndBuffer, fenceID); 749 if (r) { 750 rsc->setError(RS_ERROR_DRIVER, "Error canceling output buffer."); 751 return; 752 } 753 ANativeWindow_release(old); 754 drv->wndSurface = nullptr; 755 drv->wndBuffer = nullptr; 756 } 757 758 if (nw) { 759 int32_t r = ANativeWindow_setBuffersGeometry(nw, alloc->mHal.drvState.lod[0].dimX, 760 alloc->mHal.drvState.lod[0].dimY, 761 WINDOW_FORMAT_RGBA_8888); 762 if (r) { 763 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer geometry."); 764 return; 765 } 766 767 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 768 r = ANativeWindow_setUsage(nw, 769 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN); 770 if (r) { 771 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage."); 772 return; 773 } 774 } 775 776 IoGetBuffer(rsc, alloc, nw); 777 drv->wndSurface = nw; 778 } 779 780 return; 781 #endif 782 } 783 784 void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) { 785 #ifndef RS_COMPATIBILITY_LIB 786 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 787 ANativeWindow *nw = drv->wndSurface; 788 #ifndef RS_VENDOR_LIB 789 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 790 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 791 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 792 return; 793 } 794 #endif 795 if (nw) { 796 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 797 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer); 798 int fenceID = -1; 799 int32_t r = AHardwareBuffer_unlock(ahwb, &fenceID); 800 if (r) { 801 rsc->setError(RS_ERROR_DRIVER, "Error unlock output buffer."); 802 close(fenceID); 803 return; 804 } 805 r = ANativeWindow_queueBuffer(nw, drv->wndBuffer, fenceID); 806 if (r) { 807 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer."); 808 return; 809 } 810 drv->wndBuffer = nullptr; 811 IoGetBuffer(rsc, alloc, nw); 812 } 813 } else { 814 rsc->setError(RS_ERROR_DRIVER, "Sent IO buffer with no attached surface."); 815 return; 816 } 817 #endif 818 } 819 820 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) { 821 if (alloc->mHal.state.yuv) { 822 DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState); 823 } 824 } 825 826 827 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 828 uint32_t xoff, uint32_t lod, size_t count, 829 const void *data, size_t sizeBytes) { 830 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 831 832 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 833 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 834 size_t size = count * eSize; 835 if (ptr != data) { 836 // Skip the copy if we are the same allocation. This can arise from 837 // our Bitmap optimization, where we share the same storage. 838 if (alloc->mHal.state.hasReferences) { 839 alloc->incRefs(data, count); 840 alloc->decRefs(ptr, count); 841 } 842 memcpy(ptr, data, size); 843 } 844 drv->uploadDeferred = true; 845 } 846 847 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 848 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 849 uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) { 850 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 851 852 size_t eSize = alloc->mHal.state.elementSizeBytes; 853 size_t lineSize = eSize * w; 854 if (!stride) { 855 stride = lineSize; 856 } 857 858 if (alloc->mHal.drvState.lod[0].mallocPtr) { 859 const uint8_t *src = static_cast<const uint8_t *>(data); 860 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 861 if (dst == src) { 862 // Skip the copy if we are the same allocation. This can arise from 863 // our Bitmap optimization, where we share the same storage. 864 drv->uploadDeferred = true; 865 return; 866 } 867 868 for (uint32_t line=yoff; line < (yoff+h); line++) { 869 if (alloc->mHal.state.hasReferences) { 870 alloc->incRefs(src, w); 871 alloc->decRefs(dst, w); 872 } 873 memcpy(dst, src, lineSize); 874 src += stride; 875 dst += alloc->mHal.drvState.lod[lod].stride; 876 } 877 if (alloc->mHal.state.yuv) { 878 size_t clineSize = lineSize; 879 int lod = 1; 880 int maxLod = 2; 881 if (alloc->mHal.state.yuv == RS_YUV_YV12) { 882 maxLod = 3; 883 clineSize >>= 1; 884 } else if (alloc->mHal.state.yuv == RS_YUV_NV21) { 885 lod = 2; 886 maxLod = 3; 887 } 888 889 while (lod < maxLod) { 890 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 891 892 for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) { 893 memcpy(dst, src, clineSize); 894 // When copying from an array to an Allocation, the src pointer 895 // to the array should just move by the number of bytes copied. 896 src += clineSize; 897 dst += alloc->mHal.drvState.lod[lod].stride; 898 } 899 lod++; 900 } 901 902 } 903 drv->uploadDeferred = true; 904 } else { 905 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h); 906 } 907 } 908 909 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 910 uint32_t xoff, uint32_t yoff, uint32_t zoff, 911 uint32_t lod, 912 uint32_t w, uint32_t h, uint32_t d, const void *data, 913 size_t sizeBytes, size_t stride) { 914 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 915 916 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 917 uint32_t lineSize = eSize * w; 918 if (!stride) { 919 stride = lineSize; 920 } 921 922 if (alloc->mHal.drvState.lod[0].mallocPtr) { 923 const uint8_t *src = static_cast<const uint8_t *>(data); 924 for (uint32_t z = zoff; z < (d + zoff); z++) { 925 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod, 926 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 927 if (dst == src) { 928 // Skip the copy if we are the same allocation. This can arise from 929 // our Bitmap optimization, where we share the same storage. 930 drv->uploadDeferred = true; 931 return; 932 } 933 934 for (uint32_t line=yoff; line < (yoff+h); line++) { 935 if (alloc->mHal.state.hasReferences) { 936 alloc->incRefs(src, w); 937 alloc->decRefs(dst, w); 938 } 939 memcpy(dst, src, lineSize); 940 src += stride; 941 dst += alloc->mHal.drvState.lod[lod].stride; 942 } 943 } 944 drv->uploadDeferred = true; 945 } 946 } 947 948 void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc, 949 uint32_t xoff, uint32_t lod, size_t count, 950 void *data, size_t sizeBytes) { 951 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 952 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 953 if (data != ptr) { 954 // Skip the copy if we are the same allocation. This can arise from 955 // our Bitmap optimization, where we share the same storage. 956 memcpy(data, ptr, count * eSize); 957 } 958 } 959 960 void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc, 961 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 962 uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) { 963 size_t eSize = alloc->mHal.state.elementSizeBytes; 964 size_t lineSize = eSize * w; 965 if (!stride) { 966 stride = lineSize; 967 } 968 969 if (alloc->mHal.drvState.lod[0].mallocPtr) { 970 uint8_t *dst = static_cast<uint8_t *>(data); 971 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 972 if (dst == src) { 973 // Skip the copy if we are the same allocation. This can arise from 974 // our Bitmap optimization, where we share the same storage. 975 return; 976 } 977 978 for (uint32_t line=yoff; line < (yoff+h); line++) { 979 memcpy(dst, src, lineSize); 980 dst += stride; 981 src += alloc->mHal.drvState.lod[lod].stride; 982 } 983 } else { 984 ALOGE("Add code to readback from non-script memory"); 985 } 986 } 987 988 989 void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc, 990 uint32_t xoff, uint32_t yoff, uint32_t zoff, 991 uint32_t lod, 992 uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) { 993 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 994 uint32_t lineSize = eSize * w; 995 if (!stride) { 996 stride = lineSize; 997 } 998 999 if (alloc->mHal.drvState.lod[0].mallocPtr) { 1000 uint8_t *dst = static_cast<uint8_t *>(data); 1001 for (uint32_t z = zoff; z < (d + zoff); z++) { 1002 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod, 1003 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1004 if (dst == src) { 1005 // Skip the copy if we are the same allocation. This can arise from 1006 // our Bitmap optimization, where we share the same storage. 1007 return; 1008 } 1009 1010 for (uint32_t line=yoff; line < (yoff+h); line++) { 1011 memcpy(dst, src, lineSize); 1012 dst += stride; 1013 src += alloc->mHal.drvState.lod[lod].stride; 1014 } 1015 } 1016 } 1017 } 1018 1019 void * rsdAllocationLock1D(const android::renderscript::Context *rsc, 1020 const android::renderscript::Allocation *alloc) { 1021 return alloc->mHal.drvState.lod[0].mallocPtr; 1022 } 1023 1024 void rsdAllocationUnlock1D(const android::renderscript::Context *rsc, 1025 const android::renderscript::Allocation *alloc) { 1026 1027 } 1028 1029 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, 1030 const android::renderscript::Allocation *dstAlloc, 1031 uint32_t dstXoff, uint32_t dstLod, size_t count, 1032 const android::renderscript::Allocation *srcAlloc, 1033 uint32_t srcXoff, uint32_t srcLod) { 1034 } 1035 1036 1037 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, 1038 const android::renderscript::Allocation *dstAlloc, 1039 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 1040 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 1041 const android::renderscript::Allocation *srcAlloc, 1042 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 1043 RsAllocationCubemapFace srcFace) { 1044 size_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 1045 for (uint32_t i = 0; i < h; i ++) { 1046 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace); 1047 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace); 1048 memcpy(dstPtr, srcPtr, w * elementSize); 1049 1050 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 1051 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 1052 } 1053 } 1054 1055 void rsdAllocationData3D_alloc_script(const android::renderscript::Context *rsc, 1056 const android::renderscript::Allocation *dstAlloc, 1057 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, 1058 uint32_t w, uint32_t h, uint32_t d, 1059 const android::renderscript::Allocation *srcAlloc, 1060 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod) { 1061 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 1062 for (uint32_t j = 0; j < d; j++) { 1063 for (uint32_t i = 0; i < h; i ++) { 1064 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, 1065 dstLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1066 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, 1067 srcLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1068 memcpy(dstPtr, srcPtr, w * elementSize); 1069 1070 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 1071 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 1072 } 1073 } 1074 } 1075 1076 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, 1077 const android::renderscript::Allocation *dstAlloc, 1078 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 1079 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 1080 const android::renderscript::Allocation *srcAlloc, 1081 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 1082 RsAllocationCubemapFace srcFace) { 1083 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 1084 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 1085 "yet implemented."); 1086 return; 1087 } 1088 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, 1089 dstLod, dstFace, w, h, srcAlloc, 1090 srcXoff, srcYoff, srcLod, srcFace); 1091 } 1092 1093 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, 1094 const android::renderscript::Allocation *dstAlloc, 1095 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, 1096 uint32_t dstLod, 1097 uint32_t w, uint32_t h, uint32_t d, 1098 const android::renderscript::Allocation *srcAlloc, 1099 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, 1100 uint32_t srcLod) { 1101 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 1102 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 1103 "yet implemented."); 1104 return; 1105 } 1106 rsdAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff, 1107 dstLod, w, h, d, srcAlloc, 1108 srcXoff, srcYoff, srcZoff, srcLod); 1109 } 1110 1111 void rsdAllocationElementData(const Context *rsc, const Allocation *alloc, 1112 uint32_t x, uint32_t y, uint32_t z, 1113 const void *data, uint32_t cIdx, size_t sizeBytes) { 1114 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 1115 1116 uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1117 1118 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 1119 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 1120 1121 if (alloc->mHal.state.hasReferences) { 1122 e->incRefs(data); 1123 e->decRefs(ptr); 1124 } 1125 1126 memcpy(ptr, data, sizeBytes); 1127 drv->uploadDeferred = true; 1128 } 1129 1130 void rsdAllocationElementRead(const Context *rsc, const Allocation *alloc, 1131 uint32_t x, uint32_t y, uint32_t z, 1132 void *data, uint32_t cIdx, size_t sizeBytes) { 1133 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 1134 1135 uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1136 1137 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 1138 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 1139 1140 memcpy(data, ptr, sizeBytes); 1141 } 1142 1143 static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 1144 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 1145 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 1146 1147 for (uint32_t y=0; y < h; y++) { 1148 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 1149 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2, lod, face); 1150 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2+1, lod, face); 1151 1152 for (uint32_t x=0; x < w; x++) { 1153 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 1154 oPtr ++; 1155 i1 += 2; 1156 i2 += 2; 1157 } 1158 } 1159 } 1160 1161 static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 1162 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 1163 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 1164 1165 for (uint32_t y=0; y < h; y++) { 1166 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 1167 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, 0, lod, face); 1168 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face); 1169 1170 for (uint32_t x=0; x < w; x++) { 1171 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 1172 oPtr ++; 1173 i1 += 2; 1174 i2 += 2; 1175 } 1176 } 1177 } 1178 1179 static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 1180 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 1181 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 1182 1183 for (uint32_t y=0; y < h; y++) { 1184 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 1185 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, 0, lod, face); 1186 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face); 1187 1188 for (uint32_t x=0; x < w; x++) { 1189 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 1190 oPtr ++; 1191 i1 += 2; 1192 i2 += 2; 1193 } 1194 } 1195 } 1196 1197 void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) { 1198 if(!alloc->mHal.drvState.lod[0].mallocPtr) { 1199 return; 1200 } 1201 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; 1202 for (uint32_t face = 0; face < numFaces; face ++) { 1203 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) { 1204 switch (alloc->getType()->getElement()->getSizeBits()) { 1205 case 32: 1206 mip8888(alloc, lod, (RsAllocationCubemapFace)face); 1207 break; 1208 case 16: 1209 mip565(alloc, lod, (RsAllocationCubemapFace)face); 1210 break; 1211 case 8: 1212 mip8(alloc, lod, (RsAllocationCubemapFace)face); 1213 break; 1214 } 1215 } 1216 } 1217 } 1218 1219 uint32_t rsdAllocationGrallocBits(const android::renderscript::Context *rsc, 1220 android::renderscript::Allocation *alloc) 1221 { 1222 return 0; 1223 } 1224 1225 void rsdAllocationUpdateCachedObject(const Context *rsc, 1226 const Allocation *alloc, 1227 rs_allocation *obj) 1228 { 1229 obj->p = alloc; 1230 #ifdef __LP64__ 1231 obj->unused1 = nullptr; 1232 obj->unused2 = nullptr; 1233 obj->unused3 = nullptr; 1234 #endif 1235 } 1236