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