SurfaceTexture.cpp revision 87f3265bb082160efdfdfb87a79698c67ebad447
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        if (mCurrentTexture == buf) {
441            // The current texture no longer references the buffer in this slot
442            // since we just allocated a new buffer.
443            mCurrentTexture = INVALID_BUFFER_SLOT;
444        }
445        returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
446    }
447    ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", buf,
448            mSlots[buf].mGraphicBuffer->handle, returnFlags);
449    return returnFlags;
450}
451
452status_t SurfaceTexture::setSynchronousMode(bool enabled) {
453    ST_LOGV("setSynchronousMode: enabled=%d", enabled);
454    Mutex::Autolock lock(mMutex);
455
456    if (mAbandoned) {
457        ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
458        return NO_INIT;
459    }
460
461    status_t err = OK;
462    if (!mAllowSynchronousMode && enabled)
463        return err;
464
465    if (!enabled) {
466        // going to asynchronous mode, drain the queue
467        err = drainQueueLocked();
468        if (err != NO_ERROR)
469            return err;
470    }
471
472    if (mSynchronousMode != enabled) {
473        // - if we're going to asynchronous mode, the queue is guaranteed to be
474        // empty here
475        // - if the client set the number of buffers, we're guaranteed that
476        // we have at least 3 (because we don't allow less)
477        mSynchronousMode = enabled;
478        mDequeueCondition.signal();
479    }
480    return err;
481}
482
483status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
484        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
485    ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
486
487    sp<FrameAvailableListener> listener;
488
489    { // scope for the lock
490        Mutex::Autolock lock(mMutex);
491        if (mAbandoned) {
492            ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
493            return NO_INIT;
494        }
495        if (buf < 0 || buf >= mBufferCount) {
496            ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
497                    mBufferCount, buf);
498            return -EINVAL;
499        } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
500            ST_LOGE("queueBuffer: slot %d is not owned by the client "
501                    "(state=%d)", buf, mSlots[buf].mBufferState);
502            return -EINVAL;
503        } else if (buf == mCurrentTexture) {
504            ST_LOGE("queueBuffer: slot %d is current!", buf);
505            return -EINVAL;
506        } else if (!mSlots[buf].mRequestBufferCalled) {
507            ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
508                    "buffer", buf);
509            return -EINVAL;
510        }
511
512        if (mSynchronousMode) {
513            // In synchronous mode we queue all buffers in a FIFO.
514            mQueue.push_back(buf);
515
516            // Synchronous mode always signals that an additional frame should
517            // be consumed.
518            listener = mFrameAvailableListener;
519        } else {
520            // In asynchronous mode we only keep the most recent buffer.
521            if (mQueue.empty()) {
522                mQueue.push_back(buf);
523
524                // Asynchronous mode only signals that a frame should be
525                // consumed if no previous frame was pending. If a frame were
526                // pending then the consumer would have already been notified.
527                listener = mFrameAvailableListener;
528            } else {
529                Fifo::iterator front(mQueue.begin());
530                // buffer currently queued is freed
531                mSlots[*front].mBufferState = BufferSlot::FREE;
532                // and we record the new buffer index in the queued list
533                *front = buf;
534            }
535        }
536
537        mSlots[buf].mBufferState = BufferSlot::QUEUED;
538        mSlots[buf].mCrop = mNextCrop;
539        mSlots[buf].mTransform = mNextTransform;
540        mSlots[buf].mScalingMode = mNextScalingMode;
541        mSlots[buf].mTimestamp = timestamp;
542        mFrameCounter++;
543        mSlots[buf].mFrameNumber = mFrameCounter;
544
545        mDequeueCondition.signal();
546
547        *outWidth = mDefaultWidth;
548        *outHeight = mDefaultHeight;
549        *outTransform = 0;
550    } // scope for the lock
551
552    // call back without lock held
553    if (listener != 0) {
554        listener->onFrameAvailable();
555    }
556    return OK;
557}
558
559void SurfaceTexture::cancelBuffer(int buf) {
560    ST_LOGV("cancelBuffer: slot=%d", buf);
561    Mutex::Autolock lock(mMutex);
562
563    if (mAbandoned) {
564        ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
565        return;
566    }
567
568    if (buf < 0 || buf >= mBufferCount) {
569        ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
570                mBufferCount, buf);
571        return;
572    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
573        ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
574                buf, mSlots[buf].mBufferState);
575        return;
576    }
577    mSlots[buf].mBufferState = BufferSlot::FREE;
578    mSlots[buf].mFrameNumber = 0;
579    mDequeueCondition.signal();
580}
581
582status_t SurfaceTexture::setCrop(const Rect& crop) {
583    ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
584            crop.bottom);
585
586    Mutex::Autolock lock(mMutex);
587    if (mAbandoned) {
588        ST_LOGE("setCrop: SurfaceTexture has been abandoned!");
589        return NO_INIT;
590    }
591    mNextCrop = crop;
592    return OK;
593}
594
595status_t SurfaceTexture::setTransform(uint32_t transform) {
596    ST_LOGV("setTransform: xform=%#x", transform);
597    Mutex::Autolock lock(mMutex);
598    if (mAbandoned) {
599        ST_LOGE("setTransform: SurfaceTexture has been abandoned!");
600        return NO_INIT;
601    }
602    mNextTransform = transform;
603    return OK;
604}
605
606status_t SurfaceTexture::connect(int api,
607        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
608    ST_LOGV("connect: api=%d", api);
609    Mutex::Autolock lock(mMutex);
610
611    if (mAbandoned) {
612        ST_LOGE("connect: SurfaceTexture has been abandoned!");
613        return NO_INIT;
614    }
615
616    int err = NO_ERROR;
617    switch (api) {
618        case NATIVE_WINDOW_API_EGL:
619        case NATIVE_WINDOW_API_CPU:
620        case NATIVE_WINDOW_API_MEDIA:
621        case NATIVE_WINDOW_API_CAMERA:
622            if (mConnectedApi != NO_CONNECTED_API) {
623                ST_LOGE("connect: already connected (cur=%d, req=%d)",
624                        mConnectedApi, api);
625                err = -EINVAL;
626            } else {
627                mConnectedApi = api;
628                *outWidth = mDefaultWidth;
629                *outHeight = mDefaultHeight;
630                *outTransform = 0;
631            }
632            break;
633        default:
634            err = -EINVAL;
635            break;
636    }
637    return err;
638}
639
640status_t SurfaceTexture::disconnect(int api) {
641    ST_LOGV("disconnect: api=%d", api);
642    Mutex::Autolock lock(mMutex);
643
644    if (mAbandoned) {
645        ST_LOGE("disconnect: SurfaceTexture has been abandoned!");
646        return NO_INIT;
647    }
648
649    int err = NO_ERROR;
650    switch (api) {
651        case NATIVE_WINDOW_API_EGL:
652        case NATIVE_WINDOW_API_CPU:
653        case NATIVE_WINDOW_API_MEDIA:
654        case NATIVE_WINDOW_API_CAMERA:
655            if (mConnectedApi == api) {
656                drainQueueAndFreeBuffersLocked();
657                mConnectedApi = NO_CONNECTED_API;
658                mNextCrop.makeInvalid();
659                mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
660                mNextTransform = 0;
661                mDequeueCondition.signal();
662            } else {
663                ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
664                        mConnectedApi, api);
665                err = -EINVAL;
666            }
667            break;
668        default:
669            ST_LOGE("disconnect: unknown API %d", api);
670            err = -EINVAL;
671            break;
672    }
673    return err;
674}
675
676status_t SurfaceTexture::setScalingMode(int mode) {
677    ST_LOGV("setScalingMode: mode=%d", mode);
678
679    switch (mode) {
680        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
681        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
682            break;
683        default:
684            ST_LOGE("unknown scaling mode: %d", mode);
685            return BAD_VALUE;
686    }
687
688    Mutex::Autolock lock(mMutex);
689    mNextScalingMode = mode;
690    return OK;
691}
692
693status_t SurfaceTexture::updateTexImage() {
694    ST_LOGV("updateTexImage");
695    Mutex::Autolock lock(mMutex);
696
697    if (mAbandoned) {
698        ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
699        return NO_INIT;
700    }
701
702    // In asynchronous mode the list is guaranteed to be one buffer
703    // deep, while in synchronous mode we use the oldest buffer.
704    if (!mQueue.empty()) {
705        Fifo::iterator front(mQueue.begin());
706        int buf = *front;
707
708        // Update the GL texture object.
709        EGLImageKHR image = mSlots[buf].mEglImage;
710        if (image == EGL_NO_IMAGE_KHR) {
711            EGLDisplay dpy = eglGetCurrentDisplay();
712            if (mSlots[buf].mGraphicBuffer == 0) {
713                ST_LOGE("buffer at slot %d is null", buf);
714                return BAD_VALUE;
715            }
716            image = createImage(dpy, mSlots[buf].mGraphicBuffer);
717            mSlots[buf].mEglImage = image;
718            mSlots[buf].mEglDisplay = dpy;
719            if (image == EGL_NO_IMAGE_KHR) {
720                // NOTE: if dpy was invalid, createImage() is guaranteed to
721                // fail. so we'd end up here.
722                return -EINVAL;
723            }
724        }
725
726        GLint error;
727        while ((error = glGetError()) != GL_NO_ERROR) {
728            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
729        }
730
731        glBindTexture(mTexTarget, mTexName);
732        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
733
734        bool failed = false;
735        while ((error = glGetError()) != GL_NO_ERROR) {
736            ST_LOGE("error binding external texture image %p (slot %d): %#04x",
737                    image, buf, error);
738            failed = true;
739        }
740        if (failed) {
741            return -EINVAL;
742        }
743
744        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
745                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf,
746                mSlots[buf].mGraphicBuffer->handle);
747
748        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
749            // The current buffer becomes FREE if it was still in the queued
750            // state. If it has already been given to the client
751            // (synchronous mode), then it stays in DEQUEUED state.
752            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
753                mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
754        }
755
756        // Update the SurfaceTexture state.
757        mCurrentTexture = buf;
758        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
759        mCurrentCrop = mSlots[buf].mCrop;
760        mCurrentTransform = mSlots[buf].mTransform;
761        mCurrentScalingMode = mSlots[buf].mScalingMode;
762        mCurrentTimestamp = mSlots[buf].mTimestamp;
763        computeCurrentTransformMatrix();
764
765        // Now that we've passed the point at which failures can happen,
766        // it's safe to remove the buffer from the front of the queue.
767        mQueue.erase(front);
768        mDequeueCondition.signal();
769    } else {
770        // We always bind the texture even if we don't update its contents.
771        glBindTexture(mTexTarget, mTexName);
772    }
773
774    return OK;
775}
776
777bool SurfaceTexture::isExternalFormat(uint32_t format)
778{
779    switch (format) {
780    // supported YUV formats
781    case HAL_PIXEL_FORMAT_YV12:
782    // Legacy/deprecated YUV formats
783    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
784    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
785    case HAL_PIXEL_FORMAT_YCbCr_422_I:
786        return true;
787    }
788
789    // Any OEM format needs to be considered
790    if (format>=0x100 && format<=0x1FF)
791        return true;
792
793    return false;
794}
795
796GLenum SurfaceTexture::getCurrentTextureTarget() const {
797    return mTexTarget;
798}
799
800void SurfaceTexture::getTransformMatrix(float mtx[16]) {
801    Mutex::Autolock lock(mMutex);
802    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
803}
804
805void SurfaceTexture::computeCurrentTransformMatrix() {
806    ST_LOGV("computeCurrentTransformMatrix");
807
808    float xform[16];
809    for (int i = 0; i < 16; i++) {
810        xform[i] = mtxIdentity[i];
811    }
812    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
813        float result[16];
814        mtxMul(result, xform, mtxFlipH);
815        for (int i = 0; i < 16; i++) {
816            xform[i] = result[i];
817        }
818    }
819    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
820        float result[16];
821        mtxMul(result, xform, mtxFlipV);
822        for (int i = 0; i < 16; i++) {
823            xform[i] = result[i];
824        }
825    }
826    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
827        float result[16];
828        mtxMul(result, xform, mtxRot90);
829        for (int i = 0; i < 16; i++) {
830            xform[i] = result[i];
831        }
832    }
833
834    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
835    float tx, ty, sx, sy;
836    if (!mCurrentCrop.isEmpty()) {
837        // In order to prevent bilinear sampling at the of the crop rectangle we
838        // may need to shrink it by 2 texels in each direction.  Normally this
839        // would just need to take 1/2 a texel off each end, but because the
840        // chroma channels will likely be subsampled we need to chop off a whole
841        // texel.  This will cause artifacts if someone does nearest sampling
842        // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
843        // accomodate the bilinear and nearest sampling uses.
844        //
845        // If nearest sampling turns out to be a desirable usage of these
846        // textures then we could add the ability to switch a SurfaceTexture to
847        // nearest-mode.  Preferably, however, the image producers (video
848        // decoder, camera, etc.) would simply not use a crop rectangle (or at
849        // least not tell the framework about it) so that the GPU can do the
850        // correct edge behavior.
851        int xshrink = 0, yshrink = 0;
852        if (mCurrentCrop.left > 0) {
853            tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
854            xshrink++;
855        } else {
856            tx = 0.0f;
857        }
858        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
859            xshrink++;
860        }
861        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
862            ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
863                    float(buf->getHeight());
864            yshrink++;
865        } else {
866            ty = 0.0f;
867        }
868        if (mCurrentCrop.top > 0) {
869            yshrink++;
870        }
871        sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
872        sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
873    } else {
874        tx = 0.0f;
875        ty = 0.0f;
876        sx = 1.0f;
877        sy = 1.0f;
878    }
879    float crop[16] = {
880        sx, 0, 0, 0,
881        0, sy, 0, 0,
882        0, 0, 1, 0,
883        tx, ty, 0, 1,
884    };
885
886    float mtxBeforeFlipV[16];
887    mtxMul(mtxBeforeFlipV, crop, xform);
888
889    // SurfaceFlinger expects the top of its window textures to be at a Y
890    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
891    // want to expose this to applications, however, so we must add an
892    // additional vertical flip to the transform after all the other transforms.
893    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
894}
895
896nsecs_t SurfaceTexture::getTimestamp() {
897    ST_LOGV("getTimestamp");
898    Mutex::Autolock lock(mMutex);
899    return mCurrentTimestamp;
900}
901
902void SurfaceTexture::setFrameAvailableListener(
903        const sp<FrameAvailableListener>& listener) {
904    ST_LOGV("setFrameAvailableListener");
905    Mutex::Autolock lock(mMutex);
906    mFrameAvailableListener = listener;
907}
908
909void SurfaceTexture::freeBufferLocked(int i) {
910    mSlots[i].mGraphicBuffer = 0;
911    mSlots[i].mBufferState = BufferSlot::FREE;
912    mSlots[i].mFrameNumber = 0;
913    if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
914        eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
915        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
916        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
917    }
918}
919
920void SurfaceTexture::freeAllBuffersLocked() {
921    LOGW_IF(!mQueue.isEmpty(),
922            "freeAllBuffersLocked called but mQueue is not empty");
923    mCurrentTexture = INVALID_BUFFER_SLOT;
924    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
925        freeBufferLocked(i);
926    }
927}
928
929void SurfaceTexture::freeAllBuffersExceptHeadLocked() {
930    LOGW_IF(!mQueue.isEmpty(),
931            "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
932    int head = -1;
933    if (!mQueue.empty()) {
934        Fifo::iterator front(mQueue.begin());
935        head = *front;
936    }
937    mCurrentTexture = INVALID_BUFFER_SLOT;
938    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
939        if (i != head) {
940            freeBufferLocked(i);
941        }
942    }
943}
944
945status_t SurfaceTexture::drainQueueLocked() {
946    while (mSynchronousMode && !mQueue.isEmpty()) {
947        mDequeueCondition.wait(mMutex);
948        if (mAbandoned) {
949            ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
950            return NO_INIT;
951        }
952        if (mConnectedApi == NO_CONNECTED_API) {
953            ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!");
954            return NO_INIT;
955        }
956    }
957    return NO_ERROR;
958}
959
960status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() {
961    status_t err = drainQueueLocked();
962    if (err == NO_ERROR) {
963        if (mSynchronousMode) {
964            freeAllBuffersLocked();
965        } else {
966            freeAllBuffersExceptHeadLocked();
967        }
968    }
969    return err;
970}
971
972EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
973        const sp<GraphicBuffer>& graphicBuffer) {
974    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
975    EGLint attrs[] = {
976        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
977        EGL_NONE,
978    };
979    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
980            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
981    if (image == EGL_NO_IMAGE_KHR) {
982        EGLint error = eglGetError();
983        ST_LOGE("error creating EGLImage: %#x", error);
984    }
985    return image;
986}
987
988sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
989    Mutex::Autolock lock(mMutex);
990    return mCurrentTextureBuf;
991}
992
993Rect SurfaceTexture::getCurrentCrop() const {
994    Mutex::Autolock lock(mMutex);
995    return mCurrentCrop;
996}
997
998uint32_t SurfaceTexture::getCurrentTransform() const {
999    Mutex::Autolock lock(mMutex);
1000    return mCurrentTransform;
1001}
1002
1003uint32_t SurfaceTexture::getCurrentScalingMode() const {
1004    Mutex::Autolock lock(mMutex);
1005    return mCurrentScalingMode;
1006}
1007
1008bool SurfaceTexture::isSynchronousMode() const {
1009    Mutex::Autolock lock(mMutex);
1010    return mSynchronousMode;
1011}
1012
1013int SurfaceTexture::query(int what, int* outValue)
1014{
1015    Mutex::Autolock lock(mMutex);
1016
1017    if (mAbandoned) {
1018        ST_LOGE("query: SurfaceTexture has been abandoned!");
1019        return NO_INIT;
1020    }
1021
1022    int value;
1023    switch (what) {
1024    case NATIVE_WINDOW_WIDTH:
1025        value = mDefaultWidth;
1026        break;
1027    case NATIVE_WINDOW_HEIGHT:
1028        value = mDefaultHeight;
1029        break;
1030    case NATIVE_WINDOW_FORMAT:
1031        value = mPixelFormat;
1032        break;
1033    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
1034        value = mSynchronousMode ?
1035                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
1036        break;
1037    default:
1038        return BAD_VALUE;
1039    }
1040    outValue[0] = value;
1041    return NO_ERROR;
1042}
1043
1044void SurfaceTexture::abandon() {
1045    Mutex::Autolock lock(mMutex);
1046    mQueue.clear();
1047    mAbandoned = true;
1048    mCurrentTextureBuf.clear();
1049    freeAllBuffersLocked();
1050    mDequeueCondition.signal();
1051}
1052
1053void SurfaceTexture::setName(const String8& name) {
1054    mName = name;
1055}
1056
1057void SurfaceTexture::dump(String8& result) const
1058{
1059    char buffer[1024];
1060    dump(result, "", buffer, 1024);
1061}
1062
1063void SurfaceTexture::dump(String8& result, const char* prefix,
1064        char* buffer, size_t SIZE) const
1065{
1066    Mutex::Autolock _l(mMutex);
1067    snprintf(buffer, SIZE,
1068            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
1069            "mPixelFormat=%d, mTexName=%d\n",
1070            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
1071            mDefaultHeight, mPixelFormat, mTexName);
1072    result.append(buffer);
1073
1074    String8 fifo;
1075    int fifoSize = 0;
1076    Fifo::const_iterator i(mQueue.begin());
1077    while (i != mQueue.end()) {
1078        snprintf(buffer, SIZE, "%02d ", *i++);
1079        fifoSize++;
1080        fifo.append(buffer);
1081    }
1082
1083    snprintf(buffer, SIZE,
1084            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
1085            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
1086            ,
1087            prefix, mCurrentCrop.left,
1088            mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
1089            mCurrentTransform, mCurrentTexture,
1090            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
1091            mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
1092    );
1093    result.append(buffer);
1094
1095    struct {
1096        const char * operator()(int state) const {
1097            switch (state) {
1098                case BufferSlot::DEQUEUED: return "DEQUEUED";
1099                case BufferSlot::QUEUED: return "QUEUED";
1100                case BufferSlot::FREE: return "FREE";
1101                default: return "Unknown";
1102            }
1103        }
1104    } stateName;
1105
1106    for (int i=0 ; i<mBufferCount ; i++) {
1107        const BufferSlot& slot(mSlots[i]);
1108        snprintf(buffer, SIZE,
1109                "%s%s[%02d] "
1110                "state=%-8s, crop=[%d,%d,%d,%d], "
1111                "transform=0x%02x, timestamp=%lld",
1112                prefix, (i==mCurrentTexture)?">":" ", i,
1113                stateName(slot.mBufferState),
1114                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
1115                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
1116        );
1117        result.append(buffer);
1118
1119        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
1120        if (buf != NULL) {
1121            snprintf(buffer, SIZE,
1122                    ", %p [%4ux%4u:%4u,%3X]",
1123                    buf->handle, buf->width, buf->height, buf->stride,
1124                    buf->format);
1125            result.append(buffer);
1126        }
1127        result.append("\n");
1128    }
1129}
1130
1131static void mtxMul(float out[16], const float a[16], const float b[16]) {
1132    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1133    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1134    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1135    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1136
1137    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1138    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1139    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1140    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1141
1142    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1143    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1144    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1145    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1146
1147    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1148    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1149    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1150    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1151}
1152
1153}; // namespace android
1154