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