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