1 /* 2 * Copyright (C) 2011-2012 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 "rsdRuntime.h" 20 #include "rsdAllocation.h" 21 #include "rsdFrameBufferObj.h" 22 23 #include "rsAllocation.h" 24 25 #include "system/window.h" 26 #include "hardware/gralloc.h" 27 #include "ui/Rect.h" 28 #include "ui/GraphicBufferMapper.h" 29 #include "gui/SurfaceTexture.h" 30 31 #include <GLES/gl.h> 32 #include <GLES2/gl2.h> 33 #include <GLES/glext.h> 34 35 using namespace android; 36 using namespace android::renderscript; 37 38 39 40 const static GLenum gFaceOrder[] = { 41 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 42 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 43 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 44 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 45 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 46 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 47 }; 48 49 50 GLenum rsdTypeToGLType(RsDataType t) { 51 switch (t) { 52 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5; 53 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1; 54 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4; 55 56 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT; 57 case RS_TYPE_FLOAT_32: return GL_FLOAT; 58 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE; 59 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT; 60 case RS_TYPE_SIGNED_8: return GL_BYTE; 61 case RS_TYPE_SIGNED_16: return GL_SHORT; 62 default: break; 63 } 64 return 0; 65 } 66 67 GLenum rsdKindToGLFormat(RsDataKind k) { 68 switch (k) { 69 case RS_KIND_PIXEL_L: return GL_LUMINANCE; 70 case RS_KIND_PIXEL_A: return GL_ALPHA; 71 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA; 72 case RS_KIND_PIXEL_RGB: return GL_RGB; 73 case RS_KIND_PIXEL_RGBA: return GL_RGBA; 74 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16; 75 default: break; 76 } 77 return 0; 78 } 79 80 uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc, 81 uint32_t xoff, uint32_t yoff, uint32_t lod, 82 RsAllocationCubemapFace face) { 83 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 84 uint8_t *ptr = (uint8_t *)drv->lod[lod].mallocPtr; 85 ptr += face * drv->faceOffset; 86 ptr += yoff * drv->lod[lod].stride; 87 ptr += xoff * alloc->mHal.state.elementSizeBytes; 88 return ptr; 89 } 90 91 92 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr, 93 uint32_t xoff, uint32_t yoff, uint32_t lod, 94 RsAllocationCubemapFace face, uint32_t w, uint32_t h) { 95 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 96 97 rsAssert(drv->textureID); 98 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID); 99 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1); 100 GLenum t = GL_TEXTURE_2D; 101 if (alloc->mHal.state.hasFaces) { 102 t = gFaceOrder[face]; 103 } 104 RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr); 105 } 106 107 108 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) { 109 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 110 111 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID); 112 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1); 113 114 uint32_t faceCount = 1; 115 if (alloc->mHal.state.hasFaces) { 116 faceCount = 6; 117 } 118 119 rsdGLCheckError(rsc, "Upload2DTexture 1 "); 120 for (uint32_t face = 0; face < faceCount; face ++) { 121 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) { 122 const uint8_t *p = GetOffsetPtr(alloc, 0, 0, lod, (RsAllocationCubemapFace)face); 123 124 GLenum t = GL_TEXTURE_2D; 125 if (alloc->mHal.state.hasFaces) { 126 t = gFaceOrder[face]; 127 } 128 129 if (isFirstUpload) { 130 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat, 131 alloc->mHal.state.type->getLODDimX(lod), 132 alloc->mHal.state.type->getLODDimY(lod), 133 0, drv->glFormat, drv->glType, p); 134 } else { 135 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0, 136 alloc->mHal.state.type->getLODDimX(lod), 137 alloc->mHal.state.type->getLODDimY(lod), 138 drv->glFormat, drv->glType, p); 139 } 140 } 141 } 142 143 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) { 144 RSD_CALL_GL(glGenerateMipmap, drv->glTarget); 145 } 146 rsdGLCheckError(rsc, "Upload2DTexture"); 147 } 148 149 static void UploadToTexture(const Context *rsc, const Allocation *alloc) { 150 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 151 152 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) { 153 if (!drv->textureID) { 154 RSD_CALL_GL(glGenTextures, 1, &drv->textureID); 155 } 156 return; 157 } 158 159 if (!drv->glType || !drv->glFormat) { 160 return; 161 } 162 163 if (!drv->lod[0].mallocPtr) { 164 return; 165 } 166 167 bool isFirstUpload = false; 168 169 if (!drv->textureID) { 170 RSD_CALL_GL(glGenTextures, 1, &drv->textureID); 171 isFirstUpload = true; 172 } 173 174 Upload2DTexture(rsc, alloc, isFirstUpload); 175 176 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { 177 if (alloc->mHal.drvState.mallocPtrLOD0) { 178 free(alloc->mHal.drvState.mallocPtrLOD0); 179 alloc->mHal.drvState.mallocPtrLOD0 = NULL; 180 drv->lod[0].mallocPtr = NULL; 181 } 182 } 183 rsdGLCheckError(rsc, "UploadToTexture"); 184 } 185 186 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) { 187 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 188 189 if (!drv->glFormat) { 190 return; 191 } 192 193 if (!drv->renderTargetID) { 194 RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID); 195 196 if (!drv->renderTargetID) { 197 // This should generally not happen 198 ALOGE("allocateRenderTarget failed to gen mRenderTargetID"); 199 rsc->dumpDebug(); 200 return; 201 } 202 RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID); 203 RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat, 204 alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY); 205 } 206 rsdGLCheckError(rsc, "AllocateRenderTarget"); 207 } 208 209 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) { 210 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 211 212 rsAssert(!alloc->mHal.state.type->getDimY()); 213 rsAssert(!alloc->mHal.state.type->getDimZ()); 214 215 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; 216 217 if (!drv->bufferID) { 218 RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID); 219 } 220 if (!drv->bufferID) { 221 ALOGE("Upload to buffer object failed"); 222 drv->uploadDeferred = true; 223 return; 224 } 225 RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID); 226 RSD_CALL_GL(glBufferData, drv->glTarget, alloc->mHal.state.type->getSizeBytes(), 227 alloc->mHal.drvState.mallocPtrLOD0, GL_DYNAMIC_DRAW); 228 RSD_CALL_GL(glBindBuffer, drv->glTarget, 0); 229 rsdGLCheckError(rsc, "UploadToBufferObject"); 230 } 231 232 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, 233 const Type *type, uint8_t *ptr) { 234 235 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 236 237 drv->lod[0].dimX = type->getDimX(); 238 drv->lod[0].dimY = type->getDimY(); 239 drv->lod[0].mallocPtr = 0; 240 drv->lod[0].stride = drv->lod[0].dimX * type->getElementSizeBytes(); 241 drv->lodCount = type->getLODCount(); 242 drv->faceCount = type->getDimFaces(); 243 244 size_t offsets[Allocation::MAX_LOD]; 245 memset(offsets, 0, sizeof(offsets)); 246 247 size_t o = drv->lod[0].stride * rsMax(drv->lod[0].dimY, 1u) * rsMax(drv->lod[0].dimZ, 1u); 248 if(drv->lodCount > 1) { 249 uint32_t tx = drv->lod[0].dimX; 250 uint32_t ty = drv->lod[0].dimY; 251 uint32_t tz = drv->lod[0].dimZ; 252 for (uint32_t lod=1; lod < drv->lodCount; lod++) { 253 drv->lod[lod].dimX = tx; 254 drv->lod[lod].dimY = ty; 255 drv->lod[lod].dimZ = tz; 256 drv->lod[lod].stride = tx * type->getElementSizeBytes(); 257 offsets[lod] = o; 258 o += drv->lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u); 259 if (tx > 1) tx >>= 1; 260 if (ty > 1) ty >>= 1; 261 if (tz > 1) tz >>= 1; 262 } 263 } 264 drv->faceOffset = o; 265 266 drv->lod[0].mallocPtr = ptr; 267 for (uint32_t lod=1; lod < drv->lodCount; lod++) { 268 drv->lod[lod].mallocPtr = ptr + offsets[lod]; 269 } 270 alloc->mHal.drvState.strideLOD0 = drv->lod[0].stride; 271 alloc->mHal.drvState.mallocPtrLOD0 = ptr; 272 273 size_t allocSize = drv->faceOffset; 274 if(drv->faceCount) { 275 allocSize *= 6; 276 } 277 278 return allocSize; 279 } 280 281 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { 282 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 283 if (!drv) { 284 return false; 285 } 286 alloc->mHal.drv = drv; 287 288 // Calculate the object size. 289 size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), NULL); 290 291 uint8_t * ptr = NULL; 292 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) { 293 } else { 294 295 ptr = (uint8_t *)malloc(allocSize); 296 if (!ptr) { 297 free(drv); 298 return false; 299 } 300 } 301 // Build the pointer tables 302 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr); 303 if(allocSize != verifySize) { 304 rsAssert(!"Size mismatch"); 305 } 306 307 drv->glTarget = GL_NONE; 308 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 309 if (alloc->mHal.state.hasFaces) { 310 drv->glTarget = GL_TEXTURE_CUBE_MAP; 311 } else { 312 drv->glTarget = GL_TEXTURE_2D; 313 } 314 } else { 315 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 316 drv->glTarget = GL_ARRAY_BUFFER; 317 } 318 } 319 320 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType()); 321 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind()); 322 323 if (forceZero && ptr) { 324 memset(ptr, 0, alloc->mHal.state.type->getSizeBytes()); 325 } 326 327 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { 328 drv->uploadDeferred = true; 329 } 330 331 332 drv->readBackFBO = NULL; 333 334 return true; 335 } 336 337 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { 338 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 339 340 if (drv->bufferID) { 341 // Causes a SW crash.... 342 //ALOGV(" mBufferID %i", mBufferID); 343 //glDeleteBuffers(1, &mBufferID); 344 //mBufferID = 0; 345 } 346 if (drv->textureID) { 347 RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID); 348 drv->textureID = 0; 349 } 350 if (drv->renderTargetID) { 351 RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID); 352 drv->renderTargetID = 0; 353 } 354 355 if (alloc->mHal.drvState.mallocPtrLOD0) { 356 free(alloc->mHal.drvState.mallocPtrLOD0); 357 alloc->mHal.drvState.mallocPtrLOD0 = NULL; 358 } 359 if (drv->readBackFBO != NULL) { 360 delete drv->readBackFBO; 361 drv->readBackFBO = NULL; 362 } 363 free(drv); 364 alloc->mHal.drv = NULL; 365 } 366 367 void rsdAllocationResize(const Context *rsc, const Allocation *alloc, 368 const Type *newType, bool zeroNew) { 369 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 370 371 void * oldPtr = drv->lod[0].mallocPtr; 372 // Calculate the object size 373 size_t s = AllocationBuildPointerTable(rsc, alloc, newType, NULL); 374 uint8_t *ptr = (uint8_t *)realloc(oldPtr, s); 375 // Build the relative pointer tables. 376 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr); 377 if(s != verifySize) { 378 rsAssert(!"Size mismatch"); 379 } 380 381 const uint32_t oldDimX = alloc->mHal.state.dimensionX; 382 const uint32_t dimX = newType->getDimX(); 383 384 if (dimX > oldDimX) { 385 uint32_t stride = alloc->mHal.state.elementSizeBytes; 386 memset(((uint8_t *)alloc->mHal.drvState.mallocPtrLOD0) + stride * oldDimX, 387 0, stride * (dimX - oldDimX)); 388 } 389 } 390 391 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) { 392 if (!alloc->getIsScript()) { 393 return; // nothing to sync 394 } 395 396 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 397 RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer; 398 399 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 400 if (!drv->textureID && !drv->renderTargetID) { 401 return; // nothing was rendered here yet, so nothing to sync 402 } 403 if (drv->readBackFBO == NULL) { 404 drv->readBackFBO = new RsdFrameBufferObj(); 405 drv->readBackFBO->setColorTarget(drv, 0); 406 drv->readBackFBO->setDimensions(alloc->getType()->getDimX(), 407 alloc->getType()->getDimY()); 408 } 409 410 // Bind the framebuffer object so we can read back from it 411 drv->readBackFBO->setActive(rsc); 412 413 // Do the readback 414 RSD_CALL_GL(glReadPixels, 0, 0, drv->lod[0].dimX, drv->lod[0].dimY, 415 drv->glFormat, drv->glType, drv->lod[0].mallocPtr); 416 417 // Revert framebuffer to its original 418 lastFbo->setActive(rsc); 419 } 420 421 422 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, 423 RsAllocationUsageType src) { 424 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 425 426 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 427 if(!alloc->getIsRenderTarget()) { 428 rsc->setError(RS_ERROR_FATAL_DRIVER, 429 "Attempting to sync allocation from render target, " 430 "for non-render target allocation"); 431 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) { 432 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA" 433 "render target"); 434 } else { 435 rsdAllocationSyncFromFBO(rsc, alloc); 436 } 437 return; 438 } 439 440 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT); 441 442 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 443 UploadToTexture(rsc, alloc); 444 } else { 445 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) && 446 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) { 447 AllocateRenderTarget(rsc, alloc); 448 } 449 } 450 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 451 UploadToBufferObject(rsc, alloc); 452 } 453 454 drv->uploadDeferred = false; 455 } 456 457 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 458 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 459 drv->uploadDeferred = true; 460 } 461 462 int32_t rsdAllocationInitSurfaceTexture(const Context *rsc, const Allocation *alloc) { 463 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 464 UploadToTexture(rsc, alloc); 465 return drv->textureID; 466 } 467 468 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 469 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 470 471 int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer); 472 if (r) { 473 rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer."); 474 return false; 475 } 476 477 // Must lock the whole surface 478 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 479 Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height); 480 481 void *dst = NULL; 482 mapper.lock(drv->wndBuffer->handle, 483 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN, 484 bounds, &dst); 485 drv->lod[0].mallocPtr = dst; 486 alloc->mHal.drvState.mallocPtrLOD0 = dst; 487 drv->lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes; 488 489 return true; 490 } 491 492 void rsdAllocationSetSurfaceTexture(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 493 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 494 495 //ALOGE("rsdAllocationSetSurfaceTexture %p %p", alloc, nw); 496 497 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 498 //TODO finish support for render target + script 499 drv->wnd = nw; 500 return; 501 } 502 503 504 // Cleanup old surface if there is one. 505 if (alloc->mHal.state.wndSurface) { 506 ANativeWindow *old = alloc->mHal.state.wndSurface; 507 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 508 mapper.unlock(drv->wndBuffer->handle); 509 old->queueBuffer(old, drv->wndBuffer, -1); 510 } 511 512 if (nw != NULL) { 513 int32_t r; 514 uint32_t flags = 0; 515 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 516 flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN; 517 } 518 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 519 flags |= GRALLOC_USAGE_HW_RENDER; 520 } 521 522 r = native_window_set_usage(nw, flags); 523 if (r) { 524 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage."); 525 return; 526 } 527 528 r = native_window_set_buffers_dimensions(nw, alloc->mHal.state.dimensionX, 529 alloc->mHal.state.dimensionY); 530 if (r) { 531 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions."); 532 return; 533 } 534 535 r = native_window_set_buffer_count(nw, 3); 536 if (r) { 537 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer count."); 538 return; 539 } 540 541 IoGetBuffer(rsc, alloc, nw); 542 } 543 } 544 545 void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) { 546 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 547 ANativeWindow *nw = alloc->mHal.state.wndSurface; 548 549 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 550 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 551 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 552 return; 553 } 554 555 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 556 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 557 mapper.unlock(drv->wndBuffer->handle); 558 int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1); 559 if (r) { 560 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer."); 561 return; 562 } 563 564 IoGetBuffer(rsc, alloc, nw); 565 } 566 } 567 568 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) { 569 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 570 alloc->mHal.state.surfaceTexture->updateTexImage(); 571 } 572 573 574 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 575 uint32_t xoff, uint32_t lod, uint32_t count, 576 const void *data, size_t sizeBytes) { 577 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 578 579 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 580 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 581 uint32_t size = count * eSize; 582 583 if (alloc->mHal.state.hasReferences) { 584 alloc->incRefs(data, count); 585 alloc->decRefs(ptr, count); 586 } 587 588 memcpy(ptr, data, size); 589 drv->uploadDeferred = true; 590 } 591 592 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 593 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 594 uint32_t w, uint32_t h, const void *data, size_t sizeBytes) { 595 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 596 597 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 598 uint32_t lineSize = eSize * w; 599 600 if (drv->lod[0].mallocPtr) { 601 const uint8_t *src = static_cast<const uint8_t *>(data); 602 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face); 603 604 for (uint32_t line=yoff; line < (yoff+h); line++) { 605 if (alloc->mHal.state.hasReferences) { 606 alloc->incRefs(src, w); 607 alloc->decRefs(dst, w); 608 } 609 memcpy(dst, src, lineSize); 610 src += lineSize; 611 dst += drv->lod[lod].stride; 612 } 613 drv->uploadDeferred = true; 614 } else { 615 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h); 616 } 617 } 618 619 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 620 uint32_t xoff, uint32_t yoff, uint32_t zoff, 621 uint32_t lod, RsAllocationCubemapFace face, 622 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { 623 624 } 625 626 void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc, 627 uint32_t xoff, uint32_t lod, uint32_t count, 628 void *data, size_t sizeBytes) { 629 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 630 631 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 632 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 633 memcpy(data, ptr, count * eSize); 634 } 635 636 void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc, 637 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 638 uint32_t w, uint32_t h, void *data, size_t sizeBytes) { 639 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 640 641 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 642 uint32_t lineSize = eSize * w; 643 644 if (drv->lod[0].mallocPtr) { 645 uint8_t *dst = static_cast<uint8_t *>(data); 646 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, lod, face); 647 648 for (uint32_t line=yoff; line < (yoff+h); line++) { 649 memcpy(dst, src, lineSize); 650 dst += lineSize; 651 src += drv->lod[lod].stride; 652 } 653 } else { 654 ALOGE("Add code to readback from non-script memory"); 655 } 656 } 657 658 void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc, 659 uint32_t xoff, uint32_t yoff, uint32_t zoff, 660 uint32_t lod, RsAllocationCubemapFace face, 661 uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes) { 662 663 } 664 665 void * rsdAllocationLock1D(const android::renderscript::Context *rsc, 666 const android::renderscript::Allocation *alloc) { 667 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 668 return drv->lod[0].mallocPtr; 669 } 670 671 void rsdAllocationUnlock1D(const android::renderscript::Context *rsc, 672 const android::renderscript::Allocation *alloc) { 673 674 } 675 676 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, 677 const android::renderscript::Allocation *dstAlloc, 678 uint32_t dstXoff, uint32_t dstLod, uint32_t count, 679 const android::renderscript::Allocation *srcAlloc, 680 uint32_t srcXoff, uint32_t srcLod) { 681 } 682 683 684 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, 685 const android::renderscript::Allocation *dstAlloc, 686 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 687 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 688 const android::renderscript::Allocation *srcAlloc, 689 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 690 RsAllocationCubemapFace srcFace) { 691 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 692 for (uint32_t i = 0; i < h; i ++) { 693 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace); 694 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace); 695 memcpy(dstPtr, srcPtr, w * elementSize); 696 697 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 698 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 699 } 700 } 701 702 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, 703 const android::renderscript::Allocation *dstAlloc, 704 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 705 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 706 const android::renderscript::Allocation *srcAlloc, 707 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 708 RsAllocationCubemapFace srcFace) { 709 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 710 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 711 "yet implemented."); 712 return; 713 } 714 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, 715 dstLod, dstFace, w, h, srcAlloc, 716 srcXoff, srcYoff, srcLod, srcFace); 717 } 718 719 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, 720 const android::renderscript::Allocation *dstAlloc, 721 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, 722 uint32_t dstLod, RsAllocationCubemapFace dstFace, 723 uint32_t w, uint32_t h, uint32_t d, 724 const android::renderscript::Allocation *srcAlloc, 725 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, 726 uint32_t srcLod, RsAllocationCubemapFace srcFace) { 727 } 728 729 void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc, 730 uint32_t x, 731 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 732 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 733 734 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 735 uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 736 737 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 738 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 739 740 if (alloc->mHal.state.hasReferences) { 741 e->incRefs(data); 742 e->decRefs(ptr); 743 } 744 745 memcpy(ptr, data, sizeBytes); 746 drv->uploadDeferred = true; 747 } 748 749 void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc, 750 uint32_t x, uint32_t y, 751 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 752 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 753 754 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 755 uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 756 757 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 758 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 759 760 if (alloc->mHal.state.hasReferences) { 761 e->incRefs(data); 762 e->decRefs(ptr); 763 } 764 765 memcpy(ptr, data, sizeBytes); 766 drv->uploadDeferred = true; 767 } 768 769 static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 770 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 771 uint32_t w = drv->lod[lod + 1].dimX; 772 uint32_t h = drv->lod[lod + 1].dimY; 773 774 for (uint32_t y=0; y < h; y++) { 775 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face); 776 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2, lod, face); 777 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face); 778 779 for (uint32_t x=0; x < w; x++) { 780 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 781 oPtr ++; 782 i1 += 2; 783 i2 += 2; 784 } 785 } 786 } 787 788 static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 789 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 790 uint32_t w = drv->lod[lod + 1].dimX; 791 uint32_t h = drv->lod[lod + 1].dimY; 792 793 for (uint32_t y=0; y < h; y++) { 794 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face); 795 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, lod, face); 796 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face); 797 798 for (uint32_t x=0; x < w; x++) { 799 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 800 oPtr ++; 801 i1 += 2; 802 i2 += 2; 803 } 804 } 805 } 806 807 static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 808 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 809 uint32_t w = drv->lod[lod + 1].dimX; 810 uint32_t h = drv->lod[lod + 1].dimY; 811 812 for (uint32_t y=0; y < h; y++) { 813 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, lod + 1, face); 814 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, lod, face); 815 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, lod, face); 816 817 for (uint32_t x=0; x < w; x++) { 818 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 819 oPtr ++; 820 i1 += 2; 821 i2 += 2; 822 } 823 } 824 } 825 826 void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) { 827 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 828 if(!drv->lod[0].mallocPtr) { 829 return; 830 } 831 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; 832 for (uint32_t face = 0; face < numFaces; face ++) { 833 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) { 834 switch (alloc->getType()->getElement()->getSizeBits()) { 835 case 32: 836 mip8888(alloc, lod, (RsAllocationCubemapFace)face); 837 break; 838 case 16: 839 mip565(alloc, lod, (RsAllocationCubemapFace)face); 840 break; 841 case 8: 842 mip8(alloc, lod, (RsAllocationCubemapFace)face); 843 break; 844 } 845 } 846 } 847 } 848 849 850