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