1 /* 2 * Copyright (C) 2011 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 <GLES/gl.h> 27 #include <GLES2/gl2.h> 28 #include <GLES/glext.h> 29 30 using namespace android; 31 using namespace android::renderscript; 32 33 34 35 const static GLenum gFaceOrder[] = { 36 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 37 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 38 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 39 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 40 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 41 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 42 }; 43 44 45 GLenum rsdTypeToGLType(RsDataType t) { 46 switch (t) { 47 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5; 48 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1; 49 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4; 50 51 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT; 52 case RS_TYPE_FLOAT_32: return GL_FLOAT; 53 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE; 54 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT; 55 case RS_TYPE_SIGNED_8: return GL_BYTE; 56 case RS_TYPE_SIGNED_16: return GL_SHORT; 57 default: break; 58 } 59 return 0; 60 } 61 62 GLenum rsdKindToGLFormat(RsDataKind k) { 63 switch (k) { 64 case RS_KIND_PIXEL_L: return GL_LUMINANCE; 65 case RS_KIND_PIXEL_A: return GL_ALPHA; 66 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA; 67 case RS_KIND_PIXEL_RGB: return GL_RGB; 68 case RS_KIND_PIXEL_RGBA: return GL_RGBA; 69 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16; 70 default: break; 71 } 72 return 0; 73 } 74 75 76 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr, 77 uint32_t xoff, uint32_t yoff, uint32_t lod, 78 RsAllocationCubemapFace face, uint32_t w, uint32_t h) { 79 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 80 81 rsAssert(drv->textureID); 82 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID); 83 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1); 84 GLenum t = GL_TEXTURE_2D; 85 if (alloc->mHal.state.hasFaces) { 86 t = gFaceOrder[face]; 87 } 88 RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr); 89 } 90 91 92 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) { 93 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 94 95 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID); 96 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1); 97 98 uint32_t faceCount = 1; 99 if (alloc->mHal.state.hasFaces) { 100 faceCount = 6; 101 } 102 103 rsdGLCheckError(rsc, "Upload2DTexture 1 "); 104 for (uint32_t face = 0; face < faceCount; face ++) { 105 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) { 106 const uint8_t *p = (const uint8_t *)drv->mallocPtr; 107 p += alloc->mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0); 108 109 GLenum t = GL_TEXTURE_2D; 110 if (alloc->mHal.state.hasFaces) { 111 t = gFaceOrder[face]; 112 } 113 114 if (isFirstUpload) { 115 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat, 116 alloc->mHal.state.type->getLODDimX(lod), 117 alloc->mHal.state.type->getLODDimY(lod), 118 0, drv->glFormat, drv->glType, p); 119 } else { 120 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0, 121 alloc->mHal.state.type->getLODDimX(lod), 122 alloc->mHal.state.type->getLODDimY(lod), 123 drv->glFormat, drv->glType, p); 124 } 125 } 126 } 127 128 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) { 129 RSD_CALL_GL(glGenerateMipmap, drv->glTarget); 130 } 131 rsdGLCheckError(rsc, "Upload2DTexture"); 132 } 133 134 static void UploadToTexture(const Context *rsc, const Allocation *alloc) { 135 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 136 137 if (!drv->glType || !drv->glFormat) { 138 return; 139 } 140 141 if (!alloc->getPtr()) { 142 return; 143 } 144 145 bool isFirstUpload = false; 146 147 if (!drv->textureID) { 148 RSD_CALL_GL(glGenTextures, 1, &drv->textureID); 149 isFirstUpload = true; 150 } 151 152 Upload2DTexture(rsc, alloc, isFirstUpload); 153 154 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { 155 if (drv->mallocPtr) { 156 free(drv->mallocPtr); 157 drv->mallocPtr = NULL; 158 } 159 } 160 rsdGLCheckError(rsc, "UploadToTexture"); 161 } 162 163 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) { 164 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 165 166 if (!drv->glFormat) { 167 return; 168 } 169 170 if (!drv->renderTargetID) { 171 RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID); 172 173 if (!drv->renderTargetID) { 174 // This should generally not happen 175 LOGE("allocateRenderTarget failed to gen mRenderTargetID"); 176 rsc->dumpDebug(); 177 return; 178 } 179 RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID); 180 RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat, 181 alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY); 182 } 183 rsdGLCheckError(rsc, "AllocateRenderTarget"); 184 } 185 186 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) { 187 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 188 189 rsAssert(!alloc->mHal.state.type->getDimY()); 190 rsAssert(!alloc->mHal.state.type->getDimZ()); 191 192 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; 193 194 if (!drv->bufferID) { 195 RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID); 196 } 197 if (!drv->bufferID) { 198 LOGE("Upload to buffer object failed"); 199 drv->uploadDeferred = true; 200 return; 201 } 202 RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID); 203 RSD_CALL_GL(glBufferData, drv->glTarget, alloc->mHal.state.type->getSizeBytes(), 204 drv->mallocPtr, GL_DYNAMIC_DRAW); 205 RSD_CALL_GL(glBindBuffer, drv->glTarget, 0); 206 rsdGLCheckError(rsc, "UploadToBufferObject"); 207 } 208 209 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { 210 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 211 if (!drv) { 212 return false; 213 } 214 215 void * ptr = malloc(alloc->mHal.state.type->getSizeBytes()); 216 if (!ptr) { 217 free(drv); 218 return false; 219 } 220 221 drv->glTarget = GL_NONE; 222 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 223 if (alloc->mHal.state.hasFaces) { 224 drv->glTarget = GL_TEXTURE_CUBE_MAP; 225 } else { 226 drv->glTarget = GL_TEXTURE_2D; 227 } 228 } else { 229 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 230 drv->glTarget = GL_ARRAY_BUFFER; 231 } 232 } 233 234 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType()); 235 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind()); 236 237 238 alloc->mHal.drvState.mallocPtr = ptr; 239 drv->mallocPtr = (uint8_t *)ptr; 240 alloc->mHal.drv = drv; 241 if (forceZero) { 242 memset(ptr, 0, alloc->mHal.state.type->getSizeBytes()); 243 } 244 245 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { 246 drv->uploadDeferred = true; 247 } 248 249 drv->readBackFBO = NULL; 250 251 return true; 252 } 253 254 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { 255 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 256 257 if (drv->bufferID) { 258 // Causes a SW crash.... 259 //LOGV(" mBufferID %i", mBufferID); 260 //glDeleteBuffers(1, &mBufferID); 261 //mBufferID = 0; 262 } 263 if (drv->textureID) { 264 RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID); 265 drv->textureID = 0; 266 } 267 if (drv->renderTargetID) { 268 RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID); 269 drv->renderTargetID = 0; 270 } 271 272 if (drv->mallocPtr) { 273 free(drv->mallocPtr); 274 drv->mallocPtr = NULL; 275 } 276 if (drv->readBackFBO != NULL) { 277 delete drv->readBackFBO; 278 drv->readBackFBO = NULL; 279 } 280 free(drv); 281 alloc->mHal.drv = NULL; 282 } 283 284 void rsdAllocationResize(const Context *rsc, const Allocation *alloc, 285 const Type *newType, bool zeroNew) { 286 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 287 288 drv->mallocPtr = (uint8_t *)realloc(drv->mallocPtr, newType->getSizeBytes()); 289 290 // fixme 291 ((Allocation *)alloc)->mHal.drvState.mallocPtr = drv->mallocPtr; 292 293 const uint32_t oldDimX = alloc->mHal.state.dimensionX; 294 const uint32_t dimX = newType->getDimX(); 295 296 if (dimX > oldDimX) { 297 const Element *e = alloc->mHal.state.type->getElement(); 298 uint32_t stride = e->getSizeBytes(); 299 memset(((uint8_t *)drv->mallocPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX)); 300 } 301 } 302 303 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) { 304 if (!alloc->getIsScript()) { 305 return; // nothing to sync 306 } 307 308 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 309 RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer; 310 311 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 312 if (!drv->textureID && !drv->renderTargetID) { 313 return; // nothing was rendered here yet, so nothing to sync 314 } 315 if (drv->readBackFBO == NULL) { 316 drv->readBackFBO = new RsdFrameBufferObj(); 317 drv->readBackFBO->setColorTarget(drv, 0); 318 drv->readBackFBO->setDimensions(alloc->getType()->getDimX(), 319 alloc->getType()->getDimY()); 320 } 321 322 // Bind the framebuffer object so we can read back from it 323 drv->readBackFBO->setActive(rsc); 324 325 // Do the readback 326 RSD_CALL_GL(glReadPixels, 0, 0, alloc->getType()->getDimX(), alloc->getType()->getDimY(), 327 drv->glFormat, drv->glType, alloc->getPtr()); 328 329 // Revert framebuffer to its original 330 lastFbo->setActive(rsc); 331 } 332 333 334 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, 335 RsAllocationUsageType src) { 336 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 337 338 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 339 if(!alloc->getIsRenderTarget()) { 340 rsc->setError(RS_ERROR_FATAL_DRIVER, 341 "Attempting to sync allocation from render target, " 342 "for non-render target allocation"); 343 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) { 344 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA" 345 "render target"); 346 } else { 347 rsdAllocationSyncFromFBO(rsc, alloc); 348 } 349 return; 350 } 351 352 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT); 353 354 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 355 UploadToTexture(rsc, alloc); 356 } else { 357 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 358 AllocateRenderTarget(rsc, alloc); 359 } 360 } 361 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 362 UploadToBufferObject(rsc, alloc); 363 } 364 365 drv->uploadDeferred = false; 366 } 367 368 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 369 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 370 drv->uploadDeferred = true; 371 } 372 373 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 374 uint32_t xoff, uint32_t lod, uint32_t count, 375 const void *data, uint32_t sizeBytes) { 376 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 377 378 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 379 uint8_t * ptr = drv->mallocPtr; 380 ptr += eSize * xoff; 381 uint32_t size = count * eSize; 382 383 if (alloc->mHal.state.hasReferences) { 384 alloc->incRefs(data, count); 385 alloc->decRefs(ptr, count); 386 } 387 388 memcpy(ptr, data, size); 389 drv->uploadDeferred = true; 390 } 391 392 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 393 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 394 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) { 395 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 396 397 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 398 uint32_t lineSize = eSize * w; 399 uint32_t destW = alloc->mHal.state.dimensionX; 400 401 if (drv->mallocPtr) { 402 const uint8_t *src = static_cast<const uint8_t *>(data); 403 uint8_t *dst = drv->mallocPtr; 404 dst += alloc->mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff); 405 406 for (uint32_t line=yoff; line < (yoff+h); line++) { 407 if (alloc->mHal.state.hasReferences) { 408 alloc->incRefs(src, w); 409 alloc->decRefs(dst, w); 410 } 411 memcpy(dst, src, lineSize); 412 src += lineSize; 413 dst += destW * eSize; 414 } 415 drv->uploadDeferred = true; 416 } else { 417 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h); 418 } 419 } 420 421 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 422 uint32_t xoff, uint32_t yoff, uint32_t zoff, 423 uint32_t lod, RsAllocationCubemapFace face, 424 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { 425 426 } 427 428 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, 429 const android::renderscript::Allocation *dstAlloc, 430 uint32_t dstXoff, uint32_t dstLod, uint32_t count, 431 const android::renderscript::Allocation *srcAlloc, 432 uint32_t srcXoff, uint32_t srcLod) { 433 } 434 435 uint8_t *getOffsetPtr(const android::renderscript::Allocation *alloc, 436 uint32_t xoff, uint32_t yoff, uint32_t lod, 437 RsAllocationCubemapFace face) { 438 uint8_t *ptr = static_cast<uint8_t *>(alloc->getPtr()); 439 ptr += alloc->getType()->getLODOffset(lod, xoff, yoff); 440 441 if (face != 0) { 442 uint32_t totalSizeBytes = alloc->getType()->getSizeBytes(); 443 uint32_t faceOffset = totalSizeBytes / 6; 444 ptr += faceOffset * (uint32_t)face; 445 } 446 return ptr; 447 } 448 449 450 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, 451 const android::renderscript::Allocation *dstAlloc, 452 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 453 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 454 const android::renderscript::Allocation *srcAlloc, 455 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 456 RsAllocationCubemapFace srcFace) { 457 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); 458 for (uint32_t i = 0; i < h; i ++) { 459 uint8_t *dstPtr = getOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace); 460 uint8_t *srcPtr = getOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace); 461 memcpy(dstPtr, srcPtr, w * elementSize); 462 463 //LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", 464 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); 465 } 466 } 467 468 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, 469 const android::renderscript::Allocation *dstAlloc, 470 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, 471 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, 472 const android::renderscript::Allocation *srcAlloc, 473 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, 474 RsAllocationCubemapFace srcFace) { 475 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { 476 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " 477 "yet implemented."); 478 return; 479 } 480 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, 481 dstLod, dstFace, w, h, srcAlloc, 482 srcXoff, srcYoff, srcLod, srcFace); 483 } 484 485 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, 486 const android::renderscript::Allocation *dstAlloc, 487 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, 488 uint32_t dstLod, RsAllocationCubemapFace dstFace, 489 uint32_t w, uint32_t h, uint32_t d, 490 const android::renderscript::Allocation *srcAlloc, 491 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, 492 uint32_t srcLod, RsAllocationCubemapFace srcFace) { 493 } 494 495 void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc, 496 uint32_t x, 497 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 498 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 499 500 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 501 uint8_t * ptr = drv->mallocPtr; 502 ptr += eSize * x; 503 504 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 505 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 506 507 if (alloc->mHal.state.hasReferences) { 508 e->incRefs(data); 509 e->decRefs(ptr); 510 } 511 512 memcpy(ptr, data, sizeBytes); 513 drv->uploadDeferred = true; 514 } 515 516 void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc, 517 uint32_t x, uint32_t y, 518 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 519 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 520 521 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 522 uint8_t * ptr = drv->mallocPtr; 523 ptr += eSize * (x + y * alloc->mHal.state.dimensionX); 524 525 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 526 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 527 528 if (alloc->mHal.state.hasReferences) { 529 e->incRefs(data); 530 e->decRefs(ptr); 531 } 532 533 memcpy(ptr, data, sizeBytes); 534 drv->uploadDeferred = true; 535 } 536 537 538