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 40uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc, 41 uint32_t xoff, uint32_t yoff, uint32_t lod, 42 RsAllocationCubemapFace face) { 43 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 44 uint8_t *ptr = (uint8_t *)drv->lod[lod].mallocPtr; 45 ptr += face * drv->faceOffset; 46 ptr += yoff * drv->lod[lod].stride; 47 ptr += xoff * alloc->mHal.state.elementSizeBytes; 48 return ptr; 49} 50 51 52static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr, 53 uint32_t xoff, uint32_t yoff, uint32_t lod, 54 RsAllocationCubemapFace face, uint32_t w, uint32_t h) { 55} 56 57 58static void UploadToTexture(const Context *rsc, const Allocation *alloc) { 59} 60 61static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) { 62} 63 64static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) { 65} 66 67static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc, 68 const Type *type, uint8_t *ptr) { 69 70 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 71 72 drv->lod[0].dimX = type->getDimX(); 73 drv->lod[0].dimY = type->getDimY(); 74 drv->lod[0].mallocPtr = 0; 75 drv->lod[0].stride = drv->lod[0].dimX * type->getElementSizeBytes(); 76 drv->lodCount = type->getLODCount(); 77 drv->faceCount = type->getDimFaces(); 78 79 size_t offsets[Allocation::MAX_LOD]; 80 memset(offsets, 0, sizeof(offsets)); 81 82 size_t o = drv->lod[0].stride * rsMax(drv->lod[0].dimY, 1u) * rsMax(drv->lod[0].dimZ, 1u); 83 if(drv->lodCount > 1) { 84 uint32_t tx = drv->lod[0].dimX; 85 uint32_t ty = drv->lod[0].dimY; 86 uint32_t tz = drv->lod[0].dimZ; 87 for (uint32_t lod=1; lod < drv->lodCount; lod++) { 88 drv->lod[lod].dimX = tx; 89 drv->lod[lod].dimY = ty; 90 drv->lod[lod].dimZ = tz; 91 drv->lod[lod].stride = tx * type->getElementSizeBytes(); 92 offsets[lod] = o; 93 o += drv->lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u); 94 if (tx > 1) tx >>= 1; 95 if (ty > 1) ty >>= 1; 96 if (tz > 1) tz >>= 1; 97 } 98 } 99 drv->faceOffset = o; 100 101 drv->lod[0].mallocPtr = ptr; 102 for (uint32_t lod=1; lod < drv->lodCount; lod++) { 103 drv->lod[lod].mallocPtr = ptr + offsets[lod]; 104 } 105 alloc->mHal.drvState.strideLOD0 = drv->lod[0].stride; 106 alloc->mHal.drvState.mallocPtrLOD0 = ptr; 107 108 size_t allocSize = drv->faceOffset; 109 if(drv->faceCount) { 110 allocSize *= 6; 111 } 112 113 return allocSize; 114} 115 116bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { 117 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 118 if (!drv) { 119 return false; 120 } 121 alloc->mHal.drv = drv; 122 123 // Calculate the object size. 124 size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), NULL); 125 126 ALOGE("alloc usage %i", alloc->mHal.state.usageFlags); 127 128 uint8_t * ptr = NULL; 129 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) { 130 } else { 131 132 ptr = (uint8_t *)malloc(allocSize); 133 if (!ptr) { 134 free(drv); 135 return false; 136 } 137 } 138 // Build the pointer tables 139 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr); 140 if(allocSize != verifySize) { 141 rsAssert(!"Size mismatch"); 142 } 143 144 drv->glTarget = GL_NONE; 145 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 146 if (alloc->mHal.state.hasFaces) { 147 drv->glTarget = GL_TEXTURE_CUBE_MAP; 148 } else { 149 drv->glTarget = GL_TEXTURE_2D; 150 } 151 } else { 152 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 153 drv->glTarget = GL_ARRAY_BUFFER; 154 } 155 } 156 157 drv->glType = 0; 158 drv->glFormat = 0; 159 160 if (forceZero && ptr) { 161 memset(ptr, 0, alloc->mHal.state.type->getSizeBytes()); 162 } 163 164 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { 165 drv->uploadDeferred = true; 166 } 167 168 169 drv->readBackFBO = NULL; 170 171 return true; 172} 173 174void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { 175 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 176 177 if (alloc->mHal.drvState.mallocPtrLOD0) { 178 free(alloc->mHal.drvState.mallocPtrLOD0); 179 alloc->mHal.drvState.mallocPtrLOD0 = NULL; 180 } 181 free(drv); 182 alloc->mHal.drv = NULL; 183} 184 185void rsdAllocationResize(const Context *rsc, const Allocation *alloc, 186 const Type *newType, bool zeroNew) { 187 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 188 189 void * oldPtr = drv->lod[0].mallocPtr; 190 // Calculate the object size 191 size_t s = AllocationBuildPointerTable(rsc, alloc, newType, NULL); 192 uint8_t *ptr = (uint8_t *)realloc(oldPtr, s); 193 // Build the relative pointer tables. 194 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr); 195 if(s != verifySize) { 196 rsAssert(!"Size mismatch"); 197 } 198 199 const uint32_t oldDimX = alloc->mHal.state.dimensionX; 200 const uint32_t dimX = newType->getDimX(); 201 202 if (dimX > oldDimX) { 203 uint32_t stride = alloc->mHal.state.elementSizeBytes; 204 memset(((uint8_t *)alloc->mHal.drvState.mallocPtrLOD0) + stride * oldDimX, 205 0, stride * (dimX - oldDimX)); 206 } 207} 208 209static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) { 210} 211 212 213void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, 214 RsAllocationUsageType src) { 215 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 216 217 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 218 if(!alloc->getIsRenderTarget()) { 219 rsc->setError(RS_ERROR_FATAL_DRIVER, 220 "Attempting to sync allocation from render target, " 221 "for non-render target allocation"); 222 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) { 223 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA" 224 "render target"); 225 } else { 226 rsdAllocationSyncFromFBO(rsc, alloc); 227 } 228 return; 229 } 230 231 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT); 232 233 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 234 UploadToTexture(rsc, alloc); 235 } else { 236 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) && 237 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) { 238 AllocateRenderTarget(rsc, alloc); 239 } 240 } 241 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 242 UploadToBufferObject(rsc, alloc); 243 } 244 245 drv->uploadDeferred = false; 246} 247 248void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 249 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 250 drv->uploadDeferred = true; 251} 252 253int32_t rsdAllocationInitSurfaceTexture(const Context *rsc, const Allocation *alloc) { 254 return 0; 255} 256 257void rsdAllocationSetSurfaceTexture(const Context *rsc, Allocation *alloc, ANativeWindow *nw) { 258} 259 260void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) { 261} 262 263void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) { 264} 265 266 267void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 268 uint32_t xoff, uint32_t lod, uint32_t count, 269 const void *data, size_t sizeBytes) { 270 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 271 272 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 273 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 274 uint32_t size = count * eSize; 275 276 if (alloc->mHal.state.hasReferences) { 277 alloc->incRefs(data, count); 278 alloc->decRefs(ptr, count); 279 } 280 281 memcpy(ptr, data, size); 282 drv->uploadDeferred = true; 283} 284 285void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 286 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 287 uint32_t w, uint32_t h, const void *data, size_t sizeBytes) { 288 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 289 290 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 291 uint32_t lineSize = eSize * w; 292 293 if (drv->lod[0].mallocPtr) { 294 const uint8_t *src = static_cast<const uint8_t *>(data); 295 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face); 296 297 for (uint32_t line=yoff; line < (yoff+h); line++) { 298 if (alloc->mHal.state.hasReferences) { 299 alloc->incRefs(src, w); 300 alloc->decRefs(dst, w); 301 } 302 memcpy(dst, src, lineSize); 303 src += lineSize; 304 dst += drv->lod[lod].stride; 305 } 306 drv->uploadDeferred = true; 307 } else { 308 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h); 309 } 310} 311 312void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 313 uint32_t xoff, uint32_t yoff, uint32_t zoff, 314 uint32_t lod, RsAllocationCubemapFace face, 315 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { 316 317} 318 319void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc, 320 uint32_t xoff, uint32_t lod, uint32_t count, 321 void *data, size_t sizeBytes) { 322 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 323 324 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 325 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 326 memcpy(data, ptr, count * eSize); 327} 328 329void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc, 330 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 331 uint32_t w, uint32_t h, void *data, size_t sizeBytes) { 332 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 333 334 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 335 uint32_t lineSize = eSize * w; 336 337 if (drv->lod[0].mallocPtr) { 338 uint8_t *dst = static_cast<uint8_t *>(data); 339 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, lod, face); 340 341 for (uint32_t line=yoff; line < (yoff+h); line++) { 342 memcpy(dst, src, lineSize); 343 dst += lineSize; 344 src += drv->lod[lod].stride; 345 } 346 } else { 347 ALOGE("Add code to readback from non-script memory"); 348 } 349} 350 351void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc, 352 uint32_t xoff, uint32_t yoff, uint32_t zoff, 353 uint32_t lod, RsAllocationCubemapFace face, 354 uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes) { 355 356} 357 358void * rsdAllocationLock1D(const android::renderscript::Context *rsc, 359 const android::renderscript::Allocation *alloc) { 360 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 361 return drv->lod[0].mallocPtr; 362} 363 364void rsdAllocationUnlock1D(const android::renderscript::Context *rsc, 365 const android::renderscript::Allocation *alloc) { 366 367} 368 369void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, 370 const android::renderscript::Allocation *dstAlloc, 371 uint32_t dstXoff, uint32_t dstLod, uint32_t count, 372 const android::renderscript::Allocation *srcAlloc, 373 uint32_t srcXoff, uint32_t srcLod) { 374} 375 376 377void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, 378 const android::renderscript::Allocation *dstAlloc, 379 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 380 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 381 const android::renderscript::Allocation *srcAlloc, 382 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 383 RsAllocationCubemapFace srcFace) { 384 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 385 for (uint32_t i = 0; i < h; i ++) { 386 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace); 387 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace); 388 memcpy(dstPtr, srcPtr, w * elementSize); 389 390 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 391 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 392 } 393} 394 395void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, 396 const android::renderscript::Allocation *dstAlloc, 397 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 398 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 399 const android::renderscript::Allocation *srcAlloc, 400 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 401 RsAllocationCubemapFace srcFace) { 402 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 403 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 404 "yet implemented."); 405 return; 406 } 407 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, 408 dstLod, dstFace, w, h, srcAlloc, 409 srcXoff, srcYoff, srcLod, srcFace); 410} 411 412void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, 413 const android::renderscript::Allocation *dstAlloc, 414 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, 415 uint32_t dstLod, RsAllocationCubemapFace dstFace, 416 uint32_t w, uint32_t h, uint32_t d, 417 const android::renderscript::Allocation *srcAlloc, 418 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, 419 uint32_t srcLod, RsAllocationCubemapFace srcFace) { 420} 421 422void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc, 423 uint32_t x, 424 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 425 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 426 427 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 428 uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 429 430 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 431 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 432 433 if (alloc->mHal.state.hasReferences) { 434 e->incRefs(data); 435 e->decRefs(ptr); 436 } 437 438 memcpy(ptr, data, sizeBytes); 439 drv->uploadDeferred = true; 440} 441 442void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc, 443 uint32_t x, uint32_t y, 444 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 445 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 446 447 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 448 uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); 449 450 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 451 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 452 453 if (alloc->mHal.state.hasReferences) { 454 e->incRefs(data); 455 e->decRefs(ptr); 456 } 457 458 memcpy(ptr, data, sizeBytes); 459 drv->uploadDeferred = true; 460} 461 462static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 463 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 464 uint32_t w = drv->lod[lod + 1].dimX; 465 uint32_t h = drv->lod[lod + 1].dimY; 466 467 for (uint32_t y=0; y < h; y++) { 468 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face); 469 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2, lod, face); 470 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face); 471 472 for (uint32_t x=0; x < w; x++) { 473 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 474 oPtr ++; 475 i1 += 2; 476 i2 += 2; 477 } 478 } 479} 480 481static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 482 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 483 uint32_t w = drv->lod[lod + 1].dimX; 484 uint32_t h = drv->lod[lod + 1].dimY; 485 486 for (uint32_t y=0; y < h; y++) { 487 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face); 488 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, lod, face); 489 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face); 490 491 for (uint32_t x=0; x < w; x++) { 492 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 493 oPtr ++; 494 i1 += 2; 495 i2 += 2; 496 } 497 } 498} 499 500static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) { 501 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 502 uint32_t w = drv->lod[lod + 1].dimX; 503 uint32_t h = drv->lod[lod + 1].dimY; 504 505 for (uint32_t y=0; y < h; y++) { 506 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, lod + 1, face); 507 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, lod, face); 508 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, lod, face); 509 510 for (uint32_t x=0; x < w; x++) { 511 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 512 oPtr ++; 513 i1 += 2; 514 i2 += 2; 515 } 516 } 517} 518 519void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) { 520 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 521 if(!drv->lod[0].mallocPtr) { 522 return; 523 } 524 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1; 525 for (uint32_t face = 0; face < numFaces; face ++) { 526 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) { 527 switch (alloc->getType()->getElement()->getSizeBits()) { 528 case 32: 529 mip8888(alloc, lod, (RsAllocationCubemapFace)face); 530 break; 531 case 16: 532 mip565(alloc, lod, (RsAllocationCubemapFace)face); 533 break; 534 case 8: 535 mip8(alloc, lod, (RsAllocationCubemapFace)face); 536 break; 537 } 538 } 539 } 540} 541 542 543