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