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