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