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