rsdAllocation.cpp revision 3bbc0fd40264ddae1592706d9023865b7b3e3195
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[1].dimX = state->lod[0].dimX / 2; 260 state->lod[1].dimY = state->lod[0].dimY / 2; 261 state->lod[1].stride = rsRound(state->lod[0].stride >> 1, 16); 262 state->lod[1].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) + 263 (state->lod[0].stride * state->lod[0].dimY); 264 uvSize += state->lod[1].stride * state->lod[1].dimY; 265 266 state->lod[2].dimX = state->lod[1].dimX; 267 state->lod[2].dimY = state->lod[1].dimY; 268 state->lod[2].stride = state->lod[1].stride; 269 state->lod[2].mallocPtr = ((uint8_t *)state->lod[1].mallocPtr) + 270 (state->lod[1].stride * state->lod[1].dimY); 271 uvSize += state->lod[2].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 only 379 if (alloc->mHal.state.usageFlags != (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED)) { 380 ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT and USAGE_SHARED"); 381 return false; 382 } 383 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) { 384 ALOGE("User-allocated buffers must not have multiple faces or LODs"); 385 return false; 386 } 387 388 // rows must be 16-byte aligned 389 // validate that here, otherwise fall back to not use the user-backed allocation 390 if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % 16) != 0) { 391 ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation"); 392 drv->useUserProvidedPtr = false; 393 394 ptr = allocAlignedMemory(allocSize, forceZero); 395 if (!ptr) { 396 alloc->mHal.drv = NULL; 397 free(drv); 398 return false; 399 } 400 401 } else { 402 drv->useUserProvidedPtr = true; 403 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr; 404 } 405 } else { 406 ptr = allocAlignedMemory(allocSize, forceZero); 407 if (!ptr) { 408 alloc->mHal.drv = NULL; 409 free(drv); 410 return false; 411 } 412 } 413 // Build the pointer tables 414 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr); 415 if(allocSize != verifySize) { 416 rsAssert(!"Size mismatch"); 417 } 418 419#ifndef RS_SERVER 420 drv->glTarget = GL_NONE; 421 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 422 if (alloc->mHal.state.hasFaces) { 423 drv->glTarget = GL_TEXTURE_CUBE_MAP; 424 } else { 425 drv->glTarget = GL_TEXTURE_2D; 426 } 427 } else { 428 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 429 drv->glTarget = GL_ARRAY_BUFFER; 430 } 431 } 432#endif 433 434#ifndef RS_COMPATIBILITY_LIB 435 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType()); 436 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind()); 437#else 438 drv->glType = 0; 439 drv->glFormat = 0; 440#endif 441 442 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { 443 drv->uploadDeferred = true; 444 } 445 446 447 drv->readBackFBO = NULL; 448 449 // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted 450 if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) { 451 rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0); 452 } 453 454 return true; 455} 456 457void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { 458 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 459 460#ifndef RS_COMPATIBILITY_LIB 461 if (drv->bufferID) { 462 // Causes a SW crash.... 463 //ALOGV(" mBufferID %i", mBufferID); 464 //glDeleteBuffers(1, &mBufferID); 465 //mBufferID = 0; 466 } 467 if (drv->textureID) { 468 RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID); 469 drv->textureID = 0; 470 } 471 if (drv->renderTargetID) { 472 RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID); 473 drv->renderTargetID = 0; 474 } 475#endif 476 477 if (alloc->mHal.drvState.lod[0].mallocPtr) { 478 // don't free user-allocated ptrs 479 if (!(drv->useUserProvidedPtr)) { 480 free(alloc->mHal.drvState.lod[0].mallocPtr); 481 } 482 alloc->mHal.drvState.lod[0].mallocPtr = NULL; 483 } 484 485#ifndef RS_COMPATIBILITY_LIB 486 if (drv->readBackFBO != NULL) { 487 delete drv->readBackFBO; 488 drv->readBackFBO = NULL; 489 } 490 491 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) && 492 (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { 493 494 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 495 ANativeWindow *nw = drv->wndSurface; 496 if (nw) { 497 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 498 mapper.unlock(drv->wndBuffer->handle); 499 int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1); 500 } 501 } 502#endif 503 504 free(drv); 505 alloc->mHal.drv = NULL; 506} 507 508void rsdAllocationResize(const Context *rsc, const Allocation *alloc, 509 const Type *newType, bool zeroNew) { 510 const uint32_t oldDimX = alloc->mHal.drvState.lod[0].dimX; 511 const uint32_t dimX = newType->getDimX(); 512 513 // can't resize Allocations with user-allocated buffers 514 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) { 515 ALOGE("Resize cannot be called on a USAGE_SHARED allocation"); 516 return; 517 } 518 void * oldPtr = alloc->mHal.drvState.lod[0].mallocPtr; 519 // Calculate the object size 520 size_t s = AllocationBuildPointerTable(rsc, alloc, newType, NULL); 521 uint8_t *ptr = (uint8_t *)realloc(oldPtr, s); 522 // Build the relative pointer tables. 523 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr); 524 if(s != verifySize) { 525 rsAssert(!"Size mismatch"); 526 } 527 528 529 if (dimX > oldDimX) { 530 size_t stride = alloc->mHal.state.elementSizeBytes; 531 memset(((uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr) + stride * oldDimX, 532 0, stride * (dimX - oldDimX)); 533 } 534} 535 536static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) { 537#ifndef RS_COMPATIBILITY_LIB 538 if (!alloc->getIsScript()) { 539 return; // nothing to sync 540 } 541 542 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 543 RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer; 544 545 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 546 if (!drv->textureID && !drv->renderTargetID) { 547 return; // nothing was rendered here yet, so nothing to sync 548 } 549 if (drv->readBackFBO == NULL) { 550 drv->readBackFBO = new RsdFrameBufferObj(); 551 drv->readBackFBO->setColorTarget(drv, 0); 552 drv->readBackFBO->setDimensions(alloc->getType()->getDimX(), 553 alloc->getType()->getDimY()); 554 } 555 556 // Bind the framebuffer object so we can read back from it 557 drv->readBackFBO->setActive(rsc); 558 559 // Do the readback 560 RSD_CALL_GL(glReadPixels, 0, 0, alloc->mHal.drvState.lod[0].dimX, 561 alloc->mHal.drvState.lod[0].dimY, 562 drv->glFormat, drv->glType, alloc->mHal.drvState.lod[0].mallocPtr); 563 564 // Revert framebuffer to its original 565 lastFbo->setActive(rsc); 566#endif 567} 568 569 570void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, 571 RsAllocationUsageType src) { 572 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 573 574 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 575 if(!alloc->getIsRenderTarget()) { 576 rsc->setError(RS_ERROR_FATAL_DRIVER, 577 "Attempting to sync allocation from render target, " 578 "for non-render target allocation"); 579 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) { 580 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA" 581 "render target"); 582 } else { 583 rsdAllocationSyncFromFBO(rsc, alloc); 584 } 585 return; 586 } 587 588 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT); 589 590 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 591 UploadToTexture(rsc, alloc); 592 } else { 593 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) && 594 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) { 595 AllocateRenderTarget(rsc, alloc); 596 } 597 } 598 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 599 UploadToBufferObject(rsc, alloc); 600 } 601 602 drv->uploadDeferred = false; 603} 604 605void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 606 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 607 drv->uploadDeferred = true; 608} 609 610void* rsdAllocationGetSurface(const Context *rsc, const Allocation *alloc) { 611#ifndef RS_COMPATIBILITY_LIB 612 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 613 614 // Configure CpuConsumer to be in asynchronous mode 615 drv->cpuConsumer = new CpuConsumer(2, false); 616 sp<IGraphicBufferProducer> bp = drv->cpuConsumer->getProducerInterface(); 617 bp->incStrong(NULL); 618 return bp.get(); 619#else 620 return NULL; 621#endif 622} 623 624#ifndef RS_COMPATIBILITY_LIB 625static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 626 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 627 628 int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer); 629 if (r) { 630 rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer."); 631 return false; 632 } 633 634 // Must lock the whole surface 635 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 636 Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height); 637 638 void *dst = NULL; 639 mapper.lock(drv->wndBuffer->handle, 640 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN, 641 bounds, &dst); 642 alloc->mHal.drvState.lod[0].mallocPtr = dst; 643 alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes; 644 rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0); 645 646 return true; 647} 648#endif 649 650void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 651#ifndef RS_COMPATIBILITY_LIB 652 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 653 ANativeWindow *old = drv->wndSurface; 654 655 if (nw) { 656 nw->incStrong(NULL); 657 } 658 659 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 660 //TODO finish support for render target + script 661 drv->wnd = nw; 662 return; 663 } 664 665 // Cleanup old surface if there is one. 666 if (drv->wndSurface) { 667 ANativeWindow *old = drv->wndSurface; 668 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 669 mapper.unlock(drv->wndBuffer->handle); 670 old->cancelBuffer(old, drv->wndBuffer, -1); 671 drv->wndSurface = NULL; 672 old->decStrong(NULL); 673 } 674 675 if (nw != NULL) { 676 int32_t r; 677 uint32_t flags = 0; 678 r = native_window_set_buffer_count(nw, 3); 679 if (r) { 680 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer count."); 681 goto error; 682 } 683 684 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 685 flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN; 686 } 687 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 688 flags |= GRALLOC_USAGE_HW_RENDER; 689 } 690 691 r = native_window_set_usage(nw, flags); 692 if (r) { 693 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage."); 694 goto error; 695 } 696 697 r = native_window_set_buffers_dimensions(nw, alloc->mHal.drvState.lod[0].dimX, 698 alloc->mHal.drvState.lod[0].dimY); 699 if (r) { 700 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions."); 701 goto error; 702 } 703 704 int format = 0; 705 const Element *e = alloc->mHal.state.type->getElement(); 706 switch(e->getType()) { 707 case RS_TYPE_UNSIGNED_8: 708 switch (e->getVectorSize()) { 709 case 1: 710 rsAssert(e->getKind() == RS_KIND_PIXEL_A); 711 format = PIXEL_FORMAT_A_8; 712 break; 713 case 4: 714 rsAssert(e->getKind() == RS_KIND_PIXEL_RGBA); 715 format = PIXEL_FORMAT_RGBA_8888; 716 break; 717 default: 718 rsAssert(0); 719 } 720 break; 721 default: 722 rsAssert(0); 723 } 724 725 r = native_window_set_buffers_format(nw, format); 726 if (r) { 727 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer format."); 728 goto error; 729 } 730 731 IoGetBuffer(rsc, alloc, nw); 732 drv->wndSurface = nw; 733 } 734 735 return; 736 737 error: 738 739 if (nw) { 740 nw->decStrong(NULL); 741 } 742 743 744#endif 745} 746 747void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) { 748#ifndef RS_COMPATIBILITY_LIB 749 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 750 ANativeWindow *nw = drv->wndSurface; 751 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 752 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 753 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 754 return; 755 } 756 if (nw) { 757 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 758 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 759 mapper.unlock(drv->wndBuffer->handle); 760 int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1); 761 if (r) { 762 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer."); 763 return; 764 } 765 766 IoGetBuffer(rsc, alloc, nw); 767 } 768 } else { 769 rsc->setError(RS_ERROR_DRIVER, "Sent IO buffer with no attached surface."); 770 return; 771 } 772#endif 773} 774 775void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) { 776#ifndef RS_COMPATIBILITY_LIB 777 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 778 779 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 780 CpuConsumer::LockedBuffer lb; 781 status_t ret = drv->cpuConsumer->lockNextBuffer(&lb); 782 if (ret == OK) { 783 if (drv->lb.data != NULL) { 784 drv->cpuConsumer->unlockBuffer(drv->lb); 785 } 786 drv->lb = lb; 787 alloc->mHal.drvState.lod[0].mallocPtr = drv->lb.data; 788 alloc->mHal.drvState.lod[0].stride = drv->lb.stride * 789 alloc->mHal.state.elementSizeBytes; 790 791 if (alloc->mHal.state.yuv) { 792 DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState); 793 } 794 } else if (ret == BAD_VALUE) { 795 // No new frame, don't do anything 796 } else { 797 rsc->setError(RS_ERROR_DRIVER, "Error receiving IO input buffer."); 798 } 799 800 } else { 801 drv->surfaceTexture->updateTexImage(); 802 } 803 804 805#endif 806} 807 808 809void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 810 uint32_t xoff, uint32_t lod, size_t count, 811 const void *data, size_t sizeBytes) { 812 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 813 814 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 815 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 816 size_t size = count * eSize; 817 818 if (ptr != data) { 819 // Skip the copy if we are the same allocation. This can arise from 820 // our Bitmap optimization, where we share the same storage. 821 if (alloc->mHal.state.hasReferences) { 822 alloc->incRefs(data, count); 823 alloc->decRefs(ptr, count); 824 } 825 memcpy(ptr, data, size); 826 } 827 drv->uploadDeferred = true; 828} 829 830void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 831 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 832 uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) { 833 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 834 835 size_t eSize = alloc->mHal.state.elementSizeBytes; 836 size_t lineSize = eSize * w; 837 if (!stride) { 838 stride = lineSize; 839 } 840 841 if (alloc->mHal.drvState.lod[0].mallocPtr) { 842 const uint8_t *src = static_cast<const uint8_t *>(data); 843 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 844 if (dst == src) { 845 // Skip the copy if we are the same allocation. This can arise from 846 // our Bitmap optimization, where we share the same storage. 847 drv->uploadDeferred = true; 848 return; 849 } 850 851 for (uint32_t line=yoff; line < (yoff+h); line++) { 852 if (alloc->mHal.state.hasReferences) { 853 alloc->incRefs(src, w); 854 alloc->decRefs(dst, w); 855 } 856 memcpy(dst, src, lineSize); 857 src += stride; 858 dst += alloc->mHal.drvState.lod[lod].stride; 859 } 860 if (alloc->mHal.state.yuv) { 861 int lod = 1; 862 while (alloc->mHal.drvState.lod[lod].mallocPtr) { 863 size_t lineSize = alloc->mHal.drvState.lod[lod].dimX; 864 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 865 866 for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) { 867 memcpy(dst, src, lineSize); 868 src += lineSize; 869 dst += alloc->mHal.drvState.lod[lod].stride; 870 } 871 lod++; 872 } 873 874 } 875 drv->uploadDeferred = true; 876 } else { 877 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h); 878 } 879} 880 881void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 882 uint32_t xoff, uint32_t yoff, uint32_t zoff, 883 uint32_t lod, 884 uint32_t w, uint32_t h, uint32_t d, const void *data, 885 size_t sizeBytes, size_t stride) { 886 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 887 888 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 889 uint32_t lineSize = eSize * w; 890 if (!stride) { 891 stride = lineSize; 892 } 893 894 if (alloc->mHal.drvState.lod[0].mallocPtr) { 895 const uint8_t *src = static_cast<const uint8_t *>(data); 896 for (uint32_t z = zoff; z < d; z++) { 897 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod, 898 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 899 if (dst == src) { 900 // Skip the copy if we are the same allocation. This can arise from 901 // our Bitmap optimization, where we share the same storage. 902 drv->uploadDeferred = true; 903 return; 904 } 905 906 for (uint32_t line=yoff; line < (yoff+h); line++) { 907 if (alloc->mHal.state.hasReferences) { 908 alloc->incRefs(src, w); 909 alloc->decRefs(dst, w); 910 } 911 memcpy(dst, src, lineSize); 912 src += stride; 913 dst += alloc->mHal.drvState.lod[lod].stride; 914 } 915 } 916 drv->uploadDeferred = true; 917 } 918} 919 920void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc, 921 uint32_t xoff, uint32_t lod, size_t count, 922 void *data, size_t sizeBytes) { 923 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 924 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 925 if (data != ptr) { 926 // Skip the copy if we are the same allocation. This can arise from 927 // our Bitmap optimization, where we share the same storage. 928 memcpy(data, ptr, count * eSize); 929 } 930} 931 932void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc, 933 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 934 uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) { 935 size_t eSize = alloc->mHal.state.elementSizeBytes; 936 size_t lineSize = eSize * w; 937 if (!stride) { 938 stride = lineSize; 939 } 940 941 if (alloc->mHal.drvState.lod[0].mallocPtr) { 942 uint8_t *dst = static_cast<uint8_t *>(data); 943 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face); 944 if (dst == src) { 945 // Skip the copy if we are the same allocation. This can arise from 946 // our Bitmap optimization, where we share the same storage. 947 return; 948 } 949 950 for (uint32_t line=yoff; line < (yoff+h); line++) { 951 memcpy(dst, src, lineSize); 952 dst += stride; 953 src += alloc->mHal.drvState.lod[lod].stride; 954 } 955 } else { 956 ALOGE("Add code to readback from non-script memory"); 957 } 958} 959 960 961void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc, 962 uint32_t xoff, uint32_t yoff, uint32_t zoff, 963 uint32_t lod, 964 uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) { 965 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 966 uint32_t lineSize = eSize * w; 967 if (!stride) { 968 stride = lineSize; 969 } 970 971 if (alloc->mHal.drvState.lod[0].mallocPtr) { 972 uint8_t *dst = static_cast<uint8_t *>(data); 973 for (uint32_t z = zoff; z < d; z++) { 974 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod, 975 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 976 if (dst == src) { 977 // Skip the copy if we are the same allocation. This can arise from 978 // our Bitmap optimization, where we share the same storage. 979 return; 980 } 981 982 for (uint32_t line=yoff; line < (yoff+h); line++) { 983 memcpy(dst, src, lineSize); 984 dst += stride; 985 src += alloc->mHal.drvState.lod[lod].stride; 986 } 987 } 988 } 989} 990 991void * rsdAllocationLock1D(const android::renderscript::Context *rsc, 992 const android::renderscript::Allocation *alloc) { 993 return alloc->mHal.drvState.lod[0].mallocPtr; 994} 995 996void rsdAllocationUnlock1D(const android::renderscript::Context *rsc, 997 const android::renderscript::Allocation *alloc) { 998 999} 1000 1001void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, 1002 const android::renderscript::Allocation *dstAlloc, 1003 uint32_t dstXoff, uint32_t dstLod, size_t count, 1004 const android::renderscript::Allocation *srcAlloc, 1005 uint32_t srcXoff, uint32_t srcLod) { 1006} 1007 1008 1009void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, 1010 const android::renderscript::Allocation *dstAlloc, 1011 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 1012 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 1013 const android::renderscript::Allocation *srcAlloc, 1014 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 1015 RsAllocationCubemapFace srcFace) { 1016 size_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 1017 for (uint32_t i = 0; i < h; i ++) { 1018 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace); 1019 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace); 1020 memcpy(dstPtr, srcPtr, w * elementSize); 1021 1022 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 1023 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 1024 } 1025} 1026 1027void rsdAllocationData3D_alloc_script(const android::renderscript::Context *rsc, 1028 const android::renderscript::Allocation *dstAlloc, 1029 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, 1030 uint32_t w, uint32_t h, uint32_t d, 1031 const android::renderscript::Allocation *srcAlloc, 1032 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod) { 1033 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 1034 for (uint32_t j = 0; j < d; j++) { 1035 for (uint32_t i = 0; i < h; i ++) { 1036 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, 1037 dstLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1038 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, 1039 srcLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1040 memcpy(dstPtr, srcPtr, w * elementSize); 1041 1042 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 1043 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 1044 } 1045 } 1046} 1047 1048void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, 1049 const android::renderscript::Allocation *dstAlloc, 1050 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 1051 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 1052 const android::renderscript::Allocation *srcAlloc, 1053 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 1054 RsAllocationCubemapFace srcFace) { 1055 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 1056 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 1057 "yet implemented."); 1058 return; 1059 } 1060 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, 1061 dstLod, dstFace, w, h, srcAlloc, 1062 srcXoff, srcYoff, srcLod, srcFace); 1063} 1064 1065void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, 1066 const android::renderscript::Allocation *dstAlloc, 1067 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, 1068 uint32_t dstLod, 1069 uint32_t w, uint32_t h, uint32_t d, 1070 const android::renderscript::Allocation *srcAlloc, 1071 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, 1072 uint32_t srcLod) { 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 rsdAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff, 1079 dstLod, w, h, d, srcAlloc, 1080 srcXoff, srcYoff, srcZoff, srcLod); 1081} 1082 1083void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc, 1084 uint32_t x, 1085 const void *data, uint32_t cIdx, size_t sizeBytes) { 1086 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 1087 1088 size_t eSize = alloc->mHal.state.elementSizeBytes; 1089 uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1090 1091 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 1092 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 1093 1094 if (alloc->mHal.state.hasReferences) { 1095 e->incRefs(data); 1096 e->decRefs(ptr); 1097 } 1098 1099 memcpy(ptr, data, sizeBytes); 1100 drv->uploadDeferred = true; 1101} 1102 1103void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc, 1104 uint32_t x, uint32_t y, 1105 const void *data, uint32_t cIdx, size_t sizeBytes) { 1106 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 1107 1108 size_t eSize = alloc->mHal.state.elementSizeBytes; 1109 uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 1110 1111 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 1112 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 1113 1114 if (alloc->mHal.state.hasReferences) { 1115 e->incRefs(data); 1116 e->decRefs(ptr); 1117 } 1118 1119 memcpy(ptr, data, sizeBytes); 1120 drv->uploadDeferred = true; 1121} 1122 1123static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 1124 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX; 1125 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY; 1126 1127 for (uint32_t y=0; y < h; y++) { 1128 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 1129 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2, lod, face); 1130 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2+1, lod, face); 1131 1132 for (uint32_t x=0; x < w; x++) { 1133 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 1134 oPtr ++; 1135 i1 += 2; 1136 i2 += 2; 1137 } 1138 } 1139} 1140 1141static void mip8888(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 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 1147 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, 0, lod, face); 1148 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face); 1149 1150 for (uint32_t x=0; x < w; x++) { 1151 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 1152 oPtr ++; 1153 i1 += 2; 1154 i2 += 2; 1155 } 1156 } 1157} 1158 1159static void mip8(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 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face); 1165 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, 0, lod, face); 1166 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face); 1167 1168 for (uint32_t x=0; x < w; x++) { 1169 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 1170 oPtr ++; 1171 i1 += 2; 1172 i2 += 2; 1173 } 1174 } 1175} 1176 1177void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) { 1178 if(!alloc->mHal.drvState.lod[0].mallocPtr) { 1179 return; 1180 } 1181 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; 1182 for (uint32_t face = 0; face < numFaces; face ++) { 1183 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) { 1184 switch (alloc->getType()->getElement()->getSizeBits()) { 1185 case 32: 1186 mip8888(alloc, lod, (RsAllocationCubemapFace)face); 1187 break; 1188 case 16: 1189 mip565(alloc, lod, (RsAllocationCubemapFace)face); 1190 break; 1191 case 8: 1192 mip8(alloc, lod, (RsAllocationCubemapFace)face); 1193 break; 1194 } 1195 } 1196 } 1197} 1198