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