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