GLConsumer.cpp revision 97eba8904c2f221c42a9473407223a4c3a213f75
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
299fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis#include <hardware/hardware.h>
309fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
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
4297eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddennamespace android {
4397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
4401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis// This compile option makes SurfaceTexture use the
4501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis// EGL_ANDROID_native_fence_sync extension to create Android native fences to
4601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis// signal when all GLES reads for a given buffer have completed.  It is not
4701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis// compatible with using the EGL_KHR_fence_sync extension for the same
4801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis// purpose.
4901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis#ifdef USE_NATIVE_FENCE_SYNC
5001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis#ifdef USE_FENCE_SYNC
5101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis#error "USE_NATIVE_FENCE_SYNC and USE_FENCE_SYNC are incompatible"
5201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis#endif
5397eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddenconst bool SurfaceTexture::sUseNativeFenceSync = true;
5401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis#else
5597eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddenconst bool SurfaceTexture::sUseNativeFenceSync = false;
5661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis#endif
5761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
5861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis// This compile option makes SurfaceTexture use the EGL_ANDROID_sync_wait
5961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis// extension to insert server-side waits into the GLES command stream.  This
6061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis// feature requires the EGL_ANDROID_native_fence_sync and
6161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis// EGL_ANDROID_wait_sync extensions.
6261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis#ifdef USE_WAIT_SYNC
6361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennisstatic const bool useWaitSync = true;
6461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis#else
6561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennisstatic const bool useWaitSync = false;
6601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis#endif
6701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis
68fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis// Macros for including the SurfaceTexture name in log messages
696807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
709d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
71a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
7232397c1cd3327905173b36baa6fd1c579bc328ffSteve Block#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
73e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
7429b5762efc359022168e5099c1d17925444d3147Mathias Agopian
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
92f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
93f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
94f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
95f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
96f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
97f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
98f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
99f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
100f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot180[16] = {
101f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
102f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
103f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
104f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 1, 0, 1,
105f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
106f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot270[16] = {
107f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
108f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
109f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
110f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
111f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
112f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
113f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
114f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
115fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
116fb1b5a2f333800574b0da435d1200cf9b13d723fJamie GennisSurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
117b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
1189fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),
1191d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
1201d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
1215c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
122b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
12386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef USE_FENCE_SYNC
12486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
12586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#else
12686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(false),
12786edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
128eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
129ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
130ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
13174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
13274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1336b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
1346ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("SurfaceTexture");
135b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
136fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
137fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
138fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
1399fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
14231a353da225af5329735451c761b430d82dfda1bJamie Gennisstatus_t SurfaceTexture::setDefaultMaxBufferCount(int bufferCount) {
1438072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
14431a353da225af5329735451c761b430d82dfda1bJamie Gennis    return mBufferQueue->setDefaultMaxBufferCount(bufferCount);
1458072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1468072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1478ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
148a5c75c01620179ce00812354778a29a80d76e71fMathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
149a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
150b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
151016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
152016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
153b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferSize(w, h);
154a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
155a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1568ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::updateTexImage() {
157bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
158bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("updateTexImage");
159bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
160bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
161bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
162bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("updateTexImage: SurfaceTexture is abandoned!");
163bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
164bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
165bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
166bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
167bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
168bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
169bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
170bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
171bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
172bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    BufferQueue::BufferItem item;
173bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
174bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
175bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
176bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
177bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = acquireBufferLocked(&item);
178bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
179bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
180bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
181bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGV("updateTexImage: no buffers were available");
182bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
183bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
184bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
185bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("updateTexImage: acquire failed: %s (%d)",
186bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
187bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
188bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
189bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
190bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
191bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
192bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = releaseAndUpdateLocked(item);
193bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
194bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
195bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
196bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
197bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
198bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
19997eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
20097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
2012c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
2022c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
2039fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisstatus_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) {
2049fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    status_t err = ConsumerBase::acquireBufferLocked(item);
2059fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
2069fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
2079fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
2089fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2099fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    int slot = item->mBuf;
2109fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (item->mGraphicBuffer != NULL) {
211bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // This buffer has not been acquired before, so we must assume
212bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // that any EGLImage in mEglSlots is stale.
2139fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
214bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
215bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
216bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                      slot);
217bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                // keep going
218bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            }
2199fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
2209fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
2219fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
2229fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2239fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
2249fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
2259fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2269fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisstatus_t SurfaceTexture::releaseBufferLocked(int buf, EGLDisplay display,
227b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis       EGLSyncKHR eglFence) {
228bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = ConsumerBase::releaseBufferLocked(buf, display, eglFence);
2299fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
230d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
2319fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2329fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
2339fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
2349fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
235bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFaddenstatus_t SurfaceTexture::releaseAndUpdateLocked(const BufferQueue::BufferItem& item)
236bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
2379abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
2389abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
23974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
240bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("releaseAndUpdate: SurfaceTexture is not attached to an OpenGL "
24174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
24274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
24374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
24474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
245bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
246bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
247bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
248bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
249ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
250ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
251bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    int buf = item.mBuf;
252bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
253bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // If the mEglSlot entry is empty, create an EGLImage for the gralloc
254bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // buffer currently in the slot in ConsumerBase.
255bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    //
256bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
257bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // means the buffer was previously acquired), if we destroyed the
258bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // EGLImage when detaching from a context but the buffer has not been
259bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // re-allocated.
260bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
261bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer);
262bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (image == EGL_NO_IMAGE_KHR) {
263bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGW("releaseAndUpdate: unable to createImage on display=%p slot=%d",
264bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                  mEglDisplay, buf);
265bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
266bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
267bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        mEglSlots[buf].mEglImage = image;
268ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
269ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
270bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
271bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = syncForReleaseLocked(mEglDisplay);
272bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
273bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // Release the buffer we just acquired.  It's not safe to
274bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // release the old buffer, so instead we just drop the new frame.
275bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        releaseBufferLocked(buf, mEglDisplay, EGL_NO_SYNC_KHR);
276bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
277bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
278ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
279bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("releaseAndUpdate: (slot=%d buf=%p) -> (slot=%d buf=%p)",
280bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture,
281bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
282bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            buf, mSlots[buf].mGraphicBuffer->handle);
283eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
284bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
285bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
286bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t status = releaseBufferLocked(mCurrentTexture, mEglDisplay,
287bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                mEglSlots[mCurrentTexture].mEglFence);
288bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
289bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)",
290bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                   strerror(-status), status);
291bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = status;
292bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // keep going, with error raised [?]
2932c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
294bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
2952c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
296bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Update the SurfaceTexture state.
297bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTexture = buf;
298bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
299bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
300bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
301bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
302bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
303bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
304bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
305bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
306bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
307bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
308bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
309bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
31097eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddenstatus_t SurfaceTexture::bindTextureImageLocked() {
311bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
312bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
313bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
314bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
315bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
316bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
317bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
318bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
319bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
320bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
321bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
322bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
323bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (mCurrentTextureBuf == NULL) {
324bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: no currently-bound texture");
325bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return NO_INIT;
3268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
32797eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        status_t err = bindUnslottedBufferLocked(mEglDisplay);
32897eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        if (err != NO_ERROR) {
32997eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden            return err;
33097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        }
331bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    } else {
332bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
3330eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
3349fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
33574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3369fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
337bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: error binding external texture image %p"
338bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                    ": %#04x", image, error);
339bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
3408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
341bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
34297eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
34397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
34497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
34597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
346bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
3479a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
348bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFaddenstatus_t SurfaceTexture::checkAndUpdateEglStateLocked() {
349bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
350bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
35186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
352bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
353bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            dpy == EGL_NO_DISPLAY) {
354bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
355bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
356bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
357b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
358bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
359bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ctx == EGL_NO_CONTEXT) {
360bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
361bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
3628ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
36350c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
364bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
365bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
366bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
3678ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
3688ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
369ef19414bd8b77a26f5751f3845be79025a8263feJesse Hallvoid SurfaceTexture::setReleaseFence(int fenceFd) {
3703d1d09c0c116c42f7d083f87628b5f8377b1f275Jamie Gennis    sp<Fence> fence(new Fence(fenceFd));
37145cb2ba1d52d81e20702b62610422fb09aaedeaeJamie Gennis    if (fenceFd == -1 || mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)
372ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall        return;
373b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis    status_t err = addReleaseFence(mCurrentTexture, fence);
374b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis    if (err != OK) {
375b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis        ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
376b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis                strerror(-err), err);
377ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
378ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
379ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
38074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::detachFromContext() {
38174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
38274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
38374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
38474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
38574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
38674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: abandoned SurfaceTexture");
38774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
38874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
38974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
39174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: SurfaceTexture is not attached to a "
39274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
39374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
39474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
39574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
39774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
39874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
40074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
40174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
40274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
40374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
40574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
40674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
40774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
40874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
41074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
41174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
41274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
41374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
41474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
41674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
41774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4189aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // Because we're giving up the EGLDisplay we need to free all the EGLImages
4199aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // that are associated with it.  They'll be recreated when the
4209aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a
4219aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // new EGLDisplay).
4229aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
4239fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR img = mEglSlots[i].mEglImage;
4245c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
4259aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
4269fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
4279aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        }
4289aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    }
4299aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis
43074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
43174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
43274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
43374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
43474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
43574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
43674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
43774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::attachToContext(GLuint tex) {
43874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
43974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
44074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
44174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
44374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: abandoned SurfaceTexture");
44474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
44574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
44674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
44874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: SurfaceTexture is already attached to a "
44974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
45074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
45174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
45274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
45474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
45574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
45774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
45874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
45974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
46074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
46174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
46274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
46374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
46474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
46574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
46674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
46774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
46874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    glBindTexture(mTexTarget, tex);
46974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
47074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
4715c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // The EGLImageKHR that was associated with the slot was destroyed when
4725c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // the SurfaceTexture was detached from the old context, so we need to
4735c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // recreate it here.
474bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t err = bindUnslottedBufferLocked(dpy);
475bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err != NO_ERROR) {
47674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
47774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
47874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
47974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
48074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
48174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
48274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
48374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
48474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
48574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
48674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
48774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
488bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFaddenstatus_t SurfaceTexture::bindUnslottedBufferLocked(EGLDisplay dpy) {
489bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
490bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture, mCurrentTextureBuf.get());
491bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
492bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Create a temporary EGLImageKHR.
493bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
494bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (image == EGL_NO_IMAGE_KHR) {
495bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return UNKNOWN_ERROR;
496bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
497bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
498bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Attach the current buffer to the GL texture.
499bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
500bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
501bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
502bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = OK;
503bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
504bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
505bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                "(slot %d): %#04x", image, mCurrentTexture, error);
506bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        err = UNKNOWN_ERROR;
507bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
508bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
509bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We destroy the EGLImageKHR here because the current buffer may no
510bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // longer be associated with one of the buffer slots, so we have
511bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // nowhere to to store it.  If the buffer is still associated with a
512bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // slot then another EGLImageKHR will be created next time that buffer
513bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // gets acquired in updateTexImage.
514bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    eglDestroyImageKHR(dpy, image);
515bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
516bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
517bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
518bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
519bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
52074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
52174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
52274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
52301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
52497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        if (sUseNativeFenceSync) {
52501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
52601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
52701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
52801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
52901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
53074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
53174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
53201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
53301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
53498ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
53501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
53601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
53701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
53801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
53901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
54001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
5419504eb915c9628e130f45019bdefda0168089886Jesse Hall            status_t err = addReleaseFenceLocked(mCurrentTexture, fence);
54201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
54301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error adding release fence: "
54401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
54501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
54601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
54701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis        } else if (mUseFenceSync) {
54801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
54901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
55001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
55101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
55201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
55301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
55401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
55501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
55601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: error waiting for previous "
55701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
55801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
55901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
56001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
56101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
56201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
56301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
56401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
56501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
56674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
56701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
56801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
56901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
57001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
57101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
57201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
57301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
57401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
57501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
57601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
57774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
57874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
57974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
58174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
58274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5837a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
5847a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
5857a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
5867a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
5877a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
5887a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
5897a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
5907a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
5917a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
5927a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5937a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
5947a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5957a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
5967a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
5977a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5987a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5997a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
6007a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6017a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6027a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
603fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
6047a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6057a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
606f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
607f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
608736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
609736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
610736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
6115c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennisvoid SurfaceTexture::setFilteringEnabled(bool enabled) {
6125c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
613e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
614e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGE("setFilteringEnabled: SurfaceTexture is abandoned!");
615e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
616e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
6175c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
6185c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
619e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
620e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf==NULL) {
621e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
622e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
623e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
624e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf != NULL) {
625e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
6265c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
6275c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
6285c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
629e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopianvoid SurfaceTexture::computeCurrentTransformMatrixLocked() {
630e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    ST_LOGV("computeCurrentTransformMatrixLocked");
631f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
632a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
633a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
634a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
635a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
636a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
637a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
638a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
639a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
640a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
641a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
642a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
643a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
644a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
645a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
646a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
647a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
648a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
649a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
650a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
651a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
652a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
653a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
654a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
655a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
656f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
657f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
658eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
659e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
660e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (buf == NULL) {
661e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
662e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
663e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
664d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    Rect cropRect = mCurrentCrop;
6655c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
6665c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferWidth = buf->getWidth();
6675c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferHeight = buf->getHeight();
668d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    if (!cropRect.isEmpty()) {
6695c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        float shrinkAmount = 0.0f;
6705c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (mFilteringEnabled) {
6715c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // In order to prevent bilinear sampling beyond the edge of the
6725c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // crop rectangle we may need to shrink it by 2 texels in each
6735c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // dimension.  Normally this would just need to take 1/2 a texel
6745c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // off each end, but because the chroma channels of YUV420 images
6755c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // are subsampled we may need to shrink the crop region by a whole
6765c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // texel on each side.
6775c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            switch (buf->getPixelFormat()) {
6785c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_8888:
6795c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBX_8888:
6805c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_888:
6815c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_565:
6825c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_BGRA_8888:
6835c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_5551:
6845c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_4444:
6855c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // We know there's no subsampling of any channels, so we
6865c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // only need to shrink by a half a pixel.
6875c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 0.5;
6884f9c284de4b9159126f69eb1219c410f66cc872cRomain Guy                    break;
6899fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
6905c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                default:
6915c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // If we don't recognize the format, we must assume the
6925c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // worst case (that we care about), which is YUV420.
6935c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 1.0;
6949fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    break;
6955c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
6965c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
6975c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
6985c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        // Only shrink the dimensions that are not the size of the buffer.
6995c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.width() < bufferWidth) {
7005c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
7015c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
7025c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferWidth;
7035c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
7045c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.height() < bufferHeight) {
7055c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
7065c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
7075c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
7085c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
7095c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
710a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
711f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
712a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
713a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
714f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
715d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
716f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
717f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
718a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
719a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
720a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
721a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
722a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
723a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
724a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
725736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
726f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
727f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
7281d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
7296ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
7301d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
7311d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
7321d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
7331d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
7348ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
7358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
7368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
7378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
7388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
7398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
7408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
7418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
7428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
7433cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
7443cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
745fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
7468ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
7478ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
7488ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
7498ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
7507a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
7517a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
7527a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
7537a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7547a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7557a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
7567a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
757016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
758016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
759016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
760016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newWidth = mCurrentCrop.width();
761016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newHeight = mCurrentCrop.height();
762016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
763016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
764016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
765016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too wide: newWidth = %d", newWidth);
766016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
767016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
768016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too tall: newHeight = %d", newHeight);
769016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
770016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
771016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
772016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth < mCurrentCrop.width()) {
773016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dw = (newWidth - mCurrentCrop.width())/2;
774016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
775016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
776016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
777016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newHeight < mCurrentCrop.height()) {
778016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dh = (newHeight - mCurrentCrop.height())/2;
779016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
780016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
781016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
782016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
783016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
784016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
785016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
786016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
787016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
788016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
7897a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7907a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7917a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
7927a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
7937a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
7947a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7957a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7967734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopianuint32_t SurfaceTexture::getCurrentScalingMode() const {
7977734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
7987734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
7997734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
8007734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
801dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hallsp<Fence> SurfaceTexture::getCurrentFence() const {
802dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
803dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
804dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
805dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
80661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennisstatus_t SurfaceTexture::doGLFenceWait() const {
80761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
8083941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
8093941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
8103941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
8113941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennisstatus_t SurfaceTexture::doGLFenceWaitLocked() const {
81261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
81361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
81461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
81561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
81661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
81761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
81861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
81961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
82061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
82161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
82261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLContext");
82361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
82461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
82561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
82661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mCurrentFence != NULL) {
82761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        if (useWaitSync) {
82861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
82961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
83061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
83161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
83261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
83361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
83461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
83561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
83661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
83761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
83861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
83961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
84061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
84161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
84261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
84361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
84461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
84561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
84661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
84761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
84861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
84961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
85061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglWaitSyncANDROID(dpy, sync, 0);
85161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
85261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
85361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
85461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
85561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
85661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
85761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
85861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
859ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall            status_t err = mCurrentFence->waitForever(1000,
860ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall                    "SurfaceTexture::doGLFenceWaitLocked");
86161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
86261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
86361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
86461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
86561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
86661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
86761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
86861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
86961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
87061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
87159769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennisbool SurfaceTexture::isSynchronousMode() const {
87259769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    Mutex::Autolock lock(mMutex);
873b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->isSynchronousMode();
87459769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis}
87559769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
876fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennisvoid SurfaceTexture::freeBufferLocked(int slotIndex) {
877fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
8789abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
8799abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
8809abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
8819fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
8829aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    if (img != EGL_NO_IMAGE_KHR) {
8839aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
8849aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        eglDestroyImageKHR(mEglDisplay, img);
885fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
8869fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
8879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
888fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
889fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
8909fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisvoid SurfaceTexture::abandonLocked() {
8919fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ST_LOGV("abandonLocked");
8929fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mCurrentTextureBuf.clear();
8939fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
8947b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
8957b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
896fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennisvoid SurfaceTexture::setName(const String8& name) {
897eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
898fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
899b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(name);
900b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
901b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
902b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
903b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
904b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
905b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
906b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
907b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
908b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
90985b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
910b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setConsumerUsageBits(usage);
911b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
912b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
913b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setTransformHint(uint32_t hint) {
914b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
915b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setTransformHint(hint);
916b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
917b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
918b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring BufferQueue from SurfaceTexture
919b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Should not be in final interface once users of SurfaceTexture are clean up.
920b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setSynchronousMode(bool enabled) {
921b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
922b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setSynchronousMode(enabled);
923b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
924b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
9259fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisvoid SurfaceTexture::dumpLocked(String8& result, const char* prefix,
9269fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        char* buffer, size_t size) const
92768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
9289fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    snprintf(buffer, size,
9299fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
9309fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
9319fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
9329fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
9339fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
93468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
93568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
9369fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::dumpLocked(result, prefix, buffer, size);
93768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
93868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
939f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
940f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
941f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
942f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
943f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
944f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
945f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
946f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
947f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
948f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
949f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
950f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
951f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
952f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
953f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
954f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
955f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
956f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
957f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
958f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
959f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
960f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
9618ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
962