1 /* 2 * Copyright (C) 2010 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 #define LOG_TAG "GLConsumer" 18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 19 //#define LOG_NDEBUG 0 20 21 #define GL_GLEXT_PROTOTYPES 22 #define EGL_EGLEXT_PROTOTYPES 23 24 #include <inttypes.h> 25 26 #include <EGL/egl.h> 27 #include <EGL/eglext.h> 28 #include <GLES2/gl2.h> 29 #include <GLES2/gl2ext.h> 30 #include <cutils/compiler.h> 31 32 #include <hardware/hardware.h> 33 34 #include <gui/BufferItem.h> 35 #include <gui/GLConsumer.h> 36 #include <gui/ISurfaceComposer.h> 37 #include <gui/SurfaceComposerClient.h> 38 39 #include <private/gui/ComposerService.h> 40 #include <private/gui/SyncFeatures.h> 41 42 #include <utils/Log.h> 43 #include <utils/String8.h> 44 #include <utils/Trace.h> 45 46 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); 47 #define CROP_EXT_STR "EGL_ANDROID_image_crop" 48 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content" 49 #define EGL_PROTECTED_CONTENT_EXT 0x32C0 50 51 namespace android { 52 53 // Macros for including the GLConsumer name in log messages 54 #define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) 55 #define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) 56 //#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) 57 #define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) 58 #define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) 59 60 static const struct { 61 uint32_t width, height; 62 char const* bits; 63 } kDebugData = { 15, 12, 64 "_______________" 65 "_______________" 66 "_____XX_XX_____" 67 "__X_X_____X_X__" 68 "__X_XXXXXXX_X__" 69 "__XXXXXXXXXXX__" 70 "___XX_XXX_XX___" 71 "____XXXXXXX____" 72 "_____X___X_____" 73 "____X_____X____" 74 "_______________" 75 "_______________" 76 }; 77 78 // Transform matrices 79 static float mtxIdentity[16] = { 80 1, 0, 0, 0, 81 0, 1, 0, 0, 82 0, 0, 1, 0, 83 0, 0, 0, 1, 84 }; 85 static float mtxFlipH[16] = { 86 -1, 0, 0, 0, 87 0, 1, 0, 0, 88 0, 0, 1, 0, 89 1, 0, 0, 1, 90 }; 91 static float mtxFlipV[16] = { 92 1, 0, 0, 0, 93 0, -1, 0, 0, 94 0, 0, 1, 0, 95 0, 1, 0, 1, 96 }; 97 static float mtxRot90[16] = { 98 0, 1, 0, 0, 99 -1, 0, 0, 0, 100 0, 0, 1, 0, 101 1, 0, 0, 1, 102 }; 103 104 static void mtxMul(float out[16], const float a[16], const float b[16]); 105 106 Mutex GLConsumer::sStaticInitLock; 107 sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer; 108 109 static bool hasEglAndroidImageCropImpl() { 110 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 111 const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS); 112 size_t cropExtLen = strlen(CROP_EXT_STR); 113 size_t extsLen = strlen(exts); 114 bool equal = !strcmp(CROP_EXT_STR, exts); 115 bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1); 116 bool atEnd = (cropExtLen+1) < extsLen && 117 !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1)); 118 bool inMiddle = strstr(exts, " " CROP_EXT_STR " "); 119 return equal || atStart || atEnd || inMiddle; 120 } 121 122 static bool hasEglAndroidImageCrop() { 123 // Only compute whether the extension is present once the first time this 124 // function is called. 125 static bool hasIt = hasEglAndroidImageCropImpl(); 126 return hasIt; 127 } 128 129 static bool hasEglProtectedContentImpl() { 130 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 131 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); 132 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR); 133 size_t extsLen = strlen(exts); 134 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts); 135 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1); 136 bool atEnd = (cropExtLen+1) < extsLen && 137 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1)); 138 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " "); 139 return equal || atStart || atEnd || inMiddle; 140 } 141 142 static bool hasEglProtectedContent() { 143 // Only compute whether the extension is present once the first time this 144 // function is called. 145 static bool hasIt = hasEglProtectedContentImpl(); 146 return hasIt; 147 } 148 149 static bool isEglImageCroppable(const Rect& crop) { 150 return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0); 151 } 152 153 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, 154 uint32_t texTarget, bool useFenceSync, bool isControlledByApp) : 155 ConsumerBase(bq, isControlledByApp), 156 mCurrentCrop(Rect::EMPTY_RECT), 157 mCurrentTransform(0), 158 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 159 mCurrentFence(Fence::NO_FENCE), 160 mCurrentTimestamp(0), 161 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN), 162 mCurrentFrameNumber(0), 163 mDefaultWidth(1), 164 mDefaultHeight(1), 165 mFilteringEnabled(true), 166 mTexName(tex), 167 mUseFenceSync(useFenceSync), 168 mTexTarget(texTarget), 169 mEglDisplay(EGL_NO_DISPLAY), 170 mEglContext(EGL_NO_CONTEXT), 171 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), 172 mAttached(true) 173 { 174 GLC_LOGV("GLConsumer"); 175 176 memcpy(mCurrentTransformMatrix, mtxIdentity, 177 sizeof(mCurrentTransformMatrix)); 178 179 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); 180 } 181 182 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget, 183 bool useFenceSync, bool isControlledByApp) : 184 ConsumerBase(bq, isControlledByApp), 185 mCurrentCrop(Rect::EMPTY_RECT), 186 mCurrentTransform(0), 187 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 188 mCurrentFence(Fence::NO_FENCE), 189 mCurrentTimestamp(0), 190 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN), 191 mCurrentFrameNumber(0), 192 mDefaultWidth(1), 193 mDefaultHeight(1), 194 mFilteringEnabled(true), 195 mTexName(0), 196 mUseFenceSync(useFenceSync), 197 mTexTarget(texTarget), 198 mEglDisplay(EGL_NO_DISPLAY), 199 mEglContext(EGL_NO_CONTEXT), 200 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), 201 mAttached(false) 202 { 203 GLC_LOGV("GLConsumer"); 204 205 memcpy(mCurrentTransformMatrix, mtxIdentity, 206 sizeof(mCurrentTransformMatrix)); 207 208 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); 209 } 210 211 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) 212 { 213 Mutex::Autolock lock(mMutex); 214 if (mAbandoned) { 215 GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!"); 216 return NO_INIT; 217 } 218 mDefaultWidth = w; 219 mDefaultHeight = h; 220 return mConsumer->setDefaultBufferSize(w, h); 221 } 222 223 status_t GLConsumer::updateTexImage() { 224 ATRACE_CALL(); 225 GLC_LOGV("updateTexImage"); 226 Mutex::Autolock lock(mMutex); 227 228 if (mAbandoned) { 229 GLC_LOGE("updateTexImage: GLConsumer is abandoned!"); 230 return NO_INIT; 231 } 232 233 // Make sure the EGL state is the same as in previous calls. 234 status_t err = checkAndUpdateEglStateLocked(); 235 if (err != NO_ERROR) { 236 return err; 237 } 238 239 BufferItem item; 240 241 // Acquire the next buffer. 242 // In asynchronous mode the list is guaranteed to be one buffer 243 // deep, while in synchronous mode we use the oldest buffer. 244 err = acquireBufferLocked(&item, 0); 245 if (err != NO_ERROR) { 246 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 247 // We always bind the texture even if we don't update its contents. 248 GLC_LOGV("updateTexImage: no buffers were available"); 249 glBindTexture(mTexTarget, mTexName); 250 err = NO_ERROR; 251 } else { 252 GLC_LOGE("updateTexImage: acquire failed: %s (%d)", 253 strerror(-err), err); 254 } 255 return err; 256 } 257 258 // Release the previous buffer. 259 err = updateAndReleaseLocked(item); 260 if (err != NO_ERROR) { 261 // We always bind the texture. 262 glBindTexture(mTexTarget, mTexName); 263 return err; 264 } 265 266 // Bind the new buffer to the GL texture, and wait until it's ready. 267 return bindTextureImageLocked(); 268 } 269 270 271 status_t GLConsumer::releaseTexImage() { 272 ATRACE_CALL(); 273 GLC_LOGV("releaseTexImage"); 274 Mutex::Autolock lock(mMutex); 275 276 if (mAbandoned) { 277 GLC_LOGE("releaseTexImage: GLConsumer is abandoned!"); 278 return NO_INIT; 279 } 280 281 // Make sure the EGL state is the same as in previous calls. 282 status_t err = NO_ERROR; 283 284 if (mAttached) { 285 err = checkAndUpdateEglStateLocked(true); 286 if (err != NO_ERROR) { 287 return err; 288 } 289 } else { 290 // if we're detached, no need to validate EGL's state -- we won't use it. 291 } 292 293 // Update the GLConsumer state. 294 int buf = mCurrentTexture; 295 if (buf != BufferQueue::INVALID_BUFFER_SLOT) { 296 297 GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached); 298 299 if (mAttached) { 300 // Do whatever sync ops we need to do before releasing the slot. 301 err = syncForReleaseLocked(mEglDisplay); 302 if (err != NO_ERROR) { 303 GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err); 304 return err; 305 } 306 } else { 307 // if we're detached, we just use the fence that was created in detachFromContext() 308 // so... basically, nothing more to do here. 309 } 310 311 err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); 312 if (err < NO_ERROR) { 313 GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)", 314 strerror(-err), err); 315 return err; 316 } 317 318 if (mReleasedTexImage == NULL) { 319 mReleasedTexImage = new EglImage(getDebugTexImageBuffer()); 320 } 321 322 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; 323 mCurrentTextureImage = mReleasedTexImage; 324 mCurrentCrop.makeInvalid(); 325 mCurrentTransform = 0; 326 mCurrentTimestamp = 0; 327 mCurrentDataSpace = HAL_DATASPACE_UNKNOWN; 328 mCurrentFence = Fence::NO_FENCE; 329 mCurrentFenceTime = FenceTime::NO_FENCE; 330 331 if (mAttached) { 332 // This binds a dummy buffer (mReleasedTexImage). 333 status_t result = bindTextureImageLocked(); 334 if (result != NO_ERROR) { 335 return result; 336 } 337 } else { 338 // detached, don't touch the texture (and we may not even have an 339 // EGLDisplay here. 340 } 341 } 342 343 return NO_ERROR; 344 } 345 346 sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() { 347 Mutex::Autolock _l(sStaticInitLock); 348 if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) { 349 // The first time, create the debug texture in case the application 350 // continues to use it. 351 sp<GraphicBuffer> buffer = new GraphicBuffer( 352 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888, 353 GraphicBuffer::USAGE_SW_WRITE_RARELY, 354 "[GLConsumer debug texture]"); 355 uint32_t* bits; 356 buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits)); 357 uint32_t stride = buffer->getStride(); 358 uint32_t height = buffer->getHeight(); 359 memset(bits, 0, stride * height * 4); 360 for (uint32_t y = 0; y < kDebugData.height; y++) { 361 for (uint32_t x = 0; x < kDebugData.width; x++) { 362 bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ? 363 0xFF000000 : 0xFFFFFFFF; 364 } 365 bits += stride; 366 } 367 buffer->unlock(); 368 sReleasedTexImageBuffer = buffer; 369 } 370 return sReleasedTexImageBuffer; 371 } 372 373 status_t GLConsumer::acquireBufferLocked(BufferItem *item, 374 nsecs_t presentWhen, uint64_t maxFrameNumber) { 375 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, 376 maxFrameNumber); 377 if (err != NO_ERROR) { 378 return err; 379 } 380 381 // If item->mGraphicBuffer is not null, this buffer has not been acquired 382 // before, so any prior EglImage created is using a stale buffer. This 383 // replaces any old EglImage with a new one (using the new buffer). 384 if (item->mGraphicBuffer != NULL) { 385 int slot = item->mSlot; 386 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer); 387 } 388 389 return NO_ERROR; 390 } 391 392 status_t GLConsumer::releaseBufferLocked(int buf, 393 sp<GraphicBuffer> graphicBuffer, 394 EGLDisplay display, EGLSyncKHR eglFence) { 395 // release the buffer if it hasn't already been discarded by the 396 // BufferQueue. This can happen, for example, when the producer of this 397 // buffer has reallocated the original buffer slot after this buffer 398 // was acquired. 399 status_t err = ConsumerBase::releaseBufferLocked( 400 buf, graphicBuffer, display, eglFence); 401 mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR; 402 return err; 403 } 404 405 status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item, 406 PendingRelease* pendingRelease) 407 { 408 status_t err = NO_ERROR; 409 410 int slot = item.mSlot; 411 412 if (!mAttached) { 413 GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " 414 "ES context"); 415 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, 416 mEglDisplay, EGL_NO_SYNC_KHR); 417 return INVALID_OPERATION; 418 } 419 420 // Confirm state. 421 err = checkAndUpdateEglStateLocked(); 422 if (err != NO_ERROR) { 423 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, 424 mEglDisplay, EGL_NO_SYNC_KHR); 425 return err; 426 } 427 428 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage 429 // if nessessary, for the gralloc buffer currently in the slot in 430 // ConsumerBase. 431 // We may have to do this even when item.mGraphicBuffer == NULL (which 432 // means the buffer was previously acquired). 433 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop); 434 if (err != NO_ERROR) { 435 GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", 436 mEglDisplay, slot); 437 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, 438 mEglDisplay, EGL_NO_SYNC_KHR); 439 return UNKNOWN_ERROR; 440 } 441 442 // Do whatever sync ops we need to do before releasing the old slot. 443 if (slot != mCurrentTexture) { 444 err = syncForReleaseLocked(mEglDisplay); 445 if (err != NO_ERROR) { 446 // Release the buffer we just acquired. It's not safe to 447 // release the old buffer, so instead we just drop the new frame. 448 // As we are still under lock since acquireBuffer, it is safe to 449 // release by slot. 450 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, 451 mEglDisplay, EGL_NO_SYNC_KHR); 452 return err; 453 } 454 } 455 456 GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", 457 mCurrentTexture, mCurrentTextureImage != NULL ? 458 mCurrentTextureImage->graphicBufferHandle() : 0, 459 slot, mSlots[slot].mGraphicBuffer->handle); 460 461 // Hang onto the pointer so that it isn't freed in the call to 462 // releaseBufferLocked() if we're in shared buffer mode and both buffers are 463 // the same. 464 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage; 465 466 // release old buffer 467 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 468 if (pendingRelease == nullptr) { 469 status_t status = releaseBufferLocked( 470 mCurrentTexture, mCurrentTextureImage->graphicBuffer(), 471 mEglDisplay, mEglSlots[mCurrentTexture].mEglFence); 472 if (status < NO_ERROR) { 473 GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", 474 strerror(-status), status); 475 err = status; 476 // keep going, with error raised [?] 477 } 478 } else { 479 pendingRelease->currentTexture = mCurrentTexture; 480 pendingRelease->graphicBuffer = 481 mCurrentTextureImage->graphicBuffer(); 482 pendingRelease->display = mEglDisplay; 483 pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence; 484 pendingRelease->isPending = true; 485 } 486 } 487 488 // Update the GLConsumer state. 489 mCurrentTexture = slot; 490 mCurrentTextureImage = nextTextureImage; 491 mCurrentCrop = item.mCrop; 492 mCurrentTransform = item.mTransform; 493 mCurrentScalingMode = item.mScalingMode; 494 mCurrentTimestamp = item.mTimestamp; 495 mCurrentDataSpace = item.mDataSpace; 496 mCurrentFence = item.mFence; 497 mCurrentFenceTime = item.mFenceTime; 498 mCurrentFrameNumber = item.mFrameNumber; 499 500 computeCurrentTransformMatrixLocked(); 501 502 return err; 503 } 504 505 status_t GLConsumer::bindTextureImageLocked() { 506 if (mEglDisplay == EGL_NO_DISPLAY) { 507 ALOGE("bindTextureImage: invalid display"); 508 return INVALID_OPERATION; 509 } 510 511 GLenum error; 512 while ((error = glGetError()) != GL_NO_ERROR) { 513 GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error); 514 } 515 516 glBindTexture(mTexTarget, mTexName); 517 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && 518 mCurrentTextureImage == NULL) { 519 GLC_LOGE("bindTextureImage: no currently-bound texture"); 520 return NO_INIT; 521 } 522 523 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, 524 mCurrentCrop); 525 if (err != NO_ERROR) { 526 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", 527 mEglDisplay, mCurrentTexture); 528 return UNKNOWN_ERROR; 529 } 530 mCurrentTextureImage->bindToTextureTarget(mTexTarget); 531 532 // In the rare case that the display is terminated and then initialized 533 // again, we can't detect that the display changed (it didn't), but the 534 // image is invalid. In this case, repeat the exact same steps while 535 // forcing the creation of a new image. 536 if ((error = glGetError()) != GL_NO_ERROR) { 537 glBindTexture(mTexTarget, mTexName); 538 status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, 539 mCurrentCrop, 540 true); 541 if (result != NO_ERROR) { 542 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", 543 mEglDisplay, mCurrentTexture); 544 return UNKNOWN_ERROR; 545 } 546 mCurrentTextureImage->bindToTextureTarget(mTexTarget); 547 if ((error = glGetError()) != GL_NO_ERROR) { 548 GLC_LOGE("bindTextureImage: error binding external image: %#04x", error); 549 return UNKNOWN_ERROR; 550 } 551 } 552 553 // Wait for the new buffer to be ready. 554 return doGLFenceWaitLocked(); 555 } 556 557 status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) { 558 EGLDisplay dpy = eglGetCurrentDisplay(); 559 EGLContext ctx = eglGetCurrentContext(); 560 561 if (!contextCheck) { 562 // if this is the first time we're called, mEglDisplay/mEglContext have 563 // never been set, so don't error out (below). 564 if (mEglDisplay == EGL_NO_DISPLAY) { 565 mEglDisplay = dpy; 566 } 567 if (mEglContext == EGL_NO_CONTEXT) { 568 mEglContext = ctx; 569 } 570 } 571 572 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) { 573 GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay"); 574 return INVALID_OPERATION; 575 } 576 577 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) { 578 GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext"); 579 return INVALID_OPERATION; 580 } 581 582 mEglDisplay = dpy; 583 mEglContext = ctx; 584 return NO_ERROR; 585 } 586 587 void GLConsumer::setReleaseFence(const sp<Fence>& fence) { 588 if (fence->isValid() && 589 mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 590 status_t err = addReleaseFence(mCurrentTexture, 591 mCurrentTextureImage->graphicBuffer(), fence); 592 if (err != OK) { 593 GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", 594 strerror(-err), err); 595 } 596 } 597 } 598 599 status_t GLConsumer::detachFromContext() { 600 ATRACE_CALL(); 601 GLC_LOGV("detachFromContext"); 602 Mutex::Autolock lock(mMutex); 603 604 if (mAbandoned) { 605 GLC_LOGE("detachFromContext: abandoned GLConsumer"); 606 return NO_INIT; 607 } 608 609 if (!mAttached) { 610 GLC_LOGE("detachFromContext: GLConsumer is not attached to a " 611 "context"); 612 return INVALID_OPERATION; 613 } 614 615 EGLDisplay dpy = eglGetCurrentDisplay(); 616 EGLContext ctx = eglGetCurrentContext(); 617 618 if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) { 619 GLC_LOGE("detachFromContext: invalid current EGLDisplay"); 620 return INVALID_OPERATION; 621 } 622 623 if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) { 624 GLC_LOGE("detachFromContext: invalid current EGLContext"); 625 return INVALID_OPERATION; 626 } 627 628 if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) { 629 status_t err = syncForReleaseLocked(dpy); 630 if (err != OK) { 631 return err; 632 } 633 634 glDeleteTextures(1, &mTexName); 635 } 636 637 mEglDisplay = EGL_NO_DISPLAY; 638 mEglContext = EGL_NO_CONTEXT; 639 mAttached = false; 640 641 return OK; 642 } 643 644 status_t GLConsumer::attachToContext(uint32_t tex) { 645 ATRACE_CALL(); 646 GLC_LOGV("attachToContext"); 647 Mutex::Autolock lock(mMutex); 648 649 if (mAbandoned) { 650 GLC_LOGE("attachToContext: abandoned GLConsumer"); 651 return NO_INIT; 652 } 653 654 if (mAttached) { 655 GLC_LOGE("attachToContext: GLConsumer is already attached to a " 656 "context"); 657 return INVALID_OPERATION; 658 } 659 660 EGLDisplay dpy = eglGetCurrentDisplay(); 661 EGLContext ctx = eglGetCurrentContext(); 662 663 if (dpy == EGL_NO_DISPLAY) { 664 GLC_LOGE("attachToContext: invalid current EGLDisplay"); 665 return INVALID_OPERATION; 666 } 667 668 if (ctx == EGL_NO_CONTEXT) { 669 GLC_LOGE("attachToContext: invalid current EGLContext"); 670 return INVALID_OPERATION; 671 } 672 673 // We need to bind the texture regardless of whether there's a current 674 // buffer. 675 glBindTexture(mTexTarget, GLuint(tex)); 676 677 mEglDisplay = dpy; 678 mEglContext = ctx; 679 mTexName = tex; 680 mAttached = true; 681 682 if (mCurrentTextureImage != NULL) { 683 // This may wait for a buffer a second time. This is likely required if 684 // this is a different context, since otherwise the wait could be skipped 685 // by bouncing through another context. For the same context the extra 686 // wait is redundant. 687 status_t err = bindTextureImageLocked(); 688 if (err != NO_ERROR) { 689 return err; 690 } 691 } 692 693 return OK; 694 } 695 696 697 status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { 698 GLC_LOGV("syncForReleaseLocked"); 699 700 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 701 if (SyncFeatures::getInstance().useNativeFenceSync()) { 702 EGLSyncKHR sync = eglCreateSyncKHR(dpy, 703 EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); 704 if (sync == EGL_NO_SYNC_KHR) { 705 GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", 706 eglGetError()); 707 return UNKNOWN_ERROR; 708 } 709 glFlush(); 710 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync); 711 eglDestroySyncKHR(dpy, sync); 712 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 713 GLC_LOGE("syncForReleaseLocked: error dup'ing native fence " 714 "fd: %#x", eglGetError()); 715 return UNKNOWN_ERROR; 716 } 717 sp<Fence> fence(new Fence(fenceFd)); 718 status_t err = addReleaseFenceLocked(mCurrentTexture, 719 mCurrentTextureImage->graphicBuffer(), fence); 720 if (err != OK) { 721 GLC_LOGE("syncForReleaseLocked: error adding release fence: " 722 "%s (%d)", strerror(-err), err); 723 return err; 724 } 725 } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) { 726 EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence; 727 if (fence != EGL_NO_SYNC_KHR) { 728 // There is already a fence for the current slot. We need to 729 // wait on that before replacing it with another fence to 730 // ensure that all outstanding buffer accesses have completed 731 // before the producer accesses it. 732 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); 733 if (result == EGL_FALSE) { 734 GLC_LOGE("syncForReleaseLocked: error waiting for previous " 735 "fence: %#x", eglGetError()); 736 return UNKNOWN_ERROR; 737 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 738 GLC_LOGE("syncForReleaseLocked: timeout waiting for previous " 739 "fence"); 740 return TIMED_OUT; 741 } 742 eglDestroySyncKHR(dpy, fence); 743 } 744 745 // Create a fence for the outstanding accesses in the current 746 // OpenGL ES context. 747 fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 748 if (fence == EGL_NO_SYNC_KHR) { 749 GLC_LOGE("syncForReleaseLocked: error creating fence: %#x", 750 eglGetError()); 751 return UNKNOWN_ERROR; 752 } 753 glFlush(); 754 mEglSlots[mCurrentTexture].mEglFence = fence; 755 } 756 } 757 758 return OK; 759 } 760 761 bool GLConsumer::isExternalFormat(PixelFormat format) 762 { 763 switch (format) { 764 // supported YUV formats 765 case HAL_PIXEL_FORMAT_YV12: 766 // Legacy/deprecated YUV formats 767 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 768 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 769 case HAL_PIXEL_FORMAT_YCbCr_422_I: 770 return true; 771 } 772 773 // Any OEM format needs to be considered 774 if (format>=0x100 && format<=0x1FF) 775 return true; 776 777 return false; 778 } 779 780 uint32_t GLConsumer::getCurrentTextureTarget() const { 781 return mTexTarget; 782 } 783 784 void GLConsumer::getTransformMatrix(float mtx[16]) { 785 Mutex::Autolock lock(mMutex); 786 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix)); 787 } 788 789 void GLConsumer::setFilteringEnabled(bool enabled) { 790 Mutex::Autolock lock(mMutex); 791 if (mAbandoned) { 792 GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!"); 793 return; 794 } 795 bool needsRecompute = mFilteringEnabled != enabled; 796 mFilteringEnabled = enabled; 797 798 if (needsRecompute && mCurrentTextureImage==NULL) { 799 GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); 800 } 801 802 if (needsRecompute && mCurrentTextureImage != NULL) { 803 computeCurrentTransformMatrixLocked(); 804 } 805 } 806 807 void GLConsumer::computeCurrentTransformMatrixLocked() { 808 GLC_LOGV("computeCurrentTransformMatrixLocked"); 809 sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ? 810 nullptr : mCurrentTextureImage->graphicBuffer(); 811 if (buf == nullptr) { 812 GLC_LOGD("computeCurrentTransformMatrixLocked: " 813 "mCurrentTextureImage is NULL"); 814 } 815 computeTransformMatrix(mCurrentTransformMatrix, buf, 816 isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop, 817 mCurrentTransform, mFilteringEnabled); 818 } 819 820 void GLConsumer::computeTransformMatrix(float outTransform[16], 821 const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform, 822 bool filtering) { 823 824 float xform[16]; 825 for (int i = 0; i < 16; i++) { 826 xform[i] = mtxIdentity[i]; 827 } 828 if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { 829 float result[16]; 830 mtxMul(result, xform, mtxFlipH); 831 for (int i = 0; i < 16; i++) { 832 xform[i] = result[i]; 833 } 834 } 835 if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { 836 float result[16]; 837 mtxMul(result, xform, mtxFlipV); 838 for (int i = 0; i < 16; i++) { 839 xform[i] = result[i]; 840 } 841 } 842 if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 843 float result[16]; 844 mtxMul(result, xform, mtxRot90); 845 for (int i = 0; i < 16; i++) { 846 xform[i] = result[i]; 847 } 848 } 849 850 float mtxBeforeFlipV[16]; 851 if (!cropRect.isEmpty()) { 852 float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f; 853 float bufferWidth = buf->getWidth(); 854 float bufferHeight = buf->getHeight(); 855 float shrinkAmount = 0.0f; 856 if (filtering) { 857 // In order to prevent bilinear sampling beyond the edge of the 858 // crop rectangle we may need to shrink it by 2 texels in each 859 // dimension. Normally this would just need to take 1/2 a texel 860 // off each end, but because the chroma channels of YUV420 images 861 // are subsampled we may need to shrink the crop region by a whole 862 // texel on each side. 863 switch (buf->getPixelFormat()) { 864 case PIXEL_FORMAT_RGBA_8888: 865 case PIXEL_FORMAT_RGBX_8888: 866 case PIXEL_FORMAT_RGBA_FP16: 867 case PIXEL_FORMAT_RGBA_1010102: 868 case PIXEL_FORMAT_RGB_888: 869 case PIXEL_FORMAT_RGB_565: 870 case PIXEL_FORMAT_BGRA_8888: 871 // We know there's no subsampling of any channels, so we 872 // only need to shrink by a half a pixel. 873 shrinkAmount = 0.5; 874 break; 875 876 default: 877 // If we don't recognize the format, we must assume the 878 // worst case (that we care about), which is YUV420. 879 shrinkAmount = 1.0; 880 break; 881 } 882 } 883 884 // Only shrink the dimensions that are not the size of the buffer. 885 if (cropRect.width() < bufferWidth) { 886 tx = (float(cropRect.left) + shrinkAmount) / bufferWidth; 887 sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / 888 bufferWidth; 889 } 890 if (cropRect.height() < bufferHeight) { 891 ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / 892 bufferHeight; 893 sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / 894 bufferHeight; 895 } 896 float crop[16] = { 897 sx, 0, 0, 0, 898 0, sy, 0, 0, 899 0, 0, 1, 0, 900 tx, ty, 0, 1, 901 }; 902 903 mtxMul(mtxBeforeFlipV, crop, xform); 904 } else { 905 for (int i = 0; i < 16; i++) { 906 mtxBeforeFlipV[i] = xform[i]; 907 } 908 } 909 910 // SurfaceFlinger expects the top of its window textures to be at a Y 911 // coordinate of 0, so GLConsumer must behave the same way. We don't 912 // want to expose this to applications, however, so we must add an 913 // additional vertical flip to the transform after all the other transforms. 914 mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV); 915 } 916 917 nsecs_t GLConsumer::getTimestamp() { 918 GLC_LOGV("getTimestamp"); 919 Mutex::Autolock lock(mMutex); 920 return mCurrentTimestamp; 921 } 922 923 android_dataspace GLConsumer::getCurrentDataSpace() { 924 GLC_LOGV("getCurrentDataSpace"); 925 Mutex::Autolock lock(mMutex); 926 return mCurrentDataSpace; 927 } 928 929 uint64_t GLConsumer::getFrameNumber() { 930 GLC_LOGV("getFrameNumber"); 931 Mutex::Autolock lock(mMutex); 932 return mCurrentFrameNumber; 933 } 934 935 sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const { 936 Mutex::Autolock lock(mMutex); 937 938 if (outSlot != nullptr) { 939 *outSlot = mCurrentTexture; 940 } 941 942 return (mCurrentTextureImage == nullptr) ? 943 NULL : mCurrentTextureImage->graphicBuffer(); 944 } 945 946 Rect GLConsumer::getCurrentCrop() const { 947 Mutex::Autolock lock(mMutex); 948 949 Rect outCrop = mCurrentCrop; 950 if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { 951 uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width()); 952 uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height()); 953 954 if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) { 955 newWidth = newHeight * mDefaultWidth / mDefaultHeight; 956 GLC_LOGV("too wide: newWidth = %d", newWidth); 957 } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) { 958 newHeight = newWidth * mDefaultHeight / mDefaultWidth; 959 GLC_LOGV("too tall: newHeight = %d", newHeight); 960 } 961 962 uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width()); 963 uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height()); 964 965 // The crop is too wide 966 if (newWidth < currentWidth) { 967 uint32_t dw = currentWidth - newWidth; 968 auto halfdw = dw / 2; 969 outCrop.left += halfdw; 970 // Not halfdw because it would subtract 1 too few when dw is odd 971 outCrop.right -= (dw - halfdw); 972 // The crop is too tall 973 } else if (newHeight < currentHeight) { 974 uint32_t dh = currentHeight - newHeight; 975 auto halfdh = dh / 2; 976 outCrop.top += halfdh; 977 // Not halfdh because it would subtract 1 too few when dh is odd 978 outCrop.bottom -= (dh - halfdh); 979 } 980 981 GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]", 982 outCrop.left, outCrop.top, 983 outCrop.right,outCrop.bottom); 984 } 985 986 return outCrop; 987 } 988 989 uint32_t GLConsumer::getCurrentTransform() const { 990 Mutex::Autolock lock(mMutex); 991 return mCurrentTransform; 992 } 993 994 uint32_t GLConsumer::getCurrentScalingMode() const { 995 Mutex::Autolock lock(mMutex); 996 return mCurrentScalingMode; 997 } 998 999 sp<Fence> GLConsumer::getCurrentFence() const { 1000 Mutex::Autolock lock(mMutex); 1001 return mCurrentFence; 1002 } 1003 1004 std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const { 1005 Mutex::Autolock lock(mMutex); 1006 return mCurrentFenceTime; 1007 } 1008 1009 status_t GLConsumer::doGLFenceWait() const { 1010 Mutex::Autolock lock(mMutex); 1011 return doGLFenceWaitLocked(); 1012 } 1013 1014 status_t GLConsumer::doGLFenceWaitLocked() const { 1015 1016 EGLDisplay dpy = eglGetCurrentDisplay(); 1017 EGLContext ctx = eglGetCurrentContext(); 1018 1019 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) { 1020 GLC_LOGE("doGLFenceWait: invalid current EGLDisplay"); 1021 return INVALID_OPERATION; 1022 } 1023 1024 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) { 1025 GLC_LOGE("doGLFenceWait: invalid current EGLContext"); 1026 return INVALID_OPERATION; 1027 } 1028 1029 if (mCurrentFence->isValid()) { 1030 if (SyncFeatures::getInstance().useWaitSync()) { 1031 // Create an EGLSyncKHR from the current fence. 1032 int fenceFd = mCurrentFence->dup(); 1033 if (fenceFd == -1) { 1034 GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); 1035 return -errno; 1036 } 1037 EGLint attribs[] = { 1038 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, 1039 EGL_NONE 1040 }; 1041 EGLSyncKHR sync = eglCreateSyncKHR(dpy, 1042 EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); 1043 if (sync == EGL_NO_SYNC_KHR) { 1044 close(fenceFd); 1045 GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", 1046 eglGetError()); 1047 return UNKNOWN_ERROR; 1048 } 1049 1050 // XXX: The spec draft is inconsistent as to whether this should 1051 // return an EGLint or void. Ignore the return value for now, as 1052 // it's not strictly needed. 1053 eglWaitSyncKHR(dpy, sync, 0); 1054 EGLint eglErr = eglGetError(); 1055 eglDestroySyncKHR(dpy, sync); 1056 if (eglErr != EGL_SUCCESS) { 1057 GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", 1058 eglErr); 1059 return UNKNOWN_ERROR; 1060 } 1061 } else { 1062 status_t err = mCurrentFence->waitForever( 1063 "GLConsumer::doGLFenceWaitLocked"); 1064 if (err != NO_ERROR) { 1065 GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err); 1066 return err; 1067 } 1068 } 1069 } 1070 1071 return NO_ERROR; 1072 } 1073 1074 void GLConsumer::freeBufferLocked(int slotIndex) { 1075 GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); 1076 if (slotIndex == mCurrentTexture) { 1077 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; 1078 } 1079 mEglSlots[slotIndex].mEglImage.clear(); 1080 ConsumerBase::freeBufferLocked(slotIndex); 1081 } 1082 1083 void GLConsumer::abandonLocked() { 1084 GLC_LOGV("abandonLocked"); 1085 mCurrentTextureImage.clear(); 1086 ConsumerBase::abandonLocked(); 1087 } 1088 1089 void GLConsumer::setName(const String8& name) { 1090 Mutex::Autolock _l(mMutex); 1091 if (mAbandoned) { 1092 GLC_LOGE("setName: GLConsumer is abandoned!"); 1093 return; 1094 } 1095 mName = name; 1096 mConsumer->setConsumerName(name); 1097 } 1098 1099 status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) { 1100 Mutex::Autolock lock(mMutex); 1101 if (mAbandoned) { 1102 GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!"); 1103 return NO_INIT; 1104 } 1105 return mConsumer->setDefaultBufferFormat(defaultFormat); 1106 } 1107 1108 status_t GLConsumer::setDefaultBufferDataSpace( 1109 android_dataspace defaultDataSpace) { 1110 Mutex::Autolock lock(mMutex); 1111 if (mAbandoned) { 1112 GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!"); 1113 return NO_INIT; 1114 } 1115 return mConsumer->setDefaultBufferDataSpace(defaultDataSpace); 1116 } 1117 1118 status_t GLConsumer::setConsumerUsageBits(uint64_t usage) { 1119 Mutex::Autolock lock(mMutex); 1120 if (mAbandoned) { 1121 GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!"); 1122 return NO_INIT; 1123 } 1124 usage |= DEFAULT_USAGE_FLAGS; 1125 return mConsumer->setConsumerUsageBits(usage); 1126 } 1127 1128 status_t GLConsumer::setTransformHint(uint32_t hint) { 1129 Mutex::Autolock lock(mMutex); 1130 if (mAbandoned) { 1131 GLC_LOGE("setTransformHint: GLConsumer is abandoned!"); 1132 return NO_INIT; 1133 } 1134 return mConsumer->setTransformHint(hint); 1135 } 1136 1137 status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { 1138 Mutex::Autolock lock(mMutex); 1139 if (mAbandoned) { 1140 GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!"); 1141 return NO_INIT; 1142 } 1143 return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers); 1144 } 1145 1146 void GLConsumer::dumpLocked(String8& result, const char* prefix) const 1147 { 1148 result.appendFormat( 1149 "%smTexName=%d mCurrentTexture=%d\n" 1150 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n", 1151 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left, 1152 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, 1153 mCurrentTransform); 1154 1155 ConsumerBase::dumpLocked(result, prefix); 1156 } 1157 1158 static void mtxMul(float out[16], const float a[16], const float b[16]) { 1159 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; 1160 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; 1161 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; 1162 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; 1163 1164 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; 1165 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; 1166 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; 1167 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; 1168 1169 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; 1170 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; 1171 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; 1172 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; 1173 1174 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; 1175 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; 1176 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; 1177 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; 1178 } 1179 1180 GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) : 1181 mGraphicBuffer(graphicBuffer), 1182 mEglImage(EGL_NO_IMAGE_KHR), 1183 mEglDisplay(EGL_NO_DISPLAY), 1184 mCropRect(Rect::EMPTY_RECT) { 1185 } 1186 1187 GLConsumer::EglImage::~EglImage() { 1188 if (mEglImage != EGL_NO_IMAGE_KHR) { 1189 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { 1190 ALOGE("~EglImage: eglDestroyImageKHR failed"); 1191 } 1192 eglTerminate(mEglDisplay); 1193 } 1194 } 1195 1196 status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, 1197 const Rect& cropRect, 1198 bool forceCreation) { 1199 // If there's an image and it's no longer valid, destroy it. 1200 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR; 1201 bool displayInvalid = mEglDisplay != eglDisplay; 1202 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect; 1203 if (haveImage && (displayInvalid || cropInvalid || forceCreation)) { 1204 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { 1205 ALOGE("createIfNeeded: eglDestroyImageKHR failed"); 1206 } 1207 eglTerminate(mEglDisplay); 1208 mEglImage = EGL_NO_IMAGE_KHR; 1209 mEglDisplay = EGL_NO_DISPLAY; 1210 } 1211 1212 // If there's no image, create one. 1213 if (mEglImage == EGL_NO_IMAGE_KHR) { 1214 mEglDisplay = eglDisplay; 1215 mCropRect = cropRect; 1216 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect); 1217 } 1218 1219 // Fail if we can't create a valid image. 1220 if (mEglImage == EGL_NO_IMAGE_KHR) { 1221 mEglDisplay = EGL_NO_DISPLAY; 1222 mCropRect.makeInvalid(); 1223 const sp<GraphicBuffer>& buffer = mGraphicBuffer; 1224 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d", 1225 buffer->getWidth(), buffer->getHeight(), buffer->getStride(), 1226 buffer->getUsage(), buffer->getPixelFormat()); 1227 return UNKNOWN_ERROR; 1228 } 1229 1230 return OK; 1231 } 1232 1233 void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) { 1234 glEGLImageTargetTexture2DOES(texTarget, 1235 static_cast<GLeglImageOES>(mEglImage)); 1236 } 1237 1238 EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, 1239 const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) { 1240 EGLClientBuffer cbuf = 1241 static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer()); 1242 const bool createProtectedImage = 1243 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && 1244 hasEglProtectedContent(); 1245 EGLint attrs[] = { 1246 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 1247 EGL_IMAGE_CROP_LEFT_ANDROID, crop.left, 1248 EGL_IMAGE_CROP_TOP_ANDROID, crop.top, 1249 EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right, 1250 EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom, 1251 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE, 1252 createProtectedImage ? EGL_TRUE : EGL_NONE, 1253 EGL_NONE, 1254 }; 1255 if (!crop.isValid()) { 1256 // No crop rect to set, so leave the crop out of the attrib array. Make 1257 // sure to propagate the protected content attrs if they are set. 1258 attrs[2] = attrs[10]; 1259 attrs[3] = attrs[11]; 1260 attrs[4] = EGL_NONE; 1261 } else if (!isEglImageCroppable(crop)) { 1262 // The crop rect is not at the origin, so we can't set the crop on the 1263 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop 1264 // extension. In the future we can add a layered extension that 1265 // removes this restriction if there is hardware that can support it. 1266 attrs[2] = attrs[10]; 1267 attrs[3] = attrs[11]; 1268 attrs[4] = EGL_NONE; 1269 } 1270 eglInitialize(dpy, 0, 0); 1271 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 1272 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); 1273 if (image == EGL_NO_IMAGE_KHR) { 1274 EGLint error = eglGetError(); 1275 ALOGE("error creating EGLImage: %#x", error); 1276 eglTerminate(dpy); 1277 } 1278 return image; 1279 } 1280 1281 }; // namespace android 1282