GLConsumer.cpp revision 74bed55fff0132be319bcd1703970516ae28b3a9
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"
181c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis//#define LOG_NDEBUG 0
208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define GL_GLEXT_PROTOTYPES
228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define EGL_EGLEXT_PROTOTYPES
238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/egl.h>
258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/eglext.h>
268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2.h>
278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2ext.h>
288ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian#include <hardware/hardware.h>
307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3190ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/IGraphicBufferAlloc.h>
3290ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/ISurfaceComposer.h>
3390ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/SurfaceComposerClient.h>
3490ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/SurfaceTexture.h>
3541f673c9b3aac0d96e41c928845c39186d565212Mathias Agopian
3690ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <private/gui/ComposerService.h>
378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <utils/Log.h>
3968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian#include <utils/String8.h>
401c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#include <utils/Trace.h>
418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
4386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// to synchronize access to the buffers.  It will cause dequeueBuffer to stall,
4486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// waiting for the GL reads for the buffer being dequeued to complete before
4586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// allowing the buffer to be dequeued.
4686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef USE_FENCE_SYNC
4786edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
4886edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
4986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
5086edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
5186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
52fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis// Macros for including the SurfaceTexture name in log messages
536807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
549d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
55a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
5632397c1cd3327905173b36baa6fd1c579bc328ffSteve Block#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
57e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5829b5762efc359022168e5099c1d17925444d3147Mathias Agopian
598ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisnamespace android {
608ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
61f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
62f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
63f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
64f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
65f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
66f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
67f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
68f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
69f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
70f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
71f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
72f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
73f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot180[16] = {
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 1, 0, 1,
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
92f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot270[16] = {
93f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
94f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
95f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
96f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
97f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
98f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
99f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
100f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
101eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam// Get an ID that's unique within this process.
102eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lamstatic int32_t createProcessUniqueId() {
103eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    static volatile int32_t globalCounter = 0;
104eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    return android_atomic_inc(&globalCounter);
105eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam}
106fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
107fb1b5a2f333800574b0da435d1200cf9b13d723fJamie GennisSurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
108b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
1091d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
1101d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
111b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
11286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef USE_FENCE_SYNC
11386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
11486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#else
11586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(false),
11686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
117eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
118ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
119ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
120eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mAbandoned(false),
12174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
12274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1236b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
124eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    // Choose a name using the PID and a process-unique ID.
125eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
1266ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("SurfaceTexture");
127b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    if (bufferQueue == 0) {
128b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        ST_LOGV("Creating a new BufferQueue");
129b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        mBufferQueue = new BufferQueue(allowSynchronousMode);
130b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    }
131b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    else {
132b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        mBufferQueue = bufferQueue;
133b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    }
134b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
135fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
136fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
137fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
138fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
139fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    // reference once the ctor ends, as that would cause the refcount of 'this'
140fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
141fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    // that's what we create.
142fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    wp<BufferQueue::ConsumerListener> listener;
143fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    sp<BufferQueue::ConsumerListener> proxy;
144fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    listener = static_cast<BufferQueue::ConsumerListener*>(this);
145fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    proxy = new BufferQueue::ProxyConsumerListener(listener);
146fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
147fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    status_t err = mBufferQueue->consumerConnect(proxy);
148fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (err != NO_ERROR) {
149fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        ST_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)",
150fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis                strerror(-err), err);
151fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    } else {
152fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mBufferQueue->setConsumerName(mName);
153fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
1548ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1558ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1568ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisSurfaceTexture::~SurfaceTexture() {
1576ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("~SurfaceTexture");
158b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
159eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    abandon();
1608ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1618ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1628072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatus_t SurfaceTexture::setBufferCountServer(int bufferCount) {
1638072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
164b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setBufferCountServer(bufferCount);
1658072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1668072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1678ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
168a5c75c01620179ce00812354778a29a80d76e71fMathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
169a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
170b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
171b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferSize(w, h);
172a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
173a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1748ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::updateTexImage() {
1751c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis    ATRACE_CALL();
1766ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("updateTexImage");
1778ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
1788ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
179e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    if (mAbandoned) {
18074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("updateTexImage: SurfaceTexture is abandoned!");
1818e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        return NO_INIT;
182e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    }
183e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian
18474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
18574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("updateTexImage: SurfaceTexture is not attached to an OpenGL "
18674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
18774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
18874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
18974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
190ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
191ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
192ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
19374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
19474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            dpy == EGL_NO_DISPLAY) {
195ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis        ST_LOGE("updateTexImage: invalid current EGLDisplay");
19674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
197ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
198ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
19974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
20074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ctx == EGL_NO_CONTEXT) {
201ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis        ST_LOGE("updateTexImage: invalid current EGLContext");
20274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
203ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
204ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
205ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay = dpy;
206ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext = ctx;
207ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
208b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    BufferQueue::BufferItem item;
209eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
21050c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // In asynchronous mode the list is guaranteed to be one buffer
21150c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // deep, while in synchronous mode we use the oldest buffer.
212fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (mBufferQueue->acquireBuffer(&item) == NO_ERROR) {
213eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        int buf = item.mBuf;
214eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        // This buffer was newly allocated, so we need to clean up on our side
215eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        if (item.mGraphicBuffer != NULL) {
216eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mGraphicBuffer = 0;
217eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
218ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis                eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage);
219eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
220eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            }
221eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
222eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        }
223b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
224f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        // Update the GL texture object.
225eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        EGLImageKHR image = mEGLSlots[buf].mEglImage;
2268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
227eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            if (item.mGraphicBuffer == 0) {
22874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                ST_LOGE("updateTexImage: buffer at slot %d is null", buf);
2298e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian                return BAD_VALUE;
230e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian            }
231eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            image = createImage(dpy, item.mGraphicBuffer);
232eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mEglImage = image;
2333cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            if (image == EGL_NO_IMAGE_KHR) {
2343cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // NOTE: if dpy was invalid, createImage() is guaranteed to
2353cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // fail. so we'd end up here.
23674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
2373cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            }
2388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2390eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
2400eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        GLint error;
2410eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
242fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
2430eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
2447a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
245fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
246fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
2477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
24874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = OK;
2490eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
25074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ST_LOGE("updateTexImage: error binding external texture image %p "
25174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                    "(slot %d): %#04x", image, buf, error);
25274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            err = UNKNOWN_ERROR;
2530eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
25474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
25574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err == OK) {
25674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            err = syncForReleaseLocked(dpy);
2578ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2589a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
25974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
26074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // Release the buffer we just acquired.  It's not safe to
26174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // release the old buffer, so instead we just drop the new frame.
26274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
26374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR;
26474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
26586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        }
26686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
26786edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
26886edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                mCurrentTexture,
26986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
270eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0);
2716ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis
27274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // Release the old buffer
27374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
27474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            mBufferQueue->releaseBuffer(mCurrentTexture, dpy,
27574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                    mEGLSlots[mCurrentTexture].mFence);
27674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR;
27774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
278b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
2799a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        // Update the SurfaceTexture state.
280b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mCurrentTexture = buf;
281eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
282eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentCrop = item.mCrop;
283eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTransform = item.mTransform;
284eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentScalingMode = item.mScalingMode;
285eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTimestamp = item.mTimestamp;
286736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis        computeCurrentTransformMatrix();
2877a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    } else {
2887a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        // We always bind the texture even if we don't update its contents.
289fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
2908ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
29150c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
2928ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2948ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
29574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::detachFromContext() {
29674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
29774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
29874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
29974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
30074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
30174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: abandoned SurfaceTexture");
30274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
30374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
30474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
30574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
30674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: SurfaceTexture is not attached to a "
30774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
30874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
30974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
31074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
31174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
31274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
31374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
31474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
31574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
31674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
31774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
31874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
31974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
32074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
32174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
32274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
32374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
32474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
32574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
32674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
32774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
32874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
32974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
33074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
33174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
33274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
33374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
33474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
33574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
33674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
33774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
33874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
33974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
34074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::attachToContext(GLuint tex) {
34174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
34274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
34374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
34474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
34574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
34674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: abandoned SurfaceTexture");
34774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
34874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
34974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
35174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: SurfaceTexture is already attached to a "
35274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
35374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
35474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
35574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
35774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
35874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
36074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
36174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
36274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
36374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
36474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
36574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
36674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
36774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
36874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
36974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
37074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
37174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    glBindTexture(mTexTarget, tex);
37274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
37474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // If the current buffer is no longer associated with a slot, then it
37574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // doesn't have an EGLImage.  In that case we create one now, but we also
37674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // destroy it once we've used it to attach the buffer to the OpenGL ES
37774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // texture.
37874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        bool imageNeedsDestroy = false;
37974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        EGLImageKHR image = EGL_NO_IMAGE_KHR;
38074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
38174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            image = mEGLSlots[mCurrentTexture].mEglImage;
38274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            imageNeedsDestroy = false;
38374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        } else {
38474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            image = createImage(dpy, mCurrentTextureBuf);
38574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            if (image == EGL_NO_IMAGE_KHR) {
38674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
38774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
38874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            imageNeedsDestroy = true;
38974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
39074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // Attach the current buffer to the GL texture.
39274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
39374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        GLint error;
39574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = OK;
39674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
39774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ST_LOGE("attachToContext: error binding external texture image %p "
39874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                    "(slot %d): %#04x", image, mCurrentTexture, error);
39974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            err = UNKNOWN_ERROR;
40074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
40174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (imageNeedsDestroy) {
40374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            eglDestroyImageKHR(dpy, image);
40474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
40574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
40774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
40874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
40974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
41074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
41274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
41374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
41474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
41574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
41774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
41874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
42074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
42174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
42374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        EGLSyncKHR fence = mEGLSlots[mCurrentTexture].mFence;
42474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (fence != EGL_NO_SYNC_KHR) {
42574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // There is already a fence for the current slot.  We need to wait
42674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // on that before replacing it with another fence to ensure that all
42774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // outstanding buffer accesses have completed before the producer
42874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // accesses it.
42974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
43074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            if (result == EGL_FALSE) {
43174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                ST_LOGE("syncForReleaseLocked: error waiting for previous "
43274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                        "fence: %#x", eglGetError());
43374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
43474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
43574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
43674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                        "fence");
43774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return TIMED_OUT;
43874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
43974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            eglDestroySyncKHR(dpy, fence);
44074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
44174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // Create a fence for the outstanding accesses in the current OpenGL ES
44374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // context.
44474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
44574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (fence == EGL_NO_SYNC_KHR) {
44674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
44774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                    eglGetError());
44874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return UNKNOWN_ERROR;
44974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
45074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glFlush();
45174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        mEGLSlots[mCurrentTexture].mFence = fence;
45274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
45374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
45574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
45674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4577a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
4587a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
4597a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
4607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
4617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
4627a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
4637a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
4647a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
4657a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
4667a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
4677a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
4687a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
4697a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
4707a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
4717a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
4727a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
4737a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
4747a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
4757a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
4767a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
477fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
4787a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
4797a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
480f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
481f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
482736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
483736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
484736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
485736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennisvoid SurfaceTexture::computeCurrentTransformMatrix() {
4866ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("computeCurrentTransformMatrix");
487f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
488a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
489a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
490a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
491a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
492a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
493a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
494a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
495a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
496a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
497a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
498a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
499a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
500a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
501a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
502a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
503a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
504a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
505a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
506a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
507a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
508a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
509a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
510a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
511a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
512f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
513f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
514eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
515a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float tx, ty, sx, sy;
516a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (!mCurrentCrop.isEmpty()) {
517d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // In order to prevent bilinear sampling at the of the crop rectangle we
518d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // may need to shrink it by 2 texels in each direction.  Normally this
519d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // would just need to take 1/2 a texel off each end, but because the
520d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // chroma channels will likely be subsampled we need to chop off a whole
521d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // texel.  This will cause artifacts if someone does nearest sampling
522d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
523d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // accomodate the bilinear and nearest sampling uses.
524d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        //
525d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // If nearest sampling turns out to be a desirable usage of these
526d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // textures then we could add the ability to switch a SurfaceTexture to
527d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // nearest-mode.  Preferably, however, the image producers (video
528d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // decoder, camera, etc.) would simply not use a crop rectangle (or at
529d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // least not tell the framework about it) so that the GPU can do the
530d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // correct edge behavior.
531d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        int xshrink = 0, yshrink = 0;
532d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.left > 0) {
533d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
534d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
535d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
536d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = 0.0f;
537d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
538a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
539d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
540d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
541a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
542d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
543d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    float(buf->getHeight());
544d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
545d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
546d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = 0.0f;
547d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
548d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.top > 0) {
549d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
550d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
551d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
552d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
553a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    } else {
554a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        tx = 0.0f;
555a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        ty = 0.0f;
556a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx = 1.0f;
557a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sy = 1.0f;
558a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
559f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
560a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
561a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
562f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
563d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
564f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
565f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
566a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
567a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
568a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
569a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
570a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
571a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
572a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
573736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
574f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
575f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
5761d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
5776ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
5781d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
5791d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
5801d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
5811d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
582c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennisvoid SurfaceTexture::setFrameAvailableListener(
583292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi        const sp<FrameAvailableListener>& listener) {
5846ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setFrameAvailableListener");
585c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    Mutex::Autolock lock(mMutex);
586fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    mFrameAvailableListener = listener;
587c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis}
588c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis
5898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
5908ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
5918ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
5928ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
5938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
5948ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
5958ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
5968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
5978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
5983cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
5993cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
600fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
6018ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
6028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
6038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
6048ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
6057a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
6067a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
6077a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
6087a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6097a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6107a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
6117a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
6127a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentCrop;
6137a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6147a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6157a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
6167a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
6177a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
6187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6197a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6207734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopianuint32_t SurfaceTexture::getCurrentScalingMode() const {
6217734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
6227734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
6237734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
6247734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
62559769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennisbool SurfaceTexture::isSynchronousMode() const {
62659769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    Mutex::Autolock lock(mMutex);
627b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->isSynchronousMode();
62859769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis}
62959769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
630fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennisvoid SurfaceTexture::freeBufferLocked(int slotIndex) {
631fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
632fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    mEGLSlots[slotIndex].mGraphicBuffer = 0;
633fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (mEGLSlots[slotIndex].mEglImage != EGL_NO_IMAGE_KHR) {
634fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        EGLImageKHR img = mEGLSlots[slotIndex].mEglImage;
635fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
636ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
637fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        }
638fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
639fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
640fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
641fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
6427b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisvoid SurfaceTexture::abandon() {
643fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("abandon");
6447b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    Mutex::Autolock lock(mMutex);
645fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
646fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (!mAbandoned) {
647fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mAbandoned = true;
648fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mCurrentTextureBuf.clear();
649fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
650fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        // destroy all egl buffers
651fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
652fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis            freeBufferLocked(i);
653eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        }
654eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
655fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        // disconnect from the BufferQueue
656fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mBufferQueue->consumerDisconnect();
657fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mBufferQueue.clear();
658fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
6597b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
6607b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
661fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennisvoid SurfaceTexture::setName(const String8& name) {
662eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
663fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
664b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(name);
665b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
666b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
667b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
668b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
669b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
670b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
671b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
672b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
673b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
674b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setConsumerUsageBits(usage);
675b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
676b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
677b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setTransformHint(uint32_t hint) {
678b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
679b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setTransformHint(hint);
680b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
681b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
682b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring BufferQueue from SurfaceTexture
683b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Should not be in final interface once users of SurfaceTexture are clean up.
684b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setSynchronousMode(bool enabled) {
685b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
686b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setSynchronousMode(enabled);
687b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
688b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
689b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring, should not be in final interface
690b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamsp<BufferQueue> SurfaceTexture::getBufferQueue() const {
691b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
692b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue;
693b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
694b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
695b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring, should not be in final interface
696b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setBufferCount(int bufferCount) {
697b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
698b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setBufferCount(bufferCount);
699b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
700b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
701b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring, should not be in final interface
702b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::connect(int api,
703b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam                uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
704b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
705b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->connect(api, outWidth, outHeight, outTransform);
706fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis}
707fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
708fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennisvoid SurfaceTexture::onFrameAvailable() {
709fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("onFrameAvailable");
710fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
711fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    sp<FrameAvailableListener> listener;
712fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    { // scope for the lock
713fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        Mutex::Autolock lock(mMutex);
714fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        listener = mFrameAvailableListener;
715fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
716fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
717fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (listener != NULL) {
718fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        ST_LOGV("actually calling onFrameAvailable");
719fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        listener->onFrameAvailable();
720fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
721fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
722fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
723fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennisvoid SurfaceTexture::onBuffersReleased() {
724fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("onBuffersReleased");
725fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
726fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    Mutex::Autolock lock(mMutex);
727fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
728fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (mAbandoned) {
729fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        // Nothing to do if we're already abandoned.
730fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        return;
731fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
732fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
733fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    uint32_t mask = 0;
734fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    mBufferQueue->getReleasedBuffers(&mask);
735fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
736fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        if (mask & (1 << i)) {
737fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis            freeBufferLocked(i);
738fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        }
739fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
740f71c4ae136f7749b9dfdaa2dd64d771868eeeb2dDaniel Lam
741f71c4ae136f7749b9dfdaa2dd64d771868eeeb2dDaniel Lam    mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
742fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
743fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
74468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopianvoid SurfaceTexture::dump(String8& result) const
74568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
74668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    char buffer[1024];
74768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    dump(result, "", buffer, 1024);
74868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
74968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
75068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopianvoid SurfaceTexture::dump(String8& result, const char* prefix,
75168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        char* buffer, size_t SIZE) const
75268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
75368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    Mutex::Autolock _l(mMutex);
754fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    snprintf(buffer, SIZE, "%smTexName=%d, mAbandoned=%d\n", prefix, mTexName,
755fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis            int(mAbandoned));
75668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
75768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
75868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    snprintf(buffer, SIZE,
759fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n",
760fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis            prefix, mCurrentCrop.left,
76168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
762eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mCurrentTransform, mCurrentTexture
76368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    );
76468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
76568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
766fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    if (!mAbandoned) {
767fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis        mBufferQueue->dump(result, prefix, buffer, SIZE);
768fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
76968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
77068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
771f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
772f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
773f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
774f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
775f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
776f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
777f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
778f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
779f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
780f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
781f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
782f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
783f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
784f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
785f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
786f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
787f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
788f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
789f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
790f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
791f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
792f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
7938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
794