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