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