rsdAllocation.cpp revision 5b9be087cf874fa3282c6e5c83da09a6d218ecf4
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 = nw->dequeueBuffer(nw, &drv->wndBuffer); 473 if (r) { 474 rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer."); 475 return false; 476 } 477 478 // This lock is implicitly released by the queue buffer in IoSend 479 r = nw->lockBuffer(nw, drv->wndBuffer); 480 if (r) { 481 rsc->setError(RS_ERROR_DRIVER, "Error locking next IO output buffer."); 482 return false; 483 } 484 485 // Must lock the whole surface 486 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 487 Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height); 488 489 void *dst = NULL; 490 mapper.lock(drv->wndBuffer->handle, 491 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN, 492 bounds, &dst); 493 drv->lod[0].mallocPtr = dst; 494 alloc->mHal.drvState.mallocPtrLOD0 = dst; 495 drv->lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes; 496 497 return true; 498} 499 500void rsdAllocationSetSurfaceTexture(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 501 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 502 503 //ALOGE("rsdAllocationSetSurfaceTexture %p %p", alloc, nw); 504 505 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 506 //TODO finish support for render target + script 507 drv->wnd = nw; 508 return; 509 } 510 511 512 // Cleanup old surface if there is one. 513 if (alloc->mHal.state.wndSurface) { 514 ANativeWindow *old = alloc->mHal.state.wndSurface; 515 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 516 mapper.unlock(drv->wndBuffer->handle); 517 old->queueBuffer(old, drv->wndBuffer); 518 } 519 520 if (nw != NULL) { 521 int32_t r; 522 uint32_t flags = 0; 523 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 524 flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN; 525 } 526 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 527 flags |= GRALLOC_USAGE_HW_RENDER; 528 } 529 530 r = native_window_set_usage(nw, flags); 531 if (r) { 532 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage."); 533 return; 534 } 535 536 r = native_window_set_buffers_dimensions(nw, alloc->mHal.state.dimensionX, 537 alloc->mHal.state.dimensionY); 538 if (r) { 539 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions."); 540 return; 541 } 542 543 r = native_window_set_buffer_count(nw, 3); 544 if (r) { 545 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer count."); 546 return; 547 } 548 549 IoGetBuffer(rsc, alloc, nw); 550 } 551} 552 553void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) { 554 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 555 ANativeWindow *nw = alloc->mHal.state.wndSurface; 556 557 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 558 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 559 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 560 return; 561 } 562 563 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) { 564 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 565 mapper.unlock(drv->wndBuffer->handle); 566 int32_t r = nw->queueBuffer(nw, drv->wndBuffer); 567 if (r) { 568 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer."); 569 return; 570 } 571 572 IoGetBuffer(rsc, alloc, nw); 573 } 574} 575 576void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) { 577 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 578 alloc->mHal.state.surfaceTexture->updateTexImage(); 579} 580 581 582void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 583 uint32_t xoff, uint32_t lod, uint32_t count, 584 const void *data, size_t sizeBytes) { 585 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 586 587 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 588 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 589 uint32_t size = count * eSize; 590 591 if (alloc->mHal.state.hasReferences) { 592 alloc->incRefs(data, count); 593 alloc->decRefs(ptr, count); 594 } 595 596 memcpy(ptr, data, size); 597 drv->uploadDeferred = true; 598} 599 600void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 601 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 602 uint32_t w, uint32_t h, const void *data, size_t sizeBytes) { 603 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 604 605 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 606 uint32_t lineSize = eSize * w; 607 608 if (drv->lod[0].mallocPtr) { 609 const uint8_t *src = static_cast<const uint8_t *>(data); 610 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face); 611 612 for (uint32_t line=yoff; line < (yoff+h); line++) { 613 if (alloc->mHal.state.hasReferences) { 614 alloc->incRefs(src, w); 615 alloc->decRefs(dst, w); 616 } 617 memcpy(dst, src, lineSize); 618 src += lineSize; 619 dst += drv->lod[lod].stride; 620 } 621 drv->uploadDeferred = true; 622 } else { 623 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h); 624 } 625} 626 627void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 628 uint32_t xoff, uint32_t yoff, uint32_t zoff, 629 uint32_t lod, RsAllocationCubemapFace face, 630 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { 631 632} 633 634void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc, 635 uint32_t xoff, uint32_t lod, uint32_t count, 636 void *data, size_t sizeBytes) { 637 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 638 639 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 640 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 641 memcpy(data, ptr, count * eSize); 642} 643 644void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc, 645 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 646 uint32_t w, uint32_t h, void *data, size_t sizeBytes) { 647 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 648 649 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 650 uint32_t lineSize = eSize * w; 651 652 if (drv->lod[0].mallocPtr) { 653 uint8_t *dst = static_cast<uint8_t *>(data); 654 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, lod, face); 655 656 for (uint32_t line=yoff; line < (yoff+h); line++) { 657 memcpy(dst, src, lineSize); 658 dst += lineSize; 659 src += drv->lod[lod].stride; 660 } 661 } else { 662 ALOGE("Add code to readback from non-script memory"); 663 } 664} 665 666void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc, 667 uint32_t xoff, uint32_t yoff, uint32_t zoff, 668 uint32_t lod, RsAllocationCubemapFace face, 669 uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes) { 670 671} 672 673void * rsdAllocationLock1D(const android::renderscript::Context *rsc, 674 const android::renderscript::Allocation *alloc) { 675 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 676 return drv->lod[0].mallocPtr; 677} 678 679void rsdAllocationUnlock1D(const android::renderscript::Context *rsc, 680 const android::renderscript::Allocation *alloc) { 681 682} 683 684void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, 685 const android::renderscript::Allocation *dstAlloc, 686 uint32_t dstXoff, uint32_t dstLod, uint32_t count, 687 const android::renderscript::Allocation *srcAlloc, 688 uint32_t srcXoff, uint32_t srcLod) { 689} 690 691 692void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, 693 const android::renderscript::Allocation *dstAlloc, 694 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 695 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 696 const android::renderscript::Allocation *srcAlloc, 697 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 698 RsAllocationCubemapFace srcFace) { 699 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 700 for (uint32_t i = 0; i < h; i ++) { 701 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace); 702 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace); 703 memcpy(dstPtr, srcPtr, w * elementSize); 704 705 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 706 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 707 } 708} 709 710void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, 711 const android::renderscript::Allocation *dstAlloc, 712 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 713 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 714 const android::renderscript::Allocation *srcAlloc, 715 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 716 RsAllocationCubemapFace srcFace) { 717 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 718 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 719 "yet implemented."); 720 return; 721 } 722 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, 723 dstLod, dstFace, w, h, srcAlloc, 724 srcXoff, srcYoff, srcLod, srcFace); 725} 726 727void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, 728 const android::renderscript::Allocation *dstAlloc, 729 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, 730 uint32_t dstLod, RsAllocationCubemapFace dstFace, 731 uint32_t w, uint32_t h, uint32_t d, 732 const android::renderscript::Allocation *srcAlloc, 733 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, 734 uint32_t srcLod, RsAllocationCubemapFace srcFace) { 735} 736 737void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc, 738 uint32_t x, 739 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 740 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 741 742 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 743 uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 744 745 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 746 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 747 748 if (alloc->mHal.state.hasReferences) { 749 e->incRefs(data); 750 e->decRefs(ptr); 751 } 752 753 memcpy(ptr, data, sizeBytes); 754 drv->uploadDeferred = true; 755} 756 757void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc, 758 uint32_t x, uint32_t y, 759 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 760 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 761 762 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 763 uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 764 765 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 766 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 767 768 if (alloc->mHal.state.hasReferences) { 769 e->incRefs(data); 770 e->decRefs(ptr); 771 } 772 773 memcpy(ptr, data, sizeBytes); 774 drv->uploadDeferred = true; 775} 776 777static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 778 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 779 uint32_t w = drv->lod[lod + 1].dimX; 780 uint32_t h = drv->lod[lod + 1].dimY; 781 782 for (uint32_t y=0; y < h; y++) { 783 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face); 784 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2, lod, face); 785 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face); 786 787 for (uint32_t x=0; x < w; x++) { 788 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 789 oPtr ++; 790 i1 += 2; 791 i2 += 2; 792 } 793 } 794} 795 796static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 797 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 798 uint32_t w = drv->lod[lod + 1].dimX; 799 uint32_t h = drv->lod[lod + 1].dimY; 800 801 for (uint32_t y=0; y < h; y++) { 802 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face); 803 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, lod, face); 804 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face); 805 806 for (uint32_t x=0; x < w; x++) { 807 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 808 oPtr ++; 809 i1 += 2; 810 i2 += 2; 811 } 812 } 813} 814 815static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 816 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 817 uint32_t w = drv->lod[lod + 1].dimX; 818 uint32_t h = drv->lod[lod + 1].dimY; 819 820 for (uint32_t y=0; y < h; y++) { 821 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, lod + 1, face); 822 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, lod, face); 823 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, lod, face); 824 825 for (uint32_t x=0; x < w; x++) { 826 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 827 oPtr ++; 828 i1 += 2; 829 i2 += 2; 830 } 831 } 832} 833 834void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) { 835 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 836 if(!drv->lod[0].mallocPtr) { 837 return; 838 } 839 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; 840 for (uint32_t face = 0; face < numFaces; face ++) { 841 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) { 842 switch (alloc->getType()->getElement()->getSizeBits()) { 843 case 32: 844 mip8888(alloc, lod, (RsAllocationCubemapFace)face); 845 break; 846 case 16: 847 mip565(alloc, lod, (RsAllocationCubemapFace)face); 848 break; 849 case 8: 850 mip8(alloc, lod, (RsAllocationCubemapFace)face); 851 break; 852 } 853 } 854 } 855} 856 857 858