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