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