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