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 "SurfaceTexture"
     18 //#define LOG_NDEBUG 0
     19 
     20 #define GL_GLEXT_PROTOTYPES
     21 #define EGL_EGLEXT_PROTOTYPES
     22 
     23 #include <EGL/egl.h>
     24 #include <EGL/eglext.h>
     25 #include <GLES2/gl2.h>
     26 #include <GLES2/gl2ext.h>
     27 
     28 #include <gui/SurfaceTexture.h>
     29 
     30 #include <hardware/hardware.h>
     31 
     32 #include <surfaceflinger/ISurfaceComposer.h>
     33 #include <surfaceflinger/SurfaceComposerClient.h>
     34 #include <surfaceflinger/IGraphicBufferAlloc.h>
     35 
     36 #include <utils/Log.h>
     37 #include <utils/String8.h>
     38 
     39 // This compile option causes SurfaceTexture to return the buffer that is currently
     40 // attached to the GL texture from dequeueBuffer when no other buffers are
     41 // available.  It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
     42 // implicit cross-process synchronization to prevent the buffer from being
     43 // written to before the buffer has (a) been detached from the GL texture and
     44 // (b) all GL reads from the buffer have completed.
     45 #ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
     46 #define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    true
     47 #warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
     48 #else
     49 #define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    false
     50 #endif
     51 
     52 // This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
     53 // to synchronize access to the buffers.  It will cause dequeueBuffer to stall,
     54 // waiting for the GL reads for the buffer being dequeued to complete before
     55 // allowing the buffer to be dequeued.
     56 #ifdef USE_FENCE_SYNC
     57 #ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
     58 #error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
     59 #endif
     60 #endif
     61 
     62 // Macros for including the SurfaceTexture name in log messages
     63 #define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
     64 #define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
     65 #define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
     66 #define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
     67 #define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
     68 
     69 namespace android {
     70 
     71 // Transform matrices
     72 static float mtxIdentity[16] = {
     73     1, 0, 0, 0,
     74     0, 1, 0, 0,
     75     0, 0, 1, 0,
     76     0, 0, 0, 1,
     77 };
     78 static float mtxFlipH[16] = {
     79     -1, 0, 0, 0,
     80     0, 1, 0, 0,
     81     0, 0, 1, 0,
     82     1, 0, 0, 1,
     83 };
     84 static float mtxFlipV[16] = {
     85     1, 0, 0, 0,
     86     0, -1, 0, 0,
     87     0, 0, 1, 0,
     88     0, 1, 0, 1,
     89 };
     90 static float mtxRot90[16] = {
     91     0, 1, 0, 0,
     92     -1, 0, 0, 0,
     93     0, 0, 1, 0,
     94     1, 0, 0, 1,
     95 };
     96 static float mtxRot180[16] = {
     97     -1, 0, 0, 0,
     98     0, -1, 0, 0,
     99     0, 0, 1, 0,
    100     1, 1, 0, 1,
    101 };
    102 static float mtxRot270[16] = {
    103     0, -1, 0, 0,
    104     1, 0, 0, 0,
    105     0, 0, 1, 0,
    106     0, 1, 0, 1,
    107 };
    108 
    109 static void mtxMul(float out[16], const float a[16], const float b[16]);
    110 
    111 // Get an ID that's unique within this process.
    112 static int32_t createProcessUniqueId() {
    113     static volatile int32_t globalCounter = 0;
    114     return android_atomic_inc(&globalCounter);
    115 }
    116 
    117 SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
    118         GLenum texTarget, bool useFenceSync) :
    119     mDefaultWidth(1),
    120     mDefaultHeight(1),
    121     mPixelFormat(PIXEL_FORMAT_RGBA_8888),
    122     mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
    123     mClientBufferCount(0),
    124     mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
    125     mCurrentTexture(INVALID_BUFFER_SLOT),
    126     mCurrentTransform(0),
    127     mCurrentTimestamp(0),
    128     mNextTransform(0),
    129     mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
    130     mTexName(tex),
    131     mSynchronousMode(false),
    132     mAllowSynchronousMode(allowSynchronousMode),
    133     mConnectedApi(NO_CONNECTED_API),
    134     mAbandoned(false),
    135 #ifdef USE_FENCE_SYNC
    136     mUseFenceSync(useFenceSync),
    137 #else
    138     mUseFenceSync(false),
    139 #endif
    140     mTexTarget(texTarget),
    141     mFrameCounter(0) {
    142     // Choose a name using the PID and a process-unique ID.
    143     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
    144 
    145     ST_LOGV("SurfaceTexture");
    146     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    147     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
    148     mNextCrop.makeInvalid();
    149     memcpy(mCurrentTransformMatrix, mtxIdentity,
    150             sizeof(mCurrentTransformMatrix));
    151 }
    152 
    153 SurfaceTexture::~SurfaceTexture() {
    154     ST_LOGV("~SurfaceTexture");
    155     freeAllBuffersLocked();
    156 }
    157 
    158 status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
    159     if (bufferCount > NUM_BUFFER_SLOTS)
    160         return BAD_VALUE;
    161 
    162     // special-case, nothing to do
    163     if (bufferCount == mBufferCount)
    164         return OK;
    165 
    166     if (!mClientBufferCount &&
    167         bufferCount >= mBufferCount) {
    168         // easy, we just have more buffers
    169         mBufferCount = bufferCount;
    170         mServerBufferCount = bufferCount;
    171         mDequeueCondition.signal();
    172     } else {
    173         // we're here because we're either
    174         // - reducing the number of available buffers
    175         // - or there is a client-buffer-count in effect
    176 
    177         // less than 2 buffers is never allowed
    178         if (bufferCount < 2)
    179             return BAD_VALUE;
    180 
    181         // when there is non client-buffer-count in effect, the client is not
    182         // allowed to dequeue more than one buffer at a time,
    183         // so the next time they dequeue a buffer, we know that they don't
    184         // own one. the actual resizing will happen during the next
    185         // dequeueBuffer.
    186 
    187         mServerBufferCount = bufferCount;
    188     }
    189     return OK;
    190 }
    191 
    192 status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
    193     Mutex::Autolock lock(mMutex);
    194     return setBufferCountServerLocked(bufferCount);
    195 }
    196 
    197 status_t SurfaceTexture::setBufferCount(int bufferCount) {
    198     ST_LOGV("setBufferCount: count=%d", bufferCount);
    199     Mutex::Autolock lock(mMutex);
    200 
    201     if (mAbandoned) {
    202         ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
    203         return NO_INIT;
    204     }
    205     if (bufferCount > NUM_BUFFER_SLOTS) {
    206         ST_LOGE("setBufferCount: bufferCount larger than slots available");
    207         return BAD_VALUE;
    208     }
    209 
    210     // Error out if the user has dequeued buffers
    211     for (int i=0 ; i<mBufferCount ; i++) {
    212         if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
    213             ST_LOGE("setBufferCount: client owns some buffers");
    214             return -EINVAL;
    215         }
    216     }
    217 
    218     const int minBufferSlots = mSynchronousMode ?
    219             MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
    220     if (bufferCount == 0) {
    221         mClientBufferCount = 0;
    222         bufferCount = (mServerBufferCount >= minBufferSlots) ?
    223                 mServerBufferCount : minBufferSlots;
    224         return setBufferCountServerLocked(bufferCount);
    225     }
    226 
    227     if (bufferCount < minBufferSlots) {
    228         ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
    229                 "minimum (%d)", bufferCount, minBufferSlots);
    230         return BAD_VALUE;
    231     }
    232 
    233     // here we're guaranteed that the client doesn't have dequeued buffers
    234     // and will release all of its buffer references.
    235     freeAllBuffersLocked();
    236     mBufferCount = bufferCount;
    237     mClientBufferCount = bufferCount;
    238     mCurrentTexture = INVALID_BUFFER_SLOT;
    239     mQueue.clear();
    240     mDequeueCondition.signal();
    241     return OK;
    242 }
    243 
    244 status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
    245 {
    246     ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
    247     if (!w || !h) {
    248         ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
    249                 w, h);
    250         return BAD_VALUE;
    251     }
    252 
    253     Mutex::Autolock lock(mMutex);
    254     mDefaultWidth = w;
    255     mDefaultHeight = h;
    256     return OK;
    257 }
    258 
    259 status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    260     ST_LOGV("requestBuffer: slot=%d", slot);
    261     Mutex::Autolock lock(mMutex);
    262     if (mAbandoned) {
    263         ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
    264         return NO_INIT;
    265     }
    266     if (slot < 0 || mBufferCount <= slot) {
    267         ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
    268                 mBufferCount, slot);
    269         return BAD_VALUE;
    270     }
    271     mSlots[slot].mRequestBufferCalled = true;
    272     *buf = mSlots[slot].mGraphicBuffer;
    273     return NO_ERROR;
    274 }
    275 
    276 status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
    277         uint32_t format, uint32_t usage) {
    278     ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
    279 
    280     if ((w && !h) || (!w && h)) {
    281         ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
    282         return BAD_VALUE;
    283     }
    284 
    285     status_t returnFlags(OK);
    286     EGLDisplay dpy = EGL_NO_DISPLAY;
    287     EGLSyncKHR fence = EGL_NO_SYNC_KHR;
    288 
    289     { // Scope for the lock
    290         Mutex::Autolock lock(mMutex);
    291 
    292         int found = -1;
    293         int foundSync = -1;
    294         int dequeuedCount = 0;
    295         bool tryAgain = true;
    296         while (tryAgain) {
    297             if (mAbandoned) {
    298                 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
    299                 return NO_INIT;
    300             }
    301 
    302             // We need to wait for the FIFO to drain if the number of buffer
    303             // needs to change.
    304             //
    305             // The condition "number of buffers needs to change" is true if
    306             // - the client doesn't care about how many buffers there are
    307             // - AND the actual number of buffer is different from what was
    308             //   set in the last setBufferCountServer()
    309             //                         - OR -
    310             //   setBufferCountServer() was set to a value incompatible with
    311             //   the synchronization mode (for instance because the sync mode
    312             //   changed since)
    313             //
    314             // As long as this condition is true AND the FIFO is not empty, we
    315             // wait on mDequeueCondition.
    316 
    317             const int minBufferCountNeeded = mSynchronousMode ?
    318                     MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
    319 
    320             const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
    321                     ((mServerBufferCount != mBufferCount) ||
    322                             (mServerBufferCount < minBufferCountNeeded));
    323 
    324             if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
    325                 // wait for the FIFO to drain
    326                 mDequeueCondition.wait(mMutex);
    327                 // NOTE: we continue here because we need to reevaluate our
    328                 // whole state (eg: we could be abandoned or disconnected)
    329                 continue;
    330             }
    331 
    332             if (numberOfBuffersNeedsToChange) {
    333                 // here we're guaranteed that mQueue is empty
    334                 freeAllBuffersLocked();
    335                 mBufferCount = mServerBufferCount;
    336                 if (mBufferCount < minBufferCountNeeded)
    337                     mBufferCount = minBufferCountNeeded;
    338                 mCurrentTexture = INVALID_BUFFER_SLOT;
    339                 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
    340             }
    341 
    342             // look for a free buffer to give to the client
    343             found = INVALID_BUFFER_SLOT;
    344             foundSync = INVALID_BUFFER_SLOT;
    345             dequeuedCount = 0;
    346             for (int i = 0; i < mBufferCount; i++) {
    347                 const int state = mSlots[i].mBufferState;
    348                 if (state == BufferSlot::DEQUEUED) {
    349                     dequeuedCount++;
    350                 }
    351 
    352                 // if buffer is FREE it CANNOT be current
    353                 LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
    354                         "dequeueBuffer: buffer %d is both FREE and current!",
    355                         i);
    356 
    357                 if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
    358                     if (state == BufferSlot::FREE || i == mCurrentTexture) {
    359                         foundSync = i;
    360                         if (i != mCurrentTexture) {
    361                             found = i;
    362                             break;
    363                         }
    364                     }
    365                 } else {
    366                     if (state == BufferSlot::FREE) {
    367                         /* We return the oldest of the free buffers to avoid
    368                          * stalling the producer if possible.  This is because
    369                          * the consumer may still have pending reads of the
    370                          * buffers in flight.
    371                          */
    372                         bool isOlder = mSlots[i].mFrameNumber <
    373                                 mSlots[found].mFrameNumber;
    374                         if (found < 0 || isOlder) {
    375                             foundSync = i;
    376                             found = i;
    377                         }
    378                     }
    379                 }
    380             }
    381 
    382             // clients are not allowed to dequeue more than one buffer
    383             // if they didn't set a buffer count.
    384             if (!mClientBufferCount && dequeuedCount) {
    385                 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
    386                         "setting the buffer count");
    387                 return -EINVAL;
    388             }
    389 
    390             // See whether a buffer has been queued since the last
    391             // setBufferCount so we know whether to perform the
    392             // MIN_UNDEQUEUED_BUFFERS check below.
    393             bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
    394             if (bufferHasBeenQueued) {
    395                 // make sure the client is not trying to dequeue more buffers
    396                 // than allowed.
    397                 const int avail = mBufferCount - (dequeuedCount+1);
    398                 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
    399                     ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
    400                             "(dequeued=%d)",
    401                             MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
    402                             dequeuedCount);
    403                     return -EBUSY;
    404                 }
    405             }
    406 
    407             // we're in synchronous mode and didn't find a buffer, we need to
    408             // wait for some buffers to be consumed
    409             tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
    410             if (tryAgain) {
    411                 mDequeueCondition.wait(mMutex);
    412             }
    413         }
    414 
    415         if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
    416             // foundSync guaranteed to be != INVALID_BUFFER_SLOT
    417             found = foundSync;
    418         }
    419 
    420         if (found == INVALID_BUFFER_SLOT) {
    421             // This should not happen.
    422             ST_LOGE("dequeueBuffer: no available buffer slots");
    423             return -EBUSY;
    424         }
    425 
    426         const int buf = found;
    427         *outBuf = found;
    428 
    429         const bool useDefaultSize = !w && !h;
    430         if (useDefaultSize) {
    431             // use the default size
    432             w = mDefaultWidth;
    433             h = mDefaultHeight;
    434         }
    435 
    436         const bool updateFormat = (format != 0);
    437         if (!updateFormat) {
    438             // keep the current (or default) format
    439             format = mPixelFormat;
    440         }
    441 
    442         // buffer is now in DEQUEUED (but can also be current at the same time,
    443         // if we're in synchronous mode)
    444         mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
    445 
    446         const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
    447         if ((buffer == NULL) ||
    448             (uint32_t(buffer->width)  != w) ||
    449             (uint32_t(buffer->height) != h) ||
    450             (uint32_t(buffer->format) != format) ||
    451             ((uint32_t(buffer->usage) & usage) != usage))
    452         {
    453             usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    454             status_t error;
    455             sp<GraphicBuffer> graphicBuffer(
    456                     mGraphicBufferAlloc->createGraphicBuffer(
    457                             w, h, format, usage, &error));
    458             if (graphicBuffer == 0) {
    459                 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
    460                         "failed");
    461                 return error;
    462             }
    463             if (updateFormat) {
    464                 mPixelFormat = format;
    465             }
    466             mSlots[buf].mGraphicBuffer = graphicBuffer;
    467             mSlots[buf].mRequestBufferCalled = false;
    468             mSlots[buf].mFence = EGL_NO_SYNC_KHR;
    469             if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
    470                 eglDestroyImageKHR(mSlots[buf].mEglDisplay,
    471                         mSlots[buf].mEglImage);
    472                 mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
    473                 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
    474             }
    475             if (mCurrentTexture == buf) {
    476                 // The current texture no longer references the buffer in this slot
    477                 // since we just allocated a new buffer.
    478                 mCurrentTexture = INVALID_BUFFER_SLOT;
    479             }
    480             returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
    481         }
    482 
    483         dpy = mSlots[buf].mEglDisplay;
    484         fence = mSlots[buf].mFence;
    485         mSlots[buf].mFence = EGL_NO_SYNC_KHR;
    486     }
    487 
    488     if (fence != EGL_NO_SYNC_KHR) {
    489         EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
    490         // If something goes wrong, log the error, but return the buffer without
    491         // synchronizing access to it.  It's too late at this point to abort the
    492         // dequeue operation.
    493         if (result == EGL_FALSE) {
    494             LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
    495         } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
    496             LOGE("dequeueBuffer: timeout waiting for fence");
    497         }
    498         eglDestroySyncKHR(dpy, fence);
    499     }
    500 
    501     ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
    502             mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
    503 
    504     return returnFlags;
    505 }
    506 
    507 status_t SurfaceTexture::setSynchronousMode(bool enabled) {
    508     ST_LOGV("setSynchronousMode: enabled=%d", enabled);
    509     Mutex::Autolock lock(mMutex);
    510 
    511     if (mAbandoned) {
    512         ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
    513         return NO_INIT;
    514     }
    515 
    516     status_t err = OK;
    517     if (!mAllowSynchronousMode && enabled)
    518         return err;
    519 
    520     if (!enabled) {
    521         // going to asynchronous mode, drain the queue
    522         err = drainQueueLocked();
    523         if (err != NO_ERROR)
    524             return err;
    525     }
    526 
    527     if (mSynchronousMode != enabled) {
    528         // - if we're going to asynchronous mode, the queue is guaranteed to be
    529         // empty here
    530         // - if the client set the number of buffers, we're guaranteed that
    531         // we have at least 3 (because we don't allow less)
    532         mSynchronousMode = enabled;
    533         mDequeueCondition.signal();
    534     }
    535     return err;
    536 }
    537 
    538 status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
    539         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
    540     ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
    541 
    542     sp<FrameAvailableListener> listener;
    543 
    544     { // scope for the lock
    545         Mutex::Autolock lock(mMutex);
    546         if (mAbandoned) {
    547             ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
    548             return NO_INIT;
    549         }
    550         if (buf < 0 || buf >= mBufferCount) {
    551             ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
    552                     mBufferCount, buf);
    553             return -EINVAL;
    554         } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
    555             ST_LOGE("queueBuffer: slot %d is not owned by the client "
    556                     "(state=%d)", buf, mSlots[buf].mBufferState);
    557             return -EINVAL;
    558         } else if (buf == mCurrentTexture) {
    559             ST_LOGE("queueBuffer: slot %d is current!", buf);
    560             return -EINVAL;
    561         } else if (!mSlots[buf].mRequestBufferCalled) {
    562             ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
    563                     "buffer", buf);
    564             return -EINVAL;
    565         }
    566 
    567         if (mSynchronousMode) {
    568             // In synchronous mode we queue all buffers in a FIFO.
    569             mQueue.push_back(buf);
    570 
    571             // Synchronous mode always signals that an additional frame should
    572             // be consumed.
    573             listener = mFrameAvailableListener;
    574         } else {
    575             // In asynchronous mode we only keep the most recent buffer.
    576             if (mQueue.empty()) {
    577                 mQueue.push_back(buf);
    578 
    579                 // Asynchronous mode only signals that a frame should be
    580                 // consumed if no previous frame was pending. If a frame were
    581                 // pending then the consumer would have already been notified.
    582                 listener = mFrameAvailableListener;
    583             } else {
    584                 Fifo::iterator front(mQueue.begin());
    585                 // buffer currently queued is freed
    586                 mSlots[*front].mBufferState = BufferSlot::FREE;
    587                 // and we record the new buffer index in the queued list
    588                 *front = buf;
    589             }
    590         }
    591 
    592         mSlots[buf].mBufferState = BufferSlot::QUEUED;
    593         mSlots[buf].mCrop = mNextCrop;
    594         mSlots[buf].mTransform = mNextTransform;
    595         mSlots[buf].mScalingMode = mNextScalingMode;
    596         mSlots[buf].mTimestamp = timestamp;
    597         mFrameCounter++;
    598         mSlots[buf].mFrameNumber = mFrameCounter;
    599 
    600         mDequeueCondition.signal();
    601 
    602         *outWidth = mDefaultWidth;
    603         *outHeight = mDefaultHeight;
    604         *outTransform = 0;
    605     } // scope for the lock
    606 
    607     // call back without lock held
    608     if (listener != 0) {
    609         listener->onFrameAvailable();
    610     }
    611     return OK;
    612 }
    613 
    614 void SurfaceTexture::cancelBuffer(int buf) {
    615     ST_LOGV("cancelBuffer: slot=%d", buf);
    616     Mutex::Autolock lock(mMutex);
    617 
    618     if (mAbandoned) {
    619         ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
    620         return;
    621     }
    622 
    623     if (buf < 0 || buf >= mBufferCount) {
    624         ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
    625                 mBufferCount, buf);
    626         return;
    627     } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
    628         ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
    629                 buf, mSlots[buf].mBufferState);
    630         return;
    631     }
    632     mSlots[buf].mBufferState = BufferSlot::FREE;
    633     mSlots[buf].mFrameNumber = 0;
    634     mDequeueCondition.signal();
    635 }
    636 
    637 status_t SurfaceTexture::setCrop(const Rect& crop) {
    638     ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
    639             crop.bottom);
    640 
    641     Mutex::Autolock lock(mMutex);
    642     if (mAbandoned) {
    643         ST_LOGE("setCrop: SurfaceTexture has been abandoned!");
    644         return NO_INIT;
    645     }
    646     mNextCrop = crop;
    647     return OK;
    648 }
    649 
    650 status_t SurfaceTexture::setTransform(uint32_t transform) {
    651     ST_LOGV("setTransform: xform=%#x", transform);
    652     Mutex::Autolock lock(mMutex);
    653     if (mAbandoned) {
    654         ST_LOGE("setTransform: SurfaceTexture has been abandoned!");
    655         return NO_INIT;
    656     }
    657     mNextTransform = transform;
    658     return OK;
    659 }
    660 
    661 status_t SurfaceTexture::connect(int api,
    662         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
    663     ST_LOGV("connect: api=%d", api);
    664     Mutex::Autolock lock(mMutex);
    665 
    666     if (mAbandoned) {
    667         ST_LOGE("connect: SurfaceTexture has been abandoned!");
    668         return NO_INIT;
    669     }
    670 
    671     int err = NO_ERROR;
    672     switch (api) {
    673         case NATIVE_WINDOW_API_EGL:
    674         case NATIVE_WINDOW_API_CPU:
    675         case NATIVE_WINDOW_API_MEDIA:
    676         case NATIVE_WINDOW_API_CAMERA:
    677             if (mConnectedApi != NO_CONNECTED_API) {
    678                 ST_LOGE("connect: already connected (cur=%d, req=%d)",
    679                         mConnectedApi, api);
    680                 err = -EINVAL;
    681             } else {
    682                 mConnectedApi = api;
    683                 *outWidth = mDefaultWidth;
    684                 *outHeight = mDefaultHeight;
    685                 *outTransform = 0;
    686             }
    687             break;
    688         default:
    689             err = -EINVAL;
    690             break;
    691     }
    692     return err;
    693 }
    694 
    695 status_t SurfaceTexture::disconnect(int api) {
    696     ST_LOGV("disconnect: api=%d", api);
    697     Mutex::Autolock lock(mMutex);
    698 
    699     if (mAbandoned) {
    700         // it is not really an error to disconnect after the surface
    701         // has been abandoned, it should just be a no-op.
    702         return NO_ERROR;
    703     }
    704 
    705     int err = NO_ERROR;
    706     switch (api) {
    707         case NATIVE_WINDOW_API_EGL:
    708         case NATIVE_WINDOW_API_CPU:
    709         case NATIVE_WINDOW_API_MEDIA:
    710         case NATIVE_WINDOW_API_CAMERA:
    711             if (mConnectedApi == api) {
    712                 drainQueueAndFreeBuffersLocked();
    713                 mConnectedApi = NO_CONNECTED_API;
    714                 mNextCrop.makeInvalid();
    715                 mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
    716                 mNextTransform = 0;
    717                 mDequeueCondition.signal();
    718             } else {
    719                 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
    720                         mConnectedApi, api);
    721                 err = -EINVAL;
    722             }
    723             break;
    724         default:
    725             ST_LOGE("disconnect: unknown API %d", api);
    726             err = -EINVAL;
    727             break;
    728     }
    729     return err;
    730 }
    731 
    732 status_t SurfaceTexture::setScalingMode(int mode) {
    733     ST_LOGV("setScalingMode: mode=%d", mode);
    734 
    735     switch (mode) {
    736         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
    737         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
    738             break;
    739         default:
    740             ST_LOGE("unknown scaling mode: %d", mode);
    741             return BAD_VALUE;
    742     }
    743 
    744     Mutex::Autolock lock(mMutex);
    745     mNextScalingMode = mode;
    746     return OK;
    747 }
    748 
    749 status_t SurfaceTexture::updateTexImage() {
    750     ST_LOGV("updateTexImage");
    751     Mutex::Autolock lock(mMutex);
    752 
    753     if (mAbandoned) {
    754         ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
    755         return NO_INIT;
    756     }
    757 
    758     // In asynchronous mode the list is guaranteed to be one buffer
    759     // deep, while in synchronous mode we use the oldest buffer.
    760     if (!mQueue.empty()) {
    761         Fifo::iterator front(mQueue.begin());
    762         int buf = *front;
    763 
    764         // Update the GL texture object.
    765         EGLImageKHR image = mSlots[buf].mEglImage;
    766         EGLDisplay dpy = eglGetCurrentDisplay();
    767         if (image == EGL_NO_IMAGE_KHR) {
    768             if (mSlots[buf].mGraphicBuffer == 0) {
    769                 ST_LOGE("buffer at slot %d is null", buf);
    770                 return BAD_VALUE;
    771             }
    772             image = createImage(dpy, mSlots[buf].mGraphicBuffer);
    773             mSlots[buf].mEglImage = image;
    774             mSlots[buf].mEglDisplay = dpy;
    775             if (image == EGL_NO_IMAGE_KHR) {
    776                 // NOTE: if dpy was invalid, createImage() is guaranteed to
    777                 // fail. so we'd end up here.
    778                 return -EINVAL;
    779             }
    780         }
    781 
    782         GLint error;
    783         while ((error = glGetError()) != GL_NO_ERROR) {
    784             ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
    785         }
    786 
    787         glBindTexture(mTexTarget, mTexName);
    788         glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
    789 
    790         bool failed = false;
    791         while ((error = glGetError()) != GL_NO_ERROR) {
    792             ST_LOGE("error binding external texture image %p (slot %d): %#04x",
    793                     image, buf, error);
    794             failed = true;
    795         }
    796         if (failed) {
    797             return -EINVAL;
    798         }
    799 
    800         if (mCurrentTexture != INVALID_BUFFER_SLOT) {
    801             if (mUseFenceSync) {
    802                 EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
    803                         NULL);
    804                 if (fence == EGL_NO_SYNC_KHR) {
    805                     LOGE("updateTexImage: error creating fence: %#x",
    806                             eglGetError());
    807                     return -EINVAL;
    808                 }
    809                 glFlush();
    810                 mSlots[mCurrentTexture].mFence = fence;
    811             }
    812         }
    813 
    814         ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
    815                 mCurrentTexture,
    816                 mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
    817                 buf, mSlots[buf].mGraphicBuffer->handle);
    818 
    819         if (mCurrentTexture != INVALID_BUFFER_SLOT) {
    820             // The current buffer becomes FREE if it was still in the queued
    821             // state. If it has already been given to the client
    822             // (synchronous mode), then it stays in DEQUEUED state.
    823             if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) {
    824                 mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
    825             }
    826         }
    827 
    828         // Update the SurfaceTexture state.
    829         mCurrentTexture = buf;
    830         mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
    831         mCurrentCrop = mSlots[buf].mCrop;
    832         mCurrentTransform = mSlots[buf].mTransform;
    833         mCurrentScalingMode = mSlots[buf].mScalingMode;
    834         mCurrentTimestamp = mSlots[buf].mTimestamp;
    835         computeCurrentTransformMatrix();
    836 
    837         // Now that we've passed the point at which failures can happen,
    838         // it's safe to remove the buffer from the front of the queue.
    839         mQueue.erase(front);
    840         mDequeueCondition.signal();
    841     } else {
    842         // We always bind the texture even if we don't update its contents.
    843         glBindTexture(mTexTarget, mTexName);
    844     }
    845 
    846     return OK;
    847 }
    848 
    849 bool SurfaceTexture::isExternalFormat(uint32_t format)
    850 {
    851     switch (format) {
    852     // supported YUV formats
    853     case HAL_PIXEL_FORMAT_YV12:
    854     // Legacy/deprecated YUV formats
    855     case HAL_PIXEL_FORMAT_YCbCr_422_SP:
    856     case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    857     case HAL_PIXEL_FORMAT_YCbCr_422_I:
    858         return true;
    859     }
    860 
    861     // Any OEM format needs to be considered
    862     if (format>=0x100 && format<=0x1FF)
    863         return true;
    864 
    865     return false;
    866 }
    867 
    868 GLenum SurfaceTexture::getCurrentTextureTarget() const {
    869     return mTexTarget;
    870 }
    871 
    872 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
    873     Mutex::Autolock lock(mMutex);
    874     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
    875 }
    876 
    877 void SurfaceTexture::computeCurrentTransformMatrix() {
    878     ST_LOGV("computeCurrentTransformMatrix");
    879 
    880     float xform[16];
    881     for (int i = 0; i < 16; i++) {
    882         xform[i] = mtxIdentity[i];
    883     }
    884     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
    885         float result[16];
    886         mtxMul(result, xform, mtxFlipH);
    887         for (int i = 0; i < 16; i++) {
    888             xform[i] = result[i];
    889         }
    890     }
    891     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
    892         float result[16];
    893         mtxMul(result, xform, mtxFlipV);
    894         for (int i = 0; i < 16; i++) {
    895             xform[i] = result[i];
    896         }
    897     }
    898     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
    899         float result[16];
    900         mtxMul(result, xform, mtxRot90);
    901         for (int i = 0; i < 16; i++) {
    902             xform[i] = result[i];
    903         }
    904     }
    905 
    906     sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
    907     float tx, ty, sx, sy;
    908     if (!mCurrentCrop.isEmpty()) {
    909         // In order to prevent bilinear sampling at the of the crop rectangle we
    910         // may need to shrink it by 2 texels in each direction.  Normally this
    911         // would just need to take 1/2 a texel off each end, but because the
    912         // chroma channels will likely be subsampled we need to chop off a whole
    913         // texel.  This will cause artifacts if someone does nearest sampling
    914         // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
    915         // accomodate the bilinear and nearest sampling uses.
    916         //
    917         // If nearest sampling turns out to be a desirable usage of these
    918         // textures then we could add the ability to switch a SurfaceTexture to
    919         // nearest-mode.  Preferably, however, the image producers (video
    920         // decoder, camera, etc.) would simply not use a crop rectangle (or at
    921         // least not tell the framework about it) so that the GPU can do the
    922         // correct edge behavior.
    923         int xshrink = 0, yshrink = 0;
    924         if (mCurrentCrop.left > 0) {
    925             tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
    926             xshrink++;
    927         } else {
    928             tx = 0.0f;
    929         }
    930         if (mCurrentCrop.right < int32_t(buf->getWidth())) {
    931             xshrink++;
    932         }
    933         if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
    934             ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
    935                     float(buf->getHeight());
    936             yshrink++;
    937         } else {
    938             ty = 0.0f;
    939         }
    940         if (mCurrentCrop.top > 0) {
    941             yshrink++;
    942         }
    943         sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
    944         sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
    945     } else {
    946         tx = 0.0f;
    947         ty = 0.0f;
    948         sx = 1.0f;
    949         sy = 1.0f;
    950     }
    951     float crop[16] = {
    952         sx, 0, 0, 0,
    953         0, sy, 0, 0,
    954         0, 0, 1, 0,
    955         tx, ty, 0, 1,
    956     };
    957 
    958     float mtxBeforeFlipV[16];
    959     mtxMul(mtxBeforeFlipV, crop, xform);
    960 
    961     // SurfaceFlinger expects the top of its window textures to be at a Y
    962     // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
    963     // want to expose this to applications, however, so we must add an
    964     // additional vertical flip to the transform after all the other transforms.
    965     mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
    966 }
    967 
    968 nsecs_t SurfaceTexture::getTimestamp() {
    969     ST_LOGV("getTimestamp");
    970     Mutex::Autolock lock(mMutex);
    971     return mCurrentTimestamp;
    972 }
    973 
    974 void SurfaceTexture::setFrameAvailableListener(
    975         const sp<FrameAvailableListener>& listener) {
    976     ST_LOGV("setFrameAvailableListener");
    977     Mutex::Autolock lock(mMutex);
    978     mFrameAvailableListener = listener;
    979 }
    980 
    981 void SurfaceTexture::freeBufferLocked(int i) {
    982     mSlots[i].mGraphicBuffer = 0;
    983     mSlots[i].mBufferState = BufferSlot::FREE;
    984     mSlots[i].mFrameNumber = 0;
    985     if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
    986         eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
    987         mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
    988         mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
    989     }
    990 }
    991 
    992 void SurfaceTexture::freeAllBuffersLocked() {
    993     LOGW_IF(!mQueue.isEmpty(),
    994             "freeAllBuffersLocked called but mQueue is not empty");
    995     mCurrentTexture = INVALID_BUFFER_SLOT;
    996     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
    997         freeBufferLocked(i);
    998     }
    999 }
   1000 
   1001 void SurfaceTexture::freeAllBuffersExceptHeadLocked() {
   1002     LOGW_IF(!mQueue.isEmpty(),
   1003             "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
   1004     int head = -1;
   1005     if (!mQueue.empty()) {
   1006         Fifo::iterator front(mQueue.begin());
   1007         head = *front;
   1008     }
   1009     mCurrentTexture = INVALID_BUFFER_SLOT;
   1010     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   1011         if (i != head) {
   1012             freeBufferLocked(i);
   1013         }
   1014     }
   1015 }
   1016 
   1017 status_t SurfaceTexture::drainQueueLocked() {
   1018     while (mSynchronousMode && !mQueue.isEmpty()) {
   1019         mDequeueCondition.wait(mMutex);
   1020         if (mAbandoned) {
   1021             ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
   1022             return NO_INIT;
   1023         }
   1024         if (mConnectedApi == NO_CONNECTED_API) {
   1025             ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!");
   1026             return NO_INIT;
   1027         }
   1028     }
   1029     return NO_ERROR;
   1030 }
   1031 
   1032 status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() {
   1033     status_t err = drainQueueLocked();
   1034     if (err == NO_ERROR) {
   1035         if (mSynchronousMode) {
   1036             freeAllBuffersLocked();
   1037         } else {
   1038             freeAllBuffersExceptHeadLocked();
   1039         }
   1040     }
   1041     return err;
   1042 }
   1043 
   1044 EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
   1045         const sp<GraphicBuffer>& graphicBuffer) {
   1046     EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
   1047     EGLint attrs[] = {
   1048         EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
   1049         EGL_NONE,
   1050     };
   1051     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
   1052             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
   1053     if (image == EGL_NO_IMAGE_KHR) {
   1054         EGLint error = eglGetError();
   1055         ST_LOGE("error creating EGLImage: %#x", error);
   1056     }
   1057     return image;
   1058 }
   1059 
   1060 sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
   1061     Mutex::Autolock lock(mMutex);
   1062     return mCurrentTextureBuf;
   1063 }
   1064 
   1065 Rect SurfaceTexture::getCurrentCrop() const {
   1066     Mutex::Autolock lock(mMutex);
   1067     return mCurrentCrop;
   1068 }
   1069 
   1070 uint32_t SurfaceTexture::getCurrentTransform() const {
   1071     Mutex::Autolock lock(mMutex);
   1072     return mCurrentTransform;
   1073 }
   1074 
   1075 uint32_t SurfaceTexture::getCurrentScalingMode() const {
   1076     Mutex::Autolock lock(mMutex);
   1077     return mCurrentScalingMode;
   1078 }
   1079 
   1080 bool SurfaceTexture::isSynchronousMode() const {
   1081     Mutex::Autolock lock(mMutex);
   1082     return mSynchronousMode;
   1083 }
   1084 
   1085 int SurfaceTexture::query(int what, int* outValue)
   1086 {
   1087     Mutex::Autolock lock(mMutex);
   1088 
   1089     if (mAbandoned) {
   1090         ST_LOGE("query: SurfaceTexture has been abandoned!");
   1091         return NO_INIT;
   1092     }
   1093 
   1094     int value;
   1095     switch (what) {
   1096     case NATIVE_WINDOW_WIDTH:
   1097         value = mDefaultWidth;
   1098         break;
   1099     case NATIVE_WINDOW_HEIGHT:
   1100         value = mDefaultHeight;
   1101         break;
   1102     case NATIVE_WINDOW_FORMAT:
   1103         value = mPixelFormat;
   1104         break;
   1105     case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
   1106         value = mSynchronousMode ?
   1107                 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
   1108         break;
   1109     default:
   1110         return BAD_VALUE;
   1111     }
   1112     outValue[0] = value;
   1113     return NO_ERROR;
   1114 }
   1115 
   1116 void SurfaceTexture::abandon() {
   1117     Mutex::Autolock lock(mMutex);
   1118     mQueue.clear();
   1119     mAbandoned = true;
   1120     mCurrentTextureBuf.clear();
   1121     freeAllBuffersLocked();
   1122     mDequeueCondition.signal();
   1123 }
   1124 
   1125 void SurfaceTexture::setName(const String8& name) {
   1126     mName = name;
   1127 }
   1128 
   1129 void SurfaceTexture::dump(String8& result) const
   1130 {
   1131     char buffer[1024];
   1132     dump(result, "", buffer, 1024);
   1133 }
   1134 
   1135 void SurfaceTexture::dump(String8& result, const char* prefix,
   1136         char* buffer, size_t SIZE) const
   1137 {
   1138     Mutex::Autolock _l(mMutex);
   1139     snprintf(buffer, SIZE,
   1140             "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
   1141             "mPixelFormat=%d, mTexName=%d\n",
   1142             prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
   1143             mDefaultHeight, mPixelFormat, mTexName);
   1144     result.append(buffer);
   1145 
   1146     String8 fifo;
   1147     int fifoSize = 0;
   1148     Fifo::const_iterator i(mQueue.begin());
   1149     while (i != mQueue.end()) {
   1150         snprintf(buffer, SIZE, "%02d ", *i++);
   1151         fifoSize++;
   1152         fifo.append(buffer);
   1153     }
   1154 
   1155     snprintf(buffer, SIZE,
   1156             "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
   1157             "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
   1158             ,
   1159             prefix, mCurrentCrop.left,
   1160             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
   1161             mCurrentTransform, mCurrentTexture,
   1162             prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
   1163             mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
   1164     );
   1165     result.append(buffer);
   1166 
   1167     struct {
   1168         const char * operator()(int state) const {
   1169             switch (state) {
   1170                 case BufferSlot::DEQUEUED: return "DEQUEUED";
   1171                 case BufferSlot::QUEUED: return "QUEUED";
   1172                 case BufferSlot::FREE: return "FREE";
   1173                 default: return "Unknown";
   1174             }
   1175         }
   1176     } stateName;
   1177 
   1178     for (int i=0 ; i<mBufferCount ; i++) {
   1179         const BufferSlot& slot(mSlots[i]);
   1180         snprintf(buffer, SIZE,
   1181                 "%s%s[%02d] "
   1182                 "state=%-8s, crop=[%d,%d,%d,%d], "
   1183                 "transform=0x%02x, timestamp=%lld",
   1184                 prefix, (i==mCurrentTexture)?">":" ", i,
   1185                 stateName(slot.mBufferState),
   1186                 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
   1187                 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
   1188         );
   1189         result.append(buffer);
   1190 
   1191         const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
   1192         if (buf != NULL) {
   1193             snprintf(buffer, SIZE,
   1194                     ", %p [%4ux%4u:%4u,%3X]",
   1195                     buf->handle, buf->width, buf->height, buf->stride,
   1196                     buf->format);
   1197             result.append(buffer);
   1198         }
   1199         result.append("\n");
   1200     }
   1201 }
   1202 
   1203 static void mtxMul(float out[16], const float a[16], const float b[16]) {
   1204     out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
   1205     out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
   1206     out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
   1207     out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
   1208 
   1209     out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
   1210     out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
   1211     out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
   1212     out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
   1213 
   1214     out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
   1215     out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
   1216     out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
   1217     out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
   1218 
   1219     out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
   1220     out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
   1221     out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
   1222     out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
   1223 }
   1224 
   1225 }; // namespace android
   1226