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 
     29 #include <hardware/hardware.h>
     30 
     31 #include <gui/GLConsumer.h>
     32 #include <gui/IGraphicBufferAlloc.h>
     33 #include <gui/ISurfaceComposer.h>
     34 #include <gui/SurfaceComposerClient.h>
     35 
     36 #include <private/gui/ComposerService.h>
     37 #include <private/gui/SyncFeatures.h>
     38 
     39 #include <utils/Log.h>
     40 #include <utils/String8.h>
     41 #include <utils/Trace.h>
     42 
     43 namespace android {
     44 
     45 // Macros for including the GLConsumer name in log messages
     46 #define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
     47 #define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
     48 #define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
     49 #define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
     50 #define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
     51 
     52 // Transform matrices
     53 static float mtxIdentity[16] = {
     54     1, 0, 0, 0,
     55     0, 1, 0, 0,
     56     0, 0, 1, 0,
     57     0, 0, 0, 1,
     58 };
     59 static float mtxFlipH[16] = {
     60     -1, 0, 0, 0,
     61     0, 1, 0, 0,
     62     0, 0, 1, 0,
     63     1, 0, 0, 1,
     64 };
     65 static float mtxFlipV[16] = {
     66     1, 0, 0, 0,
     67     0, -1, 0, 0,
     68     0, 0, 1, 0,
     69     0, 1, 0, 1,
     70 };
     71 static float mtxRot90[16] = {
     72     0, 1, 0, 0,
     73     -1, 0, 0, 0,
     74     0, 0, 1, 0,
     75     1, 0, 0, 1,
     76 };
     77 
     78 static void mtxMul(float out[16], const float a[16], const float b[16]);
     79 
     80 
     81 GLConsumer::GLConsumer(GLuint tex, bool allowSynchronousMode,
     82         GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
     83     ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),
     84     mCurrentTransform(0),
     85     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     86     mCurrentFence(Fence::NO_FENCE),
     87     mCurrentTimestamp(0),
     88     mDefaultWidth(1),
     89     mDefaultHeight(1),
     90     mFilteringEnabled(true),
     91     mTexName(tex),
     92     mUseFenceSync(useFenceSync),
     93     mTexTarget(texTarget),
     94     mEglDisplay(EGL_NO_DISPLAY),
     95     mEglContext(EGL_NO_CONTEXT),
     96     mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
     97     mAttached(true)
     98 {
     99     ST_LOGV("GLConsumer");
    100 
    101     memcpy(mCurrentTransformMatrix, mtxIdentity,
    102             sizeof(mCurrentTransformMatrix));
    103 
    104     mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
    105 }
    106 
    107 status_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
    108     Mutex::Autolock lock(mMutex);
    109     return mBufferQueue->setDefaultMaxBufferCount(bufferCount);
    110 }
    111 
    112 
    113 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
    114 {
    115     Mutex::Autolock lock(mMutex);
    116     mDefaultWidth = w;
    117     mDefaultHeight = h;
    118     return mBufferQueue->setDefaultBufferSize(w, h);
    119 }
    120 
    121 status_t GLConsumer::updateTexImage() {
    122     ATRACE_CALL();
    123     ST_LOGV("updateTexImage");
    124     Mutex::Autolock lock(mMutex);
    125 
    126     if (mAbandoned) {
    127         ST_LOGE("updateTexImage: GLConsumer is abandoned!");
    128         return NO_INIT;
    129     }
    130 
    131     // Make sure the EGL state is the same as in previous calls.
    132     status_t err = checkAndUpdateEglStateLocked();
    133     if (err != NO_ERROR) {
    134         return err;
    135     }
    136 
    137     BufferQueue::BufferItem item;
    138 
    139     // Acquire the next buffer.
    140     // In asynchronous mode the list is guaranteed to be one buffer
    141     // deep, while in synchronous mode we use the oldest buffer.
    142     err = acquireBufferLocked(&item);
    143     if (err != NO_ERROR) {
    144         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
    145             // We always bind the texture even if we don't update its contents.
    146             ST_LOGV("updateTexImage: no buffers were available");
    147             glBindTexture(mTexTarget, mTexName);
    148             err = NO_ERROR;
    149         } else {
    150             ST_LOGE("updateTexImage: acquire failed: %s (%d)",
    151                 strerror(-err), err);
    152         }
    153         return err;
    154     }
    155 
    156     // Release the previous buffer.
    157     err = releaseAndUpdateLocked(item);
    158     if (err != NO_ERROR) {
    159         // We always bind the texture.
    160         glBindTexture(mTexTarget, mTexName);
    161         return err;
    162     }
    163 
    164     // Bind the new buffer to the GL texture, and wait until it's ready.
    165     return bindTextureImageLocked();
    166 }
    167 
    168 status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item) {
    169     status_t err = ConsumerBase::acquireBufferLocked(item);
    170     if (err != NO_ERROR) {
    171         return err;
    172     }
    173 
    174     int slot = item->mBuf;
    175     if (item->mGraphicBuffer != NULL) {
    176         // This buffer has not been acquired before, so we must assume
    177         // that any EGLImage in mEglSlots is stale.
    178         if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
    179             if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
    180                 ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
    181                       slot);
    182                 // keep going
    183             }
    184             mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
    185         }
    186     }
    187 
    188     return NO_ERROR;
    189 }
    190 
    191 status_t GLConsumer::releaseBufferLocked(int buf, EGLDisplay display,
    192        EGLSyncKHR eglFence) {
    193     status_t err = ConsumerBase::releaseBufferLocked(buf, display, eglFence);
    194 
    195     mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
    196 
    197     return err;
    198 }
    199 
    200 status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item)
    201 {
    202     status_t err = NO_ERROR;
    203 
    204     if (!mAttached) {
    205         ST_LOGE("releaseAndUpdate: GLConsumer is not attached to an OpenGL "
    206                 "ES context");
    207         return INVALID_OPERATION;
    208     }
    209 
    210     // Confirm state.
    211     err = checkAndUpdateEglStateLocked();
    212     if (err != NO_ERROR) {
    213         return err;
    214     }
    215 
    216     int buf = item.mBuf;
    217 
    218     // If the mEglSlot entry is empty, create an EGLImage for the gralloc
    219     // buffer currently in the slot in ConsumerBase.
    220     //
    221     // We may have to do this even when item.mGraphicBuffer == NULL (which
    222     // means the buffer was previously acquired), if we destroyed the
    223     // EGLImage when detaching from a context but the buffer has not been
    224     // re-allocated.
    225     if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
    226         EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer);
    227         if (image == EGL_NO_IMAGE_KHR) {
    228             ST_LOGW("releaseAndUpdate: unable to createImage on display=%p slot=%d",
    229                   mEglDisplay, buf);
    230             return UNKNOWN_ERROR;
    231         }
    232         mEglSlots[buf].mEglImage = image;
    233     }
    234 
    235     // Do whatever sync ops we need to do before releasing the old slot.
    236     err = syncForReleaseLocked(mEglDisplay);
    237     if (err != NO_ERROR) {
    238         // Release the buffer we just acquired.  It's not safe to
    239         // release the old buffer, so instead we just drop the new frame.
    240         releaseBufferLocked(buf, mEglDisplay, EGL_NO_SYNC_KHR);
    241         return err;
    242     }
    243 
    244     ST_LOGV("releaseAndUpdate: (slot=%d buf=%p) -> (slot=%d buf=%p)",
    245             mCurrentTexture,
    246             mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
    247             buf, mSlots[buf].mGraphicBuffer->handle);
    248 
    249     // release old buffer
    250     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
    251         status_t status = releaseBufferLocked(mCurrentTexture, mEglDisplay,
    252                 mEglSlots[mCurrentTexture].mEglFence);
    253         if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
    254             ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)",
    255                    strerror(-status), status);
    256             err = status;
    257             // keep going, with error raised [?]
    258         }
    259     }
    260 
    261     // Update the GLConsumer state.
    262     mCurrentTexture = buf;
    263     mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
    264     mCurrentCrop = item.mCrop;
    265     mCurrentTransform = item.mTransform;
    266     mCurrentScalingMode = item.mScalingMode;
    267     mCurrentTimestamp = item.mTimestamp;
    268     mCurrentFence = item.mFence;
    269 
    270     computeCurrentTransformMatrixLocked();
    271 
    272     return err;
    273 }
    274 
    275 status_t GLConsumer::bindTextureImageLocked() {
    276     if (mEglDisplay == EGL_NO_DISPLAY) {
    277         ALOGE("bindTextureImage: invalid display");
    278         return INVALID_OPERATION;
    279     }
    280 
    281     GLint error;
    282     while ((error = glGetError()) != GL_NO_ERROR) {
    283         ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
    284     }
    285 
    286     glBindTexture(mTexTarget, mTexName);
    287     if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
    288         if (mCurrentTextureBuf == NULL) {
    289             ST_LOGE("bindTextureImage: no currently-bound texture");
    290             return NO_INIT;
    291         }
    292         status_t err = bindUnslottedBufferLocked(mEglDisplay);
    293         if (err != NO_ERROR) {
    294             return err;
    295         }
    296     } else {
    297         EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
    298 
    299         glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
    300 
    301         while ((error = glGetError()) != GL_NO_ERROR) {
    302             ST_LOGE("bindTextureImage: error binding external texture image %p"
    303                     ": %#04x", image, error);
    304             return UNKNOWN_ERROR;
    305         }
    306     }
    307 
    308     // Wait for the new buffer to be ready.
    309     return doGLFenceWaitLocked();
    310 
    311 }
    312 
    313 status_t GLConsumer::checkAndUpdateEglStateLocked() {
    314     EGLDisplay dpy = eglGetCurrentDisplay();
    315     EGLContext ctx = eglGetCurrentContext();
    316 
    317     if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
    318             dpy == EGL_NO_DISPLAY) {
    319         ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
    320         return INVALID_OPERATION;
    321     }
    322 
    323     if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
    324             ctx == EGL_NO_CONTEXT) {
    325         ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
    326         return INVALID_OPERATION;
    327     }
    328 
    329     mEglDisplay = dpy;
    330     mEglContext = ctx;
    331     return NO_ERROR;
    332 }
    333 
    334 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
    335     if (fence->isValid() &&
    336             mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
    337         status_t err = addReleaseFence(mCurrentTexture, fence);
    338         if (err != OK) {
    339             ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
    340                     strerror(-err), err);
    341         }
    342     }
    343 }
    344 
    345 status_t GLConsumer::detachFromContext() {
    346     ATRACE_CALL();
    347     ST_LOGV("detachFromContext");
    348     Mutex::Autolock lock(mMutex);
    349 
    350     if (mAbandoned) {
    351         ST_LOGE("detachFromContext: abandoned GLConsumer");
    352         return NO_INIT;
    353     }
    354 
    355     if (!mAttached) {
    356         ST_LOGE("detachFromContext: GLConsumer is not attached to a "
    357                 "context");
    358         return INVALID_OPERATION;
    359     }
    360 
    361     EGLDisplay dpy = eglGetCurrentDisplay();
    362     EGLContext ctx = eglGetCurrentContext();
    363 
    364     if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
    365         ST_LOGE("detachFromContext: invalid current EGLDisplay");
    366         return INVALID_OPERATION;
    367     }
    368 
    369     if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
    370         ST_LOGE("detachFromContext: invalid current EGLContext");
    371         return INVALID_OPERATION;
    372     }
    373 
    374     if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
    375         status_t err = syncForReleaseLocked(dpy);
    376         if (err != OK) {
    377             return err;
    378         }
    379 
    380         glDeleteTextures(1, &mTexName);
    381     }
    382 
    383     // Because we're giving up the EGLDisplay we need to free all the EGLImages
    384     // that are associated with it.  They'll be recreated when the
    385     // GLConsumer gets attached to a new OpenGL ES context (and thus gets a
    386     // new EGLDisplay).
    387     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    388         EGLImageKHR img = mEglSlots[i].mEglImage;
    389         if (img != EGL_NO_IMAGE_KHR) {
    390             eglDestroyImageKHR(mEglDisplay, img);
    391             mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
    392         }
    393     }
    394 
    395     mEglDisplay = EGL_NO_DISPLAY;
    396     mEglContext = EGL_NO_CONTEXT;
    397     mAttached = false;
    398 
    399     return OK;
    400 }
    401 
    402 status_t GLConsumer::attachToContext(GLuint tex) {
    403     ATRACE_CALL();
    404     ST_LOGV("attachToContext");
    405     Mutex::Autolock lock(mMutex);
    406 
    407     if (mAbandoned) {
    408         ST_LOGE("attachToContext: abandoned GLConsumer");
    409         return NO_INIT;
    410     }
    411 
    412     if (mAttached) {
    413         ST_LOGE("attachToContext: GLConsumer is already attached to a "
    414                 "context");
    415         return INVALID_OPERATION;
    416     }
    417 
    418     EGLDisplay dpy = eglGetCurrentDisplay();
    419     EGLContext ctx = eglGetCurrentContext();
    420 
    421     if (dpy == EGL_NO_DISPLAY) {
    422         ST_LOGE("attachToContext: invalid current EGLDisplay");
    423         return INVALID_OPERATION;
    424     }
    425 
    426     if (ctx == EGL_NO_CONTEXT) {
    427         ST_LOGE("attachToContext: invalid current EGLContext");
    428         return INVALID_OPERATION;
    429     }
    430 
    431     // We need to bind the texture regardless of whether there's a current
    432     // buffer.
    433     glBindTexture(mTexTarget, tex);
    434 
    435     if (mCurrentTextureBuf != NULL) {
    436         // The EGLImageKHR that was associated with the slot was destroyed when
    437         // the GLConsumer was detached from the old context, so we need to
    438         // recreate it here.
    439         status_t err = bindUnslottedBufferLocked(dpy);
    440         if (err != NO_ERROR) {
    441             return err;
    442         }
    443     }
    444 
    445     mEglDisplay = dpy;
    446     mEglContext = ctx;
    447     mTexName = tex;
    448     mAttached = true;
    449 
    450     return OK;
    451 }
    452 
    453 status_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) {
    454     ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
    455             mCurrentTexture, mCurrentTextureBuf.get());
    456 
    457     // Create a temporary EGLImageKHR.
    458     EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
    459     if (image == EGL_NO_IMAGE_KHR) {
    460         return UNKNOWN_ERROR;
    461     }
    462 
    463     // Attach the current buffer to the GL texture.
    464     glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
    465 
    466     GLint error;
    467     status_t err = OK;
    468     while ((error = glGetError()) != GL_NO_ERROR) {
    469         ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
    470                 "(slot %d): %#04x", image, mCurrentTexture, error);
    471         err = UNKNOWN_ERROR;
    472     }
    473 
    474     // We destroy the EGLImageKHR here because the current buffer may no
    475     // longer be associated with one of the buffer slots, so we have
    476     // nowhere to to store it.  If the buffer is still associated with a
    477     // slot then another EGLImageKHR will be created next time that buffer
    478     // gets acquired in updateTexImage.
    479     eglDestroyImageKHR(dpy, image);
    480 
    481     return err;
    482 }
    483 
    484 
    485 status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
    486     ST_LOGV("syncForReleaseLocked");
    487 
    488     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
    489         if (SyncFeatures::getInstance().useNativeFenceSync()) {
    490             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
    491                     EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
    492             if (sync == EGL_NO_SYNC_KHR) {
    493                 ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
    494                         eglGetError());
    495                 return UNKNOWN_ERROR;
    496             }
    497             glFlush();
    498             int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
    499             eglDestroySyncKHR(dpy, sync);
    500             if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
    501                 ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
    502                         "fd: %#x", eglGetError());
    503                 return UNKNOWN_ERROR;
    504             }
    505             sp<Fence> fence(new Fence(fenceFd));
    506             status_t err = addReleaseFenceLocked(mCurrentTexture, fence);
    507             if (err != OK) {
    508                 ST_LOGE("syncForReleaseLocked: error adding release fence: "
    509                         "%s (%d)", strerror(-err), err);
    510                 return err;
    511             }
    512         } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
    513             EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
    514             if (fence != EGL_NO_SYNC_KHR) {
    515                 // There is already a fence for the current slot.  We need to
    516                 // wait on that before replacing it with another fence to
    517                 // ensure that all outstanding buffer accesses have completed
    518                 // before the producer accesses it.
    519                 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
    520                 if (result == EGL_FALSE) {
    521                     ST_LOGE("syncForReleaseLocked: error waiting for previous "
    522                             "fence: %#x", eglGetError());
    523                     return UNKNOWN_ERROR;
    524                 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
    525                     ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
    526                             "fence");
    527                     return TIMED_OUT;
    528                 }
    529                 eglDestroySyncKHR(dpy, fence);
    530             }
    531 
    532             // Create a fence for the outstanding accesses in the current
    533             // OpenGL ES context.
    534             fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
    535             if (fence == EGL_NO_SYNC_KHR) {
    536                 ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
    537                         eglGetError());
    538                 return UNKNOWN_ERROR;
    539             }
    540             glFlush();
    541             mEglSlots[mCurrentTexture].mEglFence = fence;
    542         }
    543     }
    544 
    545     return OK;
    546 }
    547 
    548 bool GLConsumer::isExternalFormat(uint32_t format)
    549 {
    550     switch (format) {
    551     // supported YUV formats
    552     case HAL_PIXEL_FORMAT_YV12:
    553     // Legacy/deprecated YUV formats
    554     case HAL_PIXEL_FORMAT_YCbCr_422_SP:
    555     case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    556     case HAL_PIXEL_FORMAT_YCbCr_422_I:
    557         return true;
    558     }
    559 
    560     // Any OEM format needs to be considered
    561     if (format>=0x100 && format<=0x1FF)
    562         return true;
    563 
    564     return false;
    565 }
    566 
    567 GLenum GLConsumer::getCurrentTextureTarget() const {
    568     return mTexTarget;
    569 }
    570 
    571 void GLConsumer::getTransformMatrix(float mtx[16]) {
    572     Mutex::Autolock lock(mMutex);
    573     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
    574 }
    575 
    576 void GLConsumer::setFilteringEnabled(bool enabled) {
    577     Mutex::Autolock lock(mMutex);
    578     if (mAbandoned) {
    579         ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
    580         return;
    581     }
    582     bool needsRecompute = mFilteringEnabled != enabled;
    583     mFilteringEnabled = enabled;
    584 
    585     if (needsRecompute && mCurrentTextureBuf==NULL) {
    586         ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
    587     }
    588 
    589     if (needsRecompute && mCurrentTextureBuf != NULL) {
    590         computeCurrentTransformMatrixLocked();
    591     }
    592 }
    593 
    594 void GLConsumer::computeCurrentTransformMatrixLocked() {
    595     ST_LOGV("computeCurrentTransformMatrixLocked");
    596 
    597     float xform[16];
    598     for (int i = 0; i < 16; i++) {
    599         xform[i] = mtxIdentity[i];
    600     }
    601     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
    602         float result[16];
    603         mtxMul(result, xform, mtxFlipH);
    604         for (int i = 0; i < 16; i++) {
    605             xform[i] = result[i];
    606         }
    607     }
    608     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
    609         float result[16];
    610         mtxMul(result, xform, mtxFlipV);
    611         for (int i = 0; i < 16; i++) {
    612             xform[i] = result[i];
    613         }
    614     }
    615     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
    616         float result[16];
    617         mtxMul(result, xform, mtxRot90);
    618         for (int i = 0; i < 16; i++) {
    619             xform[i] = result[i];
    620         }
    621     }
    622 
    623     sp<GraphicBuffer>& buf(mCurrentTextureBuf);
    624 
    625     if (buf == NULL) {
    626         ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
    627     }
    628 
    629     Rect cropRect = mCurrentCrop;
    630     float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
    631     float bufferWidth = buf->getWidth();
    632     float bufferHeight = buf->getHeight();
    633     if (!cropRect.isEmpty()) {
    634         float shrinkAmount = 0.0f;
    635         if (mFilteringEnabled) {
    636             // In order to prevent bilinear sampling beyond the edge of the
    637             // crop rectangle we may need to shrink it by 2 texels in each
    638             // dimension.  Normally this would just need to take 1/2 a texel
    639             // off each end, but because the chroma channels of YUV420 images
    640             // are subsampled we may need to shrink the crop region by a whole
    641             // texel on each side.
    642             switch (buf->getPixelFormat()) {
    643                 case PIXEL_FORMAT_RGBA_8888:
    644                 case PIXEL_FORMAT_RGBX_8888:
    645                 case PIXEL_FORMAT_RGB_888:
    646                 case PIXEL_FORMAT_RGB_565:
    647                 case PIXEL_FORMAT_BGRA_8888:
    648                 case PIXEL_FORMAT_RGBA_5551:
    649                 case PIXEL_FORMAT_RGBA_4444:
    650                     // We know there's no subsampling of any channels, so we
    651                     // only need to shrink by a half a pixel.
    652                     shrinkAmount = 0.5;
    653                     break;
    654 
    655                 default:
    656                     // If we don't recognize the format, we must assume the
    657                     // worst case (that we care about), which is YUV420.
    658                     shrinkAmount = 1.0;
    659                     break;
    660             }
    661         }
    662 
    663         // Only shrink the dimensions that are not the size of the buffer.
    664         if (cropRect.width() < bufferWidth) {
    665             tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
    666             sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
    667                     bufferWidth;
    668         }
    669         if (cropRect.height() < bufferHeight) {
    670             ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
    671                     bufferHeight;
    672             sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
    673                     bufferHeight;
    674         }
    675     }
    676     float crop[16] = {
    677         sx, 0, 0, 0,
    678         0, sy, 0, 0,
    679         0, 0, 1, 0,
    680         tx, ty, 0, 1,
    681     };
    682 
    683     float mtxBeforeFlipV[16];
    684     mtxMul(mtxBeforeFlipV, crop, xform);
    685 
    686     // SurfaceFlinger expects the top of its window textures to be at a Y
    687     // coordinate of 0, so GLConsumer must behave the same way.  We don't
    688     // want to expose this to applications, however, so we must add an
    689     // additional vertical flip to the transform after all the other transforms.
    690     mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
    691 }
    692 
    693 nsecs_t GLConsumer::getTimestamp() {
    694     ST_LOGV("getTimestamp");
    695     Mutex::Autolock lock(mMutex);
    696     return mCurrentTimestamp;
    697 }
    698 
    699 EGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
    700         const sp<GraphicBuffer>& graphicBuffer) {
    701     EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
    702     EGLint attrs[] = {
    703         EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
    704         EGL_NONE,
    705     };
    706     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
    707             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
    708     if (image == EGL_NO_IMAGE_KHR) {
    709         EGLint error = eglGetError();
    710         ST_LOGE("error creating EGLImage: %#x", error);
    711     }
    712     return image;
    713 }
    714 
    715 sp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
    716     Mutex::Autolock lock(mMutex);
    717     return mCurrentTextureBuf;
    718 }
    719 
    720 Rect GLConsumer::getCurrentCrop() const {
    721     Mutex::Autolock lock(mMutex);
    722 
    723     Rect outCrop = mCurrentCrop;
    724     if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
    725         int32_t newWidth = mCurrentCrop.width();
    726         int32_t newHeight = mCurrentCrop.height();
    727 
    728         if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
    729             newWidth = newHeight * mDefaultWidth / mDefaultHeight;
    730             ST_LOGV("too wide: newWidth = %d", newWidth);
    731         } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
    732             newHeight = newWidth * mDefaultHeight / mDefaultWidth;
    733             ST_LOGV("too tall: newHeight = %d", newHeight);
    734         }
    735 
    736         // The crop is too wide
    737         if (newWidth < mCurrentCrop.width()) {
    738             int32_t dw = (newWidth - mCurrentCrop.width())/2;
    739             outCrop.left -=dw;
    740             outCrop.right += dw;
    741         // The crop is too tall
    742         } else if (newHeight < mCurrentCrop.height()) {
    743             int32_t dh = (newHeight - mCurrentCrop.height())/2;
    744             outCrop.top -= dh;
    745             outCrop.bottom += dh;
    746         }
    747 
    748         ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
    749             outCrop.left, outCrop.top,
    750             outCrop.right,outCrop.bottom);
    751     }
    752 
    753     return outCrop;
    754 }
    755 
    756 uint32_t GLConsumer::getCurrentTransform() const {
    757     Mutex::Autolock lock(mMutex);
    758     return mCurrentTransform;
    759 }
    760 
    761 uint32_t GLConsumer::getCurrentScalingMode() const {
    762     Mutex::Autolock lock(mMutex);
    763     return mCurrentScalingMode;
    764 }
    765 
    766 sp<Fence> GLConsumer::getCurrentFence() const {
    767     Mutex::Autolock lock(mMutex);
    768     return mCurrentFence;
    769 }
    770 
    771 status_t GLConsumer::doGLFenceWait() const {
    772     Mutex::Autolock lock(mMutex);
    773     return doGLFenceWaitLocked();
    774 }
    775 
    776 status_t GLConsumer::doGLFenceWaitLocked() const {
    777 
    778     EGLDisplay dpy = eglGetCurrentDisplay();
    779     EGLContext ctx = eglGetCurrentContext();
    780 
    781     if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
    782         ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
    783         return INVALID_OPERATION;
    784     }
    785 
    786     if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
    787         ST_LOGE("doGLFenceWait: invalid current EGLContext");
    788         return INVALID_OPERATION;
    789     }
    790 
    791     if (mCurrentFence->isValid()) {
    792         if (SyncFeatures::getInstance().useWaitSync()) {
    793             // Create an EGLSyncKHR from the current fence.
    794             int fenceFd = mCurrentFence->dup();
    795             if (fenceFd == -1) {
    796                 ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
    797                 return -errno;
    798             }
    799             EGLint attribs[] = {
    800                 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
    801                 EGL_NONE
    802             };
    803             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
    804                     EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
    805             if (sync == EGL_NO_SYNC_KHR) {
    806                 close(fenceFd);
    807                 ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
    808                         eglGetError());
    809                 return UNKNOWN_ERROR;
    810             }
    811 
    812             // XXX: The spec draft is inconsistent as to whether this should
    813             // return an EGLint or void.  Ignore the return value for now, as
    814             // it's not strictly needed.
    815             eglWaitSyncKHR(dpy, sync, 0);
    816             EGLint eglErr = eglGetError();
    817             eglDestroySyncKHR(dpy, sync);
    818             if (eglErr != EGL_SUCCESS) {
    819                 ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
    820                         eglErr);
    821                 return UNKNOWN_ERROR;
    822             }
    823         } else {
    824             status_t err = mCurrentFence->waitForever(
    825                     "GLConsumer::doGLFenceWaitLocked");
    826             if (err != NO_ERROR) {
    827                 ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
    828                 return err;
    829             }
    830         }
    831     }
    832 
    833     return NO_ERROR;
    834 }
    835 
    836 bool GLConsumer::isSynchronousMode() const {
    837     Mutex::Autolock lock(mMutex);
    838     return mBufferQueue->isSynchronousMode();
    839 }
    840 
    841 void GLConsumer::freeBufferLocked(int slotIndex) {
    842     ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
    843     if (slotIndex == mCurrentTexture) {
    844         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
    845     }
    846     EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
    847     if (img != EGL_NO_IMAGE_KHR) {
    848         ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
    849         eglDestroyImageKHR(mEglDisplay, img);
    850     }
    851     mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
    852     ConsumerBase::freeBufferLocked(slotIndex);
    853 }
    854 
    855 void GLConsumer::abandonLocked() {
    856     ST_LOGV("abandonLocked");
    857     mCurrentTextureBuf.clear();
    858     ConsumerBase::abandonLocked();
    859 }
    860 
    861 void GLConsumer::setName(const String8& name) {
    862     Mutex::Autolock _l(mMutex);
    863     mName = name;
    864     mBufferQueue->setConsumerName(name);
    865 }
    866 
    867 status_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
    868     Mutex::Autolock lock(mMutex);
    869     return mBufferQueue->setDefaultBufferFormat(defaultFormat);
    870 }
    871 
    872 status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
    873     Mutex::Autolock lock(mMutex);
    874     usage |= DEFAULT_USAGE_FLAGS;
    875     return mBufferQueue->setConsumerUsageBits(usage);
    876 }
    877 
    878 status_t GLConsumer::setTransformHint(uint32_t hint) {
    879     Mutex::Autolock lock(mMutex);
    880     return mBufferQueue->setTransformHint(hint);
    881 }
    882 
    883 // Used for refactoring BufferQueue from GLConsumer
    884 // Should not be in final interface once users of GLConsumer are clean up.
    885 status_t GLConsumer::setSynchronousMode(bool enabled) {
    886     Mutex::Autolock lock(mMutex);
    887     return mBufferQueue->setSynchronousMode(enabled);
    888 }
    889 
    890 void GLConsumer::dumpLocked(String8& result, const char* prefix,
    891         char* buffer, size_t size) const
    892 {
    893     snprintf(buffer, size,
    894        "%smTexName=%d mCurrentTexture=%d\n"
    895        "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
    896        prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
    897        mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
    898        mCurrentTransform);
    899     result.append(buffer);
    900 
    901     ConsumerBase::dumpLocked(result, prefix, buffer, size);
    902 }
    903 
    904 static void mtxMul(float out[16], const float a[16], const float b[16]) {
    905     out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
    906     out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
    907     out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
    908     out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
    909 
    910     out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
    911     out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
    912     out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
    913     out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
    914 
    915     out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
    916     out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
    917     out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
    918     out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
    919 
    920     out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
    921     out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
    922     out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
    923     out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
    924 }
    925 
    926 }; // namespace android
    927