GLConsumer.cpp revision 41f673c9b3aac0d96e41c928845c39186d565212
18ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/*
28ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Copyright (C) 2010 The Android Open Source Project
38ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
48ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
58ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * you may not use this file except in compliance with the License.
68ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * You may obtain a copy of the License at
78ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
88ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
98ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Unless required by applicable law or agreed to in writing, software
118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * See the License for the specific language governing permissions and
148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * limitations under the License.
158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis */
168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define LOG_TAG "SurfaceTexture"
18e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis//#define LOG_NDEBUG 0
198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define GL_GLEXT_PROTOTYPES
218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define EGL_EGLEXT_PROTOTYPES
228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/egl.h>
248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/eglext.h>
258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2.h>
268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2ext.h>
278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
288ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <gui/SurfaceTexture.h>
298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian#include <hardware/hardware.h>
317a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3241f673c9b3aac0d96e41c928845c39186d565212Mathias Agopian#include <private/gui/ComposerService.h>
3341f673c9b3aac0d96e41c928845c39186d565212Mathias Agopian
348ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <surfaceflinger/ISurfaceComposer.h>
358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <surfaceflinger/SurfaceComposerClient.h>
369a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis#include <surfaceflinger/IGraphicBufferAlloc.h>
378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <utils/Log.h>
3968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian#include <utils/String8.h>
408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
417c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
427c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    true
437c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
447c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian#else
457c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    false
467c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian#endif
4729b5762efc359022168e5099c1d17925444d3147Mathias Agopian
48fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis// Macros for including the SurfaceTexture name in log messages
496807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
50fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
51fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis#define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
52fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis#define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
53fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis#define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5429b5762efc359022168e5099c1d17925444d3147Mathias Agopian
558ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisnamespace android {
568ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
57f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
58f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
59f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
60f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
61f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
62f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
63f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
64f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
65f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
66f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
67f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
68f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
69f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
70f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
71f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
72f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
73f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot180[16] = {
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 1, 0, 1,
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot270[16] = {
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
92f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
93f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
94f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
95f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
96f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
97fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis// Get an ID that's unique within this process.
98fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennisstatic int32_t createProcessUniqueId() {
99fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    static volatile int32_t globalCounter = 0;
100fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    return android_atomic_inc(&globalCounter);
101fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis}
102fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
103fb1b5a2f333800574b0da435d1200cf9b13d723fJamie GennisSurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
104fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        GLenum texTarget) :
105a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mDefaultWidth(1),
106a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mDefaultHeight(1),
107a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
1088072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
1098072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    mClientBufferCount(0),
1108072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
1111d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTexture(INVALID_BUFFER_SLOT),
1121d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
1131d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
1141d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mNextTransform(0),
1157734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
116b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
11714a0e58074f2698829b6554f578e6762c377caa3Grace Kloba    mSynchronousMode(false),
118fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    mAllowSynchronousMode(allowSynchronousMode),
1197b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    mConnectedApi(NO_CONNECTED_API),
120fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    mAbandoned(false),
121a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli    mTexTarget(texTarget),
122a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli    mFrameCounter(0) {
123fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    // Choose a name using the PID and a process-unique ID.
124fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
125fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
1266ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("SurfaceTexture");
1279a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
1289a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
129cc57d6f8830e533734925f102307df2e6cff6de7Mathias Agopian    mNextCrop.makeInvalid();
130fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
131fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
1328ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1338ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1348ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisSurfaceTexture::~SurfaceTexture() {
1356ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("~SurfaceTexture");
136ef51b992192adf4fc432686ab346f5fc7a13bc95Mathias Agopian    freeAllBuffersLocked();
1378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1398072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatus_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
1408072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    if (bufferCount > NUM_BUFFER_SLOTS)
1418072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        return BAD_VALUE;
1428072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1438072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    // special-case, nothing to do
1448072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    if (bufferCount == mBufferCount)
1458072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        return OK;
1468072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1478072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    if (!mClientBufferCount &&
1488072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        bufferCount >= mBufferCount) {
1498072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // easy, we just have more buffers
1508072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        mBufferCount = bufferCount;
1518072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        mServerBufferCount = bufferCount;
1528072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        mDequeueCondition.signal();
1538072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    } else {
1548072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // we're here because we're either
1558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // - reducing the number of available buffers
1568072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // - or there is a client-buffer-count in effect
1578072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1588072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // less than 2 buffers is never allowed
1598072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        if (bufferCount < 2)
1608072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            return BAD_VALUE;
1618072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1628072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // when there is non client-buffer-count in effect, the client is not
1638072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // allowed to dequeue more than one buffer at a time,
1648072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // so the next time they dequeue a buffer, we know that they don't
1658072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // own one. the actual resizing will happen during the next
1668072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // dequeueBuffer.
1678072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1688072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        mServerBufferCount = bufferCount;
1698072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    }
1708072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    return OK;
1718072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1728072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1738072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatus_t SurfaceTexture::setBufferCountServer(int bufferCount) {
1748072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
1758072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    return setBufferCountServerLocked(bufferCount);
1768072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1778072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1788ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::setBufferCount(int bufferCount) {
1796ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setBufferCount: count=%d", bufferCount);
180b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    Mutex::Autolock lock(mMutex);
1819d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis
1827b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
183fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
1847b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
1857b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
186292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi    if (bufferCount > NUM_BUFFER_SLOTS) {
187fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setBufferCount: bufferCount larger than slots available");
188292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi        return BAD_VALUE;
189292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi    }
190292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi
1918072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    // Error out if the user has dequeued buffers
1928072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    for (int i=0 ; i<mBufferCount ; i++) {
1938072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
194fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("setBufferCount: client owns some buffers");
1958072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            return -EINVAL;
1968072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        }
1978072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    }
198b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
1991c121f68fc6ac4abff17203b55253d6aeee64bc5Jamie Gennis    const int minBufferSlots = mSynchronousMode ?
2001c121f68fc6ac4abff17203b55253d6aeee64bc5Jamie Gennis            MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
2018072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    if (bufferCount == 0) {
2028072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        mClientBufferCount = 0;
2038072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        bufferCount = (mServerBufferCount >= minBufferSlots) ?
2048072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                mServerBufferCount : minBufferSlots;
2058072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        return setBufferCountServerLocked(bufferCount);
2068072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    }
2078072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
2081c121f68fc6ac4abff17203b55253d6aeee64bc5Jamie Gennis    if (bufferCount < minBufferSlots) {
209fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
2101c121f68fc6ac4abff17203b55253d6aeee64bc5Jamie Gennis                "minimum (%d)", bufferCount, minBufferSlots);
2119d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis        return BAD_VALUE;
2129d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis    }
2139d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis
2148072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    // here we're guaranteed that the client doesn't have dequeued buffers
2158072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    // and will release all of its buffer references.
216ef51b992192adf4fc432686ab346f5fc7a13bc95Mathias Agopian    freeAllBuffersLocked();
2178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    mBufferCount = bufferCount;
2188072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    mClientBufferCount = bufferCount;
21967eedd74ab78c2bfed9fcdc74947b97289254ca4Jamie Gennis    mCurrentTexture = INVALID_BUFFER_SLOT;
220b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mQueue.clear();
221b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mDequeueCondition.signal();
2228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
225a5c75c01620179ce00812354778a29a80d76e71fMathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
226a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
2276ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
2283fbce7c56082e4e0d23f1c1c89983d3841853ed7Mathias Agopian    if (!w || !h) {
229fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
230fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                w, h);
2313fbce7c56082e4e0d23f1c1c89983d3841853ed7Mathias Agopian        return BAD_VALUE;
232a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
2333fbce7c56082e4e0d23f1c1c89983d3841853ed7Mathias Agopian
2343fbce7c56082e4e0d23f1c1c89983d3841853ed7Mathias Agopian    Mutex::Autolock lock(mMutex);
2353fbce7c56082e4e0d23f1c1c89983d3841853ed7Mathias Agopian    mDefaultWidth = w;
2363fbce7c56082e4e0d23f1c1c89983d3841853ed7Mathias Agopian    mDefaultHeight = h;
237a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    return OK;
238a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
239a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
2407b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisstatus_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
2416ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("requestBuffer: slot=%d", slot);
2428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
2437b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
244fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
2457b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
2467b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
2477b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (slot < 0 || mBufferCount <= slot) {
248fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
2497b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis                mBufferCount, slot);
2507b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return BAD_VALUE;
2518ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
2527b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    mSlots[slot].mRequestBufferCalled = true;
2537b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    *buf = mSlots[slot].mGraphicBuffer;
2547b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    return NO_ERROR;
255c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian}
256c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian
257c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopianstatus_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
258c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        uint32_t format, uint32_t usage) {
2596ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
260c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian
261292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi    if ((w && !h) || (!w && h)) {
262fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
263c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        return BAD_VALUE;
264c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    }
265c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian
266c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    Mutex::Autolock lock(mMutex);
2678072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
2688072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    status_t returnFlags(OK);
2698072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
270a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli    int found = -1;
271a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli    int foundSync = -1;
272b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    int dequeuedCount = 0;
273b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    bool tryAgain = true;
274b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    while (tryAgain) {
2752560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        if (mAbandoned) {
276fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
2772560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian            return NO_INIT;
2782560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        }
2792560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian
2808072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // We need to wait for the FIFO to drain if the number of buffer
2818072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // needs to change.
2828072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //
2832560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        // The condition "number of buffers needs to change" is true if
2848072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // - the client doesn't care about how many buffers there are
2858072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // - AND the actual number of buffer is different from what was
2868072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //   set in the last setBufferCountServer()
2878072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //                         - OR -
2888072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //   setBufferCountServer() was set to a value incompatible with
2898072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //   the synchronization mode (for instance because the sync mode
2908072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //   changed since)
2918072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        //
2928072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // As long as this condition is true AND the FIFO is not empty, we
2938072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // wait on mDequeueCondition.
2948072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
2952560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        const int minBufferCountNeeded = mSynchronousMode ?
2968072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
2978072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
2982560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
2998072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                ((mServerBufferCount != mBufferCount) ||
3002560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian                        (mServerBufferCount < minBufferCountNeeded));
3012560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian
3022560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
3038072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            // wait for the FIFO to drain
3042560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian            mDequeueCondition.wait(mMutex);
3052560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian            // NOTE: we continue here because we need to reevaluate our
3062560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian            // whole state (eg: we could be abandoned or disconnected)
3072560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian            continue;
3088072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        }
3098072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
3102560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        if (numberOfBuffersNeedsToChange) {
3118072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            // here we're guaranteed that mQueue is empty
312ef51b992192adf4fc432686ab346f5fc7a13bc95Mathias Agopian            freeAllBuffersLocked();
3138072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            mBufferCount = mServerBufferCount;
3148072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            if (mBufferCount < minBufferCountNeeded)
3158072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                mBufferCount = minBufferCountNeeded;
3168072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            mCurrentTexture = INVALID_BUFFER_SLOT;
3178072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
3188072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        }
3198072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
3208072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // look for a free buffer to give to the client
321b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        found = INVALID_BUFFER_SLOT;
322b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        foundSync = INVALID_BUFFER_SLOT;
323b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        dequeuedCount = 0;
324b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        for (int i = 0; i < mBufferCount; i++) {
325b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            const int state = mSlots[i].mBufferState;
326b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            if (state == BufferSlot::DEQUEUED) {
327b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                dequeuedCount++;
328b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            }
32929b5762efc359022168e5099c1d17925444d3147Mathias Agopian
33029b5762efc359022168e5099c1d17925444d3147Mathias Agopian            // if buffer is FREE it CANNOT be current
33129b5762efc359022168e5099c1d17925444d3147Mathias Agopian            LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
33229b5762efc359022168e5099c1d17925444d3147Mathias Agopian                    "dequeueBuffer: buffer %d is both FREE and current!", i);
33329b5762efc359022168e5099c1d17925444d3147Mathias Agopian
3347c6eba666917308a64fadb0f0e08d7c041311976Mathias Agopian            if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
33529b5762efc359022168e5099c1d17925444d3147Mathias Agopian                if (state == BufferSlot::FREE || i == mCurrentTexture) {
33629b5762efc359022168e5099c1d17925444d3147Mathias Agopian                    foundSync = i;
33729b5762efc359022168e5099c1d17925444d3147Mathias Agopian                    if (i != mCurrentTexture) {
33829b5762efc359022168e5099c1d17925444d3147Mathias Agopian                        found = i;
33929b5762efc359022168e5099c1d17925444d3147Mathias Agopian                        break;
34029b5762efc359022168e5099c1d17925444d3147Mathias Agopian                    }
34129b5762efc359022168e5099c1d17925444d3147Mathias Agopian                }
34229b5762efc359022168e5099c1d17925444d3147Mathias Agopian            } else {
34329b5762efc359022168e5099c1d17925444d3147Mathias Agopian                if (state == BufferSlot::FREE) {
344a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                    /** For Asynchronous mode, we need to return the oldest of free buffers
345a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                    * There is only one instance when the Framecounter overflows, this logic
346a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                    * might return the earlier buffer to client. Which is a negligible impact
347a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                    **/
348a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                    if (found < 0 || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
349a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                        foundSync = i;
350a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                        found = i;
351a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli                    }
352b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                }
353b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            }
354b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        }
3558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
3568072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // clients are not allowed to dequeue more than one buffer
3578072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // if they didn't set a buffer count.
3588072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        if (!mClientBufferCount && dequeuedCount) {
3596ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis            ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
3606ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis                    "setting the buffer count");
3618072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            return -EINVAL;
3628072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        }
3638072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
364c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis        // See whether a buffer has been queued since the last setBufferCount so
365c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis        // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
366c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis        bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
367c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis        if (bufferHasBeenQueued) {
368c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis            // make sure the client is not trying to dequeue more buffers
369c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis            // than allowed.
370c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis            const int avail = mBufferCount - (dequeuedCount+1);
371c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis            if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
372fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
373fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                        "(dequeued=%d)",
374c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis                        MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
375c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis                        dequeuedCount);
376c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis                return -EBUSY;
377c2c8dfd71b84598f01074416e57cc3469d5b8ed2Jamie Gennis            }
3788072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        }
3798072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
380b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        // we're in synchronous mode and didn't find a buffer, we need to wait
38129b5762efc359022168e5099c1d17925444d3147Mathias Agopian        // for some buffers to be consumed
382b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
383b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        if (tryAgain) {
384b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            mDequeueCondition.wait(mMutex);
385c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        }
386a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
387b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
3888072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
3898072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
3908072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        found = foundSync;
391b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    }
392b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
393c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    if (found == INVALID_BUFFER_SLOT) {
3946ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis        // This should not happen.
3956ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis        ST_LOGE("dequeueBuffer: no available buffer slots");
396c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        return -EBUSY;
397c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    }
398c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian
399c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    const int buf = found;
400c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    *outBuf = found;
401a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
402a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    const bool useDefaultSize = !w && !h;
403a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if (useDefaultSize) {
404a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        // use the default size
405a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        w = mDefaultWidth;
406a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        h = mDefaultHeight;
407a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
408a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
409a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    const bool updateFormat = (format != 0);
410a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if (!updateFormat) {
411a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        // keep the current (or default) format
412a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        format = mPixelFormat;
413a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
414a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
415b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    // buffer is now in DEQUEUED (but can also be current at the same time,
416b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    // if we're in synchronous mode)
417b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
418b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
419b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
420c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    if ((buffer == NULL) ||
421c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        (uint32_t(buffer->width)  != w) ||
422c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        (uint32_t(buffer->height) != h) ||
423c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        (uint32_t(buffer->format) != format) ||
424c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        ((uint32_t(buffer->usage) & usage) != usage))
425c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    {
426c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
427d9e8c64c3dce1612eb948a5c16ba4ff62202b423Mathias Agopian        status_t error;
428c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        sp<GraphicBuffer> graphicBuffer(
429d9e8c64c3dce1612eb948a5c16ba4ff62202b423Mathias Agopian                mGraphicBufferAlloc->createGraphicBuffer(
430d9e8c64c3dce1612eb948a5c16ba4ff62202b423Mathias Agopian                        w, h, format, usage, &error));
431c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        if (graphicBuffer == 0) {
432fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
433fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                    "failed");
434d9e8c64c3dce1612eb948a5c16ba4ff62202b423Mathias Agopian            return error;
435c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        }
436a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (updateFormat) {
437a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian            mPixelFormat = format;
438a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        }
4398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        mSlots[buf].mGraphicBuffer = graphicBuffer;
440b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mSlots[buf].mRequestBufferCalled = false;
4418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
4428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
4438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
4448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
4458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
446aaa3ecff4b49e0918c252e02b3aa18a3ad0d503dJamie Gennis        if (mCurrentTexture == buf) {
447aaa3ecff4b49e0918c252e02b3aa18a3ad0d503dJamie Gennis            // The current texture no longer references the buffer in this slot
448aaa3ecff4b49e0918c252e02b3aa18a3ad0d503dJamie Gennis            // since we just allocated a new buffer.
449aaa3ecff4b49e0918c252e02b3aa18a3ad0d503dJamie Gennis            mCurrentTexture = INVALID_BUFFER_SLOT;
450aaa3ecff4b49e0918c252e02b3aa18a3ad0d503dJamie Gennis        }
4518072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
452a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
4536ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", buf,
4546ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis            mSlots[buf].mGraphicBuffer->handle, returnFlags);
4558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    return returnFlags;
4568ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
4578ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
458b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopianstatus_t SurfaceTexture::setSynchronousMode(bool enabled) {
4596ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setSynchronousMode: enabled=%d", enabled);
460b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    Mutex::Autolock lock(mMutex);
4618072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
4627b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
463fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
4647b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
4657b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
4667b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
4678072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    status_t err = OK;
46814a0e58074f2698829b6554f578e6762c377caa3Grace Kloba    if (!mAllowSynchronousMode && enabled)
46914a0e58074f2698829b6554f578e6762c377caa3Grace Kloba        return err;
47014a0e58074f2698829b6554f578e6762c377caa3Grace Kloba
4718072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    if (!enabled) {
4728072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // going to asynchronous mode, drain the queue
4738e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        err = drainQueueLocked();
4748e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        if (err != NO_ERROR)
4758e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            return err;
4768072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    }
4778072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
478b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    if (mSynchronousMode != enabled) {
4798072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // - if we're going to asynchronous mode, the queue is guaranteed to be
4808072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // empty here
4818072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // - if the client set the number of buffers, we're guaranteed that
4828072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian        // we have at least 3 (because we don't allow less)
483b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mSynchronousMode = enabled;
484b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mDequeueCondition.signal();
485b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    }
4868072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    return err;
487b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian}
488b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
48997c602c5af5f3ffd69009bf496d86347b71a2b4cMathias Agopianstatus_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
49097c602c5af5f3ffd69009bf496d86347b71a2b4cMathias Agopian        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
4916ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
492cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian
493cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian    sp<FrameAvailableListener> listener;
494cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian
495cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian    { // scope for the lock
4968cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        Mutex::Autolock lock(mMutex);
4977b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        if (mAbandoned) {
498fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
4997b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis            return NO_INIT;
5007b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        }
5018cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        if (buf < 0 || buf >= mBufferCount) {
502fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
5038cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                    mBufferCount, buf);
5048cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            return -EINVAL;
5058cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
506fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("queueBuffer: slot %d is not owned by the client "
507fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                    "(state=%d)", buf, mSlots[buf].mBufferState);
5088cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            return -EINVAL;
5098cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        } else if (buf == mCurrentTexture) {
510fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("queueBuffer: slot %d is current!", buf);
5118cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            return -EINVAL;
5128cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        } else if (!mSlots[buf].mRequestBufferCalled) {
513fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
5148cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                    "buffer", buf);
5158cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            return -EINVAL;
5168cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        }
517cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian
5188cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        if (mSynchronousMode) {
5193d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis            // In synchronous mode we queue all buffers in a FIFO.
520b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            mQueue.push_back(buf);
5213d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis
5223d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis            // Synchronous mode always signals that an additional frame should
5233d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis            // be consumed.
5243d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis            listener = mFrameAvailableListener;
525b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        } else {
5263d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis            // In asynchronous mode we only keep the most recent buffer.
5278cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            if (mQueue.empty()) {
5288cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                mQueue.push_back(buf);
5293d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis
5303d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis                // Asynchronous mode only signals that a frame should be
5313d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis                // consumed if no previous frame was pending. If a frame were
5323d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis                // pending then the consumer would have already been notified.
5333d8063b02e06020c8062addcc9ec49048d3bdb9aJamie Gennis                listener = mFrameAvailableListener;
5348cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            } else {
5358cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                Fifo::iterator front(mQueue.begin());
5368cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                // buffer currently queued is freed
5378cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                mSlots[*front].mBufferState = BufferSlot::FREE;
5388cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                // and we record the new buffer index in the queued list
5398cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis                *front = buf;
5408cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis            }
541b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        }
542b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
5438cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mSlots[buf].mBufferState = BufferSlot::QUEUED;
5448cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mSlots[buf].mCrop = mNextCrop;
5458cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mSlots[buf].mTransform = mNextTransform;
5467734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian        mSlots[buf].mScalingMode = mNextScalingMode;
5478cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mSlots[buf].mTimestamp = timestamp;
548a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli        mFrameCounter++;
549a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli        mSlots[buf].mFrameNumber = mFrameCounter;
550a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli
5518cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mDequeueCondition.signal();
5523902be629bd94de62db0039004d0b25556227cbfMathias Agopian
5533902be629bd94de62db0039004d0b25556227cbfMathias Agopian        *outWidth = mDefaultWidth;
5543902be629bd94de62db0039004d0b25556227cbfMathias Agopian        *outHeight = mDefaultHeight;
5553902be629bd94de62db0039004d0b25556227cbfMathias Agopian        *outTransform = 0;
556cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian    } // scope for the lock
557b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
558cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian    // call back without lock held
559cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian    if (listener != 0) {
560cf46eb9817dfbfc020720d1e45b5c085252500fbMathias Agopian        listener->onFrameAvailable();
561c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    }
5628ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
5638ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
5648ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
5658ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisvoid SurfaceTexture::cancelBuffer(int buf) {
5666ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("cancelBuffer: slot=%d", buf);
5678ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
5687b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
5697b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
570fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
5717b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return;
5727b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
5737b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
574b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    if (buf < 0 || buf >= mBufferCount) {
575fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
576b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                mBufferCount, buf);
5778ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return;
578b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
579fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
580b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                buf, mSlots[buf].mBufferState);
5818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return;
5828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
583b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mSlots[buf].mBufferState = BufferSlot::FREE;
584a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli    mSlots[buf].mFrameNumber = 0;
585b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mDequeueCondition.signal();
5868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
5878ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
588f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatus_t SurfaceTexture::setCrop(const Rect& crop) {
5896ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
5906ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis            crop.bottom);
5916ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis
5928ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
5937b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
594fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setCrop: SurfaceTexture has been abandoned!");
5957b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
5967b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
597f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    mNextCrop = crop;
5988ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
5998ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
6008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
6018ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::setTransform(uint32_t transform) {
6026ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setTransform: xform=%#x", transform);
6038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
6047b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
605fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("setTransform: SurfaceTexture has been abandoned!");
6067b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
6077b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
608f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    mNextTransform = transform;
6098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
6108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
6118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
6125bfc24515bb5c8ea7975f72d538df37753733a2fMathias Agopianstatus_t SurfaceTexture::connect(int api,
6135bfc24515bb5c8ea7975f72d538df37753733a2fMathias Agopian        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
6146ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("connect: api=%d", api);
615fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    Mutex::Autolock lock(mMutex);
6167b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
6177b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
618fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("connect: SurfaceTexture has been abandoned!");
6197b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
6207b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
6217b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
622fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    int err = NO_ERROR;
623fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    switch (api) {
624fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_EGL:
625fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_CPU:
626fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_MEDIA:
627fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_CAMERA:
628fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            if (mConnectedApi != NO_CONNECTED_API) {
629fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                ST_LOGE("connect: already connected (cur=%d, req=%d)",
6308f9dbf9e13b927de2524116c30544f7dfbbbf56cMathias Agopian                        mConnectedApi, api);
631fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                err = -EINVAL;
632fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            } else {
633fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                mConnectedApi = api;
6345bfc24515bb5c8ea7975f72d538df37753733a2fMathias Agopian                *outWidth = mDefaultWidth;
6355bfc24515bb5c8ea7975f72d538df37753733a2fMathias Agopian                *outHeight = mDefaultHeight;
6365bfc24515bb5c8ea7975f72d538df37753733a2fMathias Agopian                *outTransform = 0;
637fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            }
638fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            break;
639fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        default:
640fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            err = -EINVAL;
641fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            break;
642fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    }
643fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    return err;
644fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis}
645fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis
646fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennisstatus_t SurfaceTexture::disconnect(int api) {
6476ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("disconnect: api=%d", api);
648fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    Mutex::Autolock lock(mMutex);
6497b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
6507b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
6518b8a004148f2e6337dbf02ef8046d800bf300e89Mathias Agopian        // it is not really an error to disconnect after the surface
6528b8a004148f2e6337dbf02ef8046d800bf300e89Mathias Agopian        // has been abandoned, it should just be a no-op.
6538b8a004148f2e6337dbf02ef8046d800bf300e89Mathias Agopian        return NO_ERROR;
6547b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
6557b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
656fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    int err = NO_ERROR;
657fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    switch (api) {
658fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_EGL:
659fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_CPU:
660fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_MEDIA:
661fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        case NATIVE_WINDOW_API_CAMERA:
662fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            if (mConnectedApi == api) {
6638e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian                drainQueueAndFreeBuffersLocked();
664fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                mConnectedApi = NO_CONNECTED_API;
66570e3f81d0fbc92394928c44fb0137787a8595665Mathias Agopian                mNextCrop.makeInvalid();
66670e3f81d0fbc92394928c44fb0137787a8595665Mathias Agopian                mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
66770e3f81d0fbc92394928c44fb0137787a8595665Mathias Agopian                mNextTransform = 0;
6688e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian                mDequeueCondition.signal();
669fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            } else {
670fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
6718f9dbf9e13b927de2524116c30544f7dfbbbf56cMathias Agopian                        mConnectedApi, api);
672fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                err = -EINVAL;
673fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            }
674fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            break;
675fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        default:
6766ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis            ST_LOGE("disconnect: unknown API %d", api);
677fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            err = -EINVAL;
678fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            break;
679fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    }
680fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis    return err;
681fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis}
682fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis
6837734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopianstatus_t SurfaceTexture::setScalingMode(int mode) {
6846ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setScalingMode: mode=%d", mode);
6857734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
6867734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    switch (mode) {
6877734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
6887734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
6897734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian            break;
6907734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian        default:
6916ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis            ST_LOGE("unknown scaling mode: %d", mode);
6927734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian            return BAD_VALUE;
6937734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    }
6947734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
6957734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
6967734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    mNextScalingMode = mode;
6977734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return OK;
6987734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
6997734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
7008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::updateTexImage() {
7016ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("updateTexImage");
7028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
7038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
704e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    if (mAbandoned) {
705fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
7068e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        return NO_INIT;
707e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    }
708e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian
70950c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // In asynchronous mode the list is guaranteed to be one buffer
71050c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // deep, while in synchronous mode we use the oldest buffer.
711b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    if (!mQueue.empty()) {
712b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        Fifo::iterator front(mQueue.begin());
71350c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis        int buf = *front;
714b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
715f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        // Update the GL texture object.
716b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        EGLImageKHR image = mSlots[buf].mEglImage;
7178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
7188ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGLDisplay dpy = eglGetCurrentDisplay();
719e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian            if (mSlots[buf].mGraphicBuffer == 0) {
720fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                ST_LOGE("buffer at slot %d is null", buf);
7218e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian                return BAD_VALUE;
722e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian            }
723b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            image = createImage(dpy, mSlots[buf].mGraphicBuffer);
724b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            mSlots[buf].mEglImage = image;
725b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            mSlots[buf].mEglDisplay = dpy;
7263cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            if (image == EGL_NO_IMAGE_KHR) {
7273cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // NOTE: if dpy was invalid, createImage() is guaranteed to
7283cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // fail. so we'd end up here.
7293cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                return -EINVAL;
7303cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            }
7318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
7320eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
7330eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        GLint error;
7340eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
735fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
7360eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
7377a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
738fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
739fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
7407a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7410eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        bool failed = false;
7420eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
743fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("error binding external texture image %p (slot %d): %#04x",
744b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                    image, buf, error);
7450eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis            failed = true;
7460eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
7470eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        if (failed) {
7488ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            return -EINVAL;
7498ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
7509a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
7516ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
7526ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf,
7536ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis                mSlots[buf].mGraphicBuffer->handle);
7546ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis
755b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
75650c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis            // The current buffer becomes FREE if it was still in the queued
757b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            // state. If it has already been given to the client
758b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            // (synchronous mode), then it stays in DEQUEUED state.
759b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
760b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
761b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        }
762b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
7639a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        // Update the SurfaceTexture state.
764b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mCurrentTexture = buf;
765b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
7668cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mCurrentCrop = mSlots[buf].mCrop;
7678cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mCurrentTransform = mSlots[buf].mTransform;
7687734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian        mCurrentScalingMode = mSlots[buf].mScalingMode;
7698cd5ba4b7f01d3a54a8f8bc6d1793aa5fc8e09efJamie Gennis        mCurrentTimestamp = mSlots[buf].mTimestamp;
770736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis        computeCurrentTransformMatrix();
77150c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
77250c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis        // Now that we've passed the point at which failures can happen,
77350c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis        // it's safe to remove the buffer from the front of the queue.
77450c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis        mQueue.erase(front);
775b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mDequeueCondition.signal();
7767a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    } else {
7777a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        // We always bind the texture even if we don't update its contents.
778fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
7798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
78050c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
7818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
7828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
7838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
7847a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
7857a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
7867a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
7877a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
7887a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
7897a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
7907a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
7917a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
7927a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
7937a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7947a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
7957a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7967a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
7977a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
7987a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7997a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
8007a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
8017a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
8027a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
8037a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
804fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
8057a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
8067a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
807f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
808f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
809736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
810736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
811736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
812736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennisvoid SurfaceTexture::computeCurrentTransformMatrix() {
8136ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("computeCurrentTransformMatrix");
814f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
815a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
816a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
817a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
818a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
819a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
820a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
821a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
822a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
823a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
824a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
825a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
826a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
827a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
828a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
829a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
830a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
831a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
832a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
833a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
834a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
835a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
836a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
837a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
838a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
839f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
840f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
841f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
842a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float tx, ty, sx, sy;
843a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (!mCurrentCrop.isEmpty()) {
844d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // In order to prevent bilinear sampling at the of the crop rectangle we
845d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // may need to shrink it by 2 texels in each direction.  Normally this
846d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // would just need to take 1/2 a texel off each end, but because the
847d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // chroma channels will likely be subsampled we need to chop off a whole
848d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // texel.  This will cause artifacts if someone does nearest sampling
849d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
850d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // accomodate the bilinear and nearest sampling uses.
851d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        //
852d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // If nearest sampling turns out to be a desirable usage of these
853d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // textures then we could add the ability to switch a SurfaceTexture to
854d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // nearest-mode.  Preferably, however, the image producers (video
855d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // decoder, camera, etc.) would simply not use a crop rectangle (or at
856d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // least not tell the framework about it) so that the GPU can do the
857d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // correct edge behavior.
858d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        int xshrink = 0, yshrink = 0;
859d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.left > 0) {
860d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
861d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
862d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
863d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = 0.0f;
864d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
865a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
866d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
867d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
868a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
869d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
870d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    float(buf->getHeight());
871d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
872d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
873d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = 0.0f;
874d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
875d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.top > 0) {
876d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
877d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
878d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
879d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
880a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    } else {
881a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        tx = 0.0f;
882a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        ty = 0.0f;
883a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx = 1.0f;
884a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sy = 1.0f;
885a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
886f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
887a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
888a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
889f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
890d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
891f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
892f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
893a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
894a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
895a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
896a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
897a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
898a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
899a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
900736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
901f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
902f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
9031d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
9046ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
9051d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
9061d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
9071d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
9081d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
909c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennisvoid SurfaceTexture::setFrameAvailableListener(
910292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi        const sp<FrameAvailableListener>& listener) {
9116ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setFrameAvailableListener");
912c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    Mutex::Autolock lock(mMutex);
913292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi    mFrameAvailableListener = listener;
914c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis}
915c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis
9168e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopianvoid SurfaceTexture::freeBufferLocked(int i) {
9178e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    mSlots[i].mGraphicBuffer = 0;
9188e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    mSlots[i].mBufferState = BufferSlot::FREE;
919a929748ddb67cbece3337c7fda7877fdeb973aa4Sunita Nadampalli    mSlots[i].mFrameNumber = 0;
9208e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
9218e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
9228e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
9238e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
9248e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    }
9258e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian}
9268e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian
927ef51b992192adf4fc432686ab346f5fc7a13bc95Mathias Agopianvoid SurfaceTexture::freeAllBuffersLocked() {
928ef51b992192adf4fc432686ab346f5fc7a13bc95Mathias Agopian    LOGW_IF(!mQueue.isEmpty(),
929ef51b992192adf4fc432686ab346f5fc7a13bc95Mathias Agopian            "freeAllBuffersLocked called but mQueue is not empty");
93029b5762efc359022168e5099c1d17925444d3147Mathias Agopian    mCurrentTexture = INVALID_BUFFER_SLOT;
9318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
9328e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        freeBufferLocked(i);
9338e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    }
9348e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian}
9358e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian
9368e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopianvoid SurfaceTexture::freeAllBuffersExceptHeadLocked() {
9378e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    LOGW_IF(!mQueue.isEmpty(),
9388e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
9398e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    int head = -1;
9408e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    if (!mQueue.empty()) {
9418e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        Fifo::iterator front(mQueue.begin());
9428e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        head = *front;
9438e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    }
94429b5762efc359022168e5099c1d17925444d3147Mathias Agopian    mCurrentTexture = INVALID_BUFFER_SLOT;
9458e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
9468e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        if (i != head) {
9478e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            freeBufferLocked(i);
9488ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
9498ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
9508ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
9518ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
9528e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopianstatus_t SurfaceTexture::drainQueueLocked() {
9532560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian    while (mSynchronousMode && !mQueue.isEmpty()) {
9542560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian        mDequeueCondition.wait(mMutex);
9558e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        if (mAbandoned) {
956fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
9578e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            return NO_INIT;
9588e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        }
9598e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        if (mConnectedApi == NO_CONNECTED_API) {
960fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!");
9618e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            return NO_INIT;
9628e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        }
9632560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian    }
9648e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    return NO_ERROR;
9658e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian}
9668e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian
9678e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopianstatus_t SurfaceTexture::drainQueueAndFreeBuffersLocked() {
9688e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    status_t err = drainQueueLocked();
9698e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    if (err == NO_ERROR) {
9708e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        if (mSynchronousMode) {
9718e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            freeAllBuffersLocked();
9728e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        } else {
9738e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian            freeAllBuffersExceptHeadLocked();
9748e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        }
9758e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    }
9768e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    return err;
9772560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian}
9782560d14ce8e38984032d999e3fdf8da9a47baf3cMathias Agopian
9798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
9808ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
9818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
9828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
9838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
9848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
9858ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
9868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
9878ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
9883cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
9893cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
990fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
9918ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
9928ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
9938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
9948ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
9957a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
9967a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
9977a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
9987a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9997a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
10007a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
10017a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
10027a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentCrop;
10037a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
10047a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
10057a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
10067a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
10077a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
10087a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
10097a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
10107734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopianuint32_t SurfaceTexture::getCurrentScalingMode() const {
10117734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
10127734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
10137734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
10147734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
101559769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennisbool SurfaceTexture::isSynchronousMode() const {
101659769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    Mutex::Autolock lock(mMutex);
101759769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    return mSynchronousMode;
101859769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis}
101959769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
1020eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopianint SurfaceTexture::query(int what, int* outValue)
1021eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian{
1022eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    Mutex::Autolock lock(mMutex);
10237b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
10247b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    if (mAbandoned) {
1025fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("query: SurfaceTexture has been abandoned!");
10267b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        return NO_INIT;
10277b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    }
10287b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
1029eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    int value;
1030eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    switch (what) {
1031eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    case NATIVE_WINDOW_WIDTH:
1032eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        value = mDefaultWidth;
1033eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        break;
1034eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    case NATIVE_WINDOW_HEIGHT:
1035eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        value = mDefaultHeight;
1036eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        break;
1037eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    case NATIVE_WINDOW_FORMAT:
1038eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        value = mPixelFormat;
1039eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        break;
1040eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
1041eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        value = mSynchronousMode ?
1042eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
1043eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        break;
1044eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    default:
1045eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        return BAD_VALUE;
1046eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    }
1047eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    outValue[0] = value;
1048eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    return NO_ERROR;
1049eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian}
10507a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
10517b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisvoid SurfaceTexture::abandon() {
10527b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    Mutex::Autolock lock(mMutex);
10538e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    mQueue.clear();
10547b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    mAbandoned = true;
105597a9884edcc6fbb311386ecfcd6e3045437f0df0Mathias Agopian    mCurrentTextureBuf.clear();
10568e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian    freeAllBuffersLocked();
10577b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    mDequeueCondition.signal();
10587b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
10597b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
1060fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennisvoid SurfaceTexture::setName(const String8& name) {
1061fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
1062fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis}
1063fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
106468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopianvoid SurfaceTexture::dump(String8& result) const
106568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
106668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    char buffer[1024];
106768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    dump(result, "", buffer, 1024);
106868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
106968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
107068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopianvoid SurfaceTexture::dump(String8& result, const char* prefix,
107168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        char* buffer, size_t SIZE) const
107268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
107368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    Mutex::Autolock _l(mMutex);
107468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    snprintf(buffer, SIZE,
107568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
107668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            "mPixelFormat=%d, mTexName=%d\n",
1077fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
1078fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            mDefaultHeight, mPixelFormat, mTexName);
107968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
108068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
108168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    String8 fifo;
108268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    int fifoSize = 0;
108368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    Fifo::const_iterator i(mQueue.begin());
108468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    while (i != mQueue.end()) {
108568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        snprintf(buffer, SIZE, "%02d ", *i++);
108668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        fifoSize++;
108768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        fifo.append(buffer);
108868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    }
108968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
109068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    snprintf(buffer, SIZE,
10911f8e09f40d16ae377164d86e91385ad3d8e78e82Jamie Gennis            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
109268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
109368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            ,
109468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            prefix, mCurrentCrop.left,
109568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
10961f8e09f40d16ae377164d86e91385ad3d8e78e82Jamie Gennis            mCurrentTransform, mCurrentTexture,
1097fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
1098fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
109968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    );
110068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
110168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
110268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    struct {
110368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        const char * operator()(int state) const {
110468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            switch (state) {
110568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian                case BufferSlot::DEQUEUED: return "DEQUEUED";
110668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian                case BufferSlot::QUEUED: return "QUEUED";
110768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian                case BufferSlot::FREE: return "FREE";
110868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian                default: return "Unknown";
110968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            }
111068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        }
111168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    } stateName;
111268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
111368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    for (int i=0 ; i<mBufferCount ; i++) {
111468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        const BufferSlot& slot(mSlots[i]);
111568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        snprintf(buffer, SIZE,
1116ad795baecccf239621cbffa0249c8e855296cae6Mathias Agopian                "%s%s[%02d] "
1117ad795baecccf239621cbffa0249c8e855296cae6Mathias Agopian                "state=%-8s, crop=[%d,%d,%d,%d], "
11182db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian                "transform=0x%02x, timestamp=%lld",
1119ad795baecccf239621cbffa0249c8e855296cae6Mathias Agopian                prefix, (i==mCurrentTexture)?">":" ", i,
1120ad795baecccf239621cbffa0249c8e855296cae6Mathias Agopian                stateName(slot.mBufferState),
1121fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
1122fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
112368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        );
112468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        result.append(buffer);
11252db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian
11262db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
11272db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian        if (buf != NULL) {
11282db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian            snprintf(buffer, SIZE,
11292db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian                    ", %p [%4ux%4u:%4u,%3X]",
1130fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                    buf->handle, buf->width, buf->height, buf->stride,
1131fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                    buf->format);
11322db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian            result.append(buffer);
11332db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian        }
11342db6f0a40b7f4d903f546e94af762f141953ebb2Mathias Agopian        result.append("\n");
113568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    }
113668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
113768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
1138f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
1139f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1140f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1141f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1142f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1143f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1144f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1145f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1146f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1147f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1148f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1149f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1150f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1151f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1152f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1153f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1154f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1155f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1156f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1157f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1158f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
1159f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
11608ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
1161