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