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