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