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