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